Elasticsearch 混合搜索 - Hybrid Search

作者:来自 Elastic  Valentin Crettaz

了解混合搜索、Elasticsearch 支持的混合搜索查询类型以及如何制作它们。

本文是三篇系列文章中的最后一篇,深入探讨了向量搜索(又称语义搜索)的复杂性以及它在 Elasticsearch 中的实现方式。

第一部分主要介绍嵌入(又名向量)的基础知识以及向量搜索的工作原理。

利用第一篇文章中学习到的所有向量搜索知识,第二篇文章将指导你如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。

在第三部分也是最后一部分中,我们将利用前两部分所学到的知识,并在此基础上深入研究如何在 Elasticsearch 中编写强大的混合搜索查询。

混合搜索的需求

在深入研究混合搜索领域之前,让我们快速回顾一下本系列第一篇文章中学到的词汇搜索和语义搜索的区别以及它们如何相互补充。

简而言之,当你可以控制结构化数据并且用户或多或少清楚他们正在搜索的内容时,词汇搜索非常有用。然而,当你需要使非结构化数据可搜索并且你的用户实际上不知道他们正在搜索什么时,语义搜索提供了很大的支持。如果有办法将两者结合起来,从而尽可能地从两者中榨取尽可能多的实质内容,那就太棒了。进入混合搜索!

从某种程度上来说,我们可以将混合搜索看作是词汇搜索和语义搜索的某种 “总和”。然而,如果操作正确,混合搜索会比仅仅将各个部分相加要好得多,产生的结果远远好于单独的词汇搜索或语义搜索。

运行混合搜索查询通常归结为发送至少一个词汇搜索查询和一个语义搜索查询的混合,然后合并两者的结果。词汇搜索结果由相似度算法进行评分,例如 BM25 或 TF-IDF,其分数范围通常无界,因为最高分数取决于倒排索引中存储的术语数量和频率。相比之下,语义搜索结果可以在封闭区间内进行评分,具体取决于所使用的相似度函数(例如,余弦相似度为 [0; 2])。

为了合并混合搜索查询的词汇和语义搜索结果,需要以保持检索到的文档的相对相关性的方式融合两个结果集,这是一个复杂的问题。幸运的是,有几种现有的方法可以利用;两个非常常见的是凸组合(Convex Combination - CC)和倒数秩融合(Reciprocal Rank Fusion - RRF)。

基本上,凸组合(也称为线性组合)旨在将词汇搜索结果和语义搜索结果的归一化得分按相应的权重 \alpha 和 β 进行组合,其中 0 ≤ α,β,使得:

CC 可以被看作是词汇和语义分数的加权平均值,0 到 1 之间的权重用于降低相关查询的权重,而大于 1 的权重用于提升相关查询。

然而,RRF 不需要任何分数校准或规范化,而只是根据文档在结果集中的排名对其进行评分,使用以下公式,其中 k 是一个任意常数,用于调整低排名文档的重要性:

CC 和 RRF 都有其优点和缺点,如下表 1 所示:

表 1:CC 和 RRF 的优缺点
Convex CombinationReciprocal Rank Fusion
优点良好的权重校准使 CC 比 RRF 更有效不需要任何校准,完全无人监督,也不需要知道最小/最大分数
缺点需要对权重进行良好的校准,并且最佳权重特定于每个数据集调整 k 的值并不容易,并且排名质量可能会受到结果集大小的影响

值得注意的是,并非所有人都同意这些优缺点,这取决于所做的假设和测试的数据集。一个很好的总结就是,RRF 产生的分数准确度比 CC 略低,但具有 “即插即用” 的一大优势,并且可以在无需使用标记的查询集微调权重的情况下使用。

Elastic 决定同时支持 CC 和 RRF 方法。我们将在本文后面看到如何实现这一点。如果你有兴趣了解更多有关该选择背后的理由,你可以阅读 Elastic 博客中的这篇精彩文章,还可以查看 Elastician Philipp Krenn 在 Haystack 2023 上就 RRF 发表的精彩演讲。

时间线

