Skip to content

RAG失败复盘专题

版本:v1.3

最后更新:2026-07-09

适用对象:已经做了 RAG / 知识问答 / 文档检索,线上开始出现“偶尔错、难定位、每次都像新问题”的团队

很多团队做 RAG 时最常见的误区是:

  • 只看“这次答错了没有”
  • 却不系统复盘“到底是哪一层让它答错了”

结果就是所有问题最后都被粗暴归因为:

  • 模型幻觉
  • embedding 不行
  • chunk 没切好

但真实情况通常更复杂。一次 RAG 失败,可能来自知识根本没入库、检索没召回、排序把关键证据压下去、上下文拼装失真、引用结构太弱,或者答案生成阶段根本没正确消费证据。

这也是为什么 RAG 失败复盘不能只做“错误案例记录”,而要做成一套能映射到具体修复动作的工程手册。

1. 什么是 RAG 失败复盘

更实用的理解通常是:

  • 针对一次失败回答
  • 反向拆解知识、索引、检索、排序、上下文构造和生成链路
  • 找到最先出错的那一层

重点不是证明模型不行,而是回答三个问题:

  1. 失败最早发生在哪个阶段。
  2. 这个阶段缺的是数据、策略、配置还是运行时观测。
  3. 修复动作应该落到哪个具体 owner 和哪个回归样例上。

2. 为什么 RAG 失败特别值得单独复盘

RAG 的失败来源通常比纯生成复杂,因为它至少横跨四类系统:

  • 知识数据系统
  • 索引与检索系统
  • Prompt 与上下文组装系统
  • 模型回答系统

如果不拆开看,团队很容易出现这几种错误动作:

  • 有知识没召回,却去换模型。
  • 排序失真,却只补更多文档。
  • 引用冲突,却只改 Prompt。
  • 上下文过载,却只增大 top-k。
  • 权限过滤出错,却以为是相关性问题。

所以 RAG 失败复盘最大的价值,是把“模糊错误”变成“可分层追责的错误”。

3. 一次 RAG 失败通常要先保留什么证据

如果线上连证据都没保留,复盘往往只能靠猜。

建议至少保留这些信息:

3.1 请求侧信息

  • 用户原始问题
  • 归一化后的查询
  • 查询改写结果
  • 租户、角色、权限上下文
  • 时间范围、业务场景、入口来源

3.2 检索侧信息

  • 检索模式,例如向量、关键词、混合检索
  • top-k 原始召回结果
  • 每条结果的得分、来源、chunk id、文档版本、metadata
  • rerank 前后顺序
  • 被过滤掉的结果和过滤原因

3.3 上下文构造侧信息

  • 最终拼入模型的上下文片段
  • 上下文顺序
  • 引用结构和来源标识
  • 截断、压缩、去重策略

3.4 生成侧信息

  • 使用的模型、参数和 Prompt 版本
  • 最终回答
  • 最终引用
  • 安全或格式校验结果

这些字段并不只是为了排障,也会决定你后面能不能做回归、对账、失败分桶和成本归因。

4. 一个更实用的失败分层方式

RAG 失败更适合按链路分层,而不是只记“答错了”。

4.1 覆盖失败

  • 知识库里根本没有答案
  • 有答案但没进入当前索引
  • 文档版本过旧,真实答案已变更

4.2 进入失败

  • 文档解析失败
  • 切片策略错误
  • metadata 缺失
  • 权限字段缺失
  • 文档状态未发布或未生效

4.3 召回失败

  • 有内容但没检索出来
  • 查询改写把问题改偏了
  • 向量检索偏语义相似,却丢了关键术语
  • 过滤条件过严,把正确结果筛掉

4.4 排序失败

  • 正确结果在 top-k 里,但排序靠后
  • rerank 对业务关键字段不敏感
  • 标题、字段和证据权重不合理
  • 旧版本文档被排在新版本前面

4.5 证据组装失败

  • chunk 太碎,单片段证据不完整
  • chunk 太长,噪声盖过关键信息
  • 多条证据之间缺少结构化引用关系
  • 权限与租户边界在组装阶段丢失

