我重新梳理了一遍 RAG,终于明白它不只是接个向量库

张开发
2026/4/20 1:36:15 15 分钟阅读

分享文章

我重新梳理了一遍 RAG,终于明白它不只是接个向量库
文章目录一、引言二、为什么大模型需要RAG三、RAG 到底是怎么跑起来的四、第一步先让知识进入系统1. PDF 为什么麻烦2. 为什么预处理很关键五、为什么切片是 RAG 里最容易被低估的一步1. 固定长度切片2. 带 overlap 的切片3. 语义切片3.1 句子相似度六、Embedding 和向量数据库到底在做什么1. 密集嵌入Dense Embedding1.1 GTE算法2. 稀疏嵌入Sparse Embedding2.1 BM25算法3. 向量数据库七、RAG 的检索不只是向量搜索1. 相似度检索2. 过滤检索3. 全文检索4. 混合检索八、为什么召回之后还要做 Rerank1. 融合排序2. 模型精排2.1 Cross-Encoder 为什么能做精排3. Rerank 的本质九、RAG 最后一公里怎么把检索结果交给模型1. 上下文编排2. 幻觉控制3. 为什么检索差不多答案却差很多十、RAG 的进阶优化优化的到底是什么Corrective RAG自我纠正的RAGAdaptive RAG自适应RAG十一、结尾一、引言这两天系统学习了一遍 RAG原本以为它就是文档切片 向量检索 大模型回答这么一条标准流程但真正从头到尾梳理下来之后我发现事情没那么简单。RAG 最有意思的地方不是它用了什么新概念而是它重新回答了一个很关键的问题当大模型面对企业知识、私有文档和最新资料时怎么才能不靠猜而是基于真实内容回答问题很多人第一次接触 RAG都会先记住几个关键词Embedding、向量数据库、检索、Rerank、Chunk但如果这些概念没有被串成一条完整链路就很容易变成每个词都认识但整体还是有点模糊。所以这篇文章我想不只是罗列概念而是尝试把 RAG 从头到尾重新讲清楚文档是怎么进入系统的为什么一定要切片检索为什么不只是向量搜索为什么召回之后还要重排RAG 真正难的地方到底在哪如果你也在学 Agent希望这篇梳理能帮你把 RAG 真正串起来。二、为什么大模型需要RAG先看一个最根本的问题大模型已经这么强了为什么还需要 RAG因为大模型再强也不天然知道你的私有知识。比如企业内部制度产品说明书招投标材料这些内容大模型本身并不会自动掌握。即使好像知道一些也很难保证准确更难保证是最新的。于是问题就出现了它可能根本不知道它也可能不知道但仍然生成一个看起来很对的答案后者就是我们熟悉的幻觉。而 RAG 的核心思路就是让模型在回答之前先去外部知识库里查资料再基于资料作答。所以RAG 的本质可以概括成一句话不是让模型凭记忆回答而是让模型基于证据回答。这也是为什么 RAG 特别适合企业知识库场景。企业真正需要的往往不是一个会聊天的模型而是一个能基于内部资料准确回答问题的系统。三、RAG 到底是怎么跑起来的从整体流程看一个完整的 RAG大致是这样一条链路加载文档对文档做清洗和切片把文本块做 Embedding存入向量数据库用户提问时先做检索对检索结果做重排把最相关的上下文交给大模型生成答案看起来不复杂但真正难的是这条链路里每一步都会影响最终回答质量。比如文档解析错了后面全都不准切片太碎语义不完整切片太大检索不精准召回到了但排序不对检索结果不错但上下文组织得不好所以RAG 不是单点能力而是一整套知识如何流向答案的系统设计。四、第一步先让知识进入系统RAG 的起点不是模型而是数据。因为模型最终能回答什么很大程度上取决于你给了它什么知识。现实里的知识源往往非常杂常见的包括PDF、Markdown、Word、网页等其中最常见、也最麻烦的通常是 PDF。1. PDF 为什么麻烦因为 PDF 更接近排版结果而不是天然结构化文本。它抽取出来之后经常会出现标题层级丢失、段落断裂、页眉页脚混入正文等所以RAG 里的文档加载绝不是把字读出来这么简单。更重要的是尽量保留结构。常见做法比如用pypdf抽文本适合相对规则的 PDF用unstructured做更复杂的结构解析适合版式复杂的文档如果是Markdown会相对友好很多。因为它天然带有标题、段落、列表等结构信息更适合进入后续流程。2. 为什么预处理很关键因为原始文档通常不能直接进入知识库。在正式切片前往往还要做一层清洗比如去掉无效空行、去掉重复页眉页脚、清理乱码和特殊符号等这些步骤看起来像基础工作但其实非常重要。后面做过滤检索、结果溯源、答案引用时很多能力都依赖这些结构和元数据。一句话来说就是知识库效果好不好第一步常常不是模型决定的而是文档处理决定的。五、为什么切片是 RAG 里最容易被低估的一步很多人学 RAG第一反应会把重点放在 Embedding 或向量数据库上。但真正做下来会发现切片往往才是最影响效果的环节之一。原因很简单文档太长不能整篇直接拿去检索也不可能完整塞进模型上下文。所以必须把它拆成一个个 chunk。1. 固定长度切片最基础的方式就是按固定长度切。比如每 300 字、500 字或者每 1000 token 切一块。这种方法实现简单适合快速搭原型。但问题也明显可能把一个完整语义硬切断也可能把两个不同主题拼到一起2. 带 overlap 的切片为了减少边界信息丢失通常会在相邻 chunk 之间加入 overlap也就是重叠区域。这样做的好处是即使关键信息刚好落在边界上也不容易被切丢。这是很常见、也很有效的一种工程优化。3. 语义切片更进一步的方式是按语义边界切片比如按标题切按段落切按主题变化切按句子相似度切所以切片本质上是在平衡三件事chunk 要足够小便于精准召回chunk 又要足够完整不能把语义切碎chunk 的组织方式要适配后面的生成说得更直接一点你怎么切决定了后面模型能检索到什么。3.1 句子相似度其中按句子相似度切可以单独展开一下。它的思路不是按固定长度硬切而是先判断一段文本内部语义究竟是在哪里发生变化的。如果某个位置前后已经不像在讲同一件事了那么这个位置就很适合作为切分点。比如一段文本被拆成 1、2、3、4、5、6 六个句子。如果窗口大小设为 3就可以得到 1-2-3、2-3-4、3-4-5、4-5-6 这些滑动窗口。接着把每个窗口送进 embedding 模型得到对应的语义向量再比较相邻窗口之间的差异。如果某个位置前后的差异突然变大就说明主题可能在这里发生了变化这个变化最大的点就可以作为候选切分点。本质上它不是按长度切而是沿着语义变化最明显的地方切。这种方式更符合人类阅读习惯也更容易保留完整语义。但它对文档质量要求更高实现复杂度也更高。六、Embedding 和向量数据库到底在做什么切完片之后下一步就是把文本变成可计算的语义表示这就是 Embedding。你可以把它理解成把一句话映射成一个语义坐标。这样用户提问时系统就可以根据语义距离去找最接近的文本块。1. 密集嵌入Dense Embedding最常见的一类是密集嵌入也就是 Dense Embedding。它会把文本表示成一个稠密向量比较擅长处理表达不同但意思相近的情况。比如怎么报销差旅费和出差费用报销流程是什么虽然字面不一样但语义其实很接近Dense Embedding 通常能把它们映射到比较近的位置所以特别适合做语义检索。实际工程里这一类模型常见的代表有 BGE 和 GTE 系列比如 bge-large-zh、bge-m3或者 gte-large 等。它们本质上做的都是同一件事尽量让语义相近的文本在向量空间里离得更近。1.1 GTE算法GTE 这类密集嵌入模型本质上是在做一件事把文本映射成一个能够表示语义的向量。你可以把它理解成模型先读一句话理解它大概在说什么然后再给这句话分配一个语义坐标。以后系统做检索时就不再只是比关键词而是去比较这些语义坐标之间的距离。距离越近通常说明语义越接近距离越远通常说明语义差别越大。2. 稀疏嵌入Sparse Embedding另一类是稀疏嵌入也就是 Sparse Embedding。它更偏向关键词和稀疏特征对专业术语、编号、错误码、实体词会更敏感。比如用户搜的是产品型号、法条编号、报错代码、专有名词这时候单靠 Dense 不一定最稳因为语义模型有时候能理解大意但未必能稳稳抓住关键词。在这种场景下Sparse 或全文检索往往更有效。这里一个非常经典的代表就是 BM25。它虽然不是大模型时代才出现的方法但在检索系统里一直非常实用尤其适合做关键词召回。所以在很多实际系统里Dense 和 BM25 并不是互相替代而是一起使用形成混合检索。2.1 BM25算法BM25 可以理解成一种基于关键词相关性的排序算法。它会根据查询词有没有出现、出现了多少次、这个词在整个语料里是否稀有以及文本长度是否合适来判断一段文本和问题的匹配程度。它不擅长理解深层语义但对术语、编号、错误码、专有名词这类关键词非常敏感所以在很多 RAG 系统里BM25 依然是很重要的基础能力。3. 向量数据库做完 Embedding 之后还需要把这些向量和原始文本一起存起来这就是向量数据库的工作。它解决的不是如何理解文本而是如何高效地存和如何快速地找。它通常负责几件事存储向量、做相似度搜索、保存原文和元数据、支持过滤检索以及配合混合检索和索引优化。在这一类系统里Milvus 是一个很典型的代表也是业界比较常用的向量数据库之一。真正进入向量数据库的通常不只是一个向量还会包括对应的 chunk 原文、来源文档、页码、标签、时间、业务字段等信息。因为最终系统返回给用户的不是一个抽象向量而是一段可读、可追踪、可用的知识。七、RAG 的检索不只是向量搜索初学 RAG 时很容易把它理解成一句话把问题转成向量然后去向量数据库里搜。这当然没错但只说对了一半。真实场景里的检索通常是多种方式的组合。1. 相似度检索这是最基础的一种方式。把用户问题也转成向量再找最相似的 chunk。它的优势是即使用户的说法和文档原文不完全一致也有机会召回到相关内容。2. 过滤检索有些时候仅靠语义相似还不够。比如你希望只查某个部门的文档只查 2024 年之后的制度只查产品手册不查会议纪要这时候就需要元数据过滤。它能让检索结果更可控也更贴近业务场景。3. 全文检索全文检索擅长精准命中关键词。对于这些内容它往往特别有用版本号、错误码、专有名词、编号、条款名称现实里很多问题并不只是语义理解问题而是我就要找这个词。这种时候纯向量检索并不一定最优。4. 混合检索所以在很多实际项目里最稳定的做法往往是混合检索也就是把语义检索关键词检索元数据过滤结合起来一起用。因为真实用户的问题往往既有语义理解需求也有精确匹配需求。单一路径很难兼顾两边。所以很多时候RAG 效果不好不是模型太弱而是检索策略太单一。八、为什么召回之后还要做 Rerank因为召回到了不代表排得最好。系统可能一次召回了 10 条都相关的内容但真正最适合回答当前问题的那条未必排在最前面。如果不再做一次排序优化最终交给模型的上下文就可能不是最优的。所以在 RAG 里常见做法通常不是召回完就结束而是再加一层 Rerank也就是重排。你可以把它理解成两阶段先尽可能召回一批候选内容再从候选里选出最值得给模型看的内容1. 融合排序有些场景下系统并不是只有一路召回而是会同时结合向量检索、全文检索、关键词检索等多种方式。这时候首先要解决的问题不是文本理解得够不够深而是多路结果怎么合并。常见方法有两种Weighted Ranker给不同召回通道设置不同权重再综合排序RRF Ranker不过度依赖绝对分数而更关注一条结果在多个列表中的相对排名这类方法的优点是实现简单、工程上容易落地而且对混合检索非常实用。但它们本质上更像融合排序还不是严格意义上的深度精排。2. 模型精排如果想进一步判断哪段内容最适合当前问题通常还会引入专门的精排模型比如Cross-Encoder类的reranker。它和前面的向量检索有一个很大的区别。向量检索通常属于双塔结构也就是先把问题和文本分别编码成两个向量再通过向量相似度判断它们是否接近而 Cross-Encoder 则是把问题和候选文本作为一对输入一起送进模型让模型直接输出一个匹配分数。这样做的好处是模型看到的不再是两个彼此独立的向量而是问题和文本之间更细粒度的交互信息所以通常更适合做最终排序。也正因为如此Cross-Encoder 类方法往往比普通向量相似度更准尤其适合用来判断这段内容到底是不是最适合回答当前问题。不过它的代价也更高。因为每一个候选文本都要和当前问题单独配对再跑一遍模型所以计算成本会明显高于普通向量检索。也因此在实际工程里它一般不会用来做大规模召回而是放在召回之后对前几十条候选结果再做一次精排。所以从工程角度看Cross-Encoder 类精排模型本质上是在用更高的计算成本换取更高质量的排序结果。2.1 Cross-Encoder 为什么能做精排3. Rerank 的本质Rerank 的意义可以概括成一句话不是把相关内容再找一遍而是把可能相关进一步筛成最适合当前问题的内容。Weighted Ranker 和 RRF 解决的是多路结果怎么合并得更合理Cross-Encoder 解决的是这些候选里哪个和当前问题最匹配召回解决的是先把东西找出来而 Rerank 解决的是把最该给模型看的内容排到前面。九、RAG 最后一公里怎么把检索结果交给模型检索和重排做完之后下一步才是真正把信息交给大模型也就是生成阶段。很多文章讲 RAG讲到检索和重排就差不多结束了。但真正决定回答质量的往往还包括最后一步检索到的内容究竟怎么交给模型。1. 上下文编排生成阶段最常见的做法是把检索到的若干 chunk 拼进 Prompt再连同用户问题一起发给模型。但这一步并不是简单拼接而更像是在做上下文编排。比如取几个 chunk按什么顺序放要不要去重要不要带来源内容会不会超出上下文长度这些都会直接影响最终回答质量。因为上下文不是塞得越多越好。塞太多模型可能抓不住重点塞太少信息又可能不足。所以这一层真正要解决的问题不是怎么把内容放进去而是怎么把最合适的内容用最适合模型理解的方式放进去。2. 幻觉控制生成阶段另一个核心目标是尽量降低幻觉。RAG 不能彻底消灭幻觉但可以明显降低它出现的概率。前提通常有两个一是检索结果本身足够相关二是 Prompt 约束足够明确。常见做法包括要求模型仅基于提供材料回答如果材料不足就直接说明无法确定要求在回答中标注来源或出处这些约束的本质都是尽量减少模型脱离材料自由发挥让它更像是在根据材料作答而不是凭印象补全答案。3. 为什么检索差不多答案却差很多很多时候同样是 RAG前面的检索结果看起来差不多但最终回答效果还是会有明显差异。原因就在于生成阶段并不是一个机械的拼接动作而是整条链路里的最后一次质量放大或者质量损失。如果上下文组织得不好模型即使拿到了相关材料也未必能用好。如果约束不清楚模型即使看到了证据也可能继续自由发挥。所以从工程上看生成阶段真正影响的是模型能不能把检索到的信息稳定转化成可用的答案。说得更直接一点检索决定模型能不能看到而生成决定模型能不能答好。十、RAG 的进阶优化优化的到底是什么如果说前面讲的更多还是标准 RAG 的主链路那么再往后走很多优化已经不只是检索得更准一点这么简单了。因为在真实系统里问题往往不只是能不能检索到还包括这次检索结果靠不靠谱证据够不够支撑回答要不要补一次检索不同问题是不是应该走不同流程也就是说RAG 的优化重点正在从单点能力优化逐渐走向整条链路的判断与决策优化。Corrective RAG自我纠正的RAGCorrective RAG 可以理解成一种带纠偏能力的 RAG。它不默认第一次检索结果一定靠谱而是会进一步判断当前证据是不是不足检索结果之间有没有冲突如果这次检索不理想是否需要补检索、改写查询或者调整后续流程。所以它优化的已经不只是检索而是当检索结果不够好时系统怎么自我修正。Adaptive RAG自适应RAGAdaptive RAG 更强调按问题类型动态调整策略。因为不是所有问题都值得走同样一套固定流程。有些问题一句话就能召回有些问题需要多跳检索有些问题甚至根本不该走知识库而应该直接回答或者先做路由判断。所以到了这一步RAG 就不再只是固定流水线而更像是一套带决策能力的工作流。这也是为什么现在很多人会把 RAG 和 Agent、工作流编排放在一起讨论。因为继续往后优化优化的往往已经不只是检索效果而是整套系统在不同场景下能不能做出更合适的决策。十一、结尾回过头看RAG 的价值并不在于引入了多少新概念而在于它提供了一种更可控的知识接入方式。它让大模型在生成答案之前不是直接依赖参数记忆而是先从外部知识中检索证据再基于证据生成回答。这件事对于企业知识库、私有数据问答、以及需要持续更新知识的系统来说意义非常明确。但与此同时RAG 也不是加一个向量库就能自然成立的方案。它最终效果取决于整条链路的质量包括文档解析、切片策略、召回方式、重排机制以及上下文组织方式。所以从工程视角看RAG 更像一套系统设计问题而不是单一模型能力问题。这也是我这次梳理之后最明确的一个结论RAG 的关键不在于有没有搭起来而在于每一个环节是否真正为最终回答质量服务。如果你也在学习 RAG、Agent 架构或者正在做 AI 应用落地相关的事情欢迎来找我交流。我是爱敲代码的小黄阿里巴巴高级开发工程师CSDN 博客专家平时会持续分享后端架构、中间件源码以及 AI 应用实践相关内容。我们下期再见。

更多文章