GinoGino

专为向量搜索而生[译]

20 分钟阅读人工智能

本文翻译自 Qdrant 官方博客,旨在为读者提供一份全面、深入且实用的向量搜索技术指南。文章不仅详细剖析了专用向量数据库在架构、性能和功能上的优势,还深入探讨了向量、向量索引、向量搜索等核心概念,以及在 RAG、推荐系统、大数据分析等场景的应用。此外,文章还对比了通用数据库的向量扩展、混合数据库等不同方案,为您在实际应用中选择合适的向量搜索解决方案提供参考。

复杂的问题往往需要专门的解决方案。就像我们可以用瑞士军刀开瓶或戳孔,但要砍柴还是需要斧头,软件开发也遵循同样的道理。

在本文中,我们将探讨向量搜索面临的独特挑战,并解释为什么专用解决方案是应对这些挑战的最佳选择。

向量

首先,让我们了解向量数据库的核心概念:向量

向量(也称为 Embeddings)是各种数据点(如文本、图像、视频等)的高维表示。许多最先进(SOTA)的嵌入模型生成的向量维度超过 1500 维。在最先进的 PDF 检索场景中,向量表示甚至可以达到 每页超过 100,000 维

这就引出了向量搜索的第一个挑战:向量的数据量非常大。

向量数据量巨大

举个例子,假设一个关系数据库中存储了一百万条记录。对于现代数据库来说,这并不算大数据量,许多云服务的免费套餐都能轻松处理。

但如果使用 OpenAI 的 text-embedding-ada-002 模型,为每条记录生成一个 1536 维的嵌入,那么这一百万条记录将占用约 6GB 的存储空间。因此,向量搜索的工作负载会迅速消耗掉非向量数据库原本用于其他主要用例的资源。

将向量存储在主数据库中还存在另一个潜在问题:向量始终是对其他数据的转换。

向量是一种转换

向量是通过对其他原始数据进行转换得到的。如果向量丢失,可以使用相同的嵌入模型重新生成。然而,即使嵌入模型发生微小变化,也可能导致向量空间的几何结构改变。因此,如果更新或更改了嵌入模型,就需要更新并重新索引所有数据,以保证向量比较的准确性。

如果与主数据库耦合在一起,这种更新过程可能会带来严重的复杂性,甚至可能导致整个系统不可用。

即便您计划使用通用数据库存储向量,也应该将向量相关的工作负载与主数据库分离。

不过,向量也有其优势。其中最重要的一点是向量的大小是固定的。

向量大小固定

嵌入模型的一个设计目标就是生成固定大小的向量,这一特性为我们提供了重要的优化机会。

为了实现快速搜索,向量需要能够被即时访问。无论向量存储在 RAM 还是磁盘 中,都应该采用一种允许快速访问和比较的格式。这一点至关重要,因为向量比较是向量搜索中非常频繁的操作。每次搜索查询通常需要进行数千次比较,因此即使是很小的开销也可能导致明显的性能下降。

对于专用存储而言,向量的固定大小是一个优势。由于我们确切地知道每个数据点所需的空间,因此无需处理传统数据定位的额外开销,存储中向量元素的位置可以简单地计算出来。

但如果向量与其他类型的数据(例如文本或 JSON)一起存储,情况就变得不那么直观了。因为单个数据点的大小不再固定,访问它就变得不那么容易,特别是在数据随时间推移不断添加、更新和删除的情况下。

固定大小列 vs. 可变长度表

将向量与其他类型的数据混合存储,我们会失去向量固定大小带来的所有优势,反而要承担向量数据量大的缺点,用已经存在于存储中的数据的繁重转换结果来污染存储空间。

向量搜索

与传统数据库主要作为数据存储不同,向量数据库更像是一个搜索引擎。它们被设计为 可扩展、始终 可用,并且即使在高负载下也能提供快速的搜索结果。就像 Google 或 Bing 可以同时处理数十亿个查询一样,向量数据库是专为需要快速、高吞吐量、低延迟检索的场景而设计的。

数据库指南针

三选二

分布式系统非常适合实现可扩展性。通过水平扩展,可以根据需要灵活地添加更多机器。在分布式系统领域,有一个著名的原则:CAP 定理。该定理指出,分布式系统只能同时保证三个属性中的两个:一致性(数据始终是最新的)、可用性(系统始终响应)和 分区容错性(即使在网络故障的情况下,系统也能正常运行)。

由于网络分区在任何现实世界的分布式系统中都不可避免,因此所有现代分布式数据库在设计时都考虑到了分区容错性。这迫使我们必须在 一致性可用性 之间做出选择。

CP 系统在正常运行时可以保持正常服务,但在发生故障时会优先保证数据一致性,即使可能暂时无法提供服务。

