Chico Notes
LLM Wiki / RAG

Naive RAG 为什么容易失败:四类根因拆解

从召回、分块、上下文、生成与权限角度分析朴素 RAG 的真实失败模式。

持续修订的工程笔记

朴素 RAG 的问题不是“太简单”,而是它把很多生产约束都藏起来了:文档质量、权限、版本、查询理解、排序、引用、评测。系统跑通以后,失败通常集中在四类:找不到、找不准、用不好、管不住。

失败模式总览

一、找不到:召回失败

典型现象:用户问的问题在文档里有答案,但系统回答“不知道”或者召回无关段落。

原因示例修复方向
术语不匹配用户问“远程办公 PTO”,文档写“telecommute time off”。query rewrite、同义词、hybrid search。
精确词漏召回错误码、接口名、合同编号、产品 SKU。BM25 + vector,不要只用向量。
元数据缺失用户问“2024 版政策”,chunk 没有更新时间。保存 updated_at、version、source_type。
数据未入库文档同步失败但无人知道。ingestion trace、失败重试、数据质量报表。

判断方法

先不要改 Prompt。把用户问题、改写后的 query、Top-20 召回结果全部打印出来。如果正确证据不在 Top-20,问题在检索前半段。

二、找不准:排序和候选质量失败

召回到了正确证据,不代表模型能答好。Top-K 中如果混入大量相似但不可回答的片段,LLM 很容易被噪声带偏。

常见修复方式:

  • 用 Reranker 区分“语义相似”和“能回答问题”。
  • 对同一文档的重复 chunk 做去重或多样性约束。
  • 对标题、权威来源、更新时间设置 boost。
  • 给候选结果保留分数和来源,方便 bad case 分析。

三、用不好:上下文断裂和证据失真

很多回答错误不是因为没找到文档,而是因为 chunk 缺少前置条件。比如只召回了“审批通过后可报销”,但没召回上一段“仅适用于正式员工”。

场景风险处理方式
政策文档条件和结论分离parent-child chunk,召回小块后补父级上下文。
表格行列关系丢失表格结构化抽取,保留表头和单位。
代码文档函数说明和示例分离按标题和代码块边界切分。
长 PDF页眉页脚污染解析阶段清理重复页眉页脚。

四、管不住:权限、版本和审计失败

企业 RAG 最危险的问题不是答错,而是答出用户无权访问的信息。权限不能交给 LLM 判断,必须在检索阶段生效。

生产要求:

  • Chunk 必须继承文档 ACL。
  • 权限变更要触发索引更新或查询时过滤。
  • Trace 中要记录用户身份范围、过滤条件、命中文档。
  • 日志中不要保存未脱敏的敏感上下文。

Bad Case 归因表

现象优先检查不要先做什么
答案完全无关Top-K 召回结果、query rewrite不要先换大模型。
答案部分正确chunk 是否缺上下文、是否有冲突文档不要盲目增大 Top-K。
引用不支撑答案prompt 约束、引用映射、evidence selection不要只要求“请给引用”。
同一问题时好时坏rerank 稳定性、索引版本、模型温度不要只看单次结果。
越权风险ACL 元数据、检索过滤、日志脱敏不要让 LLM 自己判断权限。

最小修复路线

  1. 保存完整 trace:query、Top-K、rerank score、上下文、答案。
  2. 使用混合检索,先解决“找不到”。
  3. 引入 reranker 和去重,解决“找不准”。
  4. 改造 chunk schema,解决“用不好”。
  5. 把 ACL 放进检索过滤,解决“管不住”。

Naive RAG 的失败不是偶然,而是缺少工程闭环。把失败归因拆清楚,优化才有方向。

讨论

继续讨论这篇笔记

有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。

On this page