为什么大多数 RAG 系统都过不了第一版验收
过去一年我参与了 4 个 RAG 项目的从 0 到 1,模式高度一致:第一周 demo 惊艳,第二周内部演示翻车,第三周业务方提出”是不是模型不行”。而真实原因几乎从不在模型。
这篇文章总结我看到的第一版验收失败模式,以及我在第二个项目之后开始用的几个反模式检查清单。如果你正在做第一个 RAG 系统,希望它能帮你少走两周弯路。
第一版验收的典型场景
第一版验收通常长这样:业务方准备 20–30 个问题,工程师现场提问,模型作答,大家围在一起判断”这个答得对不对”。如果对错比例能让业务方点头,就过;如果经常出现”答非所问”或”胡编一气”,就打回。
这个场景看起来很务实,其实埋了三个雷:
- “答对了”没有定义。每个人心里有一把尺子,且这把尺子在演示过程中会变。
- 验收问题不是真实分布。30 个手写问题里,“标准问句”占比过高,长尾和坏 case 缺席。
- demo 数据和验收数据是同一份。工程师调试时已经看过这些问题,等于在评测集上过拟合。
**反模式 01:**用同一批问题做调试和验收。这不是验收,这是演练。验收集必须独立、保密、由业务方维护。
三个最常见的失败点
1. 切片策略:被低估的”前置决策”
大多数团队用 RecursiveCharacterTextSplitter 默认值(chunk_size=1000, overlap=200)开工,跑通后再回来调。但切片决定了检索能拿到什么,这是最先需要、也是最难后期改的决策。
真实的问题往往不是切片大小,而是切片边界:
- 把一个表格切成两半,检索只命中一半,另一半永远是”看不见的证据”。
- 把一个判断和它的前提条件分开,模型拿到结论但不知道约束条件,于是把”在 A 情况下推荐 X”答成了”推荐 X”。
- 把 FAQ 的问和答切开,检索命中的是问题本身,模型从问题推导不出答案。
我后来在所有项目里加了一条规则:切片必须以”语义完整单位”为边界,而不是字符数。表格整张切、Q&A 整对切、判断和条件一起切。代价是 chunk 长度不齐,但下游有 truncation 兜底,远比割裂语义安全。
2. 上下文组织:检索 ≠ 拼接
第二常见的失败是:检索到 5 段,按相似度分数从高到低拼起来,塞给 LLM。看起来合理,但实际效果会被三件事破坏:
- 顺序敏感。LLM 对上下文开头和结尾更敏感(middle-of-context degradation),最重要的证据放中间,反而最容易被忽略。
- 重复占用 token。Top-5 里经常有 3 段是同一文档的相邻切片,内容高度重叠,等于用 5 份 token 装了 2 份信息。
- 缺少结构信号。LLM 不知道哪段是定义、哪段是案例、哪段是过期信息,只能盲目信任所有内容。
我的做法是:检索之后加一层 context composer,做三件事——按文档去重并合并相邻切片、按”定义→规则→案例”重排、为每段加一个来源前缀(如 [规范 2024] …)。这一层让后续的 prompt 工程几乎不需要做。
3. 没有事先约定”答对了”
这是最被忽视、也是最致命的。RAG 系统的输出有四种状态:
- 对且完整:答得对,关键信息都在。
- 对但不完整:答的方向对,但漏了关键条件。
- 错但能识别:答错了,但系统主动说”我不确定”。
- 错且自信:答错了,还答得斩钉截铁。
业务方验收时往往只区分”对”和”错”,但第二类和第四类是截然不同的风险。第二类可以通过补充上下文修复,第四类是 RAG 的癌症——它会摧毁用户对系统的信任,且很难从日志里发现。
所以验收前必须和业务方约定三件事:
“答对了”= 答案正确 + 关键约束完整 + 来源可追溯。“我不知道”是合法回答。错答是 P0,漏答是 P1,过度自信是 P0+。
一个真实的复盘
第二个项目我们花了两周调 rerank 模型,从 bge 调到 cohere,从向量调到混合检索,Recall@5 从 0.72 提到 0.83。但业务方的反馈是”感觉没变好”。
后来我们抽样了 50 个 bad case,发现分布是这样的:
- 检索召回不足:6 个(12%)
- 检索召回了但被 rerank 挤掉:4 个(8%)
- 上下文有答案但 LLM 没用:11 个(22%)
- 上下文里就没答案,模型硬编:23 个(46%)
- 答对了但业务方认为”不对”:6 个(12%)
也就是说,68% 的问题和检索质量无关。我们花两周优化的部分只覆盖了 20% 的问题。真正的瓶颈在切片(导致上下文没答案)和上下文组织(导致有答案但 LLM 没用)。
从那以后我形成了一个习惯:调任何东西之前,先做 bad case 归因。不做归因就调参,等于在错误的问题上做正确的优化。
怎么破:一个最小可行的验收清单
如果你正在做第一个 RAG 系统,下面是我用过的最小清单:
- 独立验收集。让业务方准备 30–50 个问题,工程师不看、不调、不接触。验收时再拿出来用。
- 切片以语义为单位。表格、Q&A、判断+条件不切开。chunk 长度不齐没关系,比割裂语义安全。
- 检索后加一层 composer。去重、重排、加来源前缀。这一层比调 rerank 模型性价比高 10 倍。
- 约定”答对了”的四类状态。把”过度自信”单列出来作为 P0。
- 每周做一次 bad case 归因。不做归因不调参。
这五条都不需要任何”高级技术”,但能让你的第一版验收通过率从 30% 提到 70%。剩下的 30% 才是模型、向量、prompt 这些真正需要打磨的部分。
结语
RAG 系统的难度不在任何一个组件,而在组件之间的衔接。切片决定了检索的上限,检索决定了上下文的上限,上下文组织决定了 LLM 的上限,LLM 决定了输出的上限,而”答对了”的定义决定了所有这些上限是否有意义。
第一版验收失败,往往不是某一环做得不够好,而是某一环的失败被放大到了整个系统。先找到那一环,再谈优化。