第 09 章 · 工程
RAG:让模型使用外部知识
走完切分、Embedding、召回、重排、生成和引用的完整检索增强链路。
学习准备与本章目标
- 开始前
- Embedding 与上下文概念
- 学完后
- 画出 RAG 全流程 · 区分召回和重排 · 定位答案失败来自哪一环
本章路线图
RAG 把“找证据”和“用证据回答”拆成可检查的两段。完整链路包括离线索引与在线查询:文档先被解析、切分和索引;请求到来后再进行查询理解、召回、重排、上下文组装、生成与引用验证。
RAG 解决的不是“模型不会搜索”这么简单
RAG 在回答前从外部资料中取回相关内容,放进上下文,再让模型基于这些证据生成。它适合知识频繁更新、需要私有资料或必须给出处的场景。
它不会自动消除幻觉:检索可能找错,文档可能过期,模型也可能忽略证据。RAG 的价值是把知识来源变得可更新、可追踪,而不是保证每次都正确。
文档进入索引前要经历什么
原始文档要解析标题、段落、表格与元数据,再切成 chunk。块太小会丢上下文,太大会混入无关内容并浪费窗口。常见做法是按语义结构切分并保留适度重叠。
每个 chunk 通过 Embedding 模型变成向量,同时保存来源、时间、权限和层级。更新与删除策略必须和原系统同步,否则索引会残留过期信息。
召回、混合搜索与重排
向量检索擅长语义相近,关键词检索擅长精确术语、编号和人名。Hybrid Search 合并两类结果,先高召回取候选;Reranker 再同时看查询与候选全文,进行更精细排序。
第一阶段追求“正确证据有没有进候选集”,第二阶段追求“它能否排到上下文前面”。两者指标和成本不同,不要只用最终答案正确率判断全部链路。
怎样评估并排查一条 RAG 链路
先判断检索:命中率、Recall@K、MRR、权限与新鲜度;再判断生成:答案是否由证据支持、引用是否对应、遇到无答案时能否拒答。测试集应包含容易混淆的文档和确实找不到答案的问题。
失败时按顺序问:查询是否需要改写、正确文档是否入库、chunk 是否完整、候选是否召回、重排是否压错、上下文是否过长、模型是否遵守证据。这样比盲目更换大模型有效得多。
什么时候应该用 RAG
RAG 适合知识频繁更新、来自私有资料、需要引用来源或必须按用户权限过滤的任务。它不适合替代确定性数据库查询,也不能自动修复模型不会执行的复杂推理。
如果答案来自结构化业务数据,优先使用数据库或 API;如果任务主要改变输出风格,提示词或 SFT 更直接;如果模型缺乏稳定的领域技能,单纯塞文档也可能不够。
文档解析与元数据
索引前要恢复文档结构:标题层级、段落、列表、表格、页码、代码块和附件关系。PDF 视觉顺序不等于文本提取顺序,扫描件还需要 OCR。解析错误会让后续检索再强也找不到完整证据。
每个 chunk 除正文外,还应保存来源 URI、文档 ID、标题路径、版本、更新时间、权限、语言和页码。元数据用于过滤、展示引用、增量更新与删除,而不是装饰字段。
Chunk 怎样切才合理
固定字符切分简单,却可能在句子、表格或代码中间断开。按标题与段落的结构化切分更易保持语义,再对过长段落做二次分割并保留适度重叠。
chunk 太小会缺上下文并增加候选数量;太大则混入无关内容、降低向量表示精度并浪费上下文。最佳大小与文档类型、Embedding 模型和问题粒度相关,应通过检索测试集选择。
父子检索是一种折中:用较小子块召回,返回包含更多上下文的父块。表格与代码则常需保留标题、列名或函数签名,避免切出无法理解的片段。
Embedding 与相似度
Embedding 模型把查询与文档映射到向量空间。常用余弦相似度为:
若向量已归一化,余弦相似度与点积排序一致。查询和文档有时需要不同前缀或编码方式,应遵循模型训练规范。
向量维度高不代表一定更好。真正要验证目标语言、领域术语、长文本和难负例上的召回。更换 Embedding 模型通常需要重建索引,模型版本必须写入索引元数据。
ANN、BM25 与混合检索
精确遍历全部向量成本高,生产系统常用 HNSW、IVF 等近似最近邻索引,以少量召回损失换速度和容量。
向量检索擅长语义相似,BM25 等稀疏检索擅长精确词、编号、专有名词和错误码。混合检索分别取得候选,再通过分数归一化或 Reciprocal Rank Fusion 合并,通常比只用一种方式稳健。
元数据过滤应尽量在检索阶段执行。先召回全库再应用权限过滤,既浪费候选,也可能造成侧信道或越权风险。
Query 改写与多路召回
用户问题可能依赖对话上下文、使用别名或包含多个子问题。Query 改写可以补全指代、生成关键词或拆分子问题,但也可能改变原意。
应保留原查询,与改写查询并行召回,并记录每路贡献。HyDE 先生成假想答案再做向量检索,可能改善抽象问题,也可能把模型幻觉带入检索方向,因此必须通过数据验证。
Reranker 为什么放在召回之后
双塔 Embedding 可以离线编码文档,适合大规模初筛;Cross-Encoder 同时读取 query 与候选,交互更充分但计算昂贵,适合对几十个候选重排。
召回阶段优化 Recall@K,保证正确证据进入候选;重排阶段优化前几名质量。若正确文档根本未被召回,换更强 reranker 无法修复。
上下文组装与引用
最终放入模型的内容要去除近重复、保留标题路径、控制总 Token,并按相关度、时间或逻辑顺序排列。多个 chunk 来自同一文档时可合并相邻段,减少碎片。
提示词应明确:只能依据提供证据回答,证据不足时说明缺失,并按 chunk ID 生成引用。但“要求引用”不等于引用一定正确,系统还应验证引用 ID 存在、引用段确实支持对应陈述。
构建可诊断的评测集
测试样本至少包含问题、标准答案、相关文档 ID、允许的答案边界和权限上下文。还应加入:无答案问题、相似但错误的难负例、过期文档、多文档组合问题与越权文档。
分层指标可以是:
- 索引层:解析成功率、更新延迟、权限覆盖。
- 召回层:Recall@K、MRR、过滤正确性。
- 重排层:NDCG、首个相关结果位置。
- 生成层:正确性、忠实度、引用准确率、拒答能力。
- 系统层:延迟、成本、可用性与用户任务成功率。
更新、删除与权限
RAG 不是一次导入后永久不变。文档更新时要保证旧 chunk 被替换,删除时清除向量、缓存和派生索引。可用文档版本或内容哈希实现幂等增量同步。
权限必须绑定文档和 chunk,并在查询时使用服务端可信身份过滤。不要把权限交给模型判断,也不要把不可见文档放进上下文后再要求模型“不要泄露”。
常见误区
- top-k 越大不一定越好,噪声会挤占上下文并干扰生成。
- 向量数据库不是 RAG 的全部,普通搜索也可成为可靠召回层。
- 最终答案错不一定是模型问题,可能是索引、权限或引用错误。
- 相似度分数在不同查询间通常不可直接比较。
- RAG 能提供证据,但不能保证模型正确执行复杂计算。
章末检查
- 给一份 PDF 设计从解析到可引用 chunk 的数据结构。
- 解释 BM25、向量召回和 reranker 的职责差异。
- 正确文档在第 20 名时,应该先优化哪一层?
- 如何构造“确实没有答案”的测试样本?
- 文档删除后,系统有哪些位置需要同步清理?
延伸资料
本章进阶内容
原理专题与代码实践
完成主教材后,按顺序阅读原理专题、完成代码实践,并用掌握标准复查本章内容。
- 01
从失败案例理解 RAG 的适用边界
- 02
深入切块、召回、重排、生成与评测
- 03
用最小检索管线完成离线实验
- 04
逐层排查没有召回、排序错误和生成误用
代码实践
本章术语
六个关键词
- Chunk
- 从原文切出的最小索引与检索单元。
- Dense Retrieval
- 使用连续向量相似度召回文档。
- BM25
- 基于词频和逆文档频率的稀疏检索方法。
- ANN
- 以少量精度损失换取速度的近似最近邻检索。
- Reranker
- 对初召回候选进行更精细相关性排序的模型。
- Faithfulness
- 生成陈述是否能由提供证据支持。
章节记录
