跳到主要内容

一次 RAG 检索命中率异常排查

· 阅读需 3 分钟
一介布衣
全栈开发者 / 技术写作者

补档说明:本文属于「AI 工程落地周记」系列,计划发布时间为 2025-03-08 16:10。当前先保留为草稿,后续补充真实案例、代码片段和复盘细节后再发布。

这次排查很典型:业务方反馈“最近知识库回答突然变差”,但表面上看系统并没有报错,模型也没换,接口响应时间甚至还是正常的。真正的问题出在一个很容易被忽略的指标上,检索命中率突然掉了一截。

一开始大家本能地怀疑 Prompt、怀疑模型、怀疑重排,但继续查下去才发现,问题不是最后生成阶段,而是索引更新后,一部分文档的元数据缺失,导致相关片段虽然被召回了,却没有排进最终候选。

现象

最明显的信号不是“完全答不上来”,而是“答得像知道一点,但关键结论总差一口气”。这类问题特别容易被误判成模型理解能力下降。

后来我们对同一批问题做回放,发现:

  • top-k 里偶尔还能看到正确片段。
  • 但最终给模型的上下文里,关键片段经常没进去。
  • 相同问题在不同时间段的召回排序会明显变化。

这说明问题不是“完全检索不到”,而是“检索质量的稳定性出问题了”。

判断

这次排查再次提醒我,RAG 出现异常时,不能只看最终答案。至少要把链路拆成三段分别看:

  • 召回有没有拿到正确候选。
  • 重排有没有把正确候选保住。
  • 上下文拼装有没有把关键片段挤掉。

如果没有这三层可观测,团队很容易一上来就去改 Prompt,最后越改越偏。

处理

这次我们的处理顺序是:

  1. 先抽固定问题回放检索结果。
  2. 对比索引更新前后的候选差异。
  3. 发现元数据缺失后修补索引构建流程。
  4. 再看重排和最终回答是否恢复。

这个顺序最大的价值,是能把“检索层异常”和“生成层异常”彻底拆开。

结论

RAG 命中率异常最危险的地方,不是它会直接报错,而是它会伪装成“模型最近有点不稳定”。所以只要做 RAG,就一定要保留中间层观测能力,不然很多问题会在错误的层上浪费很久。