原创

RAG入门指南:检索增强生成全解析

温馨提示:
本文最后更新于 2026年03月16日,已超过 8 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

第一课:RAG到底是什么?

RAG=先查资料,再让大模型回答。


他的英文全称是Retrieval-Augmented Generation,中文一般叫:检索增强生成。


先不要管英文有多长,我们先拆成两个部分来看:


Retrieval:检索,查找资料

Generation:生成,让模型组织语言输出答案

所有他的大致意思是:大模型回答问题前,不是只靠训练过的知识,而是先去查找相关资料,再根据资料组织语言,进行回答。


为什么会有RAG

先说一个现实的问题,如果你直接问大模型:


公司的内部制度是什么?某个PDF第三章讲了什么?某个最新的政策怎么规定?


这时候模型 会遇到3个麻烦


他不知道你的私有资料:你公司的内部文档、你的笔记、你的产品手册,这些内容本来就不在他的训练数据里。

他的知识可能过时:模型训练完成后,世界仍然在发展,新文档,新政策,新资料出现,他可能根本没见过

他可能回答会偏:这就是我们说的幻觉,明明不知道,但却一本正经乱说。

所有RAG的思想就是:能不能让大模型在回答之前,先看一眼我们提供的材料,再回答。


RAG像是开卷考试

不用 RAG 的大模型

像一个学生,考试时:不准翻书只能靠脑子里的记忆答题


那它就可能:记错,忘了,瞎猜


用了 RAG 的大模型

像一个学生,考试时:先看试卷的题目,根据题目去资料库翻书,找到相关内容,再根据书上的内容答题


这时候答案通常会:更准确,更贴近你给的资料,更少胡说八道


所以先记一句:


RAG 本质上,就是给大模型加一个“查资料”的能力。但有一点要知道,好的RAG系统在找不到依据时,不会像考试一样自己编,而是明确说明找不到对应信息。


RAG的知识库是什么?

很多初学者一听到知识库,觉得很玄,其实知识库=一堆可以被系统搜索的资料 ,这些资料可能是PDF、Word、网页、Markdown文档、FAQ、数据库里的文本内容等等。所以RAG并不是提升模型智商,而是提升回答时的信息来源质量。


第二课:RAG的完整流程

我们用一个例子来学:


当我们问模型:员工请病假需要提供什么材料?


系统会怎么做?


第一步:接收用户信息

用户输入问题:员工请病假需要提供什么材料?


系统这时知道两件事:


你想问的是病假

你想知道员工需要哪些材料

第二步:去知识库找相关内容

系统不会直接回答,而是先去知识库里查,知识库里可能有员工手册、请假制度、HR政策文件等。系统会从里面找出类 似这些内容:


“员工请病假1天以上需要提供医院证明”


“连续病假申请需要附诊断材料”


“病假审批需要通过OA系统提交”


这一步叫做检索,可以先理解为:从很多资料里面,找出和当前问题最相关的几段内容


第三步:把内容当作参考资料

系统找到内容后,不会原封不动的直接甩给你,而是会把这些内容整理为上下文。


比如变成这样:


资料 1:员工请病假 1 天以上需提供医院证明

资料 2:连续病假申请需附诊断材料

资料 3:病假审批通过 OA 系统提交

这些就是给大模型看的“参考资料”。


这一步你需要记住这个词:Context(上下文),它通常是检索出来,准备用来辅助回答的材料


第四步:把问题+参考资料一起发给大模型

系统不是只把你的问题发给模型,而是会一起发:


用户问题

检索到的上下文

一段提示词要求

大概意思像这样:


“用户问:员工请病假需要提供什么材料?

下面是检索到的参考资料,请你仅基于这些资料回答;


资料 1:员工请病假 1 天以上需提供医院证明

资料 2:连续病假申请需附诊断材料

资料 3:病假审批通过 OA 系统提交

如果资料不足,请明确说明。”


这一步就是把 RAG 和普通问答真正区分开的地方。


普通问答是:只给问题


RAG 是:给问题 + 给资料


第五步:大模型生成答案

