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

第一课:RAG到底是什么?

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

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

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

  • Retrieval:检索,查找资料
  • Generation:生成,让模型组织语言输出答案

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

为什么会有RAG

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

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

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

  1. 他不知道你的私有资料:你公司的内部文档、你的笔记、你的产品手册,这些内容本来就不在他的训练数据里。
  2. 他的知识可能过时:模型训练完成后,世界仍然在发展,新文档,新政策,新资料出现,他可能根本没见过
  3. 他可能回答会偏:这就是我们说的幻觉,明明不知道,但却一本正经乱说。

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

RAG像是开卷考试

不用 RAG 的大模型

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

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

用了 RAG 的大模型

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

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

所以先记一句:

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

RAG的知识库是什么?

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

第二课:RAG的完整流程

我们用一个例子来学:

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

系统会怎么做?

第一步:接收用户信息

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

系统这时知道两件事:

  1. 你想问的是病假
  2. 你想知道员工需要哪些材料

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

系统不会直接回答,而是先去知识库里查,知识库里可能有员工手册、请假制度、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页都扔给模型,会出现我们提到的问题:

  1. 太长:模型能接收的上下文是有限的,文档太长的话,可能根本塞不进去
  2. 太浪费:只是问病假材料,没必要把其他入职流程、报销制度等内容都丢给模型
  3. 干扰太多:无关的内容太多了,会影响模型的判断,导致抓错重点
  4. 不利于准确检索:你真正需要的是其中一小段,整篇一起整理不利于定位。

所以要先把大文档拆开。

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

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

  • 卡片 1:年假规则
  • 卡片 2:病假流程
  • 卡片 3:报销标准
  • 卡片 4:加班制度

当用户问"病假材料"时,

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

而不是抱着整本书乱翻。

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

chunk的本质作用是什么

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

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

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

chunk的大小怎么定

chunk太大

假设一个chunk很大,包含了

  • 病假制度
  • 年假制度
  • 婚假制度

这会导致:

  1. 信息太杂:虽然里面可能包含了正确答案,但也混入了很多无关内容
  2. 相似度可能被稀释:用户问病假,但这个块还有很多别的内容,系统未必能判断这个块是最相关的
  3. 给模型时容易啰嗦:我们交给模型的是检索到的资料与用户问题,但检索出来的资料噪音太大,模型输出也不好聚焦用户的问题。

因此chunk太大会让检索变钝

chunk太小

那是不是chunk越小越好?

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

原文:

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

如果切得太小,变成:

  • chunk A:员工请病假 1 天以上
  • chunk B:需提供医院证明
  • chunk C:并通过 OA 系统提交审批

这时就麻烦了:

  1. 语义不完整:每一小段单独看,语义都不全,相关性都不高
  2. 上下文断裂:系统可能只检索到需要医院提供证明,却不知道这是在讲病假
  3. 模型收到的信息不连贯:把需要提供医院证明交给模型,没有把OA系统提交审批交给模型,这就会导致模型输出的答案是残缺的。

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

最理想的chunk是怎样的

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

  1. 足够小:方便精确检索
  2. 足够完整:保留基本语义,不要切断一句话或一段完整的规则的意思
  3. 可以适当重复: 让相邻两个 chunk 有一部分重复内容 (overlap)

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

什么是overlap(重叠)

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

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

比如原文是:

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

切块时可能变成:

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

你看,

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

这样做的好处是:

  1. 减少边界信息丢失
  2. 让相邻块语义更连续
  3. 检索时不容易漏掉关键内容

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

先别记数字,先记住原则

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

  • chunk size 500
  • overlap 50
  • 1000 tokens
  • 200 characters

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

  1. chunk要能表达一个相对完整的小意思
  2. 不能太大,否则噪音多
  3. 不能太小,否则语义不完整
  4. 必要时要有overlap,避免边界丢失信息

简单的标准判断

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

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

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

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

第四课:Embedding是什么

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

先记住一句核心的话:

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

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

为什么需要Embedding

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

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

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

"提交"和"交"不是完全一样的

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

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

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

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

比如

  • "员工请病假需要提交医院证明"
  • "请病假要交什么材料"

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

  • 如果很接近,说明语义相似
  • 如果差很远,说明语义不相关

所以你可以把 Embedding 理解成:

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

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

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

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

在RAG里,Embedding用在哪里

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

  1. 先处理知识库里的chunk:把每个chunk都做一次Embedding,也就是把每个chunk变成一个向量
  2. 把这些向量存起来:存到向量库或者检索系统里。
  3. 用户来提问时:把用户的问题也做一次Embedding
  4. 比较问题向量与各个chunk向量:看看哪个chunk与问题最接近
  5. 取出最相关的几个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流程里处于哪里

现在我们把流程串起来

离线准备阶段

先做这些事:

  1. 拿到文档
  2. 切chunk
  3. 每个chunk做Embedding
  4. 把chunk和向量存到向量库里

这是建库过程

在线问答阶段

用户提问时:

  1. 用户问题做Embedding
  2. 去向量库里找最相似的chunk
  3. 返回top-k结果
  4. 把这些结果交给大模型生成答案

所以你现在可以看到:

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会省去很多步骤,连知识库文档这块都是简单生成的,你没有自己亲自上手文档清洗,你无法理解每一步的重要性。

我极力推荐同学们可以参照 datawhale的https://github.com/datawhalechina/all-in-rag来动手学习,有了简单的入门,再去看他的教学会快速很多,一步步跟着做的时候,也能记得每个概念的意思。

相关推荐
小小小怪兽1 小时前
🏇Harness Engineer
agent
_YiFei1 小时前
实测零感AI、嘎嘎降AI和SpeedAI的降论文AI率效果!哪个工具网站更好用性价比更高?
人工智能
星爷AG I1 小时前
14-8 姿势控制:移动(AGI基础理论)
人工智能·agi
雪碧聊技术1 小时前
AI时代的“炼金术士”:当“抽卡师”成为内容生产的新兴职业
人工智能·aigc·ai抽卡师
云飞云共享云桌面1 小时前
SolidWorks云电脑如何多人共享访问?
运维·服务器·人工智能·3d·自动化·云计算·电脑
零千叶1 小时前
养龙虾,本地部署OpenClaw
人工智能·macos·openclaw
吴佳浩 Alben1 小时前
大模型垂直领域微调系列(二):ms-swift 框架全景
人工智能·语言模型·transformer
bst@微胖子2 小时前
OpenCV 案例三【人脸比对】
人工智能·opencv·计算机视觉