AP 系统则选择保持服务可用,通过牺牲强一致性来实现,系统会在后续逐步达到数据一致。

在这种情况下,数据库有两种主要的设计理念:

ACID:优先考虑一致性

ACID 模型确保每个事务(一组被视为单个单元的操作,如账户间转账)要么完全执行,要么完全不执行(回滚),从而使数据库始终保持在有效状态。在分布式系统中,实现 ACID 属性需要节点之间进行复杂的协调。每个节点都必须进行通信并就事务的状态达成一致,这可能会 限制系统的可用性。如果一个节点不确定另一个节点的状态,它可能会拒绝处理事务,直到确保一致性为止。这种协调也使得 扩展更具挑战性

金融机构在处理资金转账时通常使用 ACID 兼容的数据库,因为即使是账户余额的瞬间差异也是不可接受的。

BASE:优先考虑可用性

BASE 模型更注重高可用性和分区容错性。BASE 系统将数据和工作负载分布在多个节点上,使它们能够立即响应读写请求。它们遵循 最终一致性 原则,虽然数据可能暂时不是最新的,但系统最终会收敛到一个一致的状态。

社交媒体平台、流媒体服务和搜索引擎都采用 BASE 方法。对于这些应用来说,即时响应比严格的一致性更为重要。

基于 BASE 的向量搜索

考虑到向量搜索的特性(它本质上需要可用性和可扩展性),因此它应该构建在面向 BASE 的架构之上。选择 BASE 架构是出于对横向扩展、高可用性、低延迟和高吞吐量的需求。例如,采用以 BASE 为中心的架构可以让我们 轻松管理数据重分片

而且,当我们意识到向量是对已有数据的一种转换时,严格一致性的事务模型就失去了它的吸引力。如果我们总是可以通过重新转换来恢复向量化数据,那么费力保证数据强一致性又有什么意义呢?

向量索引

向量搜索 依赖于高维向量运算,这使得它在大规模计算时非常消耗资源。如果采用暴力搜索(brute-force),就需要将查询向量与数据库中的每个向量逐一比较。在具有 1 亿个 1536 维向量的数据库中,每次查询执行 1 亿次比较,这对于生产环境来说是不可行的。因此,向量数据库通常不采用暴力搜索,而是使用专门的近似最近邻 (ANN) 索引,这些索引可以在搜索精度和速度之间取得平衡。为了使这些索引在生产环境中易于维护,需要精心设计的系统架构。

HNSW 索引

HNSW(Hierarchical Navigable Small World) 是一种非常流行的向量索引,我们选择它是因为它能够同时提供高搜索速度和高准确率。然而,高性能是有代价的 -- 由于一些挑战,在生产环境中实现 HNSW 并非易事。为了充分发挥 HNSW 的优势,整个系统的架构都必须围绕它进行构建,为这个"任性"的索引提供服务。

索引复杂性

HNSW 的结构是一个多层图。当插入一个新的数据点时,算法必须将其与多个层中的现有节点进行比较,才能对其进行索引。随着向量数量的增长,这些比较会显著降低构建过程的速度,导致更新操作越来越耗时。索引操作可能会迅速成为系统的瓶颈,从而降低搜索请求的速度。

构建一个单体的 HNSW 索引意味着限制了解决方案的可扩展性 --它的规模必须设置上限,因为它的构建时间会随着元素数量的增加呈非线性增长。为了保证构建过程的可行性,并确保它不会影响搜索时间,我们提出了一种分层架构,将所有数据管理分解为称为 段(Segment) 的小单元。

存储结构

每个段隔离了向量化数据的一个子集,并支持对该子集进行所有集合级别的操作,包括搜索和索引。例如,每个段会在其所包含的数据子集上构建自己的索引。对于在集合级别工作的用户来说,分段的细节是不可见的。用户获得的搜索结果会跨越整个集合,因为系统会从各个段收集子结果,然后进行合并和去重。

通过平衡段的大小和数量,我们可以确保在搜索速度和索引时间之间取得适当的平衡,从而使系统能够灵活地适应不同的工作负载。

不可变性

通过将索引维护任务分配给不同的段,Qdrant 即使在高负载下也能确保高性能,并且还可以通过其他优化措施进一步提高性能。这些优化的灵感来自于一个理念:使用不可变结构可以带来很多好处,例如可以使用内部固定大小的列表(避免动态更新),可以根据访问模式对存储的数据进行排序(避免不可预测的随机访问)。考虑到这一点,为了进一步优化搜索速度和内存管理,我们采用了 可变段和不可变段 的策略。

类型功能说明
可变段用于快速接收新数据并处理对现有数据的更改(更新)。
不可变段一旦可变段达到一定大小,优化过程会将其转换为不可变段,并构建 HNSW 索引,你可以 在此处详细了解这些优化器。例如,这种不可变性技巧使我们能够确保有效的 租户隔离

