使用 Elasticsearch 进行词法和语义搜索

在本博客中,我们将探讨使用 Elasticsearch 检索信息的各种方法,重点是词法和语义搜索。

从向量搜索到强大的 REST API,Elasticsearch 为开发人员提供了最全面的搜索工具包。探索 GitHub 上的示例笔记本,尝试新事物。您也可以立即开始免费试用在本地运行 Elasticsearch

搜索是根据您的搜索查询或组合查询查找最相关信息的过程,相关搜索结果是与这些查询最匹配的文档。尽管与搜索相关的挑战和方法有多种,但最终目标始终不变,即尽可能找到问题的最佳答案

考虑到这一目标,在本篇博文中,我们将探讨使用 Elasticsearch 检索信息的不同方法,重点关注文本搜索:词法搜索和语义搜索。

准备工作

为此,我们将提供 Python 示例,演示在模拟电子商务产品信息生成的数据集上进行搜索的各种情况。

该数据集包含 2,500 多种产品,每种产品都有说明。这些产品分为 76 个不同的产品类别,每个类别包含的产品数量各不相同,如下所示:

树状地图可视化 - category.keyword 的前 22 个值(产品类别)

安装时您需要

我们将使用 Elastic Cloud,可免费试用

除了本博文提供的搜索查询外,Python 笔记本还能指导您完成以下过程:

  • 使用 Python 客户端与我们的弹性部署建立连接
  • 将文本嵌入模型载入 Elasticsearch 集群
  • 创建一个索引,其中包含用于索引特征向量和密集向量的映射。
  • 创建带推理处理器的摄取管道,用于文本嵌入和文本扩展

词汇检索--稀疏检索

Elasticsearch 根据文本查询对文档进行相关性排序的经典方法是使用BM25模型的 Lucene 实现,这是一种用于词法搜索的稀疏模型。这种方法沿用了传统的文本搜索方法,即寻找完全匹配的术语。

为了实现这种搜索,Elasticsearch 通过执行文本分析将文本字段数据转换为可搜索格式。

文本分析 分析器 执行, 分析器 是一套规则,用于管理提取相关词组以供搜索的过程。一个分析器必须有一个 标记符。标记化器接收字符流,并将其分解为单个标记(通常是单个单词),就像下面的例子一样:

输出

在本例中,我们使用的是默认分析器--标准分析器,它能提供基于英语语法的标记化,因此能很好地满足大多数使用要求。标记化可实现单个术语的匹配,但每个标记仍按字面进行匹配。

如果您想个性化搜索体验,可以选择不同的 内置分析器。例如,通过更新代码以使用停顿分析器,就能在任何非字母字符处将文本分解为词块,并支持删除停顿词。

输出

当内置分析器无法满足您的需求时,您可以创建一个 自定义分析器 ,该 分析器 使用零个或多个 字符过滤器 、一个 标记器 和零个或多个 标记过滤器的 适当组合。

在上述结合了标记符号化器和标记符号过滤器的示例中,文本将先由 小写过滤器 进行 小写 处理,然后再由 同义词标记符号过滤器 进行处理。

词汇匹配

BM25将根据术语的频率及其重要性来衡量文档与给定搜索查询的相关性。

下面的代码执行 匹配 查询,搜索最多两个文档,考虑到 "ecommerce-search " 索引中的 "描述" 字段值和搜索查询 " 大阳台的舒适家具 ".

改进文档的匹配标准可以提高查询的精确度。然而,更具体的结果是以较低的差异容忍度为代价的。

输出

通过分析输出结果,最相关的结果是"芭比娃娃梦幻屋" 产品,属于"玩具" 类别,其描述高度相关,因为其中包括术语"家具" 、"大型""阳台" ,这是唯一一个在描述中有 3 个术语符合搜索查询的产品,该产品也是唯一一个在描述中有术语"阳台"的产品。

排名第二的产品是"舒适摇椅" ,归类为"室内家具" ,其描述包括"舒适" 和"家具" 等术语。数据集中只有 3 种产品至少与该搜索查询的 2 个词匹配,该产品就是其中之一。

