3173 字
约 10 分钟
23
S20-A07 · RAG 失效模式:答错、答偏与答非所问

“用户说答得不对,我拿同一个问题复现,结果又是对的。”这是 RAG 上线后最常见的对话,也最多被误读——它通常不说明用户记错,而说明这次回答的正确性不由同一条 query 决定。检索受索引版本、时间过滤、并发写入、采样参数影响,两次调用可能走在两份证据上。

处理 RAG 失效的第一步不是换模型、调温度,而是把“答错”拆成四层可分别验证的判断。四层各有独立判据与修法;修错层是这类系统最大的浪费。


1. 四层失效与各自的判据

层次 用户看到的样子 判定方法 第一责任环节
没检索到 缺关键信息,或直接说“资料未提及” 正确段落是否在未截断的候选集里 切分、索引、改写、过滤
检索到但没用上 回避了明明存在的证据 证据在 prompt 里,输出却绕开 排序、截断、上下文排布
用了但理解错 引用了证据,结论反了 证据与结论并列人工比对 冲突消解、时间/单位解析
理解了但表达错 结论对,粒度或格式不对 结论正确、形式不合格 提示约束、输出校验

判定的前提是中间结果可回放。没有它,四层只能靠猜。每次请求至少落一条:

{
  "trace_id": "req-...",
  "query_rewritten": ["…", "…"],
  "retrieved": [{"chunk_id": "d41#3", "score": 0.71, "rank": 1}],
  "sent_to_model": ["d41#3", "d41#4"],
  "truncated": false,
  "answer": "…",
  "citations": ["d41#3"]
}

价值最高的是 retrieved 与 sent_to_model 的差集:为空却答错 → 生成侧问题;非空 → 问题在被丢掉的那段。

2. “没检索到”的四种成因

成因 典型信号 判定 改法方向
切分粒度 答案跨相邻两块,两半都不完整 按当前切分器重切 gold 段落,看是否被切断 语义边界切、父块配小块
同义词/口语 用户用词与文档用词不同 query 换成文档原文措辞重查,命中即证实 混合检索、查询扩展
改写不足 多轮对话里指代丢失 用改写后的 query 重查是否命中 多 query 并行、指代补全
过滤过严 候选整体为空或极小 关闭 filter 重查,命中即证实 过滤降级为排序加权

四个成因的验证成本都很低,各只需一次对照。陷阱是只看 top-k:正确块排第 23 位被截掉,与“没被索引”表现一样,修法却相反。

# 召回诊断:按问题类型分桶,区分"没索引"与"排太后"
for q in evalset:
    cands = retrieve(q.query, k=50)       # 远大于线上 k
    rank = first_index(cands, q.gold_chunk_ids)
    bucket(q.type).add(rank)              # None 记为未召回

# rank=None 占比高 → 索引/切分问题
# rank 集中在 6–30 → 排序与截断问题
# rank 集中在 1–3 仍答错 → 生成侧问题

3. “检索到但没用上”的三种成因

成因 机制 典型信号 对策
上下文过长截断 拼接超预算,尾部整块丢弃 truncated=true 且丢的是 gold 按分数排序后截断;父块按需展开
排序靠后 相关但分数低,排在无效块之后 gold 在上下文中的位置 > 前列 先重排再拼;限制无效块数量
模型忽略中段 长上下文对中段注意力弱 gold 居正中时命中率明显下降 关键证据前置/后置,长度压到必要范围

后两种常被混为一谈,判别靠位置对照:同一批证据只改位置。

A:gold 放第 1 段                        → 答对
B:gold 仍放第 1 段,前面垫 8 段无关内容  → 答错
结论:不是"没检索到",是排布问题。修法是把证据前置或压缩无关块。

4. “理解错”的三种成因

成因 表现 判定 对策
多文档冲突 两份文档说法相反,模型随机选边 单独喂冲突文档,看是否稳定选同边 显式给出优先级(版本/生效日期/权威级)
时间信息缺失 用已废止的旧规则回答 检索结果是否带有效期字段 时间作为元数据参与过滤
表格解析错 行列错位、合计行当数据行 原文表格与解析结果并排看 表格单独成块并保留表头

冲突处理的关键是不把裁决权交给模型:它在两句相反的话之间选择,行为接近随机。优先级应在检索阶段带上。

{
  "doc_id": "policy-2023",
  "effective_from": "2023-07-01",
  "effective_to": "2025-06-30",
  "supersedes": ["policy-2019"],
  "authority": "primary"
}

5. “表达错”:约束要分层

约束 放在哪里 失效方式
语气、结构、是否引用 系统提示 上下文变长后被稀释
字段、枚举、必填 结构化输出 schema 模型绕过 schema 时解析报错
事实一致性 生成后引用比对 无校验则幻觉直接出门

只靠提示词约束表达是最脆的一层:文字会被长上下文稀释,schema 可机器校验,引用比对才抓得住“说得通但没依据”。

6. 否定型与多跳为什么特别难

