点击上方“AI公园”,关注公众号,选择加“星标“或“置顶”
作者:Vipra Singh
编译:ronghuaiyang
在系列博客中,我们通过检索增强生成(RAG)应用的视角来学习大规模语言模型(LLM)。
1. 引言
在之前的博文中,我们已经讨论到将原始数据嵌入为向量的内容。为了重复利用嵌入的信息,我们需要存储这些嵌入,以便按需访问。为此,我们使用一种特殊的数据库,即向量数据库。
对于使用检索增强生成(RAG)的大规模应用来说,高效存储和检索向量的能力,包括增删改查操作、元数据过滤以及水平扩展,都是至关重要的。像ChromaDB、Pinecone和Weaviate这样的向量数据库专门针对这些需求,提供了快速检索和相似性搜索功能。
集成合适的向量数据库对于最大化RAG性能至关重要。根据应用场景的具体需求深思熟虑地选择,可以确保存储和检索的无缝衔接,从而优化检索增强生成模型的效能。
在本篇博文中,我们将深入探讨向量数据库与索引方法。
2. 向量数据库 Vs. 其他数据库
在科技行业中,一个普遍存在的误解认为向量数据库仅仅是近似最近邻(Approximate Nearest Neighbor, ANN)搜索算法的简单包装。
实际上,向量数据库是一种针对非结构化数据的综合性解决方案。与这种误解相反,它包含了现代结构化/半结构化数据库管理系统中常见的用户友好特性,包括云原生支持、多租户能力和可扩展性。它解决了独立向量索引的局限性,应对了可扩展性挑战、集成复杂性,以及缺乏实时更新和内置安全措施的问题。随着本教程的深入,这一点将变得越来越明显。
另一方面,像FAISS和ScaNN这样的轻量级ANN库充当构建向量索引的工具。这些库旨在加速多维向量的最近邻搜索。虽然它们适用于生产系统中的小型数据集,但随着数据集的增长,可扩展性就成了一个挑战。
4.1. 向量数据库是如何工作的?
众所周知,传统数据库以行和列的形式存储字符串、数字和其他类型的标量数据。相比之下,向量数据库则处理向量,因此它的优化和查询方式大相径庭。
在传统数据库中,我们通常查询的是数据库中与查询值完全匹配的行。而在向量数据库中,我们应用相似度度量来寻找与查询向量最相似的向量。
向量数据库使用了多种参与近似最近邻(ANN)搜索的不同算法组合。这些算法通过各种索引技术优化搜索过程。
这些算法被组装成一个管道,以提供对查询向量邻居的快速且准确的检索。由于向量数据库提供的结果是近似的,我们主要考虑的权衡是在准确性和速度之间。结果越准确,查询速度就越慢。然而,一个良好的系统可以在近乎完美的准确性下提供超快速的搜索。
以下是向量数据库的一个常见处理流程:
在接下来的部分中,我们将更详细地讨论这些算法,并解释它们是如何共同作用于提升向量数据库的整体性能的。
基于树的方法 在低维数据中效率高,能够提供精确的最近邻搜索。然而,由于“维度灾难”的影响,它们在高维空间中的性能通常会下降。此外,这类方法需要大量内存,并且在处理大型数据集时效率较低,导致较长的构建时间和更高的延迟。
量化方法 内存效率高,通过将向量压缩为紧凑的编码来提供快速的搜索时间。但是,这种压缩可能会导致信息损失,潜在地降低了搜索准确性。此外,这些方法在训练阶段可能会计算密集,增加了构建时间。
哈希方法 速度快且相对内存效率高,将相似向量映射到相同的哈希桶中。它们在处理高维数据和大规模数据集时表现良好,提供了高吞吐量;然而,由于哈希碰撞导致的误报和漏报,搜索结果的质量可能较低。选择合适的哈希函数数量和哈希表数量至关重要,因为它们显著影响性能。
聚类方法 可以通过缩小搜索空间到特定聚类来加速搜索操作,但搜索结果的准确性会受到聚类质量的影响。聚类通常是批量处理过程,这意味着它不适合动态数据,其中不断有新向量加入,导致频繁的重新索引。
图方法 在准确性和速度之间提供了良好的平衡。它们在处理高维数据时效率高,可以提供高质量的搜索结果。然而,它们可能对内存要求较高,因为需要存储图结构,并且图的构建也可能计算成本高昂。
向量数据库中算法的选择取决于任务的具体需求,包括数据集的大小和维度、可用的计算资源,以及在准确性和效率之间的可接受权衡。同时,值得注意的是,许多现代向量数据库采用混合方法,结合不同方法的优点以实现高速度和高准确性。理解和权衡这些算法对于任何希望从向量数据库中获得最佳性能的人来说至关重要。接下来,我们将逐一探讨这些类别中所有流行的算法。
我们首先应考察的索引是最简单的——扁平索引。
扁平索引之所以称为“扁平”,是因为我们不对输入的向量做任何修改。
由于不对向量进行近似或聚类处理——这些索引能够产生最准确的结果。我们获得了完美的搜索质量,但这是以显著增加的搜索时间为代价的。
在使用扁平索引时,我们引入查询向量xq,并将它与索引中每一个全尺寸向量进行比较,计算到每个向量的距离。
计算完所有这些距离之后,我们返回距离最近的k个作为最近邻匹配,这就是k近邻(kNN)搜索。
6.2. 平衡搜索时间
扁平索引在准确性方面表现出色,但搜索速度极慢。在相似性搜索中,搜索速度和搜索质量(准确性)之间总是存在权衡。
我们必须做的是确定我们的用例最佳平衡点位于何处。使用扁平索引时,我们处于这样的状态:
这里我们的搜索速度未经过优化,这可能适用于许多较小索引的使用场景,或者在搜索时间无关紧要的情况下。但其他应用场景需要在速度和质量之间取得更好的平衡。
那么,我们如何加快搜索速度呢?主要有两种方法:
采用上述任一方法意味着我们不再执行全面的最近邻搜索,而是执行近似最近邻(ANN)搜索,因为我们不再遍历整个高分辨率数据集。
因此,我们得到的是一个更均衡的组合,既重视搜索速度也考虑到了搜索时间:
在向量数据库中使用的基于树的算法中,Annoy(或称“Approximate Nearest Neighbors Oh Yeah”)以其高效性和简洁性脱颖而出。Annoy是一个C++库,带有Python绑定,由Spotify设计,用于在空间中查找与给定查询点接近的点(近似匹配)。它创建大型只读、基于文件的数据结构,这些结构通过内存映射进入内存,使得多个进程可以共享相同的数据。
Annoy通过使用随机投影树的森林来进行高效的ANN搜索。算法将点投射到随机超平面上,并根据点落在超平面的哪一侧来划分空间。这一过程递归进行,形成了空间分区的二叉树。创建了一个森林,每棵树都有不同的随机种子。当收到查询点时,算法遍历森林中的每棵树,找到该点所属的叶节点。然后通过收集所有树中找到的叶节点中的点列表,并从这个列表中返回与查询点最近的前k个点,来近似最近邻。
Annoy特别适合高维数据,因为在高维数据中,精确的最近邻搜索可能成本过高。它在Spotify的音乐推荐中投入生产使用,根据音频特征帮助找到相似歌曲。因此,准确性会受到森林中树的数量以及搜索过程中检查的点数的影响,这两者都可以根据任务的具体需求进行调整和优化。
Annoy的高效性和内存效率使其成为处理高维数据和大型数据库的强大选择。但也有一些权衡需要考虑。构建索引可能需要大量时间,特别是对于大型数据集而言。由于Annoy使用随机森林分区算法,索引不能随着新数据的加入而更新,必须从头重建。根据你的数据集大小或数据变化的频率,重新训练索引可能成本高昂。
7.2. 逆文档(IVF)索引
IVF(Inverted File Index)索引通过聚类来减少搜索范围。它非常受欢迎,因为易于使用,同时提供高搜索质量和合理的搜索速度。
它基于Voronoi图的概念运作——也被称为Dirichlet镶嵌(一个听起来更酷的名字)。
为了理解Voronoi图,我们可以想象将高维向量投射到二维空间中。随后在我们的二维空间中放置几个额外的点,这些点将成为我们的“聚类中心”(在此情况下为Voronoi单元)。
接着,从每个中心点向外延伸相同半径的圆。在某个点上,每个圆的周长会与其他圆相交——这样就形成了我们的单元边界:
现在,每个数据点都将被包含在一个单元内,并被分配给相应的中心点。
和使用其他索引一样,我们引入查询向量 xq —— 这个查询向量必定会落入我们某个单元内,这时我们将搜索范围限制在那个单一的单元里。
但如果查询向量落在单元边缘附近,就存在一个问题——离它最近的另一个数据点很可能位于相邻的单元中。我们称这种情况为边缘问题:
为缓解这个问题并提高搜索质量,我们可以增加一个称为nprobe的索引参数值。通过nprobe,我们可以设定要搜索的单元数量。
7.3. 随机投影 (RP)
随机投影的基本思想是利用随机投影矩阵将高维向量投影到低维空间。我们生成一个随机数构成的矩阵,该矩阵的大小是我们期望的目标低维值。接着,我们计算输入向量与该矩阵的点积,得到的投影矩阵比原始向量的维度低,但仍能保留它们之间的相似性。
查询时,我们使用相同的投影矩阵将查询向量投影到低维空间中。然后,我们将投影后的查询向量与数据库中投影后的向量进行比较,以找到最近的邻居。由于数据的维度降低,搜索过程比在整个高维空间中搜索要快得多。
只需记住,随机投影是一种近似方法,投影质量取决于投影矩阵的性质。一般来说,投影矩阵的随机性越高,投影质量越好。然而,生成真正的随机投影矩阵可能在计算上相当昂贵,特别是对于大型数据集。
构建索引的另一种方法是乘积量化(PQ),这是一种针对高维向量(如向量嵌入)的有损压缩技术。它将原始向量分解成更小的部分,通过为每个部分创建一个代表性“码”来简化每个部分的表示,然后将所有部分重新组合起来,同时不会丢失对于相似性操作至关重要的信息。PQ的过程可以分为四个步骤:分割、训练、编码和查询。
码本中代表向量的数量在表示的准确性与搜索码本的计算成本之间存在权衡。码本中代表向量越多,子空间中向量的表示就越准确,但搜索码本的计算成本就越高。相反,码本中代表向量越少,表示的准确性就越低,但计算成本也就越低。
局部敏感哈希(Locality Sensitive Hashing, LSH)的工作原理是通过哈希函数处理每个向量,将向量分组到“桶”中,该哈希函数旨在最大化哈希冲突,而非通常哈希函数所追求的最小化冲突。
这是什么意思呢?想象我们有一个Python字典。当在字典中创建新的键值对时,我们使用哈希函数对键进行哈希。键的哈希值决定了存储其相应值的“桶”位置。
典型的字典类对象所用的哈希函数会尽量减少哈希冲突,力求每个桶只分配一个值。
Python字典就是使用了典型哈希函数的哈希表的例子,这种函数最小化了哈希冲突,即两个不同对象(键)产生相同哈希值的情况。
在字典中,我们希望避免这些冲突,因为这意味着多个对象会被映射到同一个键下——但在LSH中,我们却想最大化哈希冲突。
为何要最大化冲突呢?这是因为对于搜索而言,我们利用LSH来将相似的对象聚集在一起。当我们引入一个新的查询对象(或向量)时,我们的LSH算法就能用来找到最匹配的组群:
7.6. 分级导航小世界 (HNSW)
HNSW构建了一种层次化的、树状结构,其中树的每个节点代表一组向量。节点间的边表示向量之间的相似度。算法开始时,创建一组节点,每个节点包含少量向量。这可以通过随机方式完成,也可以使用如k-means聚类算法,将每个聚类变成一个节点。
然后,算法检查每个节点的向量,并在该节点与其拥有最相似向量的节点之间绘制边。
在使用HNSW索引进行查询时,它利用这张图来遍历树结构,访问那些最有可能包含与查询向量最接近向量的节点。
DBSCAN算法基于密度可达性和密度连通性的概念进行操作。它从数据集中的一个任意点开始,如果在这个点的给定半径eps
内至少有minPts
个点,则创建一个新的聚类。这里的eps
(epsilon)是一个用户定义的输入值,表示在聚类中考虑两点间最大允许的距离,而minPts
是指形成一个聚类所需的最少数据点数目。然后,算法迭代地将eps
半径内所有直接可达的点加入到聚类中。这一过程持续进行,直到无法再向聚类中添加更多点为止。之后,算法继续处理数据集中下一个未访问的点,并重复这一过程,直到所有点都被访问过。在DBSCAN中,关键参数是eps
和minPts
,分别定义了点的聚类范围以及形成聚类所需的最小点密度。
8. 相似度度量:距离度量
相似度度量是数学方法,用于确定向量空间中两个向量的相似程度。在向量数据库中,这些度量被用来比较数据库中存储的向量,并找出与给定查询向量最相似的那些。
可以采用几种不同的相似度度量方法,包括:
确实,通常最佳实践是使用与训练嵌入时相同的相似度度量来进行搜索;然而,相似度度量的选择也应依据数据的具体特性和所解决问题的上下文来决定。以下是针对讨论过的每种相似度度量的一些主要应用领域:
欧氏距离
点积
余弦相似度
每个储存在数据库中的向量都附带有元数据。除了查询相似向量的能力之外,向量数据库还能够根据元数据查询来过滤搜索结果。为此,向量数据库通常维护两个索引:一个向量索引和一个元数据索引。它会在向量搜索之前或之后执行元数据过滤,但这两种情况都可能存在一些导致查询过程变慢的难题
过滤过程可以在向量搜索之前或之后进行,但每种方法都有可能影响查询性能的挑战:
预过滤:此方法中,在向量搜索之前进行元数据过滤。虽然这有助于减小搜索范围,但也可能导致系统忽略不满足元数据过滤标准的相关结果。此外,复杂的元数据过滤可能会因额外的计算负担而拖慢查询进程。
后过滤:在这种方法中,元数据过滤在向量搜索之后执行。这样可以确保考虑所有相关结果,但也会因完成搜索后需要剔除不相关结果而引入额外开销,从而可能减慢查询进程。
为了优化过滤过程,向量数据库采用多种技术,比如利用高级索引方法处理元数据,或采用并行处理加速过滤任务。在搜索性能与过滤准确性之间取得平衡,对于向量数据库提供高效且相关的查询结果至关重要。
为您的决策提供一份简明概要:
总之,向量数据库的选择没有统一标准,最合适的选项取决于特定项目需求、预算限制和个人喜好。
10.1. 参数对比
这篇博客为我们提供了一个关于向量数据库的精简探索,特别强调了它们在检索增强生成(RAG)应用中的关键作用。作者突出了诸如ChromaDB、Pinecone和Weaviate等流行数据库的重要性,强调了为达到最优RAG性能,高效存储与检索的必要性。
博客深入介绍了多种索引技术和算法,洞悉了Annoy、倒排文件(IVF)索引、随机投影、乘积量化、局部敏感哈希(LSH)、HNSW和DBSCAN等方法。同时,它进一步解释了余弦相似度、欧氏距离和点积等相似度量,并给出了在文档相似性、图像检索和协同过滤中的实际应用案例。
文章中还有一大部分内容致力于帮助读者选择合适的向量数据库。考虑的关键因素包括开源可用性、性能、社区强度、可扩展性、高级功能、安全性和价格。比较参数提供了快速概览,使读者能够根据自身特定需求和偏好做出明智的决策。
总之,这篇博客作为向量数据库导航的快速指南,为无缝集成和优化RAG模型提供了必需的知识基础。
英文原文:https://medium.com/@vipra_singh/building-llm-applications-vector-database-part-4-2bb29e7c798d
请长按或扫描二维码关注本公众号
喜欢的话,请给我个在看吧!