Elasticsearch 混合搜索 - Hybrid Search

打印 上一主题 下一主题

主题 888|帖子 888|积分 2664

作者:来自 Elastic  Valentin Crettaz

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

本文是三篇系列文章中的最后一篇,深入探究了向量搜索(又称语义搜索)的复杂性以及它在 Elasticsearch 中的实现方式。
第一部门主要先容嵌入(又名向量)的基础知识以及向量搜索的工作原理。
使用第一篇文章中学习到的全部向量搜索知识,第二篇文章将引导你如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。
在第三部门也是最后一部门中,我们将使用前两部门所学到的知识,并在此基础上深入研究如何在 Elasticsearch 中编写强大的混合搜索查询。

混合搜索的需求

在深入研究混合搜索领域之前,让我们快速回顾一下本系列第一篇文章中学到的词汇搜索和语义搜索的区别以及它们如何相互增补。
简而言之,当你可以控制布局化数据并且用户或多或少清晰他们正在搜索的内容时,词汇搜索非常有用。然而,当你必要使非布局化数据可搜索并且你的用户实际上不知道他们正在搜索什么时,语义搜索提供了很大的支持。假如有办法将两者结合起来,从而尽可能地从两者中榨取尽可能多的实质内容,那就太棒了。进入混合搜索!
从某种水平上来说,我们可以将混合搜索看作是词汇搜索和语义搜索的某种 “总和”。然而,假如操作正确,混合搜索会比仅仅将各个部门相加要好得多,产生的结果远远好于单独的词汇搜索或语义搜索。
运行混合搜索查询通常归结为发送至少一个词汇搜索查询和一个语义搜索查询的混合,然后归并两者的结果。词汇搜索结果由相似度算法举行评分,例如 BM25 或 TF-IDF,其分数范围通常无界,因为最高分数取决于倒排索引中存储的术语数量和频率。相比之下,语义搜索结果可以在封闭区间内举行评分,具体取决于所使用的相似度函数(例如,余弦相似度为 [0; 2])。
为了归并混合搜索查询的词汇和语义搜索结果,必要以保持检索到的文档的相对干系性的方式融合两个结果集,这是一个复杂的问题。荣幸的是,有几种现有的方法可以使用;两个非常常见的是凸组合(Convex Combination - CC)和倒数秩融合(Reciprocal Rank Fusion - RRF)。
根本上,凸组合(也称为线性组合)旨在将词汇搜索结果和语义搜索结果的归一化得分按相应的权重 
和 β 举行组合,其中 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 搜索混合以进步干系性。此类混合搜索查询如下所示:
  1. POST my-index/_search
  2. {
  3.   "size": 10,
  4.   "_source": false,
  5.   "fields": [ "price" ],
  6.   "retriever": {
  7.     "standard": {
  8.       "retrievers": [
  9.         {
  10.           "standard": {
  11.             "query": {
  12.               "match": {
  13.                 "text-field": "fox"
  14.               }
  15.             }
  16.           }
  17.         },
  18.         {
  19.           "knn": {
  20.             "field": "title_vector",
  21.             "query_vector": [0.1, 3.2, 2.1],
  22.             "k": 5,
  23.             "num_candidates": 100
  24.           }
  25.         }
  26.       ]
  27.     }
  28.   }
  29. }