问题类型 难点 表现 缓解
否定型(“X 是否不需要 Y”) 相似度不度量命题真假,否定证据往往不存在 检索到一堆讲 Y 的文档,答成“需要” 转枚举确认:取全集再逐条排除
多跳(A 的负责人所在部门) 中间结果要当下一跳的 query 只做一跳,答案看似合理实则错 拆子问题、显式中间结果、串行编排

“文档里没有”与“文档里说不需要”是两件事,相似度只度量接近程度,区分不了。否定型问题必须换范式。

7. 空结果与低分:明说不知道的判据

候选情况 建议动作 理由
无任何候选 明说没有相关资料,给出可查范围 强行作答的期望损失更大
有候选但最高分很低 先看覆盖:能否覆盖问题主实体 分数跨 query 不可比,覆盖可判
覆盖但相互冲突 并列呈现,标注来源与时间 替用户裁决等于隐藏不确定性
候选充分 作答并给引用 —
if candidates empty:            → 明说缺失 + 建议查询路径
elif not covers(candidates, q): → 只答覆盖部分
elif conflicting(candidates):   → 并列 + 标注生效日期
else:                           → 作答 + 引用

阈值别设绝对值:分数分布随 query 变化,“0.72 算不算高”没有全局答案。用覆盖度更稳。

8. 可观测信号

信号 定义 指向的层次
追问率 同会话内对同一问题连续追问 表达错、理解错
重述率 用户换措辞重问同一意图 没检索到(措辞不匹配)
人工修正率 客服/运营改写答案的比例 全层,最可靠的坏味道
空结果率 判定为“无资料”的比例 偏高 → 索引覆盖问题

人工修正率是唯一同时覆盖四层的信号,代价是要有人真的在改。它上升时先查检索日志。

9. 评测集必须包含的四类负例

负例类型 构造方式 检验的能力
文档没有 问题超出语料范围 是否敢说不知道
文档冲突 同主题两份相反说法 是否按优先级裁决并标注
部分匹配 只覆盖问题的一半 是否只答覆盖部分
过时答案 旧版本仍可检索到 是否按生效日期过滤

只测“能答对的题”,测的是理想条件下的上限;线上问题绝大多数落在上表四类里。

10. 改一处的耦合

改动 预期收益 引入的失效
增大 top-k 召回上升 上下文变长 → 中段忽略、截断丢尾
切小块 定位更准 跨块信息断裂 → 多跳更难
强过滤 噪声下降 边界样本误杀 → 空结果率上升
强化“必须引用” 幻觉下降 无引用可用时编引用
加重排 排序更准 延迟上升、吞吐下降

这是基本约束:没有单向优化。调参前先写下“我要牺牲哪一项”。

11. 定位流程:先判层,再动环节

1  取一条失败样本,固定索引快照 + 温度 0,确认可复现
2  gold 在 top-50 内?        否 → 第 2 节(切分/同义词/改写/过滤)
3  在 sent_to_model 里?      否 → 第 3 节(截断/排序/预算)
4  在里面但答案绕开它?       是 → 位置对照实验 → 排布
5  引用了证据但结论反了?     是 → 第 4 节(冲突/时间/表格)
6  结论对、形式错              → 第 5 节(约束分层)
7  只有走到第 6 步才允许改提示词

顺序的意义在成本:前四步只读日志和做对照,第 6 步起才是改提示、改模型、重跑评测。

12. 排错:六种“像模型问题”的情况

现象 原因 处理
同一问题两次答案不同 索引在写入,或温度 > 0 固定快照复现,温度 0 再判
回答总是很笼统 top-k 里全是概述块 检查切分是否把细节并入大段
答案对但引用错 引用由模型生成而非回填 引用从检索结果回填
中文专名检索不到 分词/嵌入对生僻词不敏感 补关键词通道,混合召回
长文档问答答非所问 上下文超预算被截断 先压缩再拼,别靠加预算
上线后质量缓慢下滑 语料在增,索引未重建 把索引版本纳入发布流程

13. 边界:什么时候 RAG 本就不该用

场景 更合适的做法 理由
知识本身不在语料里 补数据源,或交给人 检索变不出不存在的事实
问题域极窄、答案固定 查表或写死规则 一次查表胜过一条链路
需要精确计算或严格事务 调用工具/接口 生成模型不保证数值正确
要求逐字引用、可审计 抽取式回答 + 人工签发 生成式改写不可审计

RAG 的价值是把“模型知道什么”换成“这次给了它什么”。当“给了什么”本身不可控,它能做的只是如实暴露。


14. 自测

  1. 用户说答错了,你复现却是对的——第一个要固定的变量是什么?
  2. 正确段落在 top-50 里但不在送进模型的上下文里,属于哪一层?
  3. 同一批证据只改位置就改变了对错,说明问题在哪一层?
  4. 为什么否定型问题不能靠提高 top-k 解决?
  5. 分数阈值为什么不适合跨 query 直接比较?替代判据是什么?
  6. 把 top-k 从 5 调到 20,最可能同时引入哪两种新失效?
S20-A07 · RAG 失效模式:答错、答偏与答非所问
https://www.clxhxhhr.top/posts/6160/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。