在 2019 年的 7.0 版本中启用了对密集向量的强力 kNN 搜索之后,Elasticsearch 于 2022 年 2 月的 8.0 版本开始支持近似最近邻 (ANN) 搜索,并在 2022 年 8 月的 8.4 版本中紧随其后提供了混合搜索支持。下面的图 1 显示了 Elasticsearch 将混合搜索推向市场的时间表:

图 1:Elasticsearch 的混合搜索时间线

Elasticsearch 中的混合搜索剖析

正如我们在上一篇文章中简要暗示的那样,Elasticsearch 中的向量搜索支持是通过利用密集向量(dense)模型(因此是 density_vector 字段类型)实现的,该模型生成的向量通常包含本质上非零的值并表示多维空间中非结构化数据的含义。

然而,密集模型并不是执行语义搜索的唯一方法。 Elasticsearch 还提供了使用稀疏向量(sparse)模型的替代方法。 Elastic 创建了一个稀疏 NLP 向量模型,称为 Elastic Learned Sparse EncoderR(简称 ELSER),这是一个域外(即不在特定域上进行训练)的稀疏向量模型,不需要任何微调。它是在约 30,000 个术语的词汇上进行预训练的,并且由于它是一个稀疏模型,所以大多数向量值(即超过 99.9%)都是零。

其工作方式非常简单。在索引时,使用推理 inference 处理器生成包含术语/权重对的稀疏向量,并将其存储在 sparse_vector 类型的字段中,该字段是 dense_vector 字段类型的稀疏对应部分。在查询时,特定的 DSL 查询(也称为 sparse_vector)会将原始查询词替换为 ELSER 模型词汇表中已知的、根据权重与原始查询词最相似的词。

稀疏还是密集?

在介绍混合搜索查询之前,我们想简单强调一下稀疏模型和密集模型之间的区别。下面的图 2 显示了各个模型如何对文本 “the quick brown fox” 进行编码。

在稀疏情况下,将原始 4 个项扩展为 30 个与它们密切或远亲相关的加权项。扩展词条的权重越高,说明其与原词条的相关性越高。由于 ELSER 词汇表包含 30,000 多个术语,这意味着代表 “the quick brown fox” 的向量具有同样多的维度,并且仅包含 ~0.1% 的非零值(即~30/30,000),因此我们称这些模型为稀疏模型。

图 2:比较稀疏和密集模型编码

在密集的情况下,“the quick brown fox” 被编码成一个更小的嵌入向量,以捕捉文本的语义含义。 384 个向量元素中的每一个都包含一个非零值,表示文本片段与每个维度之间的相似度。请注意,我们赋予维度的名称(即 is_mouse、is_brown 等)纯属虚构,其目的只是为了对值进行具体描述。

另一个重要的区别是,稀疏向量是通过倒排索引来查询的(是的,就像词汇搜索一样),而正如我们在之前的文章中看到的那样,密集向量在特定的基于图或基于聚类的数据结构中被索引,可以使用近似最近邻(ANN)算法进行搜索。

我们不会进一步讨论 ELSER 的诞生细节,但如果你有兴趣了解该模型是如何诞生的,我们建议你查看 Elastic Search Labs 的这篇文章,其中详细解释了 Elastic 开发该模型的思维过程。如果你正在考虑评估 ELSER,可能值得检查 Elastic 的相关性工作台,它展示了 ELSER 与普通 BM25 词汇搜索的比较。我们也不会在本文中深入探讨下载和部署 ELSER 模型的过程,但你可以花点时间查阅官方文档,其中很好地解释了如何执行此操作。

混合搜索支持

无论你要使用密集检索还是稀疏检索,Elastic 都为这两种模型类型提供混合搜索支持。第一种类型是 query 搜索选项中指定的词汇搜索查询和 knn 搜索选项中指定的向量搜索查询(或其数组)的混合。第二个引入了一个名为 retriever 的新搜索选项(在 8.14 中引入,在 8.16 中引入 GA),它还包含可以是词汇(例如,匹配)或语义(例如,sparse_vector)性质的搜索查询数组。

如果你觉得这一切有些抽象,请不要担心,因为我们将很快深入细节,展示混合搜索在实践中是如何运作的,以及它们能带来什么好处。

