Skip to content

05 · 检索增强生成(RAG)

本章从一个纸面小语料推导词法检索结果,不依赖仓库里不存在的 RAG/SQLite 演示。学完后,你应能拆解文档进入索引再到答案的链路,手工计算简单关键词排名,区分检索错误与生成错误,定义来源与引用契约,并设计同时检查召回、答案支持和无答案行为的评测集。

检索增强生成(Retrieval-Augmented Generation,RAG)把外部材料取回给模型,让答案能够使用静态模型参数之外的内容。典型数据流包括:收集材料、解析、切分、保存文本与元数据、检索候选片段、选择或重排候选、将证据交给模型、生成有根据的答案或拒答。每一步都会产生独立错误:解析漏掉表格,切分断开条件,检索漏召回,重排把错误片段排前,生成忽略证据,引用指向错误位置。

RAG 不会自动使答案可靠。模型可能把相关但不支持结论的段落当成证据,也可能引用确实存在的文档,却在引用旁写出原文未表达的数字。系统要明确“回答中的每个可核验事实由哪些来源支持”,并在没有足够证据时允许返回无答案。

数据准备:保留出处与语义边界

Section titled “数据准备:保留出处与语义边界”

开始索引前,确定文档集合、更新方式和允许使用范围。解析时保留标题、章节层级、发布日期、版本、权限标签与原始来源。切块(chunking)把长文拆成更小的检索单元,便于在上下文预算内交给模型;若块太大,会带入过多无关文字;太小则可能丢掉条件、定义或前后文。应尽量在标题、段落或语义边界切分,并在片段中保留足以解释内容的标题路径。

每个片段至少需要稳定的 doc_id 和可复原的位置,例如页码、段落序号或字符区间。标题和位置不是展示装饰:若回答引用“来源 A”,却不能定位到具体段落,读者无法核查。文档更新或删除时,也必须同步更新派生片段和索引,否则系统可能继续回答旧内容。权限元数据应在检索阶段过滤,不能先把无权文档送入模型再期待模型自行忽略。

词法检索:先建立可检查的基线

Section titled “词法检索:先建立可检查的基线”

在小语料上可以从关键词检索开始。它简单、容易解释,也能快速暴露切分和查询设计问题。本节用一个手工算例:以下是教学构造的短片段,并非仓库内置检索器或演示程序。

ID 标题 文本
D1 退款期限 “购买后 30 天内可申请退款;商品须保持未使用。”
D2 退款处理 “审核通过后,退款通常在 5 个工作日内到账。”
D3 账号安全 “重置密码后,旧会话会在 15 分钟内失效。”
D4 退款范围 “数字商品下载后不可退款;未下载的数字商品可在 7 天内申请退款。”

用户问:“数字商品下载以后还能退款吗?”先把问题按词项拆开:数字商品、下载、以后、退款。真实中文检索需要中文分词、字符 n-gram 或适合中文的分析器;为了手算,假设规则已得到这四个词项,且忽略“以后”等功能词。给每个文档记一个简单分数:每命中一个不同查询词 +1,不考虑词频、长度与重要性。于是 D1 命中“退款”,得 1;D2 命中“退款”,得 1;D3 无匹配,得 0;D4 命中“数字商品”“下载”“退款”,得 3。Top-2 是 D4、D1 或 D2(后两者同分,平局规则需明确)。D4 明确支持“已下载不可退款”,其他退款片段仅词汇相关,不能替代这条规则。

这个玩具分数不是 BM25,也不表示质量指标。BM25 会结合词频、文档长度和词项在语料中的稀有程度等因素;向量检索则用嵌入表示语义相似性。二者都需要检查实际相关性。做完关键词基线后,如果用户用“买完文件后”而语料写“下载后”,词法系统可能漏召回;再考虑同义扩展、向量或混合检索。不能因为“语义更先进”就跳过对语料、问题和检索结果的诊断。

