向量检索跑通后,离真正掌握 RAG 还有多远

作者:袖梨 2026-09-16

不少 RAG 初学者会把文档成功入库、向量检索能够返回结果视为阶段性完成,但真正影响问答质量的问题往往才刚刚出现。检索片段是否准确、关键证据是否遗漏、生成答案是否忠于资料,都需要分层验证。要真正掌握 RAG,重点是看清整条数据链路,并能定位每一次失败发生在哪个环节。

刚开始学 RAG,很容易把目标定成一句话:把文档切块、转成向量,再让大模型根据搜索结果回答问题。

这条链路跑通当然重要,但它只证明“系统能返回内容”。被找回来的片段是不是正确、有没有漏掉关键证据、答案是否忠于资料、资料更新后能不能稳定生效,都还没有答案。

所以我更愿意把 RAG 当成一条需要逐段验证的数据链路,而不是某个框架的功能清单。这篇不是一份“我已经全部实测完”的教程,而是我根据 RAG 原始论文、综述和当前官方开发文档整理出的学习路线。目标很具体:知道先学什么、每一步练什么,以及做到什么程度才适合进入下一阶段。

先把 RAG 理解成两个系统,而不是一个聊天框

2020 年的 RAG 原始论文把它描述为参数化记忆与非参数化记忆的结合:模型参数负责语言能力,外部索引负责提供可以更新、可以追溯的知识。查询到来时,检索器先找到相关文档,生成器再结合问题与文档生成答案。

到了工程实现里,这通常可以拆成两条链路:

  • 离线链路:收集资料、清洗、切块、生成向量、写入索引;
  • 在线链路:理解问题、检索候选、排序或过滤、组织上下文、生成答案、返回引用。

这也是学习 RAG 时最先要建立的边界。文档成功入库,不代表查询能命中;查询能命中,不代表命中的片段足够回答;答案读起来顺畅,也不代表它忠于片段。

如果把这些状态揉成一个“效果不错”,后面几乎无法定位问题。

第一阶段:先做一个最小闭环,但不要急着换框架

第一个练习不需要复杂知识库。找一份自己熟悉、可以人工核对的短文档,例如产品说明、个人笔记或一个小型开源项目的文档,然后准备 10 到 20 个问题。

问题不要全是能直接复制原句的简单题,至少包括:

  • 文档中明确写出答案的问题;
  • 需要连接两个片段才能回答的问题;
  • 容易被相近术语干扰的问题;
  • 文档里根本没有答案的问题。

最小流程可以是:加载文档,切成片段,为片段生成向量,保存索引;收到问题后检索 Top K 片段,把问题和片段交给模型,并要求资料不足时明确拒答。

下面只是概念伪代码,用来标出学习对象,不代表复制后即可运行:

chunks = split(load(document))
index = embed_and_store(chunks)

contexts = retrieve(index, question, top_k=5)
answer = generate(question, contexts, require_citations=true)

这一步的学习目标不是记住 API,而是能够打印出每个中间结果:原始文档、切块结果、检索分数、最终上下文和答案引用。看不见中间状态的 RAG,很快会变成只能反复调整提示词的黑盒。

LangChain 当前的 RAG 文档同样把索引过程拆成加载、切分、向量化和存储。LlamaIndex 则把完整流程概括为加载、索引、存储、查询和评估五个阶段。这两个划分很适合做第一张学习地图。

第二阶段:把大部分时间花在数据和切块上

不少入门示例会给出一个固定 chunk size,然后直接进入向量检索。但真实资料不是等长的:标题、正文、表格、代码、FAQ 和页眉页脚承担的语义完全不同。

这一阶段要练的不是“找到一个万能数字”,而是保住文档结构。可以对同一份资料做三组对照:

  1. 固定字符切块;
  2. 按标题和段落切块;
  3. 按文档类型定制,例如 FAQ 保留问题与答案,代码保留函数边界。

每组都用同一批问题测试,并记录三个东西:正确答案需要的证据落在哪个片段、检索结果有没有召回它、片段是否带着足够的标题和来源信息。

这里很容易出现一个反直觉结果:切得更小不一定更准。小片段更容易匹配局部词义,却可能丢掉限定条件;切得太大又会混入无关内容,增加上下文成本。chunk size、overlap 和结构信息应该一起看,而不是单独调一个参数。

还要尽早加入 metadata,例如文档名、章节、更新时间、产品版本和权限范围。它们不只是为了展示引用,后面还会参与过滤、更新和访问控制。

第三阶段:先评估检索,再讨论模型回答

