Appearance
RAG 是什么
定义
RAG 是 Retrieval-Augmented Generation 的缩写,中文通常翻译为 检索增强生成。
如果只用一句话总结:
RAG 是先从外部知识源中检索与当前问题相关的信息,再把这些信息提供给模型,让模型基于它们生成回答。
最简单的流程可以表示成:
text
用户问题
↓
检索相关资料
↓
把资料交给模型
↓
生成回答这里最重要的一点是:
模型不是只依赖自己训练时学到的知识,而是在回答之前先获取一部分外部信息。
例如用户问:
公司出差住宿标准是多少?
大模型本身一般都不知道具体某家公司的内部制度。
RAG 系统会先去公司知识库里找到相关规定,再把这部分内容和用户问题一起交给模型。
于是模型回答时依据的不再只是自己的通用知识,而是刚刚检索到的公司资料。
这就是 RAG 最核心的思路。
为什么需要 RAG
大语言模型已经学习了大量知识,但它仍然不可能知道所有信息。
尤其是下面这些内容:
- 企业内部文档
- 私有项目资料
- 最新更新的产品文档
- 公司制度
- 内部 FAQ
- 大量专业或长尾资料
这些信息可能根本没有出现在模型训练数据里。
即使出现过,也可能已经发生变化。
例如一家公司今年刚修改了报销制度。
模型训练时不可能提前知道这次更新。
如果直接问:
现在差旅住宿标准是多少?
模型可能不知道,也可能根据通用经验生成一个看起来合理但实际错误的答案。
RAG 的思路不是要求模型重新训练,而是:
text
用户提问
↓
先去查最新制度
↓
找到相关内容
↓
再让模型回答这样知识更新以后,只需要更新知识库。
模型本身不一定需要发生变化。
可能有同学问:
既然模型需要这些资料,为什么不直接把所有文档都放进 Prompt?
理论上,在资料很少时确实可以这么做。
但当文档越来越多以后,很快会遇到一些问题。
例如一个企业知识库可能包含:
text
产品文档
公司制度
技术手册
客服 FAQ
项目资料
培训资料
历史公告
……用户只是问:
年假怎么申请?
模型真正需要的可能只是《员工休假管理制度》里的几个段落。
如果每次都把整个知识库全部交给模型,会带来很多没有必要的信息。
这些无关内容不仅增加上下文长度和成本,也可能干扰模型判断。
所以合理的方式应该是:
text
大量知识
↓
先检索
↓
找出最相关的一小部分
↓
交给模型模型真正需要的通常不是:
所有知识。
而是:
当前问题最相关的知识。
这也是 RAG 存在的重要原因。
一个最小 RAG 长什么样
假设现在要做一个公司内部知识库。
知识库里有一份文档:
text
《差旅费用管理办法》其中写着公司的住宿、交通和报销规定。
现在员工提出一个问题:
北京出差的住宿标准是多少?
如果直接把问题交给模型:
text
用户问题
↓
LLM
↓
回答模型可能根本不知道这家公司的具体规定。
加入 RAG 以后,流程会变成:
text
用户问题
↓
检索公司知识库
↓
找到《差旅费用管理办法》
↓
找到住宿标准相关段落
↓
问题 + 相关段落
↓
LLM
↓
生成回答例如系统最后实际交给模型的内容可能类似:
text
用户问题:
北京出差的住宿标准是多少?
参考资料:
《差旅费用管理办法》
北京地区普通员工住宿标准不超过 500 元 / 晚,
部门负责人不超过 650 元 / 晚。
请根据参考资料回答用户问题。模型这时候就可以生成:
北京地区普通员工住宿标准不超过 500 元 / 晚,部门负责人不超过 650 元 / 晚。
如果系统支持引用,还可以告诉用户:
来源:《差旅费用管理办法》
这里有一个非常重要的认识:
模型并没有因为 RAG 而突然“学会”这份公司制度。
它只是:
在回答当前问题时,临时拿到了相关资料。
下一次公司更新制度,只要知识库里的资料同步更新,后续检索到的内容也可以随之变化。
RAG 是怎么运行的
一个完整的 RAG 系统一般可以分成两个阶段:
text
准备知识库
+
用户提问后的检索与生成也可以简单理解成:
text
离线准备
+
在线回答整体流程大致如下:
text
原始文档
↓
解析
↓
切片
↓
建立索引
↓
知识库
用户问题
↓
检索相关内容
↓
组织上下文
↓
LLM
↓
生成回答准备知识库
RAG 首先要有可以检索的知识来源。
例如:
- Word 文档
- Markdown
- 网页
- 产品文档
- FAQ
- 公司制度
- 数据库中的文本资料
这些原始资料通常不能直接拿来检索,需要先经过处理。
文档解析
第一步通常是把原始文件转换成可以处理的文本内容。
例如:
text
PDF
↓
提取文字
↓
得到正文或者:
text
网页
↓
提取主要内容
↓
去掉导航、广告等无关信息不同文件类型的解析方式可能不同,但目标基本一致:
把原始资料变成后续可以检索的内容。
文本切片
文档解析以后,通常不会把整篇文档作为一个检索单位。
例如一份 100 页的产品手册,如果用户只是问:
怎么重置密码?
真正相关的可能只有其中两三个段落。
所以通常需要把长文档拆成更小的文本片段。
这些片段一般被称为:
Chunk。
例如原始文档:
text
《员工管理制度》
第一章 入职
第二章 考勤
第三章 请假
第四章 差旅
第五章 离职系统可能进一步切成:
text
Chunk 1:入职流程
Chunk 2:试用期规定
Chunk 3:考勤规则
Chunk 4:年假申请
Chunk 5:病假规定
Chunk 6:差旅住宿标准
……以后用户问年假时,就不需要把整份《员工管理制度》交给模型。
只需要找到:
text
Chunk 4:年假申请即可。
所以切片的目的很简单:
让后面的检索更加精确。
建立索引
文档切片以后,还需要让系统能够快速找到相关 Chunk。
因此通常要为这些内容建立索引。
最常见的做法之一是使用 Embedding。
Embedding 可以把文本转换成一组数字表示。
例如:
text
"如何申请年假"
↓
Embedding Model
↓
[0.12, -0.35, 0.81, ...]文档 Chunk 也可以做同样的处理。
以后用户提出一个问题时,系统可以比较问题和不同 Chunk 之间的语义相关程度,找出最接近的内容。
这些向量经常会被保存到向量数据库中。
不过需要注意:
RAG 并不等于向量数据库。
检索知识时可以使用很多方法,例如:
- 关键词检索
- 全文检索
- 向量检索
- 语义检索
- Hybrid Search
具体使用哪一种,要根据实际场景决定。
我们只需要先记住:
建立索引的目的,就是让系统以后能够快速找到和问题相关的资料。
整个知识库准备过程可以先理解成:
text
原始文档
↓
解析
↓
Chunk
↓
建立索引
↓
可检索知识库检索并生成回答
知识库准备完成以后,用户就可以开始提问。
例如:
员工一年有多少天年假?
系统首先不会直接调用 LLM。
而是先进入 Retrieval,也就是检索阶段。
Retrieval:检索
系统会根据用户问题,在知识库中查找相关 Chunk。
例如:
text
用户问题:
员工一年有多少天年假?系统可能找到:
text
Chunk A:
正式员工工作满一年后,每年享受 5 天带薪年假。
Chunk B:
工作满 10 年后,年假调整为 10 天。
Chunk C:
年假需要提前三个工作日提交申请。这些内容就是当前问题的候选资料。
有时第一次检索出来的内容并不一定完全准确。
所以真实系统里还可能继续进行:
- 过滤
- 排序
- 去重
- 重排
目的都是一样的:
尽量把真正相关的信息留下来。
例如最终只保留:
text
正式员工工作满一年后,每年享受 5 天带薪年假。
工作满 10 年后,年假调整为 10 天。Augmented:增强上下文
检索到资料以后,系统会把这些内容加入模型的输入。
例如:
text
问题:
员工一年有多少天年假?
参考资料:
1. 正式员工工作满一年后,每年享受 5 天带薪年假。
2. 工作满 10 年后,年假调整为 10 天。
请基于参考资料回答问题。这里的“增强”,就是:
用外部资料补充模型当前的上下文。
所以 Retrieval-Augmented Generation 里的 Augmented,并不是修改模型本身。
而是给模型增加新的上下文。
Generation:生成
最后才进入真正的生成阶段。
模型根据:
text
用户问题
+
检索到的资料生成最终回答。
例如:
正式员工工作满一年后,每年享受 5 天带薪年假;工作满 10 年后,年假调整为 10 天。
如果系统保留了文档来源,还可以继续返回引用:
text
来源:《员工休假管理制度》所以整个在线流程可以压缩成:
text
用户问题
↓
Retrieval
检索相关资料
↓
Augmented
补充模型上下文
↓
Generation
生成回答这也是 RAG 这个名字最直接的理解方式:
Retrieval → Augmented → Generation
RAG 适合什么任务
RAG 最典型的使用场景,是:
模型回答问题时,需要依赖大量外部知识。
企业知识库
例如员工询问:
text
报销制度
请假规则
产品资料
销售政策
内部流程这些信息通常属于企业私有知识。
大模型本身并不知道。
通过 RAG,可以让模型先检索企业内部资料,再生成回答。
产品文档问答
例如一个开发平台有几千页文档。
用户询问:
API Key 怎么创建?
系统可以:
text
用户问题
↓
检索 API 文档
↓
找到相关章节
↓
生成回答这样就不需要每次把全部产品文档交给模型。
客服知识问答
客服场景中通常有大量:
- FAQ
- 售后政策
- 产品说明
- 常见故障
- 服务流程
用户提问以后,可以先检索这些资料,再生成回复。
例如:
text
怎么申请退款?
↓
检索退款政策
↓
找到对应规则
↓
生成回答专业资料辅助
RAG 也很适合处理大量专业文档。
例如:
- 技术资料
- 法律资料
- 项目文档
- 研究资料
- 行业报告
这类场景通常都有一个共同特点:
知识很多,而且模型不一定天然知道。
综合来看,RAG 比较适合下面这些任务:
- 回答依赖外部知识
- 知识量比较大
- 知识可能持续更新
- 模型训练时不知道这些内容
- 希望回答尽量基于明确资料
- 希望能够保留引用来源
所以判断一个场景是否适合 RAG 时,可以先问一个非常简单的问题:
当前问题的主要瓶颈,是不是“模型缺少相关知识”?
如果答案是“是”,那么 RAG 通常就是一个值得优先考虑的方向。
总结
RAG 的全称是:
Retrieval-Augmented Generation
也就是:
检索增强生成。
它最核心的思路非常简单:
模型回答之前,先去外部知识源中找到与当前问题相关的资料。
一个最小的 RAG 可以表示成:
text
用户问题
↓
检索资料
↓
补充上下文
↓
LLM
↓
生成回答如果再把知识库准备过程加进来:
text
原始文档
↓
解析
↓
切片
↓
建立索引
↓
知识库
用户问题
↓
检索
↓
组织上下文
↓
LLM
↓
生成回答其中:
- 文档解析负责得到可处理的内容
- Chunk 负责把长文档拆成更合适的检索单位
- 索引负责帮助系统快速找到相关内容
- Retrieval 负责找到资料
- Augmented 负责把资料加入模型上下文
- Generation 负责生成最终回答
所以理解 RAG 时,不需要一开始就被向量数据库、Embedding、Rerank 等术语绕进去。
先记住最基本的一句话:
RAG 的核心,就是让模型在回答之前先拿到当前问题真正需要的知识。
关键就在于,如何找到这些知识,这个就尤为重要,我们后续在RAG栏目再深入讲解。