Appearance
RAG失败复盘专题
版本:
v1.3最后更新:
2026-07-09适用对象:已经做了 RAG / 知识问答 / 文档检索,线上开始出现“偶尔错、难定位、每次都像新问题”的团队
很多团队做 RAG 时最常见的误区是:
- 只看“这次答错了没有”
- 却不系统复盘“到底是哪一层让它答错了”
结果就是所有问题最后都被粗暴归因为:
- 模型幻觉
- embedding 不行
- chunk 没切好
但真实情况通常更复杂。一次 RAG 失败,可能来自知识根本没入库、检索没召回、排序把关键证据压下去、上下文拼装失真、引用结构太弱,或者答案生成阶段根本没正确消费证据。
这也是为什么 RAG 失败复盘不能只做“错误案例记录”,而要做成一套能映射到具体修复动作的工程手册。
1. 什么是 RAG 失败复盘
更实用的理解通常是:
- 针对一次失败回答
- 反向拆解知识、索引、检索、排序、上下文构造和生成链路
- 找到最先出错的那一层
重点不是证明模型不行,而是回答三个问题:
- 失败最早发生在哪个阶段。
- 这个阶段缺的是数据、策略、配置还是运行时观测。
- 修复动作应该落到哪个具体 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_bucketrewrite_versionrewrite_queryfilter_snapshotcandidate_count_before_rerankcandidate_count_after_rerankfinal_context_doc_idsfinal_context_versionsanswer_citation_idsretrieval_strategy_versionprompt_versionserving_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 复盘机制,建议至少先做到下面这些事:
- 失败日志里保留 query、top-k、rerank、最终上下文和最终引用。
- 给失败样例打上“覆盖 / 进入 / 召回 / 排序 / 组装 / 消费 / 治理”标签。
- 为每次失败生成最小 replay packet。
- 每次修复后补进回归集。
- 对高风险 query 桶单独观察新旧版本和权限边界。
- 不把“最后表现错”直接当成“模型问题”。
20. 推荐搭配阅读
21. 重点官方资源
以下资源已按 2026-07-09 做过可访问性检查:
- OpenAI File search
- OpenAI Retrieval
- OpenAI Evaluation best practices
- OpenAI Agents observability
- OpenAI Agents tracing
- Anthropic Contextual Retrieval
- Pinecone Check data freshness
- Azure AI Search Hybrid search overview
- Azure AI Search Semantic ranking overview
- Weaviate Filters
- Weaviate Reranking
22. 落地检查清单
- 是否能保留从原始 query 到最终引用的完整链路证据
- 是否能区分失败最早发生在哪一层
- 是否保留了初始候选池与 rerank 后候选池
- 是否把失败样例持续沉淀进回归集
- 是否能把“模型错误”拆回到具体的数据、检索、组装或治理问题
- 是否为高风险失败准备了 replay packet、降风险动作和 release blocker