这是我认为最值得刻意练习的一步。

给每个测试问题标出“应该命中的证据片段”,形成一份很小的答案集。然后暂时不让大模型回答,只检查检索结果:

  • Top K 中有没有正确证据;
  • 正确证据排在第几位;
  • 返回了多少看似相关但不能回答问题的片段;
  • 无答案问题是否仍被强行匹配。

这样能把“没找到”和“找到了但模型没用好”分开。

语义搜索擅长找到用词不同但含义接近的内容,关键词搜索则对专有名词、型号、错误码和精确短语更敏感。当前 OpenAI Retrieval 文档也提供了混合搜索权重与相关性阈值的调整入口。学习时可以用同一批问题比较关键词、向量和混合检索,但不要一上来就同时调整所有参数。

更稳妥的方法是一次只改变一个变量:先固定数据和切块,比较检索方式;再固定检索方式,调整 Top K;最后才考虑 query rewrite、rerank 或多路召回。

第四阶段:让生成器学会依据证据回答,也学会不回答

检索通过后,再把注意力放到生成阶段。

这里至少需要四条约束:

  • 答案以提供的资料为依据;
  • 关键结论能指向具体来源;
  • 多个来源冲突时暴露冲突,不自行拼成一个确定答案;
  • 资料不足时明确说不知道,并说明缺少什么。

评估时不要只看“像不像正确答案”。至少分开记录:

  • 答案是否回答了用户问题;
  • 答案中的事实是否得到检索片段支持;
  • 引用是否真的包含对应证据;
  • 没有答案时是否越过资料自行发挥。

RAG 综述把常见质量维度概括为上下文相关性、答案忠实度和答案相关性。它们正好对应三类故障:找错了、编多了、答偏了。

第五阶段:再学习高级 RAG,而不是反过来

当最小闭环已经有固定测试集,而且能定位问题发生在哪一层,才适合继续学习高级方法:

  • query rewrite:原始问题不适合直接检索时,先改写或拆解;
  • hybrid search:结合关键词与语义召回;
  • rerank:对候选片段重新排序;
  • parent-child retrieval:小片段负责命中,大片段负责提供完整上下文;
  • context compression:减少重复或低价值上下文;
  • iterative retrieval:回答复杂问题时分多轮检索;
  • metadata filter:按版本、部门、时间或权限缩小范围。

综述通常把 RAG 分成 Naive、Advanced 和 Modular 三类。这个分类适合用来理解技术演进,却不适合变成待安装的功能清单。每增加一个模块,都应该对应测试集中已经观察到的一类失败。

如果基础检索没有评估,增加 rerank 可能只是让错误结果换了顺序;如果文档结构已经在切块时丢失,换更大的模型也补不回来。

一条更适合工程实践的学习顺序

把前面的内容压缩成可执行路线,大致是这样:

第 1 周:看见完整链路

用一份小文档和 10 到 20 个问题跑通加载、切块、索引、检索和生成。强制打印中间结果,不追求界面。

第 2 周:只研究数据与切块

为同一份资料建立三种切块方案,对比正确证据能否进入 Top K,并检查标题、来源和版本信息是否保留。

第 3 周:建立最小评估集

给问题标注标准证据,区分检索命中、答案忠实和最终可用性。每次调整只改一个变量,保留前后结果。

第 4 周:处理真实失败

从 query rewrite、混合检索、rerank 和 metadata filter 中只选一个,解决测试集中已经存在的问题。不要为了“高级”而增加模块。

四周不是掌握 RAG 的承诺,只是一个控制学习范围的方法。真正的进度不应该用“看了多少教程”衡量,而应该看:能否解释一次错误答案究竟错在数据、索引、检索、上下文还是生成。

最后,给每次实验留一张记录表

每次修改至少留下这些字段:

数据版本:
切块策略:
embedding 模型:
检索方式与 Top K:
是否 rerank:
命中的标准证据:
答案是否被证据支持:
无答案问题是否拒答:
本次只改变了什么:
下一步要验证什么:

这张表看起来没有框架示例那么炫,但它能防止学习过程变成“换一个模型再试试”。

RAG 的入口确实是向量检索,但真正的工程能力,是知道一条答案经过了哪些环节,在哪一层失真,以及下一次只该改哪里。

参考资料

  • Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
  • Retrieval-Augmented Generation for Large Language Models: A Survey
  • LlamaIndex:Introduction to RAG
  • LangChain:Retrieval Augmented Generation
  • OpenAI:Retrieval guide

相关文章

精彩推荐