固定 512-token 分块在 40% 文档上失效;结构感知分块(按标题/对话边界/代码块)才是正解,配合重排序能显著提升检索质量。
每个 RAG demo 都能跑起来。它检索一些内容,交给 LLM,就能生成一个看似合理的答案。每个生产级 RAG 系统都会失败——至少失败一次——而且失败原因与模型本身无关。在花了四个月把一个 RAG 流水线从 notebook 搬进为真实用户解答问题的系统之后,我可以精确地告诉你差距在哪里:内容管道。检索很容易。内容才是难题。

我们流水线的第一个版本使用了固定的 512-token 分块。这是一切教程里的默认值,所以感觉挺稳妥。但它对大约 40% 的文档来说是错误的。我们索引技术手册、工单对话和内部规格文档。手册里有跨越多个分块的编号步骤;工单对话顶部是一个问题,而被接受的答案在十个段落之后。固定大小的分块以同样的方式破坏了两种模式:语义单元——一个完整的步骤、一对完整的问答——在句子中间被截断了。
我们切换到了结构感知分块:按标题分割手册、按会话边界分割工单、按代码块分割任何含代码的内容。我们评估集上的检索命中率从 61% 提升到了 83%。不是因为嵌入变了。是因为单元变了。如果你的分块与人类回答问题时愿意引用的原子单元不对齐,再多的重排序也救不了你。
向量搜索在找"语义相似"内容上很出色,但在精确术语上表现糟糕。我们的用户搜索错误码、版本号和函数名——这些字符串会被嵌入模糊化。像 ERR_9001 这样的查询返回的是关于超时和连接池的模糊匹配,而不是精确的错误页面,因为从语义上说错误码并不"相似"于任何东西——它是一个标识符。
我们添加了 BM25 作为并行检索器,在重排序前用加权分数合并结果。精确匹配查询现在几乎总能将正确页面 surfaced 到前三名。教训很无聊但很重要:混合搜索(向量 + 关键词)是 2026 年生产 RAG 的基准,不是优化。如果你向输入产品名和错误码的用户交付纯向量搜索,那你交付的就是一个 demo。
最难察觉的失败是自信的过时答案。我们的流水线索引了 12,000 份文档;其中约 8% 每月都会变化。第二个版本检索"语义最接近的分块"——结果发现,那往往是上个季度的定价页面。用户不会抱怨答案是错的。他们默默地失去了信任,然后不再提问。
修复分三部分:
updated_at 时间戳。修复之后,过时答案的报告降到了接近零。如果你的知识库有任何随时间变化的来源——定价、政策、文档、代码——新鲜度处理不是可选项,而是必选项。
人们一直在问"该用哪个嵌入模型?"在我们的基准测试中,升级嵌入模型让检索质量提升了约 4-6 个百分点。在 top-20 候选结果上加一个 cross-encoder 重排序器提升了 12 个百分点——两倍的收益,而索引成本只是很小一部分(重排序在查询时运行,所以它只处理你已经取回的候选)。
我们使用一个小型 cross-encoder,在 CPU 上每个查询约运行 30ms。流水线从混合搜索中取回 20 个候选,重排序到 5 个,然后把这 5 个交给 LLM。用户能感知到的质量飞跃是立即的。廉价检索、精确重排序、最后生成——正是这个架构让我们的系统感觉"智能"。
我们构建了一个包含 200 个真实查询的评估集,配有专家编写的黄金答案。流水线的每一次变更——新的分块器、新的重排序器、新的 prompt——都会用它打分。这听起来很明显,但这是大多数 demo 流水线唯一跳过的步骤,也是它们无法改进的原因:没有基准线,你无法判断一个变更是帮助还是伤害了系统。
评估集与代码一起在 git 中版本化管理。当用户报告一个糟糕的答案时,它会先成为一个新的评估用例,然后我们才去修复。这样"修 bug"和"防止回归"就变成了同一件事。我们的答案准确率从上线时的 74% 提升到了现在的 91%,而评估集正是让我们能够证明每一步都做出了贡献。

以下是现在我们的生产环境:
这些决策没有一个是花哨的。没有花哨的 Agent 编排,没有自动优化框架。只是在模型看到文档之前,对内容管道该做什么做出的谨慎选择。这就是"打动人的 demo"和"人们依赖的系统"之间的区别。
如果你在构建 RAG,从 Decision 1 和 5 开始——分块和评估。它们最不花哨,也最具决定性。模型很少是你的瓶颈。你的内容管道才是。
你把 RAG 搬进生产时,哪种失败最让你意外?欢迎在评论区交流经验。