4.6 消费失败

  • 模型看到了证据,但没有正确使用
  • 模型引用了错误片段
  • 多来源证据冲突时没有正确优先级
  • 引用格式太弱,导致模型难以稳定消费

4.7 治理失败

  • 旧知识没有失效
  • 错误案例没回流
  • 权限变更没同步到索引
  • 修复动作没有进入回归集

5. 一次 RAG 失败应该按什么顺序排查

建议先按“从上游到下游”的顺序排,不要一开始就盯着最终答案。

5.1 先问:知识里到底有没有答案

第一步不是看模型,而是先确认:

  • 原始知识源是否存在答案
  • 答案是否在当前时间点仍然有效
  • 正确版本是否已经进入可检索状态

这一步如果没过,后面所有优化都只是补丁。

5.2 再问:正确知识有没有变成可检索对象

即使原始文档里有答案,也未必成功进入知识系统。

需要检查:

  • 文档是否解析成功
  • chunk 是否可读且颗粒度合理
  • metadata 是否完整
  • 权限、租户、状态、版本字段是否正确

很多“召回失败”,其实根源是进入失败。

5.3 再问:检索阶段有没有把它找回来

这里要看:

  • 原始查询与改写查询是否一致
  • 混合检索里关键词和语义信号是否都有效
  • top-k 里是否至少包含正确候选
  • 过滤条件是否过强

OpenAI File search 当前文档明确说明会结合 semantic 与 keyword search;Anthropic Contextual Retrieval 也明确建议把 embeddings 与 BM25 结合,并通过 rank fusion 汇总候选。这背后的工程启发很明确:

  • 企业场景里的工单号、产品名、规则编号、时间范围和组织边界,通常很难只靠纯向量检索稳定解决。

5.4 再问:正确结果有没有被排进模型视野

即使召回成功,也不代表最终可用。

这里重点看:

  • 正确结果是否排在前面
  • 进入模型的证据是否完整
  • 是否被更高噪声的片段淹没
  • 是否被错误版本压过

真正要看的不是“有没有进前 k”,而是:

  • 最终进入模型视野的证据是否足够可用

5.5 最后问:模型有没有正确使用证据

如果前面都没问题,再看回答阶段:

  • 最终 Prompt 是否要求基于证据回答
  • 引用结构是否明确
  • 冲突证据是否有优先级
  • 答案是否显式绑定了来源

这时才适合把问题归到“消费失败”。

6. 症状到根因的快速映射

下面这类映射在真实复盘里很有用。

6.1 查不到明确编号、名称或代码

更可能是:

  • 关键词信号不足
  • 混合检索缺失
  • metadata 过滤设计不合理

优先动作:

  • 检查关键词检索是否参与
  • 检查字段索引和 filter 字段设计
  • 检查查询改写是否删掉关键术语

6.2 答案看起来“像对的”,但引用不对

更可能是:

  • 排序失败
  • 引用结构太弱
  • 上下文拼装顺序不稳定

优先动作:

  • 比较 rerank 前后顺序
  • 审核引用 schema
  • 审核 chunk 到 answer 的映射关系

6.3 老文档总压过新文档

更可能是:

  • 版本字段未入索引
  • freshness 信号没有进入排序
  • 旧知识未失效

优先动作:

  • 审核版本化和状态字段
  • 审核排序规则是否考虑新鲜度
  • 审核旧文档下线和回收流程

6.4 正确内容在召回里,但模型回答仍然错

更可能是:

  • chunk 颗粒度不合适
  • 上下文噪声太大
  • 答案绑定证据的方式太弱
  • 冲突证据优先级不清

优先动作:

  • 审核进入模型的最终上下文
  • 审核答案片段和引用片段关系
  • 审核 top-k 和 rerank 后的候选密度

7. 为什么要把“候选池”单独拿出来看

很多团队在复盘时只看:

  • 最终答案
  • 最终引用

但这还不够,因为错误往往早在候选池阶段就已经决定了。

Anthropic 当前文档对 reranking 的描述很具体:

  • 可以先取更大的初始候选池,再用 rerank 选出更小的 top-K 放入模型