模型看到问题和资料后,开始组织语言,输出结果。


例如:


根据提供的制度内容,员工请病假时通常需要提交医院证明;如果是连续病假,还需附诊断材料,并通过 OA 系统提交审批。


这时候模型的角色更像是资料整理员与回答生成器,而不是原本的百科全书


RAG的重点

很多初学者以为RAG最重要的是模型,我选好的模型,选参数高的模型就能让模型回答的好一些。其实不是,RAG很多时候成败取决于前面几步:


资料找得准不准

找出来的内容够不够相关

给模型的上下文是否干净清楚

也就是说RAG不只是生成问题,更是检索问题。


第三课:为什么要切块(Chunk)

很多人学RAG都会问,既然要查资料,那我直接把文档丢给他,让他根据文档回答就好了,我弄啥RAG。答案是:因为文档通常太长,太杂,太浪费,且不利于准确检索。所以RAG里又一个特别重要的动作:切块。


RAG不会把整篇文档拿去检索,而是会先把文档切成很多小段,这些小段,就叫chunk。中文可以理解为:文本块、内容片段、文档切片


为什么不能整篇文档直接用

假设有1份100页的员工手册,你问“请病假需要提供什么材料?”,如果把这100页都扔给模型,会出现我们提到的问题:


太长:模型能接收的上下文是有限的,文档太长的话,可能根本塞不进去

太浪费:只是问病假材料,没必要把其他入职流程、报销制度等内容都丢给模型

干扰太多:无关的内容太多了,会影响模型的判断,导致抓错重点

不利于准确检索:你真正需要的是其中一小段,整篇一起整理不利于定位。

所以要先把大文档拆开。


Chunk可以理解为把大书拆成很多小卡片

我们打一个比方,原来你有一本厚厚的书,现在我们把书按内容切成很多小卡片:


卡片 1:年假规则

卡片 2:病假流程

卡片 3:报销标准

卡片 4:加班制度

当用户问“病假材料”时,

系统就更容易找到“病假流程”那张卡片,

而不是抱着整本书乱翻。


所以:chunk 的作用,就是把大文档拆成更适合搜索和检索的小单位。


chunk的本质作用是什么

1、方便检索:系统更容易定位到相关片段


2、降低噪音:只把相关的小段交给模型,而不是整本书


3、节省上下文空间:模型看到更精炼的资料,回答更聚焦


chunk的大小怎么定

chunk太大

假设一个chunk很大,包含了


病假制度

年假制度

婚假制度

这会导致:


信息太杂:虽然里面可能包含了正确答案,但也混入了很多无关内容

相似度可能被稀释:用户问病假,但这个块还有很多别的内容,系统未必能判断这个块是最相关的

给模型时容易啰嗦:我们交给模型的是检索到的资料与用户问题,但检索出来的资料噪音太大,模型输出也不好聚焦用户的问题。

因此chunk太大会让检索变钝


chunk太小

那是不是chunk越小越好?


也不是。比如我们把一句完整的话切的太碎:


原文:


员工请病假 1 天以上需提供医院证明,并通过 OA 系统提交审批。


如果切得太小,变成:


chunk A:员工请病假 1 天以上

chunk B:需提供医院证明

chunk C:并通过 OA 系统提交审批

这时就麻烦了:


语义不完整:每一小段单独看,语义都不全,相关性都不高

上下文断裂:系统可能只检索到需要医院提供证明,却不知道这是在讲病假

模型收到的信息不连贯:把需要提供医院证明交给模型,没有把OA系统提交审批交给模型,这就会导致模型输出的答案是残缺的。

因此chunk太小,会让语义断掉。


最理想的chunk是怎样的

一个好的chunk,需要满足两件事:


足够小:方便精确检索

足够完整:保留基本语义,不要切断一句话或一段完整的规则的意思

可以适当重复: 让相邻两个 chunk 有一部分重复内容 (overlap)

既不能是一整章,也不能只剩半句话。


什么是overlap(重叠)

这是RAG里另一个常见的概念。


文本切块时,很容易在边界把意思切断,所以常常会让相邻两个chunk有一部分内容重叠,这就是overlap。


