1 引言
1.1 什么是RAG
在上一节,我们成功搭建了一个源大模型智能对话Demo,亲身体验到了大模型出色的能力。然而,在实际业务场景中,通用的基础大模型可能存在无法满足我们需求的情况,主要有以下几方面原因:
-
知识局限性:大模型的知识来源于训练数据,而这些数据主要来自于互联网上已经公开的资源,对于一些实时性的或者非公开的,由于大模型没有获取到相关数据,这部分知识也就无法被掌握。
-
数据安全性:为了使得大模型能够具备相应的知识,就需要将数据纳入到训练集进行训练。然而,对于企业来说,数据的安全性至关重要,任何形式的数据泄露都可能对企业构成致命的威胁。
-
大模型幻觉:由于大模型是基于概率统计进行构建的,其输出本质上是一系列数值运算。因此,有时会出现模型“一本正经地胡说八道”的情况,尤其是在大模型不具备的知识或不擅长的场景中。
为了上述这些问题,研究人员提出了检索增强生成(Retrieval Augmented Generation, RAG)的方法。这种方法通过引入外部知识,使大模型能够生成准确且符合上下文的答案,同时能够减少模型幻觉的出现。
由于RAG简单有效,它已经成为主流的大模型应用方案之一。
如下图所示,RAG通常包括以下三个基本步骤:
-
索引:将文档库分割成较短的 Chunk,即文本块或文档片段,然后构建成向量索引。
-
检索:计算问题和 Chunks 的相似度,检索出若干个相关的 Chunk。
-
生成:将检索到的Chunks作为背景信息,生成问题的回答。
1.2 一个完整的RAG链路
(图片来源:https://github.com/netease-youdao/QAnything)
从上图可以看到,线上接收到用户query
后,RAG会先进行检索,然后将检索到的 Chunks
和 query
一并输入到大模型,进而回答用户的问题。
为了完成检索,需要离线将文档(ppt、word、pdf等)经过解析、切割甚至OCR转写,然后进行向量化存入数据库中。
接下来,我们将分别介绍离线计算和在线计算流程。
1.2.1 离线计算
首先,知识库中包含了多种类型的文件,如pdf、word、ppt等,这些 文档
(Documents)需要提前被解析,然后切割成若干个较短的 Chunk
,并且进行清洗和去重。
由于知识库中知识的数量和质量决定了RAG的效果,因此这是非常关键且必不可少的环节。
然后,我们会将知识库中的所有 Chunk
都转成向量,这一步也称为 向量化
(Vectorization)或者 索引
(Indexing)。
向量化
需要事先构建一个 向量模型
(Embedding Model),它的作用就是将一段 Chunk
转成 向量
(Embedding)。如下图所示:
一个好的向量模型,会使得具有相同语义的文本的向量表示在语义空间中的距离会比较近,而语义不同的文本在语义空间中的距离会比较远。
由于知识库中的所有 Chunk
都需要进行 向量化
,这会使得计算量非常大,因此这一过程通常是离线完成的。
随着新知识的不断存储,向量的数量也会不断增加。这就需要将这些向量存储到 数据库
(DataBase)中进行管理,例如 Milvus 中。
至此,离线计算就完成了。
1.2.2 在线计算
在实际使用RAG系统时,当给定一条用户 查询
(Query),需要先从知识库中找到所需的知识,这一步称为 检索
(Retrieval)。
在 检索
过程中,用户查询首先会经过向量模型得到相应的向量,然后与 数据库
中所有 Chunk
的向量计算相似度,最简单的例如 余弦相似度
,然后得到最相近的一系列 Chunk
。
由于向量相似度的计算过程需要一定的时间,尤其是 数据库
非常大的时候。
这时,可以在检索之前进行 召回
(Recall),即从 数据库
中快速获得大量大概率相关的 Chunk
,然后只有这些 Chunk
会参与计算向量相似度。这样,计算的复杂度就从整个知识库降到了非常低。
召回
步骤不要求非常高的准确性,因此通常采用简单的基于字符串的匹配算法。由于这些算法不需要任何模型,速度会非常快,常用的算法有 TF-IDF
,BM25
等。
另外,也有很多工作致力于实现更快的 向量检索
,例如 faiss,annoy。
另一方面,人们发现,随着知识库的增大,除了检索的速度变慢外,检索的效果也会出现退化,如下图中绿线所示:
(图片来源:https://github.com/netease-youdao/QAnything)
这是由于 向量模型