初次检索负责从较大语料筛出候选。Top-k 太小可能漏掉唯一证据,太大可能带入冲突版本和噪声;要结合任务和上下文预算测量。重排器通常只对已召回候选重新排序,不能找回第一阶段根本没有送来的文档。混合检索可以合并词法与向量信号,但要规定去重、分数归一或融合方法。

生成阶段读取问题与候选证据,形成面向用户的回答。提示词可以要求只根据证据回答、将事实与推断分开并在缺证据时拒答,但提示词不是形式化保证。最好要求结构化输出,例如事实条目对应来源 ID,再在应用层验证每个 ID 属于本次检索结果、位置存在且用户有权访问。答案的流畅度不能代替证据核对。

引用应可定位、可核验。一个来源记录可以在概念上包含:

source_id: D4
标题: 退款范围
位置: 第 1 段
原文片段: “数字商品下载后不可退款……”
版本/时间: 当前索引版本

以上是说明数据含义的概念示例,不是可直接运行的仓库代码。答案可写:“已下载的数字商品不可退款。〔D4,第 1 段〕”检查时要问:D4 是否在本次检索结果内?引用位置是否存在?原文是否蕴含该结论?是否漏掉同一来源的限定条件?如果回答还补充“退款会在 5 天到账”,那需要 D2 支持,而且 D2 说的是“审核通过后、通常、5 个工作日”,不能删去条件或改写成保证。

引用数量不等于引用质量。每条重要事实应映射到支持它的原文;不支持的补充推断应标成推断或删除。多个文档冲突时,先定义来源优先级、版本与日期规则,并在必要时向用户暴露冲突。若证据只能回答一部分问题,应明确可回答的部分和缺失的部分。

错误诊断:检索错,还是生成错

Section titled “错误诊断:检索错,还是生成错”

先把评测用例标注为标准问题、相关来源/片段、可接受答案、必要条件和拒答要求。运行后保留检索 trace(查询、候选 ID、分数、过滤条件、索引版本)以及最终答案和引用。然后按以下方式分类:

检索是否带回支持证据 最终回答 初步诊断
否 错答或拒答 先查解析、切块、查询分析、过滤与召回;如果语料根本没有答案,则应拒答
是 错答、遗漏条件或乱引 生成/上下文组织问题,检查候选排序、提示约束、答案到引用的映射
是 正确且引用支持 该用例通过,但单例不能证明整体可靠
带回无关或过期证据 自信地错答 检索相关性、版本过滤与拒答阈值可能同时有问题

如果正确证据没有进入候选,单改 prompt 通常无济于事;如果正确证据已给模型但答案仍错,调整切块或扩大 Top-k 也未必解决。检索召回可以用“相关证据是否在前 k 个候选中”衡量;答案正确性、引用支持度和无答案行为应独立评估。还要分别报告题目类型或文档版本,避免总体分数掩盖某类问题全错。

构造小型题集时至少包含:有直接答案的问题、需要结合两个片段的问题、词面不同但语义相同的问题、容易混淆的相似问题、语料中没有答案的问题、带条件或例外的问题,以及被更新/删除文档相关的问题。每题标注支持片段、关键答案要点、不可省略的条件和预期行为(回答、部分回答或拒答)。

评测可分成三层:

  1. 检索层:正确证据是否出现在 Top-k?记录命中位置或 Recall@k;错误候选是否挤掉正确来源?
  2. 生成层:答案事实是否正确、是否覆盖必要限定、是否在证据不足时拒答?
  3. 引用层:ID、位置与版本能否解析?原文是否支持对应主张?引用是不是来自本次检索结果?