比如原文是:


员工请病假 1 天以上需提供医院证明,并通过 OA 系统提交审批。连续病假还需附诊断材料。


切块时可能变成:


chunk1:员工请病假 1 天以上需提供医院证明,并通过 OA 系统提交审批。

chunk2:并通过 OA 系统提交审批。连续病假还需附诊断材料。

你看,

“并通过 OA 系统提交审批” 这句重复出现在两个块里。


这样做的好处是:


减少边界信息丢失

让相邻块语义更连续

检索时不容易漏掉关键内容

所以overlap可以理解为:切块时故意保留一点重叠内容,避免把意思切断。


先别记数字,先记住原则

你在看视频,听别人交流的时候,可能会听到他们说:


chunk size 500

overlap 50

1000 tokens

200 characters

别被这些数字吓到了,作为初学者,你先记住这些原则


chunk要能表达一个相对完整的小意思

不能太大,否则噪音多

不能太小,否则语义不完整

必要时要有overlap,避免边界丢失信息

简单的标准判断

看到一段文本时,先问自己:


如果这一段单独拿出来,别人还能大概看懂它在说什么吗?


如果能:这可能是一个合适的chunk


如果不能:那说明切的太碎了


第四课:Embedding是什么

这一节会有一点抽象,我尽量让初学者能看懂。


先记住一句核心的话:


Embedding是把一句话的语义特点变成一串数字。


数字并不是要你做数学题,只是要理解它在RAG里到底是干啥的。


为什么需要Embedding

假设知识库里有一句话“员工请病假需要提交医院证明。”


而用户问的是:“请病假要交什么材料?”


这两句话并不是一模一样的。一个说提交医院证明,另一个说叫什么材料。如果系统只会按关键词去找,那就可能会出问题:


“提交”和“交”不是完全一样的


“医院证明”和“材料”也不是同一个词


但人一看就知道,这两句话的意思很接近,但机器不是人,它不能看一眼就知道他俩是一个问题与答案,它需要一个方式来判断意思是否相近,这个方式就是Embedding。


Embedding的本质:把文字转为可比较的语义坐标

计算机不真正懂文字的意思,一切输入对他来说都是数字,它擅长处理数字问题,所以我们把一句话转成数字让他去看懂。这串数字不是乱写的,而是要保留文字的语义信息。


比如


“员工请病假需要提交医院证明”

“请病假要交什么材料”

这两句话经过Embedding后,会变成两组数字,虽然数字很长,我们看不懂,但计算机不一样,它是数学能手,它可以去比较这两组数字的关系(怎么比较我们后面再说):


如果很接近,说明语义相似

如果差很远,说明语义不相关

所以你可以把 Embedding 理解成:


把一句话放到一个“语义空间”里,占一个位置。


意思接近的话,会离得近。

意思差很远的话,会离得远。


用数学的角度的话,就是在一个平面上,我们有(X,Y)坐标来确认位置,而两个点(X1,Y1)与(X2,Y2)之间是有距离的,这个距离就是他们的关系。只不过在语义空间中,这不是二维平面的,而是上千维的。


在RAG里,Embedding用在哪里

在RAG中,Embedding主要用在检索阶段,大致流程是这样的:


先处理知识库里的chunk:把每个chunk都做一次Embedding,也就是把每个chunk变成一个向量

把这些向量存起来:存到向量库或者检索系统里。

用户来提问时:把用户的问题也做一次Embedding

比较问题向量与各个chunk向量:看看哪个chunk与问题最接近

取出最相关的几个chunk:取出一定数量的chunk交给模型生成答案

文档切块 → 每个 chunk 做 Embedding → 存起来 → 用户提问也做 Embedding → 比较相似度 → 找到相关 chunk


什么是向量

你经常会听到这两个词:“向量”与Embedding,初学者很容易搞混,你可以记为:


Embedding:把文本转为数字表示的这个过程

向量:把文字转为数字表示的这串数字

一段文字,经过Embedding,得到一个向量。


你现在不需要会线性代数,只要知道“向量就是一串能表示语义的数字”就够了。


