为什么需要RAG
我们常说的大模型实际上说的是语言生成模型,语言生成模型是基于语言模型的,而语言模型又是属于生成模型的分支。
生成模型需要一些数据物料去喂养,也就是训练,语言的生成模型(比如GPT-4、文心一言的 “文本生成模块”)训练的数据就是文本数据。视频图片的生成模型训练的数据就是视频和图片了对吧。
数据的来源五花八门,比如互联网内容和现存的书籍绘画等。前一阵子还有个模型厂商盗取成人网站的视频来训练模型,原因是市面上流通的关于人的裸体的素材太少,而成人网站的人体素材不但数量大,而且质量高,非常有利于模型训练。
模型训练是有截止日期的,模型只知道训练截止日期以内的信息。
比如模型训练的截止日期为2016年9月,你询问模型美国总统是谁,他会回答是奥巴马,而不是现任的总统。
可以询问模型的训练截止日期,以下deepseek为例。
所以,如果想要大模型根据指定内容回答问题并减少幻觉时,就需要RAG
大模型幻觉:通俗来说就是大模型胡说八道。
大家应该都见过大模型一门正经的胡说八道时的样子。
这一点和MCP非常像,因为本质上MCP和RAG都是延伸模型能力的技术手段,但MCP的形式上是一种数据接入协议,而RAG在形式上是一种应用架构模式。
RAG简介
RAG(Retrieval-Augmented Generation, RAG)又称检索增强生成,是一种结合 “外部知识检索” 与 “大语言模型生成” 的技术范式,也就是让 LLM 在回答问题前,先主动从外部知识库中 “查资料”,再基于检索到的真实、精准信息生成回答,而非仅依赖模型自身的 “记忆”。
检索增强是啥?
在初级阶段,可以把检索增强理解成“智能搜索”。
和传统搜索有什么区别?
传统的搜索的流程是,把标量数据先存储到sql数据库,之后可以根据sql语句查询出对应数据。
同时也支持模糊搜索
产生的问题:
搜索格式过于严格,不能搜索近似的数据,因为有的时候我们的搜索场景并不严肃(比如我只想“找出所有的狗”),不需要毫厘不差的数据,只要类似的数据,那么就需要向量数据库了。
什么是向量数据库?
需要先了解向量和相似度的关系
向量:
[1.0, 0.8] 就是一个向量,集合中的每一个数字就是一个维度,代表事物的一个 “特征”。
现在,为老狗、小狗、狗、石头模拟计算相似度,以了解向量和相似度的关系:
第一步:定义2个核心维度(特征)
生物属性
: 区分有机生命体和非生命体。
成熟度
: 结合了年龄和体型大小的概念。
1.0
= 完全成熟/年老/大
0.5
= 成年/中性
0.0
= 出生
第二步:为每个概念在维度上打分
概念 | 生物属性 | 成熟度 | 2维向量 |
---|
小狗 | 1.0 (是生物) | 0.3 (年轻/小) | [1.0, 0.3] |
老狗 | 1.0 (是生物) | 1.0 (年老/大) | [1.0, 1.0] |
狗 | 1.0 (是生物) | 0.6 (成年/中等) | [1.0, 0.6] |
石头 | 0.0 (非生物) | 0.8 (古老/中性) | [0.0, 0.8] |
第三步:通过平面直角坐标系确定他们的位置,使用余弦值确定相似度
上图中,如果想要对比两个事物的相似度是多少,可以使用两个事物之间的夹角(余弦)大小来确定,夹角越小,表示相似度越高,比如,小狗和狗的夹角,比石头和狗的夹角小得多,所以小狗和狗的相似度比石头和狗的相似度高。
不过相似度还是需要确定的值来表示,不能靠肉眼来观察。
已知两个n维向量:
A=[a1,a2,…,an],B=[b1,b2,…,bn] ,其夹角的余弦相似度计算公式为:
cos(θ)=∥A∥×∥B∥A⋅B=∑i=1nai2×∑i=1nbi2∑i=1naibi
对于二维向量
A=[a1,a2] 和
B=[b1,b2],其夹角的余弦相似度计算公式为:
cos(θ)=∥A∥×∥B∥A⋅B=a12+a22×b12+b22a1b1+a2b2
计算余弦相似度步骤:(以“小狗”和“狗”为例)
- 小狗 (A) =
[1.0, 0.3]
- 狗 (B) =
[1.0, 0.6]
第1步:计算点积 A · B
点积 = (对应分量相乘再相加)
A⋅B=(1.0×1.0)+(0.3×0.6)=1.8
第2步:计算每个向量的模 (||A||, ||B||)
模 = (所有分量的平方和开根号)
∥A∥=1.02+0.32=1+0.09=1.09≈1.044
∥B∥=1.02+0.62=1+0.36=1.36≈1.166
第3步:代入公式计算余弦相似度
cos(θ)=∥A∥×∥B∥A⋅B=1.044×1.1661.8=1.2171.8=0.969
所以,“小狗”和“狗”的余弦相似度是 0.969。
最后得出结果:
对比对象 | 余弦相似度 |
---|
狗 vs 小狗 | 0.969 |
狗 vs 老狗 | 0.969 |
狗 vs 石头 | 0.514 |
通过上面的案例可以发现,在确定相似度的过程中,
是两个让人头疼的工作,好在有现成的工具能帮我们处理。
制定多少个维度,维度的值为多少
现在很多模型厂商对外开放了 Embedding 的接口,它的作用就是把一段文本处理成多维的向量数据,一般默认转化为1024维度,也就是1024个特征,维度越高,检索的相似度相对来说越准确。
现在有很多集成多家模型的门户平台,以下为某平台部分Embedding的接口。
使用方法也比较简单,请求 Embedding 的接口是带上你申请的key和要转化的文本就可以了,下面的实战会提到,非常简单。
那么,向量数据库就是专门存储这些向量数据的仓库,但不止如此,它还能使用算法帮你快速从向量数据中检索出相似度最高的前N条数据。
向量数据库的存储方式如下图:
如果想要在向量数据库中检索出与指定文本相似的数据,需要先把指定文件Embedding向量化,然后就可以从向量数据库中检索出得分最高的前N条数据。N可以自己指定。
公司在使用的向量数据库为 Milvus,目前还没人抱怨什么,应该还算靠谱,我自己在使用的是 Qdrant ,因为对node比较友好,使用起来也方便,还支持自动排序。
RAG 经典应用架构
网上流传的叫法就是经典RAG,到底经不经典还得你自己体会。
前置数据存储流程如下图:
-
拆分文本:把文本数据拆分成chunk是有一些方法论的,比如一般200到300个字符拆分一段,拆分时,chunk的头部需要和前一段的结尾有一些重复,尾部需要和后一段的前部有重复,目的是防止段落分割语义太割裂,LangChain 就有类似的工具方法。
-
Embedding:把拆分的chunk向量化,这一步有现成接口比较简单。
-
组装数据:这一步就需要结合业务来做了,把需要和chunk关联的关键数据组合到一起存储。
RAG整体工作流程如下图:
-
首先,客户端发送 “找出所有的狗” 这一请求到服务端。
-
接着,服务端借助 Embedding 技术,将该请求数据转化为向量数据。
-
随后,用此向量数据在向量数据库中进行检索,从数据库里召回相关数据,这些数据包含不同 chunk及对应的 score(匹配分数)。
-
之后,把召回的数据组装成 Prompt,Prompt 里包含数据、问题 “找出所有的狗” 以及回答要求。
-
最后,语言模型依据这个 Prompt 生成回复,再由服务端将回复返回给客户端。
总结
理论说完了,流程就是这么个流程,也不能难理解。但看似很美好,实践时却处处是坑,有很多需要细化、优化的点,后续会使用nestjs开发一个简易版的RAG应用,以便验证。
最后编辑于:2025-09-26 16:35:28
©著作权归作者所有,转载或内容合作请联系作者。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,little笔记系信息发布平台,仅提供信息存储服务。