对于用户来说,不可变段是一个透明的实现细节,用户可以随时删除向量,而添加和更新操作则会应用到可变段。这种可变性和不可变性的结合使得搜索和索引操作可以同时平稳地运行,即使在高负载下也是如此。这种方法最大限度地减少了索引时间对性能的影响,并允许在集合级别进行动态配置更改(例如启用或禁用数据量化),而无需停机。

可过滤索引

从历史上看,向量搜索并非专为过滤而设计 -- 即对搜索结果施加严格约束。向量搜索本质上是模糊的;每个文档在某种程度上都与任何查询既相似又不相似,不存在二元的"匹配/不匹配"的严格区分。因此,最初的向量搜索算法在设计时并没有考虑过滤。

然而,在许多向量搜索应用中,过滤是不可避免的,例如在 电商搜索/推荐 中。当搜索圣诞礼物时,你可能希望过滤掉所有超过 100 欧元的商品,同时仍然能够利用向量搜索的语义理解能力。

在许多向量搜索解决方案中,过滤通常有两种方法:预过滤(在运行 HNSW 搜索之前,计算所有符合过滤条件的向量的二进制掩码)或 后过滤(像往常一样运行 HNSW,然后对结果进行过滤)。

方法说明问题描述
❌ 预过滤具有计算向量掩码的线性复杂度对于大型数据集会成为性能瓶颈。
❌ 后过滤在 HNSW 搜索后应用过滤条件后过滤的问题与向量搜索的"一切都既匹配又不匹配"的特性有关:想象一个低基数 (low-cardinality) 过滤器,它只在数据库中留下少量匹配的元素。如果这些元素中没有一个与查询足够相似,能够出现在检索到的前 X 个结果中,那么它们都会被过滤掉。

Qdrant 在向量搜索的过滤方面进行了创新,进一步推进了向量搜索中的过滤,并充分认识到预过滤和后过滤策略的局限性。我们开发了一种 HNSW 的改进版本 -- 可过滤 HNSW -- 它支持在图遍历过程中进行 即时过滤。为了实现这一点,我们将 HNSW 索引的构建过程与可能的过滤条件相关联,这些过滤条件反映在 有效负载索引(基于向量的 元数据 构建的倒排索引)中。

Qdrant 的设计理念是将向量索引作为系统的核心组件。 这使得我们可以围绕向量索引来组织优化器、有效负载索引和其他组件,从而实现了构建可过滤 HNSW 的可能性。

可过滤向量索引

总而言之,优化向量搜索需要一种定制的、经过精细调整的数据和索引管理方法,即使在数据不断增长和动态变化的情况下,也能确保高性能。这种专门的架构正是 专用向量数据库在生产环境中始终优于通用数据库 的关键原因。

超越 RAG 的向量搜索

向量搜索不是文本搜索扩展

许多关于向量数据库用途的讨论都集中在检索增强生成 (RAG) -- 或其更高级的变体,即基于 Agent 的 RAG -- 其中向量数据库被用作知识源,为大型语言模型 (LLM) 提供上下文。这当然是一个重要的应用场景,但是,RAG 解决方案的热潮掩盖了向量搜索更广泛的潜力,它 远不止于增强生成式 AI

发现

向量搜索的优势在于它能够促进 发现(Discovery)。向量搜索允许你在搜索过程中不断调整你的选择,而不是从一个固定的查询开始。例如,当你在点餐时,可能并不完全清楚自己想要什么,只知道想要包含肉类,但不是汉堡;或者想要带奶酪的肉,但不是墨西哥玉米卷(tacos)。向量搜索不是搜索特定的菜肴,而是帮助你根据相似性和不相似性来浏览选项,引导你找到符合你口味的食物,而无需你事先明确定义。

推荐

向量搜索非常适合用于 推荐。想象一下你在浏览一本新书或一部新电影,你可能不是在寻找完全匹配的内容,而是在寻找能够捕捉到某种特定情绪或主题的故事,但在关键方面又与你已知的内容有所不同。例如,你可能 想要一部以巫师为主题的电影,但又不想有《哈利·波特》系列的熟悉感。这种灵活性之所以成为可能,是因为向量搜索不依赖于二元的"匹配/不匹配"概念,而是基于向量空间中的距离进行操作。

大规模非结构化数据分析

向量搜索的特性也使得它非常适合用于 大规模非结构化数据分析,例如异常检测。在大规模、非结构化且通常未标记的数据集中,向量搜索可以通过分析数据点之间的距离关系来帮助识别数据聚类和异常值。

本质不同