"Comfortable"出现在 105 个产品的描述中,"furniture"出现在 4 个产品的描述中,有 4 个不同的类别:玩具室内家具、室外家具和 "猫狗用品& 玩具"。

正如您所看到的,考虑到该查询,最相关的产品是玩具,第二相关的产品是室内家具。如果你想了解分数计算的详细信息,知道为什么这些文档是匹配的,可以将explain__query 参数设置为 true。

尽管这两个结果都是最相关的结果,但考虑到该数据集中的文档数量和术语出现率,查询"大型阳台的舒适家具" 背后的意图是搜索实际大型阳台的家具,不包括玩具和室内家具。

词法搜索相对简单快捷,但也有局限性,因为在不了解用户意图和查询的情况下,不可能总是知道所有可能的术语和同义词。自然语言使用中的一个常见现象是词汇不匹配研究表明,不同的人(同一领域的专家)对同一事物的命名平均有80% 不同。

这些局限性促使我们寻找其他包含语义知识的评分模型。基于变换器的模型擅长处理像自然语言这样的连续输入标记,它通过考虑文档和查询的数学表示来捕捉搜索的基本含义。这样就能对文本进行密集的、上下文感知的矢量表示,为语义搜索提供动力,这是一种查找相关内容的精细方法。

语义搜索 - 密集检索

在这种情况下,将数据转换成有意义的向量值后,利用k-nearest neighbor(kNN)搜索算法在数据集中找到与查询向量最相似的向量表示。Elasticsearch 支持两种 kNN 搜索方法,即精确暴力 kNN近似 kNN(也称为 ANN)。

粗暴的 kNN 可以保证准确的结果,但在处理大型数据集时并不能很好地扩展。近似 kNN 通过牺牲一些精度来提高性能,从而有效地找到近似近邻。

借助 Lucene 对 kNN 搜索和密集矢量索引的支持,Elasticsearch 利用了分层导航小世界 (HNSW) 算法,该算法在各种ann-benchmark 数据集上都表现出了强大的搜索性能。可以使用下面的示例代码在 Python 中执行近似 kNN 搜索。

使用近似 kNN 进行语义搜索

考虑到产品数据集中 " 描述"字段的嵌入情况,该代码块使用 Elasticsearch 的 kNN 返回最多两个描述与" Comfortable furniture for a large balcony " 的矢量化查询 (query_vector_build) 相似的产品。

产品嵌入之前是在摄取管道中生成的,摄取管道中的推理处理器包含 "all-mpnet-base-v2"文本嵌入模型的推理处理器,根据管道中正在摄取的数据进行推理。

选择该模型的依据是使用 "句子转换器评估"在训练过程中,使用不同的类别来评估模型。"all-mpnet-base-v2" 模型在Sentence-Transformers排行榜上显示出最佳平均性能,并在大规模文本嵌入基准 (MTEB)排行榜上占据有利位置。该模型预先训练了 微软/mpnet-base模型,并在 1B 句子对数据集上进行了微调,将句子映射到 768 维的密集向量空间。

此外,还有许多其他模型可以使用,特别是那些针对特定领域数据进行微调的模型。

输出

根据所选模型、 过滤器 近似 kNN 调整,输出结果可能会有所不同

kNN 搜索结果都属于"Outdoor Furniture" 类别,尽管"outdoor" 这个词并没有作为查询的一部分被明确提及,这凸显了语义理解在上下文中的重要性。

密集矢量搜索有几个优点:

  • 启用语义搜索
  • 处理超大数据集的可扩展性
  • 灵活处理各种数据类型

不过,密集矢量搜索也有其自身的挑战

  • 为您的使用案例选择合适的嵌入模式
  • 选定模型后,可能需要对模型进行微调,以优化特定领域数据集的性能,这一过程需要领域专家的参与
  • 此外,索引高维向量的计算成本很高

语义搜索--学习型稀疏检索

让我们来探索另一种方法:学习稀疏检索,这是执行语义搜索的另一种方式。