密集模型混合搜索

这就是我们刚才提到的第一种混合搜索类型。它基本上归结为运行词汇搜索查询与近似 k-NN 搜索混合以提高相关性。此类混合搜索查询如下所示:

POST my-index/_search
{"size": 10,"_source": false,"fields": [ "price" ],"retriever": {"standard": { "retrievers": [ {"standard": { "query": {"match": {"text-field": "fox"}}}},{"knn": { "field": "title_vector","query_vector": [0.1, 3.2, 2.1],"k": 5,"num_candidates": 100}}]}}
}

从上面我们可以看出,混合搜索查询只是使用标准检索器进行的词汇搜索查询(例如,匹配查询)和 knn 检索器中指定的向量搜索查询的组合。此查询首先在全局级别检索前五个向量匹配,然后将它们与词汇匹配相结合,最后返回十个最佳匹配。向量和词汇匹配的组合方式是通过 disjunction(即逻辑或条件),其中每个文档的分数是使用凸组合(Convex Combination计算的,即其向量和词汇分数的加权和,正如我们之前所见。

Elasticsearch 还支持使用 RRF 排名运行完全相同的混合查询,你只需使用 rrf 检索器即可完成此操作,如下所示:

POST my-index/_search
{"size": 10,"_source": false,"fields": [ "price" ],"retriever": {"rrf": { "retrievers": [ ...same as above...],"rank_constant": 60, "rank_window_size": 100}}
}

此查询的运行方式与之前的查询基本相同,只是从向量和词汇查询中检索 window_size 文档(例如,在本例中为 100),然后按 RRF 排序,而不是使用 CC 进行评分。最后,返回结果集中从 1 到 size(例如 10)排名靠前的文档。

关于这种混合查询类型最后要注意的是,RRF 排名需要商业许可证(白金版或企业版),但如果你没有,你仍然可以利用 CC 评分进行混合搜索,或者使用试用许可证,让你享受一个月的完整功能集。

稀疏模型混合搜索

用于查询稀疏模型的第二种混合搜索类型的工作方式与密集向量完全相同。下面,我们可以看到这种混合查询的样子:

POST my-index/_search
{"_source": false,"fields": [ "text-field" ],"retriever": {"rrf": { "retrievers": [ {"standard": { "query": {"match": {"text-field": "fox"}}}},{"standard": { "query": {"sparse_vector": {"field": "ml.tokens","inference_id": ".elser_model_1","query": "a quick brown fox jumps over a lazy dog"}}}}]}}
}

在上面的查询中,我们可以看到检索器数组包含一个词汇匹配查询以及一个适用于我们之前介绍的 ELSER 稀疏模型的语义 sparse_vector 查询。

密集和稀疏模型的混合搜索

到目前为止,我们已经看到了两种不同的运行混合搜索的方法,具体取决于搜索的是密集向量空间还是稀疏向量空间。此时,你可能想知道我们是否可以在同一个索引中混合密集数据和稀疏数据,并且你会很高兴地了解到这确实是可能的。一个具体的应用可能是你需要搜索包含图像的密集向量空间和包含这些图像的文本描述的稀疏向量空间。我们 standard 准检索器与 knn 检索器结合起来,这样的查询看起来是这样的:

POST my-index/_search
{"_source": false,"fields": [ "text-field" ],"retriever": {"rrf": { "retrievers": [ {"knn": {"field": "image-vector","query_vector": [0.1, 3.2, ..., 2.1],"k": 5,"num_candidates": 100}},{"standard": { "query": {"sparse_vector": {"field": "ml.tokens","inference_id": ".elser_model_1","query": "a quick brown fox jumps over a lazy dog"}}}}]}}
}

在上面的有效载荷中,我们可以看到 sparse_vector 查询在 ELSER 稀疏向量空间中搜索图像描述,在 knn 检索器中,向量搜索查询在密集向量空间中搜索图像嵌入(例如,用嵌入向量表示的 “brown fox”)。此外,我们还利用 rrf 检索器来发挥 RRF 的作用。

你甚至可以使用另一个 standard 检索器将另一个词汇搜索查询添加到组合中,它看起来像这样:

POST my-index/_search
{"_source": false,"fields": [ "text-field" ],"retriever": {"rrf": { "retrievers": [ {"knn": {"field": "image-vector","query_vector": [0.1, 3.2, ..., 2.1],"k": 5,"num_candidates": 100}},{"standard": { "query": {"match": {"text-field": "brown fox"}}}},{"standard": { "query": {"sparse_vector": {"field": "ml.tokens","inference_id": ".elser_model_1","query": "a quick brown fox jumps over a lazy dog"}}}}]}}
}

上述有效负载强调了我们可以利用一切可能的方法来指定包含词汇搜索查询、向量搜索查询和语义搜索查询的混合查询。

限制

评估 ELSER 稀疏模型时要注意的主要限制是,在运行文本推理时它仅支持最多 512 个标记。因此,如果你的数据包含需要完全可搜索的较长文本摘录,则你有两个选择:a)使用另一个支持较长文本的模型,b)将你的文本分成更小的段,或者 3)如果你使用的是 8.15 或更高版本,你可以利用 semantic_text 字段类型来处理自动分块。