这给复盘的直接启发是:

  • 要同时保留初始召回池和 rerank 后候选池

不然你根本不知道:

  • 正确证据是没召回到,还是召回到后被排掉了

8. 为什么 chunk 设计经常是隐性根因

Anthropic Contextual Retrieval 文档明确指出:

  • chunk 边界、chunk 大小和 overlap 都会影响检索表现

这意味着很多“模型没答对”的问题,真正根因可能是:

  • chunk 太短,失去上下文
  • chunk 太长,关键信号被稀释
  • 标题、表格、注释、脚注切分后语义断裂

因此复盘时要敢于回答:

  • 是不是 chunking 本身让正确答案很难被稳定消费

9. 为什么 filters 也是 RAG 失败复盘重点

Weaviate 当前文档把 filters 放在核心检索能力中。

这提醒我们:

  • 很多失败并不是“找不到”,而是“本来就不该找这个范围”

典型问题包括:

  • 多租户数据串了
  • 角色权限错了
  • 产品线边界没带上
  • 生效时间没进过滤条件

这类问题如果不单独分层,团队很容易把它误判成相关性问题。

10. 为什么 RAG 失败复盘要和评测集绑定

OpenAI 当前 eval best practices 特别强调:

  • 评测要覆盖生产数据、历史数据、典型样例、边界样例和对抗样例
  • 要持续评估每次变更

对 RAG 复盘来说,这意味着每次失败都不该止于“修一次”,而应当尽量沉淀成:

  • 固定回归样例
  • 对应失败类型标签
  • 对应 owner
  • 对应验证指标

否则系统只会重复犯错。

11. 一次完整复盘更像什么流程

text
Failure report
 -> Reproduce with original query and context
 -> Inspect source knowledge and version
 -> Inspect ingestion / chunk / metadata
 -> Inspect retrieval pool
 -> Inspect rerank and filters
 -> Inspect final prompt context
 -> Inspect final answer and citations
 -> Assign root cause and remediation
 -> Add regression case

这个流程的重点在于:

  • 不是只看最后一跳
  • 而是找到最早偏离正确路径的节点

12. 一个真正能复盘的“失败回放包”应该包含什么

很多团队说自己支持复盘,但真正事故来了,只剩:

  • 用户问题
  • 最终错误答案

这通常远远不够。

一个更像生产系统的失败回放包,至少应包含:

  • 原始 query
  • rewrite query
  • 租户与权限上下文
  • top-k 初始候选
  • rerank 前后顺序
  • 最终上下文片段
  • 最终回答与引用
  • content / index / serving version
  • trace_id / query_id / release_batch_id

如果没有这份包,后续讨论通常会退化成:

  • “我觉得像是模型问题”

12.1 回放包最好可直接重跑

更稳的做法不是只留截图,而是保留足够信息让系统能够:

  • 重放原始 query
  • 重放同一版权限上下文
  • 对比 old / new retrieval strategy
  • 对比修复前后差异

这样复盘才能从“事后回忆”变成“可重复实验”。

13. trace 字段最好能直接暴露失败最早发生在哪一层

OpenAI 当前 Agents SDK 观测文档强调:

  • tracing 可以保留模型调用、工具调用、guardrails 和自定义 spans

这给 RAG 复盘一个非常实用的启发:

  • 复盘用的关键不是“有没有 trace”
  • 而是 trace 里是否真的有检索链路关键字段

至少建议保留:

  • query_bucket
  • rewrite_version
  • rewrite_query
  • filter_snapshot
  • candidate_count_before_rerank
  • candidate_count_after_rerank
  • final_context_doc_ids
  • final_context_versions
  • answer_citation_ids
  • retrieval_strategy_version
  • prompt_version
  • serving_version

这样后面你才能真正回答:

  • 是 rewrite 改偏了
  • 是 filter 挡掉了
  • 是 rerank 压错了
  • 还是上下文装配把证据包搞脏了

14. 失败分级不是形式主义,它决定你要不要阻断发布

不是每个失败都值得当事故,但也不是每个失败都能等下周修。

一个更实用的分级方式通常至少包括:

14.1 轻度失败

