第 18 章 检索增强生成:从召回到可信回答¶
开场问题:向量库已经召回了包含答案的文档,模型为什么仍然答错?
18.1 RAG 是一条链,不是一个向量数据库¶
完整链路:
查询理解 → query 改写/分解 → 召回 → 过滤 → 重排 → 上下文组装 → 生成 → 引用校验
最终错误要沿链路归因。文档没被召回是 retrieval failure;召回了但没进入上下文是 ranking/budget failure;上下文有证据却答错才是 generation failure。只看最终正确率无法决定该修哪一段。
18.2 文档切分决定检索单元¶
块太小,语义和上下文丢失;块太大,embedding 被多个主题稀释、召回后又浪费上下文。固定 512 token 是起点,不是答案。
更好的做法是尊重文档结构:标题、段落、表格、函数、类、页面。保存 parent-child 关系:小块用于精确检索,命中后带回更大的父块供模型理解。
每块必须带元数据:来源、时间、权限、文档版本、章节路径。没有元数据,后续无法过滤过期内容、做权限控制或生成可靠引用。
18.3 Dense、Sparse 与 Hybrid¶
Dense embedding 擅长语义相似和改写;BM25 等 sparse 检索擅长精确术语、编号、错误码和罕见实体。企业知识里两者都不可缺。
Hybrid retrieval 分别取候选,再用 RRF 或归一化分数组合。不能直接把两个系统的原始分数相加,因为尺度不同。
18.4 Query 改写与分解¶
多轮对话里的“它上一版有什么问题”不能直接拿去检索,要结合历史改写成独立查询。复杂问题还需分成多个子查询,分别召回后合并。
但改写会改变用户意图。应保留原查询并做多路召回,而不是完全替换;专有名词、数字、否定条件要明确要求保留。
18.5 Reranker 在做什么¶
embedding 检索通常从百万文档快速取 top-100,精度有限;cross-encoder reranker 同时阅读 query 和每个候选,重新排出 top-5/10。它慢但候选少,能显著提升精度。
召回关心 recall@k:正确证据有没有进候选;重排关心 nDCG/MRR:正确证据是否靠前。两阶段指标不能混成一个。
18.6 上下文组装¶
不能把 top-k 原样拼起来。要做:
- 去掉重复和近重复块。
- 保留来源和层级标题。
- 同一文档的相邻块适度合并。
- 多来源证据控制多样性,避免前 k 全来自一篇文档。
- 按 token 预算选择,而不是固定块数。
- 明确告诉模型只能基于证据作答,不足时说不知道。
还要处理证据冲突和时效性。通常优先权威、更新的来源,并把冲突暴露给模型,而不是静默选一个。
18.7 引用必须可验证¶
要求模型输出 [1] 不代表引用可靠。生成后要检查:
- 引用 ID 是否存在。
- 引用段落是否支持对应主张。
- 关键主张是否都有引用。
- 是否把来源里没有的信息“搭便车”挂在引用后。
可用 NLI/judge 做规模化初筛,高风险场景仍需规则或人工。
18.8 RAG 的端到端评测¶
至少分三层:
- Retrieval:recall@k、MRR/nDCG、权限过滤正确率。
- Context:证据覆盖率、冗余率、token 成本。
- Answer:正确性、faithfulness、引用精度/召回、拒答准确率。
还要构造“知识库里没有答案”的问题。若只测有答案样本,系统会学会无论如何都编一个。
18.9 RAG 与微调怎么配合¶
RAG 提供事实,SFT 教模型怎样使用事实:引用、处理冲突、证据不足时拒答。可以用 RAG 轨迹做 SFT,但训练时应随机加入检索噪声和空结果,否则模型只会在完美检索条件下工作。
不要用微调掩盖低召回,也不要指望 RAG 自动修复模型不具备的复杂推理能力。
核心问答¶
Q:文档召回了,为什么仍答错? 可能排名靠后没进入预算、被重复块挤掉、上下文组装丢了标题,或模型没有正确利用证据。要分层记录。
Q:Dense 能完全替代 BM25 吗? 不能。错误码、编号、罕见名字和精确术语通常 sparse 更强,混合检索更稳。
Q:RAG 最容易被忽略的安全问题? 权限过滤必须发生在召回层,不能把无权查看的文档先送给模型再要求它别说。
Q:引用存在就说明 grounded 吗? 不说明。必须检查引用内容是否真的支持该主张。