优化

不可否认的是,无论是稀疏向量还是密集向量,都会变得相当长,从几十维到几千维,具体取决于你使用的推理模型。此外,无论你是在仅包含几个单词的小句子还是大段文本上运行文本推理,生成的表示含义的嵌入向量将始终具有与你使用的模型中配置的维度一样多的维度。因此,这些向量会占用文档中以及磁盘上的相当多的空间。

解决此问题最明显的优化是配置索引映射以从源文档中删除向量字段(即,dense_vector 和 sparse_vector)。这样做的话,向量值仍然会被索引和可搜索,但它们不再是源文档的一部分,从而大大减小它们的大小。通过配置映射以从 _source 中排除矢量字段来实现这一点非常简单,如下面的代码所示:

PUT my-index
{"mappings": {"_source": {"excludes": ["text_embedding.predicted_value","ml.tokens"]},"properties": {"text": {"type": "text"},"ml": {"properties": {"tokens": {"type": "rank_features"}}},"text_embedding": {"properties": {"predicted_value": {"type": "dense_vector","dims": 384,"index": true,"similarity": "cosine"}}}}}
}

为了向你展示一些具体的数字,我们进行了一个快速实验。我们已使用 msmarco-passagetest2019-top1000 数据集加载了索引,该数据集是 Microsoft MARCO Passage Ranking 完整数据集的一个子集。 60 MB 的 TSV 文件包含 182,469 个文本段落。

接下来,我们创建了另一个索引,其中包含原始文本和从 Hugging Face 提供的 msmarco-MiniLM-L-12-v3 句子转换器模型生成的嵌入向量(密集)。然后,我们重复了相同的实验,但这次配置映射以从源文档中排除密集向量。

我们还使用 ELSER 稀疏模型运行了相同的测试,一次将 sparse_vector 字段存储在文档中,一次将其排除。下表 2 显示了每个结果索引的大小,其名称不言自明。我们可以看到,通过从源中排除密集想量字段,索引大小除以 3,在 rank feature 情况下除以几乎 3.5。

IndexSize (in MB)
index-with-dense-vector-in-source376
index-without-dense-vector-in-source119
index-with-sparse_vector-in-source1,300
index-without-sparse_vector-in-source387

诚然,你的里程可能会有所不同,这些数字仅供参考,并且在很大程度上取决于你将要索引的非结构化数据的性质和大小,以及你将选择的密集或稀疏模型。

关于此优化,最后需要注意的是,如果你决定从源中排除向量,则你将无法使用索引作为源索引重新索引到另一个索引中,因为你的嵌入向量将不再可用。但是,由于索引仍然包含原始文本数据,因此你可以使用具有 inference 处理器的原始摄取管道来重新生成嵌入向量。

让我们总结一下

在本系列关于向量搜索的最后一篇文章中,我们介绍了 Elasticsearch 支持的不同类型的混合搜索查询。一种选择是使用词汇搜索(例如,查询)和向量搜索(例如,knn)的组合;另一种方法是利用新引入的带有 sparse_vector 查询的 retriever 搜索选项。