复制代码
从上面我们可以看出,混合搜索查询只是使用标准检索器举行的词汇搜索查询(例如,匹配查询)和 knn 检索器中指定的向量搜索查询的组合。此查询首先在全局级别检索前五个向量匹配,然后将它们与词汇匹配相结合,最后返回十个最佳匹配。向量和词汇匹配的组合方式是通过 disjunction(即逻辑或条件),其中每个文档的分数是使用凸组合(Convex Combination盘算的,即其向量和词汇分数的加权和,正如我们之前所见。
Elasticsearch 还支持使用 RRF 排名运行完全雷同的混合查询,你只需使用 rrf 检索器即可完成此操作,如下所示:
  1. POST my-index/_search
  2. {
  3.   "size": 10,
  4.   "_source": false,
  5.   "fields": [ "price" ],
  6.   "retriever": {
  7.     "rrf": {
  8.       "retrievers": [
  9.         ...same as above...
  10.       ],
  11.       "rank_constant": 60,
  12.       "rank_window_size": 100
  13.     }
  14.   }
  15. }
复制代码
此查询的运行方式与之前的查询根本雷同,只是从向量和词汇查询中检索 window_size 文档(例如,在本例中为 100),然后按 RRF 排序,而不是使用 CC 举行评分。最后,返回结果会合从 1 到 size(例如 10)排名靠前的文档。
关于这种混合查询类型最后要注意的是,RRF 排名必要商业允许证(白金版或企业版),但假如你没有,你仍旧可以使用 CC 评分举行混合搜索,大概使用试用允许证,让你享受一个月的完整功能集。

稀疏模子混合搜索

用于查询稀疏模子的第二种混合搜索类型的工作方式与麋集向量完全雷同。下面,我们可以看到这种混合查询的样子:
  1. POST my-index/_search
  2. {
  3.   "_source": false,
  4.   "fields": [ "text-field" ],
  5.   "retriever": {
  6.     "rrf": {
  7.       "retrievers": [
  8.         {
  9.           "standard": {
  10.             "query": {
  11.               "match": {
  12.                 "text-field": "fox"
  13.               }
  14.             }
  15.           }
  16.         },
  17.         {
  18.           "standard": {
  19.             "query": {
  20.               "sparse_vector": {
  21.                 "field": "ml.tokens",
  22.                 "inference_id": ".elser_model_1",
  23.                 "query": "a quick brown fox jumps over a lazy dog"
  24.               }
  25.             }
  26.           }
  27.         }
  28.       ]
  29.     }
  30.   }
  31. }
复制代码
在上面的查询中,我们可以看到检索器数组包罗一个词汇匹配查询以及一个实用于我们之前先容的 ELSER 稀疏模子的语义 sparse_vector 查询。

麋集和稀疏模子的混合搜索

到现在为止,我们已经看到了两种差异的运行混合搜索的方法,具体取决于搜索的是麋集向量空间还是稀疏向量空间。此时,你可能想知道我们是否可以在同一个索引中混合麋集数据和稀疏数据,并且你会很高兴地相识到这确实是可能的。一个具体的应用可能是你必要搜索包罗图像的麋集向量空间和包罗这些图像的文本形貌的稀疏向量空间。我们 standard 准检索器与 knn 检索器结合起来,如许的查询看起来是如许的:
  1. POST my-index/_search
  2. {
  3.   "_source": false,
  4.   "fields": [ "text-field" ],
  5.   "retriever": {
  6.     "rrf": {
  7.       "retrievers": [
  8.         {
  9.           "knn": {
  10.             "field": "image-vector",
  11.             "query_vector": [0.1, 3.2, ..., 2.1],
  12.             "k": 5,
  13.             "num_candidates": 100
  14.           }
  15.         },
  16.         {
  17.           "standard": {
  18.             "query": {
  19.               "sparse_vector": {
  20.                 "field": "ml.tokens",
  21.                 "inference_id": ".elser_model_1",
  22.                 "query": "a quick brown fox jumps over a lazy dog"
  23.               }
  24.             }
  25.           }
  26.         }
  27.       ]
  28.     }
  29.   }
  30. }
复制代码
在上面的有效载荷中,我们可以看到 sparse_vector 查询在 ELSER 稀疏向量空间中搜索图像形貌,在 knn 检索器中,向量搜索查询在麋集向量空间中搜索图像嵌入(例如,用嵌入向量表现的 “brown fox”)。别的,我们还使用 rrf 检索器来发挥 RRF 的作用。
你甚至可以使用另一个 standard 检索器将另一个词汇搜索查询添加到组合中,它看起来像如许:
  1. POST my-index/_search
  2. {
  3.   "_source": false,
  4.   "fields": [ "text-field" ],
  5.   "retriever": {
  6.     "rrf": {
  7.       "retrievers": [
  8.         {
  9.           "knn": {
  10.             "field": "image-vector",
  11.             "query_vector": [0.1, 3.2, ..., 2.1],
  12.             "k": 5,
  13.             "num_candidates": 100
  14.           }
  15.         },
  16.         {
  17.           "standard": {
  18.             "query": {
  19.               "match": {
  20.                 "text-field": "brown fox"
  21.               }
  22.             }
  23.           }
  24.         },
  25.         {
  26.           "standard": {
  27.             "query": {
  28.               "sparse_vector": {
  29.                 "field": "ml.tokens",
  30.                 "inference_id": ".elser_model_1",
  31.                 "query": "a quick brown fox jumps over a lazy dog"
  32.               }
  33.             }
  34.           }
  35.         }
  36.       ]
  37.     }
  38.   }
  39. }
复制代码
上述有效负载强调了我们可以使用一切可能的方法来指定包罗词汇搜索查询、向量搜索查询和语义搜索查询的混合查询。

限定

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


优化

不能否认的是,无论是稀疏向量还是麋集向量,都会变得相当长,从几十维到几千维,具体取决于你使用的推理模子。别的,无论你是在仅包罗几个单词的小句子还是大段文本上运行文本推理,生成的表现含义的嵌入向量将始终具有与你使用的模子中设置的维度一样多的维度。因此,这些向量会占用文档中以及磁盘上的相当多的空间。
解决此问题最明显的优化是设置索引映射以从源文档中删除向量字段(即,dense_vector 和 sparse_vector)。如许做的话,向量值仍旧会被索引和可搜索,但它们不再是源文档的一部门,从而大大减小它们的大小。通过设置映射以从 _source 中清除矢量字段来实现这一点非常简单,如下面的代码所示:
  1. PUT my-index
  2. {
  3.   "mappings": {
  4.     "_source": {
  5.       "excludes": [
  6.         "text_embedding.predicted_value",
  7.         "ml.tokens"
  8.       ]
  9.     },
  10.     "properties": {
  11.       "text": {
  12.         "type": "text"
  13.       },
  14.       "ml": {
  15.         "properties": {
  16.           "tokens": {
  17.             "type": "rank_features"
  18.           }
  19.         }
  20.       },
  21.       "text_embedding": {
  22.         "properties": {
  23.           "predicted_value": {
  24.             "type": "dense_vector",
  25.             "dims": 384,
  26.             "index": true,
  27.             "similarity": "cosine"
  28.           }
  29.         }
  30.       }
  31.     }
  32.   }
  33. }
复制代码
为了向你展示一些具体的数字,我们举行了一个快速实验。我们已使用 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-source376index-without-dense-vector-in-source119index-with-sparse_vector-in-source1,300index-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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

吴旭华

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表