更新索引时重跑受影响题目。修改或删除 D4 后,系统不能继续引用其旧内容;如果缓存或向量索引延迟更新,要在结果中识别索引版本或设置失效机制。删除操作应验证最终检索行为,而不只是源文件已经删除。

  1. 按本章简单词项分数,手算查询“数字商品下载以后还能退款吗?”的 D1–D4 分数和 Top-2。说明为什么 D1 虽命中“退款”却不支持对下载商品的结论。
  2. 某题的标准来源是 D4,但检索只返回 D1 与 D2。模型回答“可以在 30 天内退款”。这是哪一层的主要错误?最先查看哪些日志或环节?
  3. 某次检索已返回 D4,模型仍回答“下载后可以在 30 天内退款”,并引用 D1。错误属于哪层?至少列出两个检查点。
  4. 设计 6 道小型评测题,至少包含 1 道无答案、1 道例外条件、1 道跨片段问题。为每题列出目标片段和预期答案行为。
  5. 概念练习,不声称存在对应 demo:设计文档更新和删除后验证索引一致性的步骤,并说明如何识别旧索引仍在服务。
  1. D1=1、D2=1、D3=0、D4=3;Top-2 为 D4 与 D1/D2 中任一平局项,实际实现必须规定平局排序。只有 D4 的文本直接说明下载后不可退款。关键词重叠只是相关性线索,不构成证据蕴含。
  2. 首要错误在检索:支持结论的 D4 没进入结果。先查看解析与分块是否保留 D4 的句子、词项分析是否识别“数字商品/下载”、权限或元数据过滤是否误删、Top-k 和排名阈值,再考虑查询扩展。若语料没有 D4,问题属于语料覆盖而非排序器。
  3. 主要是生成与引用映射错误:正确证据已召回,答案反转了结论,还把 D1 的通用期限用于 D4 的例外。检查模型实际看到的片段与顺序、提示中的来源边界、答案事实到 source ID 的结构化映射、引用校验以及是否把不同规则拼接。
  4. 示例六题:①下载数字商品能否退款(D4,答不可退款);②未下载数字商品多久可申请(D4,答 7 天);③实体商品退款期限与条件(D1,答 30 天内且未使用);④审核通过多久到账(D2,保留“通常”和“工作日”);⑤退款是否补偿额外运费(语料无答案,应说明资料未提供);⑥退款申请条件及审核后到账时间(跨 D1、D2,分别引用,且不要把实体商品条件推广到数字商品)。每题都要标明必要条件和无证据时的处理。
  5. 修改源文档并记录新版本,再重新解析/分块/索引;查询应观察到新文本及新版本元数据;删除文档后执行同一查询,检查候选 ID、缓存与向量副本都不再返回旧内容。记录索引版本、摄入时间或文档哈希,若结果仍携带旧版本即可定位索引滞后。清源文件不代表派生索引已更新。

问:如何分辨 RAG 错误发生在检索还是生成? 保存可复现 trace 与标准证据。如果正确片段未进入候选,排查解析、切块、查询分析、权限过滤和召回;如果正确片段已进入模型输入而答案仍错误,排查排序、上下文组织、提示和生成约束。若标准语料里没有答案,系统应拒答,不能把检索失败伪装成模型幻觉问题。

问:为什么来源元数据需要保留到生成后? 只有稳定 ID 与位置才能将答案映射回原文,检查版本、权限和限定条件,并处理更新与删除。若只传入一段纯文本,模型即使说出正确答案,应用也难以审计来源或验证引用是否来自本次检索。

问:什么时候先用词法基线,而不是直接部署向量数据库? 语料小、问题范围清楚或需要可解释基准时,关键词检索成本低,能迅速发现解析、分块与查询词问题。若词面差异导致漏召回,再以标注题集比较向量或混合检索是否改善 Recall@k 与端到端支持率。基础链路未验证前换更复杂组件,会让错误更难定位。

问:重排器能修复所有召回问题吗? 不能。重排只调整已召回的候选。如果目标片段第一阶段没有进入候选集合,重排看不到它。召回与排序要分别测量。

  • 能手算示例语料的词项命中分数,并说明它不是 BM25。
  • 能从文档 ID 与片段位置回查引用原文。
  • 能独立评估检索召回、生成正确性、引用支持与拒答。
  • 能区分“正确证据没召回”和“正确证据已给模型但回答仍错”。
  • 知道更新/删除源文档后仍需验证派生索引与缓存。
  • 不把本章算例说成仓库已实现的 RAG 或 SQLite 演示。