我们首先快速回顾了一下融合词汇和语义搜索结果以提高准确性的诸多优势。在此过程中,我们回顾了两种融合词汇和语义搜索结果的不同方法,即凸组合(CC)和倒数排序融合(RRF),并研究了它们各自的优缺点。

然后,通过一些说明性示例,我们展示了 Elasticsearch 如何使用凸组合和倒数秩融合作为评分和排名方法,为稀疏和密集向量空间提供混合搜索支持。我们还简要介绍了 Elastic Learned Sparse EncoderR 模型(ELSER),这是他们首次尝试提供基于 30,000 个标记词汇表构建的域外稀疏模型。

最后,我们指出了 ELSER 模型的一个局限性,并解释了一些优化未来混合搜索实现的方法。

如果你喜欢阅读的内容,请务必查看本系列的其他部分:

  • 第一部分:向量搜索简介
  • 第 2 部分:如何在 Elasticsearch 中设置向量搜索

使用此自定进度的搜索 AI 实践学习来亲自尝试想量搜索。你现在可以开始免费的云试用或在本地机器上试用 Elastic。

原文:Elasticsearch hybrid search - Elasticsearch Labs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地客户端调用火山方舟 DeepSeek R1API教程

本地第三方AI聊天机器人客户端调用 DeepSeek R1,目前火山云 DeepSeek R1 API 目前测试下高速推理速度,不卡顿,联网搜索能力,可以访问更多联网信息50万免费 tokens,超出后全网最低价。 目录 一、火山方舟 DeepSeek R1A…

华为最新OD机试真题-通过软盘拷贝文件-Python-OD统一考试(E卷)

最新华为OD机试考点合集:华为OD机试2024年真题题库(E卷+D卷+C卷)_华为od机试题库-CSDN博客 题目描述 有一名 科学家只 想要从一台古董电脑中拷贝文件到自己的电脑中加以研究。 但此电脑除了有一个3.5寸软盘驱动器以外,没有任何手段可以将文件持贝出来,而且只有一张软盘…

第四十三篇——零和博弈(鞍点理论):如何找到双方的平衡点?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 这篇文章再读依然茅塞顿开;有很多需要自己去吸收的东西&#…

ESP32 ESP-IDF TFT-LCD(ST7735 128x160)自定义组件驱动显示

ESP32 ESP-IDF TFT-LCD(ST7735 128x160)自定义组件驱动显示 🌿驱动参考来源:https://blog.csdn.net/weixin_59250390/article/details/142691848📍个人相关驱动内容文章:《ESP32 ESP-IDF TFT-LCD(ST7735 128x160) LVGL基本配置和使…

请解释一下Standford Alpaca格式、sharegpt数据格式-------deepseek问答记录

1 Standford Alpaca格式 json格式数据。Stanford Alpaca 格式是一种用于训练和评估自然语言处理(NLP)模型的数据格式,特别是在指令跟随任务中。它由斯坦福大学的研究团队开发,旨在帮助模型理解和执行自然语言指令。以下是该格式的…

数据治理中 大数据处理一般都遵循哪些原则

在数据治理中,大数据处理通常遵循以下原则: 最小化原则:企业应只收集实现特定目的所需的数据,避免数据冗余和安全风险。 合法性原则:企业必须遵守相关法律法规,确保数据处理符合法律要求,降低法…

Python 基础-使用dict和set

dict Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 举个例子,假设要根据同学的名字查找对应的成绩&am…

《模式和状态管理》知识总结

一、ECUM 1.1 缩略语 我在这里列出的一些名词的含义只是我在学习过程中自己并不知晓的名词,有其他不会的名词可以自行阅读文档。(会读文档真嘟很重要) Callback:回调函数,由高级的模块提供,由低级的模块…

基于语音的阿尔茨海默病检测识别

摘要 阿尔茨海默病 (AD) 是一种进行性神经退行性疾病,会严重损害认知功能,导致记忆力减退和其他行为改变。它是全球第七大死因,有数百万人受到影响。早期准确检测 AD 对于改善患者预后和减缓疾病进展至关重要。机器学习…