为什么 Embedding 很重要

因为没有 Embedding,

系统很多时候只能做很死板的关键词匹配。


比如:


知识库里写的是:

“提交医院证明”


用户问的是:

“要交什么材料”


关键词不完全重合。

但语义其实相关。


Embedding 的价值就在这里:


它让系统有机会按“意思相近”来找内容,而不只是按字面是否一样。


这就是为什么 RAG 能做“语义检索”。


Embedding不是理解全文真相,他只是压缩语义特征

我们要明确一个点:Embedding不是说系统真的像人类一样去理解这个句子的含义,而是把一句话的重要语义特征提炼成数学表示。


所以他并不是万能的,可能会出现:


相近但不完全准确的内容被召回(初步筛选中)

专业术语表示不够好

长文本信息被压缩后有损失

这就是为什么会有:


chunk设计

重排rerank

混合检索

这些手段出现的原因


一个例子

假设知识库里有 3 个 chunk:


chunk 1

“员工请病假 1 天以上需提供医院证明。”


chunk 2

“国内出差住宿报销上限为每天 600 元。”


chunk 3

“年假需提前 3 天提交申请。”


用户问题是:


“病假要交什么材料?”


系统会做什么?


把问题转成向量

把 3 个 chunk 的向量拿来比较

发现问题和 chunk 1 最接近

所以优先取 chunk 1

讲chunk1与用户问题交给大模型生成答案

这就是 Embedding 在实际中的作用。


第五课:向量库是什么

向量库,就是专门用来存放向量,并且能快速找出“最相似向量”的地方。


先不要被这个库给吓到,可以先把他理解成一种特殊的数据库。(数据库应该都知道吧,要是数据库也不知道的话,可能得去补补这方面知识)


为什么需要向量库

前面我们说过,知识库里的每个chunk都会做Embedding,变成向量,现在假设你有10万个chunk,这些chunk变成向量后,系统要把它放在哪里?不可能丢给模型让模型记住吧,而且检索过程中系统还要做:从这么多向量里,快速找出和问题最相近的那几个。这时候,普通的存储方式就不够方便了,需要一个专门做这件事的东西,这个东西就是向量库(Vector Database/Vector Store)


向量库是干什么的

他有两个核心工作:


存向量

把每个chunk的向量存起来,不仅可以存chunk,chunk的文本内容、chunk的id、chunk的来源文档都可以一起存,记住:只有向量是一串数字,其余的是以文本形式存着的。(我们后面会再讲)


查相似向量

当用户问题也变成向量后,向量库会去找:哪些chunk的向量和这个问题向量最接近?


然后返回最相关的几个结果,所以一句话概括:

向量库=存向量+做相似度搜索


他和普通数据库有什么区别

这是初学者必须分清楚的地方。


普通数据库更擅长:精确查询、条件筛选、查id、查日期等,比如你查员工编号=10086,报销金额>500,日期在3月份。这种是普通数据库很擅长的。


向量数据库更擅长:查语义相近的文本、查意思差不多的内容、相似度搜索


比如你问:“病假要交什么材料”,知识库的原文可能是 “员工请病假 1 天以上需提供医院证明。” 他们字面不同,但语义接近,这就是向量库擅长处理的场景。


向量库在RAG流程里处于哪里

现在我们把流程串起来


离线准备阶段

先做这些事:


拿到文档

切chunk

每个chunk做Embedding

把chunk和向量存到向量库里

这是建库过程


在线问答阶段

用户提问时:


用户问题做Embedding

去向量库里找最相似的chunk

返回top-k结果

把这些结果交给大模型生成答案

所以你现在可以看到:


Embedding 负责把文本变成可比较的向量,向量库负责把这些向量存起来并快速检索。


什么是Top-k

我们刚才其实已经碰到了这个概念,当问题向量去向量库里搜索时,系统通常不会只取1个结果,而是取最相关的前几个,这就叫Top-k。


意思就是:


相似度最高的前 k 个结果


比如:


top-1:最相似的 1 个 chunk

top-3:最相似的 3 个 chunk

