Elasticsearch 8.0 近似最近邻 (ANN) 搜索简介
得益于新一代 Machine Learning 模型能够将各种内容(包括文本、图像、事件等)表示为向量,人们对向量搜索的兴趣激增。这些强大的表示形式通常被称为“嵌入模型”,它们能够以超越表面特征的方式捕捉两段内容之间的相似性。
k 最近邻 (kNN) 搜索算法可在数据集中找到与查询向量最相似的向量。结合这些向量表示,kNN 搜索为检索开启了令人兴奋的可能性:
- 查找可能包含问题答案的段落
- 在大型数据集中检测近似重复的图像
- 查找与给定歌曲听起来相似的歌曲
向量搜索有望成为搜索工具箱中的重要组成部分,与基于词条的评分等传统技术并驾齐驱。
Elasticsearch 目前支持通过 dense_vector 字段类型存储向量,并使用它们来计算文档评分。这允许用户通过扫描所有文档来执行精准的 kNN 搜索。Elasticsearch 8.0 在此功能的基础上,支持快速的近似最近邻 (ANN) 搜索。这代表了一种更具可扩展性的方法,允许向量搜索在大型数据集上高效运行。
Elasticsearch 中的 ANN
什么是近似最近邻 (ANN) 搜索?
对于低维向量上的 kNN,已有成熟的数据结构,例如 KD 树。事实上,Elasticsearch 集成了 KD 树,以支持对地理空间和数值数据进行搜索。但是,现代文本和图像嵌入模型通常会生成包含 100–1000 个元素甚至更多元素的高维向量。这些向量表示带来了一个独特的挑战,因为在高维空间中高效查找最近邻非常困难。
面对这一困难,最近邻算法通常会牺牲完美准确性来提高速度。这些近似最近邻 (ANN) 算法可能并不总是返回真正的 k 个最近向量。但它们运行高效,能在维护良好性能的前提下扩展到大型数据集。
选择 ANN 算法
设计 ANN 算法是学术研究的一个活跃领域,有许多前景广阔的算法可供选择。它们在搜索速度、实现复杂性和索引成本方面通常存在不同的取舍。值得庆幸的是,有一个名为 ann-benchmarks 的优秀开源项目,它针对多个数据集测试领先的算法并发布对比结果。
Elasticsearch 8.0 使用一种称为分层可导航小世界图表 (HNSW) 的 ANN 算法,该算法根据向量之间的相似性将它们组织成图表。HNSW 在各种 ann-benchmarks 数据集中表现出强大的搜索性能,在我们自己的测试中也表现良好。HNSW 的另一个优势在于它在工业界被广泛使用,并已在多个不同的系统中实现。除了原始学术论文外,还有许多有助于了解该算法细节的实用资源。尽管 Elasticsearch ANN 目前基于 HNSW,但该功能的设计非常灵活,使我们能够在未来整合不同的方法。
给我看看代码!
要为 ANN 搜索索引向量,我们需要设置 index: true 并指定我们用于比较它们的相似度指标:
PUT index
{
"mappings": {
"properties": {
"image-vector": {
"type": "dense_vector",
"dims": 128,
"index": true,
"similarity": "l2_norm"
}
}
}
}
PUT index/_doc
{
"image-vector": [0.12, 1.34, ...]
}GET index/_knn_search
{
"knn": {
"field": "image-vector",
"query_vector": [-0.5, 9.4, ...],
"k": 10,
"num_candidates": 100
}
}_knn_搜索 终端使用 HNSW 图表来高效检索相似向量。与执行全数据扫描的精确 kNN 不同,它能很好地扩展到大型数据集。以下是一个示例,它将 _knn_search 与基于 script_score 查询的精确方法进行了比较,该数据集包含 100 万个 128 维的图像向量,并对超过 10,000 个不同的查询进行了平均:
Approach Queries Per Second Recall (k=10)
script_score 5.257 1.000
_knn_search 849.286 0.945在本示例中,ANN 搜索比精确搜索方法快几个数量级。其召回率约为 95%,因此平均而言,它能在 10 个真正的最近邻中找到超过 9 个。
您可以在 Elasticsearch 夜间基准测试中查看 kNN 搜索的性能。这些基准测试由 es-rally 提供支持,这是一款用于 Elasticsearch 基准测试的工具,特别是其中新的 dense_vector Rally 赛道。我们计划扩展 Rally,使其在报告延迟的同时也能报告召回率,因为跟踪算法的准确性同样重要。目前,这些基准测试所使用的数据集包含数百万个向量,但通过增加索引时间或添加硬件资源,ANN 搜索完全可以扩展到超出此规模。
由 Apache Lucene 提供支持
Elasticsearch 的许多核心搜索功能均由 Lucene 库提供支持,这是一个由 Apache 软件基金会管理的开源项目。Elasticsearch ANN 也不例外,它基于一项令人兴奋的全新 Lucene 功能构建,用于存储和搜索数值向量。此功能是来自不同组织的几位开发人员通力合作的成果。它最初只是一个大胆的提议,随后迅速发展成为一个可运行(且快速)的实现。接下来面临的挑战是设计 API 并完善该功能。
自那时起,Lucene 社区持续协作,共同推动该功能向前发展。几位开发人员对此产生了兴趣并做出了贡献,包括重新设计名称、算法更新、性能改进等等。得益于大家的共同努力,Lucene 的向量搜索功能正在迅速扩展。
除了卓有成效的合作之外,在 Lucene 中开发 ANN 还带来了其他重大优势。Lucene 的实现从底层设计出发,旨在与现有功能正确集成,从而使 ANN 搜索能够与其他 Elasticsearch 功能无缝交互。如果我们依赖外部 ANN 库,这种深度集成实际上是不可能实现的。例如,Lucene ANN 通过在图表搜索期间跳过“墓碑”(tombstones),从而透明地处理已删除的文档。它还遵循 Lucene 的所有数据兼容性保证,因此您可以确信向量数据在升级后仍能正常工作。最后,其实现方式与 Elasticsearch 一样均采用 Java 编写,这使我们能够确保其安全性并简化内存管理。
未来动向
在 8.0 版本中,用于高效 ANN 搜索的 _knn_搜索 终端将作为“技术预览”发布。ANN 搜索不仅对 Elastic 而言是一个相对较新的主题,对整个行业来说也是如此,并且关于它应该如何运行,还存在许多重大的悬而未决的问题。将向量相似度分数与传统的 BM25 分数相结合的最佳方法是什么?kNN 搜索是否应支持分页?将 ANN 开发为独立的实验性终端,将使我们能够快速迭代并测试其行为。一旦我们对这些问题有了确切的答案,我们计划最终将 ANN 集成到 _搜索 API 中。(尽管 _knn_搜索 尚未正式发布 (GA),但 dense_vector 字段类型已在 7.6 版本中正式发布,并继续拥有稳定的 API。)
我们计划支持的一些关键功能包括带筛选器的 ANN,以及将 ANN 结果与传统查询结果相结合的“混合”搜索。我们也在努力提高索引速度,因为构建 HNSW 图表可能是一个非常耗时的操作。我们认为此版本仅仅是一个开始,并期待在未来的版本中不断改进 ANN 搜索。您的反馈非常有价值,有助于塑造该功能的发展方向。我们非常想听听您的想法,欢迎通过 GitHub 和我们的 Discuss 论坛(以及 Lucene)与我们联系!
日志 Elastic Cloud 控制台或注册 14 天免费试用版,即可在 Elastic Cloud 上体验 ANN 搜索。