外观
RAG 系统的工作流程
Workflow of a RAG system
要搭建一套 RAG 系统,理解其中的基础组成部分以及它们之间如何交互至关重要。因此,在这一节,我们来逐一深入探讨每个环节。
下面是一个典型 RAG 架构的示意图:

我们来一步步拆解它。
我们从一些训练时没有见过的外部知识出发,希望用这些知识来增强 LLM:

#1)创建分块(chunk)
第一步是把这些额外的知识切分成一个个分块(chunk),然后再进行嵌入并存入向量数据库。

之所以这么做,是因为额外提供的文档可能相当庞大。因此,确保文本符合嵌入模型的输入尺寸限制非常重要。

此外,如果不做分块,整份文档就只会生成一个嵌入,这在检索相关上下文时几乎没有实际用处。
#2)生成嵌入
分块完成后,我们用嵌入模型对各个分块进行嵌入。

由于这些是「上下文嵌入模型」(而非词嵌入模型),像双编码器(bi-encoder)这类模型在这里非常适用。
#3)将嵌入存入向量数据库
这些嵌入随后会被存入向量数据库:

这说明向量数据库其实充当了 RAG 应用的「记忆」,因为我们正是把所有额外知识存放在这里,用户的查询最终就是靠这些知识来回答的。
向量数据库除了向量嵌入之外,还会存储元数据和原始内容。
到这一步,我们的向量数据库就已经创建完成,信息也已录入。如果需要,还可以继续往里添加更多信息。
现在,我们进入查询这一步。
#4)用户输入查询
接下来,用户输入一个查询——一段代表他们想要获取的信息的字符串。

#5)对查询做嵌入
这个查询会用我们在第 2 步中嵌入分块时所用的同一个嵌入模型,转化成一个向量。

#6)检索相似分块
接着,这个向量化后的查询会与数据库中已有的向量做比较,找出最相似的信息。

向量数据库会返回 k 个(一个预先设定的参数)最相似的文档/分块(使用近似最近邻搜索)。

我们期望这些被检索出来的文档包含与查询相关的信息,为最终生成回答提供依据。
#7)对分块重新排序
检索完成后,选出的分块可能还需要进一步优化,以确保最相关的信息被优先呈现。
在这一重排序步骤中,会有一个更复杂的模型(通常是交叉编码器 cross-encoder)对初步检索到的分块列表逐一结合查询进行评估,为每个分块打一个相关性分数。

这个过程会重新排列分块的顺序,让最相关的内容在生成回答时被优先使用。
不过,并不是每个 RAG 应用都会实现这一步;很多时候,它们只是依赖第 6 步中从向量数据库检索相关上下文时得到的相似度分数。
#8)生成最终回答
快完成了!
最相关的分块经过重排序之后,就会被送入 LLM。
该模型会把用户最初的查询和检索到的分块一起放进一个提示词模板中,生成一个综合了所选文档信息的回答。
如下图所示:

LLM 会利用这些分块提供的上下文,生成一个连贯、贴合上下文、并能直接回应用户查询的答案。
由于分块是任何 RAG 流程中的第一步,因此理解它有哪些不同的实现方式非常重要。