例如:

  • 低风险 query 偶发引用偏弱
  • 非关键知识召回略不稳

通常适合:

  • 入回归集
  • 排入常规修复

14.2 中度失败

例如:

  • 高频 query 稳定答错
  • 新旧版本混答
  • 热门知识主命中错误文档

通常适合:

  • 当日修复
  • 增补监控与回放
  • 对相关 query 桶灰度观察

14.3 重度失败

例如:

  • 权限越界
  • 高风险制度旧版主命中
  • 删除或失效知识仍在主路径广泛服务
  • 冲突证据被系统伪装成确定答案

通常适合:

  • 立即降风险
  • 阻断发布或回滚
  • 启动事故响应

15. RAG 失败复盘最好也进入发布门禁

很多团队会对模型切换做门禁,却不对 RAG 链路切换做门禁。
这会让下面这些变化带着高风险直接上线:

  • rewrite 策略变更
  • chunk 规则切换
  • filter 规则切换
  • rerank 模型切换
  • serving alias 切换

更稳的做法通常是:

  • 让代表性失败样例变成 release blocker
  • 对高风险 query 桶单独看 old / new diff
  • 确认权限和版本边界没有退化再放量

16. 哪些指标值得跟着复盘一起看

建议至少关注:

  • top-k 召回率
  • rerank 后正确证据进入率
  • 上下文精度 / 上下文召回
  • 旧版本命中率
  • 引用正确率
  • 权限误召回率
  • 失败样例回归通过率
  • 重放成功率
  • release blocker 命中数

这些指标组合起来,通常比单看“最终答案对不对”更有诊断价值。

16.1 指标最好按 query 桶拆开

如果只看总体平均值,很多关键退化会被掩盖。
更值得单独拆桶的通常包括:

  • 编号 / 错误码 query
  • 时间敏感 query
  • 权限敏感 query
  • 高频客服 query

17. 修复动作最好和失败类型一一对应

复盘最怕的是:

  • 找到了问题
  • 但修复动作还是很泛

更实用的对应关系通常像这样:

  • 覆盖失败:补知识、补版本、补发布时间
  • 进入失败:修解析、修 chunk、补 metadata
  • 召回失败:改 query rewrite、改 hybrid strategy、改 filter
  • 排序失败:调 rerank、调 freshness / authority 信号
  • 组装失败:去重、合并、调整上下文编排
  • 消费失败:补引用 contract、补答案约束、改 prompt/schema
  • 治理失败:补下线、补失效、补评测、补门禁

18. 常见反模式

  • 一出错就怪模型
  • 不保留 top-k 候选和 rerank 前后结果
  • 只修 Prompt,不修检索和版本问题
  • 失败样例不入回归集
  • 只看平均值,不看高风险 query 桶
  • 权限、版本、时效错误混在一起排查
  • 没有 replay packet,只靠截图和口述复盘
  • 只看最终答案,不看 retrieval strategy 与上下文构造版本
  • 明知道是高风险失败,却不把它接入发布门禁

19. 一个可落地的最小复盘方案

如果团队现在还没有标准化的 RAG 复盘机制,建议至少先做到下面这些事:

  1. 失败日志里保留 query、top-k、rerank、最终上下文和最终引用。
  2. 给失败样例打上“覆盖 / 进入 / 召回 / 排序 / 组装 / 消费 / 治理”标签。
  3. 为每次失败生成最小 replay packet。
  4. 每次修复后补进回归集。
  5. 对高风险 query 桶单独观察新旧版本和权限边界。
  6. 不把“最后表现错”直接当成“模型问题”。

20. 推荐搭配阅读

21. 重点官方资源

以下资源已按 2026-07-09 做过可访问性检查:

22. 落地检查清单

  • 是否能保留从原始 query 到最终引用的完整链路证据
  • 是否能区分失败最早发生在哪一层
  • 是否保留了初始候选池与 rerank 后候选池
  • 是否把失败样例持续沉淀进回归集
  • 是否能把“模型错误”拆回到具体的数据、检索、组装或治理问题
  • 是否为高风险失败准备了 replay packet、降风险动作和 release blocker