RAG 之外的向量搜索不仅仅是一个附加功能,它是我们与数据交互方式的根本性转变。专用解决方案以原生方式集成了这些功能,并且从一开始就设计用于处理高维数学运算和基于(不)相似性的检索。相比之下,具有向量扩展功能的数据库是围绕不同的数据范式构建的,因此无法有效地支持高级向量搜索功能。

即使你想要改造这些功能,这也不仅仅是添加一个新功能的问题 -- 这是一个结构性的问题。支持高级向量搜索需要 专用的接口,这些接口能够支持向量搜索的灵活使用,包括多阶段过滤和高维空间的动态探索。

如果底层架构最初并非为此类交互而设计,那么集成这些接口将成为 软件工程团队的噩梦。最终,你会打破现有的假设,被迫采用效率低下的变通方法,并且经常会引入向后兼容性问题。这就是为什么试图将向量搜索强行添加到传统数据库上,无法达到专用系统效率的原因。

使向量搜索成为最先进的技术

现在,让我们将注意力转移到专用解决方案的另一个关键优势 -- 它们能够紧跟业界最先进的技术。

向量数据库 是专为向量检索而构建的,因此,它们提供了一系列前沿功能,这些功能对于依赖向量搜索的 AI 企业来说通常至关重要。向量数据库工程师投入了大量时间和精力来研究和实现执行向量搜索的最佳方法。许多创新自然而然地融入到向量原生架构中,而具有向量扩展功能的通用数据库可能难以有效地适应和复制这些优势。

请看 Qdrant 中实现的一些高级功能:

通过将索引构建任务转移到 GPU,Qdrant 可以显著加快数据索引过程,同时保持较低的成本。在处理热数据场景中的大型数据集时,这一点尤为重要。

Qdrant 中的 GPU 加速是我们核心团队的一位成员开发的自定义解决方案。它不依赖于特定供应商,并且原生支持 Qdrant 的所有独特架构特性,包括可过滤 HNSW 和多向量。

一些现代嵌入模型会生成一个完整的矩阵(向量列表)作为输出,而不是单个向量。Qdrant 原生支持多向量。

在使用最先进的检索模型(例如 ColBERT、ColPali 或 ColQwen)时,此功能至关重要。例如,ColPali 和 ColQwen 会生成多向量输出,原生支持它们对于实现 最先进 (SOTA) 的 PDF 检索 至关重要。

此外,我们还在不断寻求以下方面的改进:

优化方向具体措施
内存效率和压缩量化HNSW 压缩 等技术可以显著降低存储成本,同时提高系统性能。
检索算法支持最新的检索算法,包括 稀疏神经检索混合搜索 方法和 重排序器
向量数据分析和可视化诸如 距离矩阵 API 等工具可提供对向量化数据的深入分析,而 Web UI允许直观地探索数据。
搜索速度和可扩展性包括对 多租户环境 的优化,以确保高效且可扩展的搜索。

这些进步不仅仅是渐进式的改进,它们定义了针对向量搜索优化的系统与仅仅支持向量搜索的系统之间的本质区别。

紧跟向量搜索的最前沿,不仅仅关乎性能——它还关乎与不断发展的 AI 格局保持同步。

总结

在向量搜索领域,使用专用向量搜索解决方案和扩展现有数据库以支持向量操作之间存在着明显的区别。

对于处理不超过一百万个数据点的小规模应用或原型,非优化的架构可能就足够了。 但随着向量数量的增长,未优化的解决方案会迅速成为瓶颈,降低搜索操作的速度并限制可扩展性。专用向量搜索解决方案从一开始就被设计为能够高效地处理大量高维数据。

最先进的向量搜索技术发展迅速。如果你计划基于最新的技术进展进行构建,那么使用向量扩展最终会成为你的阻碍。专用向量搜索解决方案以原生方式集成了这些功能,确保你能够从持续的创新中受益,而不会影响性能。

向量搜索的强大功能还扩展到了大数据分析、推荐系统和基于发现的应用等领域。为了支持这些向量搜索应用,需要一个专用的解决方案。

何时选择专用数据库而不是扩展:

  • 大容量、实时搜索:适用于需要快速、持续访问搜索结果的、拥有大量并发用户的应用,如搜索引擎、电商推荐、社交媒体或流媒体服务。
  • 动态、非结构化数据:适用于数据不断变化,并且目标是从数据模式中发现洞察力的场景。
  • 创新型应用:如果你希望实现高级应用场景,如推荐引擎、混合搜索解决方案,或传统精确匹配或基于关键词的搜索无法满足需求的探索性数据分析。

如果你的应用依赖于大规模向量搜索,并希望紧跟行业趋势,或者需要超越简单的相似性搜索功能,那么投资专用向量搜索引擎将是明智之选。这不仅能够满足当前的需求,还能为未来的扩展奠定坚实的基础。

原文链接:Built for Vector Search