RAG 答错了别急着调参——沿证据链逐层排查的系统方法论
RAG 回答错了,最常见的第一反应是:改 Prompt、换大模型、或者把 Top-K 调大。
这三个动作都可能有用,但它们不应该成为排查起点。
最终答案只是链路最后一层。错误可能早在文档解析时就发生,也可能是 Query 被改写带偏、过滤条件挡掉了正确文档、向量召回没找到、融合时被压下去,或者 Rerank 把正确证据排到了后面。
如果连正确证据在哪一层消失都不知道,改参数更像碰运气。
🎯 核心方法论:沿证据链逐层排查
面试时的标准回答:
我会沿证据流逐层排查。先用人工标注的正确文件、页码或 Chunk 确认原文已被解析、切分并写入当前索引;再比较原 Query 与改写 Query,检查否定、实体和过滤条件;然后分别查看 BM25、向量、融合和 Rerank 的候选、分数与名次;最后确认交给模型的上下文是否包含完整证据。修复后用原 Query 和同一正确证据回归,再补一组相邻样本。
先抓住一条主线:确定证据在哪一层消失,再对那一层做最小修改。
🧭 排查前先准备「正确证据」
一条可调试样本至少准备三样东西:
| 必要信息 | 说明 |
|---|---|
| 原始 Query | 用户的原始问题 |
| 参考答案 | 正确答案应该是什么 |
| 正确证据位置 | 具体到文档、页码、Chunk 或内容区域 |
正确证据是整条调试链的坐标。 后面每一层只问一个问题:它还在不在?分数多少?排第几?为什么被保留或丢弃?
🔍 七层证据链排查
第一层:正确内容真的入库了吗?
- 原文件是否被系统接收?
- 双栏和表格结构解析是否正确?
- 切分后条件与结论是否仍在同一语义单元?
- Chunk 是否写进当前可检索索引?
如果正确证据根本不存在于索引,调 BM25 权重、替换 Embedding、扩大 Top-K 都不会修好问题。
第二层:Query 有没有被处理错?
- 原 Query → 改写 Query,否定词是否保留?
- 精确编号/错误码是否被改写稀释?
- 多跳问题拆子查询后,是否覆盖全部信息点?
不要只看改写结果是否「更像标准问题」——它的任务是提高检索可用性,不是润色句子。
第三层:过滤条件有没有挡掉正确证据?
- 知识库 ID、权限、文档状态、版本、时间
- 调用方传入参数 vs 检索层实际生效条件(后者可能更严格)
- 逐项恢复过滤,定位是哪条规则排除了正确证据
正确证据被过滤后,后面的 BM25、向量、融合和 Rerank 都看不到它。
第四层:两路召回分别找到了什么?
| 召回方式 | 擅长 | 弱点 |
|---|---|---|
| BM25 | 原词匹配、编号、专业术语 | 用户换了说法时可能漏掉 |
| 向量检索 | 语义改写 | 短 Query、领域术语、否定表达可能偏移 |
调试时分别保存两路候选、原始分数、排名和 Chunk 来源。
第五层:融合为什么把正确证据压下去了?
- 关键词分数与向量相似度不是同一把尺子
- 归一化方式、权重设置、去重键稳定性
- 保存融合前后列表、通道、原始分数、综合分
第六层:Rerank 是没起作用,还是根本没机会?
- Rerank 只能重排已有候选——正确证据没进入粗召回 Top-N,它就没有补救机会
- 检查模型输入是否被截断、语种是否适配、否定是否正确判断
- Top-N 太小可能把正确证据挡在精排外
第七层:最终上下文真的包含完整证据吗?
- 正确证据可能被最后一次阈值过滤丢掉
- 多跳问题需要两段证据,系统却只保留一段
- 标题、表头可能被清洗掉导致模型看到的内容不完整
如果正确证据已完整进入上下文,模型仍然答错,再去看 Prompt 和生成——这时修改 Prompt 才有明确依据。
📊 候选变化表:定位证据在哪一层消失
给正确证据建立一张逐层记录表:
| 层 | 检查项 | 状态 | 名次 | 备注 |
|---|---|---|---|---|
| 入库 | Chunk 是否存在、正文是否完整 | ✅/❌ | - | Chunk ID |
| 召回 | BM25 / 向量候选中的名次 | ✅/❌ | N | 分别记录两路 |
| 过滤 | 过滤后是否还在 | ✅/❌ | - | 过滤规则 |
| 融合 | 融合后名次 | ✅/❌ | N | 综合分 |
| Rerank | 重排后位置 | ✅/❌ | N | 模型版本 |
| 上下文 | 是否进入生成上下文 | ✅/❌ | - | 是否截断 |
表格价值:阻止团队凭最终相似度猜原因。 不同阶段的分数不是同一量纲,真正关心的是正确证据何时进入、何时离开。
🧪 修复后怎样防止只修好一个例子?
| 步骤 | 要求 |
|---|---|
| 1 | 必须用原始 Query 重跑,不要改得更标准 |
| 2 | 保持正确证据不变,追踪同一原文 |
| 3 | 一次只改一个主要因素 |
| 4 | 增加同类相邻样本(同类错误的不同措辞) |
| 5 | 增加反例样本(容易被副作用影响的查询) |
| 6 | 分别看检索和生成收益 |
🏷️ 不要为每个样本修一条特殊规则
失败原因分类:
| 失败类型 | 修复方向 |
|---|---|
| 表达鸿沟(口语 vs 术语) | 同义扩展 / Embedding 适配 |
| 意图保持失败(否定丢失) | Query 改写逻辑 |
| Chunk 结构问题(语义被切散) | 解析和切分 |
| 元数据问题(被状态过滤排除) | 字段和状态流转 |
| 多跳问题(证据不完整) | 子查询分解 + 上下文组装 |
分类以后,修复才有合理作用域。 表达鸿沟不能为每个口语说法手工写替换,结构问题不能靠 Rerank 猜回丢失的表头。
这道题真正考的是可观测性和归因能力。会列一堆优化手段不难,难的是知道正确证据在哪一层消失,为什么选择这项修复,又怎样证明它没有破坏其他查询。
原文来源: 微信公众号「吴师兄」(2026-07-25)
- 标题: RAG 答错了别急着调参——沿证据链逐层排查的系统方法论
- 作者: hermes/ds v4 flash
- 创建于 : 2026-07-25 08:30:00
- 更新于 : 2026-07-26 13:40:38
- 链接: https://blog.lxiol.cn/2026/07/25/rag-evidence-chain-debugging/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。