Bom详解和Dom详解

Javascript的数据类型 1.BOM(浏览器对象模型)1.1window对象(1)全局作用域:(2)窗口属性:(3)弹窗和对话框:(4)定时器:(5)导航和历史:(6)打开和关闭窗口: 1.2navigator对象(1)浏览器信息属性:(2)浏…

openharmony中HDF驱动框架关键流程说明-观察者模式

在分析openharmony 5.0的HDF驱动框架时我们会发现用了很多面向对象的思想,例如类继承、接口、单例类等,本来应该是好事情,但使用时对象之间的关系交错复杂,不太符合linux内核分层分模块的思路,导致整体理解起来比较困难…

深度学习框架及其常用模型文件保存格式

在深度学习领域,不同的框架有各自常用的模型文件保存格式。了解这些格式对于模型的训练、保存、部署和分享都非常重要。下面将详细介绍几种常见深度学习框架及其对应的模型文件保存格式。 1. PyTorch 框架 1.1 文件格式 .pt .pth 1.2 说明 这两种文件格式本质上…

Java字符串到底能有多长

文章目录 编译期运行期实际开发建议总结编译期 在编写代码时,直接写在代码里的字符串(硬编码字符串)有一个长度限制。具体来说,字符串的最大长度不能超过65534个字符。如果超过这个限制,编译器会报错。 当你在代码里直接写字符串时: String text = "我是一个很长很…

blender骨骼分层问题:某一层的骨骼怎么移动到第一层

一、原生Blender骨骼分层操作方法 1. 进入姿态模式 按A选中骨骼 →按M →鼠标左键点击相应骨骼层 注意:Blender原生界面中,骨骼层是通过姿态模式下的快捷键M勾选框直接控制的,每个勾选框对应一个层(共32层)。移动骨…

一.AI大模型开发-初识机器学习

机器学习基本概念 前言 本文主要介绍了深度学习基础,包括机器学习、深度学习的概念,机器学习的两种典型任务分类任务和回归任务,机器学习中的基础名词解释以及模型训练的基本流程等。 一.认识机器学习 1.人工智能和机器学习 人工智能&am…

cornerstone3D学习笔记-MPR

最近在研究如何利用cornerstone3D (v1.70.13) 来实现MPR功能,找到它的一个demo -- volumeBasic, 运行效果如下图 看了下主程序的示例代码,非常简单,可以说corestone3D这个库把很多细节都封装起来了,使得调用者可以很简单的快速实…

使用 Go-DeepSeek 轻松调用 DeepSeek 模型:从在线 API 到本地部署

引言 DeepSeek 是一个强大的 AI 模型平台,支持多种自然语言处理任务,如对话生成、代码补全和函数调用。为了方便 Go 开发者快速集成 DeepSeek 的功能,我开发了一个非官方的 Go 客户端库:go-deepseek。本文将详细介绍如何使用该库…

VSCode 实用快捷键

前文 VSCode 作为文本编辑神器, 熟练使用其快捷键更是效率翻倍, 本文介绍 VSCode 常用的实用的快捷键 实用快捷键 涉及到文本操作, 搜索定位, 多光标, 面板打开等快捷键 功能快捷键复制光标当前行 (不需要鼠标选中) Ctrl C 剪切光标当前行 (不需要鼠标选中) Ctrl X 当前行下…

28、深度学习-自学之路-NLP自然语言处理-做一个完形填空,让机器学习更多的内容程序展示

import sys,random,math from collections import Counter import numpy as npnp.random.seed(1) random.seed(1) f open(reviews.txt) raw_reviews f.readlines() f.close()tokens list(map(lambda x:(x.split(" ")),raw_reviews))#wordcnt Counter() 这行代码的…

用deepseek学大模型08-卷积神经网络(CNN)

yuanbao.tencent.com 从入门到精通卷积神经网络(CNN),着重介绍的目标函数,损失函数,梯度下降 标量和矩阵形式的数学推导,pytorch真实能跑的代码案例以及模型,数据,预测结果的可视化展示, 模型应用场景和优缺点&#xf…