既然我们已经介绍了RAG、文本分块和嵌入的基础知识,现在让我们逐步走一遍完整的RAG流程。这个详细的示例将向您展示在实际实现中所有部分是如何组合在一起的。
第1步:对源文本进行分块
首先,我们获取源文档并将其分解为可管理的块。在这个示例中,我们将使用两个简单的文本部分:
- 第1部分:医学研究 - "今年我们对XDR-47有了重大进展的理解,这是一种我们以前从未见过的'bug'。"
- 第2部分:软件工程 - "该部门投入了大量精力研究我们分布式系统中的各种感染途径"
第2步:生成嵌入
接下来,我们将每个文本块转换为数值嵌入。为了让这个概念更清晰,让我们假设我们有一个完美的嵌入模型,它总是返回恰好两个数字,并且我们知道每个数字代表什么:

在我们假想的模型中:
- 第一个数字:文本在多大程度上谈论医学领域
- 第二个数字:文本在多大程度上谈论软件工程
所以我们的医学研究部分得到的嵌入是[0.97, 0.34] - 非常医学化,由于"bug"这个词,也有一些软件相关性。软件工程部分得到[0.30, 0.97] - 非常注重软件,但"感染途径"带有医学含义。
归一化
在存储这些嵌入之前,它们会经过一个归一化过程,将每个向量缩放到幅度为1.0。这通常由您的嵌入API自动处理,但了解这一过程的发生是很重要的。

归一化后,我们的嵌入变为[0.944, 0.331]和[0.295, 0.955]。我们可以在单位圆上可视化这些点,每个点恰好位于圆的边缘上。

第3步:存储到向量数据库
归一化后的嵌入被存储在向量数据库中——这是一种专门优化用于存储、比较和搜索像我们的嵌入这样的长数字列表的数据库。

此时,我们暂停一下。到目前为止所做的所有工作都是提前进行的预处理。现在我们等待用户提交查询。
第4步:处理用户查询
当用户提出类似"我对这家公司很感兴趣。特别是,软件工程部门今年做了什么?"这样的问题时,我们将他们的查询通过相同的嵌入模型运行。

这个查询被嵌入为[0.1, 0.89] - 医学分数低,软件工程分数高。归一化后,它变为[0.112, 0.993]。
第5步:查找相似的嵌入
现在我们向向量数据库询问:"找到与这个用户查询嵌入最接近的存储嵌入。"数据库返回软件工程部分,因为它是最相似的。

相似度的工作原理:余弦相似度
向量数据库使用余弦相似度来确定哪些嵌入最相似。这衡量的是两个向量之间角度的余弦值。

关于余弦相似度的关键点:
- 结果范围从-1到1
- 接近1的值表示非常相似
- 接近0的值表示垂直(不相关)
- 接近-1的值表示完全相反
计算使用点积公式:cos(a) = (A · B) / (||A|| · ||B||)

在我们的示例中,用户查询与软件工程块的余弦相似度为0.983,而与医学研究块的余弦相似度仅为0.398。软件工程块显然是更好的匹配。
余弦距离
您会经常在向量数据库文档中看到"余弦距离"。这简单地就是1 - 余弦相似度,它给我们一个更容易解释的数字,其中:
- 接近0的值表示高相似度
- 较大的值表示较低的相似度
第6步:构建最终提示
最后,我们获取用户的问题和我们找到的最相关的文本块,然后将它们组合成一个给Claude的提示:

该提示包括用户的问题和我们文档中的相关上下文,使Claude能够根据知识库中的特定信息提供有根据的答案。
完整流程
这就是从头到尾的整个RAG流程:
- 对源文档进行分块
- 为每个块生成嵌入
- 将嵌入存储在向量数据库中
- 当用户提出问题时,嵌入他们的查询
- 使用余弦相似度找到最相似的存储嵌入
- 将相关块添加到带有用户问题的提示中
- 将增强后的提示发送给Claude以获得响应
理解这个过程及其背后的数学原理将帮助您有效地使用向量数据库,并在您的RAG系统没有返回预期结果时调试问题。