作为一种稀疏模型,它利用 Elasticsearch 基于 Lucene 的倒排索引,该索引得益于数十年的优化。不过,这种方法不仅仅是用 BM25 等词汇评分功能添加同义词那么简单。相反,它利用更深层次的语言知识将学习到的联想融入其中,以优化相关性。

通过扩展搜索查询以包含原始查询中不存在的相关术语,Elastic Learned Sparse Encoder可以改进稀疏向量嵌入,如下例所示。

利用弹性学习稀疏编码器进行稀疏向量搜索

输出

本例中的结果包括"Garden Furniture" 类别,该类别提供的产品与"Outdoor Furniture" 非常相似。

通过分析"ml.tokens" 、"rank_features" 字段,其中包含学习稀疏检索生成的标记,可以明显看出,在生成的各种标记中,有一些术语虽然不是搜索查询的一部分,但其含义仍然相关,如"relax" (舒适)、"sofa" (家具)和"outdoor" (阳台)。

下面的图片突出显示了查询中的一些术语,包括术语扩展和未扩展术语。

正如观察到的那样,该模型提供了一种上下文感知搜索,有助于缓解词汇不匹配问题,同时提供更多可解释的结果。在不进行特定领域再训练的情况下,它甚至可以超越密集向量模型。

在搜索方面,没有放之四海而皆准的解决方案。这些检索方法各有所长,但也面临挑战。根据不同的使用情况,最佳选择可能会有所变化。通常情况下,不同检索方法的最佳结果是互补的。因此,为了提高相关性,我们要把每种方法的优势结合起来。

实现混合搜索的方法有多种,包括线性组合、给每个得分加权和互惠等级融合(RRF),其中互惠等级融合无需指定权重。

在这段代码中,我们使用两个查询值为"大阳台的餐桌和舒适的椅子" 进行了混合搜索。我们没有使用"家具" 作为搜索词,而是指定了我们要查找的内容,并且两个搜索都考虑了相同的字段值,即"描述" 。排名由 BM25 和 ELSER 分数等权重的线性组合确定。

输出

在下面的代码中,我们将对查询使用相同的值,但会使用对等排名融合方法合并 BM25(查询参数)和 kNN(knn 参数)的得分,对文档进行合并和排名。

RRF 功能处于技术预览阶段。在全球大会之前,语法可能会有所改变。

输出

在这里,我们还可以使用不同的字段和值,Python 笔记本中提供了其中一些示例。

正如您所看到的,有了 Elasticsearch,您就可以两全其美:传统的词法搜索和矢量搜索(无论是稀疏搜索还是密集搜索),以实现您的目标并找到问题的最佳答案。

如果您想继续了解这里提到的方法,这些博客会很有用:

Elasticsearch 提供了矢量数据库以及构建矢量搜索所需的所有工具:

结论

在这篇博文中,我们探讨了使用 Elasticsearch 检索信息的各种方法,尤其侧重于文本、词法和语义搜索。为了证明这一点,我们提供了 Python 示例,使用包含电子商务产品信息的数据集展示了不同的搜索场景。

我们回顾了 BM25 的经典词汇搜索,并讨论了其优势和挑战,如词汇不匹配。我们强调了结合语义知识来克服这一问题的重要性。此外,我们还讨论了实现语义搜索的密集矢量搜索,并介绍了与这种检索方法相关的挑战,包括索引高维矢量时的计算成本。

另一方面,我们提到稀疏向量的压缩效果特别好。因此,我们讨论了 Elastic 的 "学习稀疏编码器"(Learned Sparse Encoder),该编码器可扩展搜索查询,以包含原始查询中不存在的相关术语。

在搜索方面,没有放之四海而皆准的解决方案。每种检索方法都有其优势和挑战。因此,我们还讨论了混合搜索的概念。

正如您所看到的,有了 Elasticsearch,您就可以同时拥有传统词法搜索和矢量搜索这两种搜索方式的优点!

准备好开始了吗?查看可用的Python 笔记本并开始免费试用 Elastic Cloud

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用