top-5:最相似的 5 个 chunk

为什么不总是只取 1 个? 因为一个问题的答案,可能分散在多个chunk里,多取几个,能减少漏信息的风险,但也不能取太多,不然噪音会增加太多,这个我们后面还会详细讲。


向量库里不只是向量,通常还有元数据

了向量本身,通常还会存一些附加信息,比如:原始文本内容、文档标题、来源文件名、页码、时间、标签、权限信息等等


这些叫:


metadata(元数据)


这样做的好处是:


方便返回原文

方便做过滤

方便显示来源引用

方便权限控制

他的数据结构通常长这样:


ID (标识符):1024 —— 数字或字符串(用于唯一标记)。

Vector (向量):[0.12, -0.55, 0.88, ... 1536维] —— 浮点数数组(这是唯一的“数学暗号”,专门给计算机做模糊搜索用的)。

Payload (元数据/载荷): —— 文字/JSON 格式(这是给人或大模型看的信息)。

content: "大熊猫主要栖息在四川..." —— 纯文本。

source: "大熊猫百科全书.pdf" —— 纯文本。

page: 12 —— 整数。

我们现在先不用深记,知道有这个东西就够了


现在为止,我们已经把RAG的核心骨架理清了:


文档切块 → chunk 做 Embedding → 向量存进向量库 → 用户问题做 Embedding → 去向量库查 top-k → 把结果交给大模型回答


第六课:核心组件复盘

这一节课的目的是让你把前面所学到的零散的概念连成一张图


一个最基础的 RAG 系统,通常由 5 个核心部分组成。


分别是


文档

切块器

Embedding模型

向量库/检索器

大模型

下面我们一个一个看


五个核心部分

文档

文档是RAG的知识来源,它可以是PDF、Word、网页、Markdown、产品手册等等,可以理解为RAG要查的原始资料,没有文档,就没有后面的检索。


切块器(Chunker/Text Splitter)

文档通常很长,不能整篇直接用于检索,所以要先i去而成小块,这一步的作用是让检索更精准、降低噪音、保留局部语义、方便后续Embedding。


切完后我们就得到了很多chunk,所以切块器的本质是在做:把大文档拆成适合搜索的小片段


Embedding模型

前面我们已经学了Embedding,但在实际工作中,并不需要我们取手动转成向量,而是通过Embedding模型去转,他负责把每个chunk、用户的问题转成向量。 把文本从“文字形式”变成“可比较的语义数字表示”。 有了它,系统才能做语义检索,而不是只看关键词。


向量库/检索器 (Vector  Store / Retriever)

这两个词你会经常一起看到,先简单区分一下


向量库:偏存储和搜索向量的地方


检索器:偏执行检索逻辑的模块


在入门阶段,你可以先把它们看成一类东西:负责把最相关的chunk找出来


他做的事情包括:存储chunk向量、存储元数据、接收问题向量、计算相似度、返回top-k结果


大模型LLM

大模型在RAG里主要负责最后一步:根据问题和检索到的资料,组织出自然语言答案。


注意这里有一个很重要的认知:在RAG里,大模型不负责记知识,而是负责:理解上下文、阅读问题、总结信息、组织表达


它是一个阅读理解+答案生成器


还有两个顺手认识的辅助概念

Prompt

也就是给大模型的提示词,提示词不是随便给的,在RAG里,Prompt往往需要包含:用户问题、检索到的上下文、回答要求


比如:


只能依据资料回答

找不到就说不知道

尽量简洁

给出引用来源

Context

也就是上下文,在RAG里,它通常指:检索出来并提供给大模型参考的文本内容。与我们常说的大模型容量几百万token不同,大模型的容量叫做Context Window,指的是模型一次推理时可以读取的最大token数量,只是有人会简称为context,我们要分清两个context的区别。


结尾

简单的理论部分就结束了,剩下的就是动手实践环节,我并不推荐去跟着AI,让AI一步步教你做,因为AI会省去很多步骤,连知识库文档这块都是简单生成的,你没有自己亲自上手文档清洗,你无法理解每一步的重要性。


正文到此结束