Elasticsearch:基于多个 kNN 字段对文档进行评分

2024-06-02 15:20

本文主要是介绍Elasticsearch:基于多个 kNN 字段对文档进行评分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:来自 Elastic Madhusudhan Konda

通过具有多个 kNN 字段的最接近的文档对文档进行评分

Elasticsearch 不仅仅是一个词法(文本)搜索引擎。 Elasticsearch 是多功能搜索引擎,除了传统的文本匹配之外,还支持 k 最近邻 (kNN) 搜索以及语义搜索。

Elasticsearch 中的 kNN 搜索主要用于查找多维空间中给定点的 “最近邻居”。文档被表示为一组数字(向量),在搜索时,kNN 特征会获取更接近查询向量的相关文档。 kNN 搜索通常应用于涉及向量的场景,其中向量是通过使用深度神经网络的 “嵌入” 过程从文本、图像或音频创建的。

另一方面,语义搜索是一种由自然语言处理特征驱动的搜索,它有助于根据意图和含义搜索相关结果,而不仅仅是文本匹配。

在本文中,我们的重点是搜索具有多个 kNN 字段的文档,并根据多个 kNN 向量字段对结果文档进行评分。

由于我们将在本文中详细了解 kNN 搜索,因此让我们花几分钟时间详细了解 kNN 的机制。

kNN 机制

kNN(k 最近邻居)获取的搜索结果几乎是最接近给定用户查询的 k 个文档(使用算法测量)。

它的工作方式是通过计算向量之间的距离(通常是欧几里得相似度或余弦相似度)。当我们使用 kNN 对数据集执行查询时,Elasticsearch 会找到最接近我们的查询向量的前 “k” 个条目。

在执行与搜索相关的活动以获取结果之前,必须使用适当的嵌入对索引进行预处理 —— 嵌入是向量化数据的术语。这些字段的类型是 dense_vector,用于保存数值数据。

让我们举个例子:

如果你有图像数据集,并且已使用神经网络将这些图像转换为向量,则可以使用 kNN 搜索来查找与查询图像最相似的图像。如果你提供 “披萨” 图像的向量表示,kNN 可以帮助你找到视觉上相似的其他图像,例如薄煎饼,也许还有意大利面:)

kNN 搜索是关于在向量空间中查找最近的数据点,因此适用于文本或图像嵌入的相似性搜索。相比之下,语义搜索是为了理解搜索查询中单词的含义和上下文,使其对于意图和上下文都很重要的基于文本的搜索非常强大。

为文当打分

当你有多个 k 最近邻 (kNN) 字段时,根据最接近的文档对文档进行评分需要利用 Elasticsearch 处理向量相似性的能力来对文档进行排名。这种方法在语义搜索和推荐引擎等场景中特别有用。或者我们正在处理多维数据并需要基于多个方面(字段)找到 “最接近” 或最相似的项目的情况。

文本嵌入(text embedding)及向量字段

让我们以电影(movies)索引为例,它由一些文件组成,例如标题(title)、概要(synopsis)等。我们将使用常见的数据类型(例如文本数据类型)来表示它们。除了这些普通字段之外,我们还将创建另外两个字段:title_vector 和 synopsis_vector 字段 - 顾名思义 - 它们是密集向量数据类型字段。这意味着,数据将使用称为 “文本嵌入” 的过程进行向量化。

嵌入模型是一个自然语言处理神经网络,它将输入转换为数字数组。然后,向量化数据将存储在密集向量类型字段中。数据文档可以有多个字段,包括一些用于存储向量数据的 dense_vector 字段。

因此,在下一节中,我们将混合使用普通字段和 kNN 字段来创建索引。

使用 kNN 字段创建索引

让我们创建一个名为 movies 的索引,其中包含示例电影文档。我们的文档将有多个字段,包括几个用于存储向量数据的 kNN 字段。以下片段演示了索引映射代码:

PUT /movies
{"mappings": {"properties": {"title": {"type": "text"},"title_vector.predicted_value": {"type": "dense_vector","dims": 384},"synopsis": {"type": "text"},"synopsis_vector.predicted_value": {"type": "dense_vector","dims": 384},"genre": {"type": "text"}}}
}

值得注意的是,文本类型的 title 字段有一个等效的向量类型字段:title_vector.predicted_value。类似地,synopsis 的向量字段是 synopsis_vector.predicted_value 字段。此外,密集向量场的维度 (384) 在上面的代码中提到为 dims。这表明模型将为每个摄取的字段生成 384 个维度。我们可以请求在密集向量字段上生成的最大维度是 2048。

执行此脚本将创建一个名为 movies 的新索引,其中包含两个向量字段:title_vector 和 synopsis_vector。

索引示例文档

现在我们有了索引,我们可以索引一些电影并进行搜索。除了 title 和 synopsis 字段外,文档还将包含向量字段。在索引文档之前,我们需要用相应的向量填充文档。以下代码演示了生成向量后的电影文档示例:

POST /movies/_doc/1
{"title": "The Godfather","title_vector": [0.1, 0.5, 3, 4,...], // vectorized data "synopsis": "The aging patriarch of an organized crime dynasty....","synopsis_vector": [0.2, 0.6, 1, 0.7,...] // vectorized data 
}

如你所见,需要准备好向量数据以供文档提取。有几种方法可以做到这一点:

  • 一种是在 Elasticsearch 之外调用 text_embedding 模型上的 inference API 来对数据进行向量化,如上所示(我在这里提到它作为参考,尽管我们更希望使用推理处理器管道)
  • 另一种是设置和使用推理管道。

设置推理处理器(inference processor)

我们可以设置一个摄取管道,该管道将嵌入函数应用于相关字段以生成矢量化数据。例如,以下代码创建 movie_embedding_pipeline 处理器,该处理器将为每个字段生成嵌入并将其添加到文档中:

PUT _ingest/pipeline/movie_embedding_pipeline
{"processors": [{"inference": {"model_id": ".multilingual-e5-small","target_field": "title_vector","field_map": { "title": "text_field" }}},{"inference": {"model_id": ".multilingual-e5-small","target_field": "synopsis_vector","field_map": { "synopsis": "text_field" }}}]
}

摄取管道可能需要一点解释:

  • 两个字段 - title_vector 和 synopsis_vector - 被称为 target_field - 是 dense_vector 字段类型。因此,它们存储由 multilingual-e5-small 嵌入模型生成的向量化数据
  • field_map 提到文档中的字段(在本例中为 title 和 synopsis 字段)被映射到模型的 text_field 字段
  • model_id 声明用于嵌入数据的嵌入模型
  • target_field 是向量化数据将被复制到的字段的名称

执行上述代码将创建一个 movie_embedding_pipeline 摄取管道。也就是说 - 仅包含 title 和 synopsis 的文档将通过附加字段(title_vector 和 synopsis_vector)进行增强,这些字段将具有内容的向量化版本。

索引文档

电影文档将由 title 和 synopsis 字段组成,正如预期的那样 - 因此我们可以按如下所示对其进行索引。请注意,文档通过 URL 中启用的管道处理器进行增强。以下代码片段显示了索引少量电影:

POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "The Godfather","synopsis": "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "Avatar","synopsis": "A paraplegic Marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "Godzilla","synopsis": "The world is beset by the appearance of monstrous creatures, but one of them may be the only one who can save humanity."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "The Good, The Bad and The Ugly","synopsis": "A bounty hunting scam joins two men in an uneasy alliance against a third in a race to find a fortune in gold buried in a remote cemetery."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "A Few Good Men","synopsis": "Military lawyer Lieutenant Daniel Kaffee defends Marines accused of murder. They contend they were acting under orders."
}

我们当然可以使用 _bulk API 来一次性索引文档 - 请查看此 Bulk API 文档以了解更多详细信息。

一旦这些文档被索引,你就可以通过执行搜索查询来获取电影来检查是否添加了向量化内容:

GET movies/_search

这将导致 movies 索引具有由向量化内容组成的两个附加字段,如下图所示:

现在我们已经对文档进行了索引,让我们使用 kNN 搜索功能对这些文档进行搜索。

kNN 搜索

Elasticsearch 中的 k-最近邻搜索会获取最接近给定(查询)向量的向量(文档)。Elasticsearch 支持两种类型的 kNN 搜索:

  • 近似 kNN 搜索
  • 强力(或精确)KNN 搜索

虽然两种搜索都会产生结果,但强力搜索会以最大资源利用率和查询时间为代价找到准确的结果。近似 kNN 足以满足大多数搜索情况,因为它可以提供接近准确的结果。

Elasticsearch 为近似搜索提供 knn 查询,而我们应该使用 script_score 查询进行精确 kNN 搜索。

近似搜索

让我们对 movies 进行近似搜索,如下所示。Elasticsearch 提供了一个 kNN 查询,其中包含由我们的查询要求组成的 query_build_vector 块。让我们先编写代码片段,然后再讨论其组成部分:

GET movies/_search
{"knn": {"field": "title_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "Good"}},"k": 3,"num_candidates": 100},"_source": ["id","title"]
}

传统的搜索查询支持 query 功能,但是 Elasticsearch 引入了 knn 搜索功能作为查询向量的一等公民。

knn 块由我们要搜索的字段组成 - 在本例中,它是标题向量 - title_vector.predicted_value 字段。请记住,这是我们之前在映射中提到的字段的名称。

query_vector_builder 是我们需要提供查询以及嵌入查询所需的模型的地方。在本例中,我们将 multilingual-e5-small 设置为我们的模型,文本只是 “Good”。Elasticsearch 将使用文本嵌入模型 (multilingual-e5-small) 对相关查询进行向量化。然后,它将向量查询与可用的标题向量进行比较。

k 值表示需要返回多少文档作为结果。

此查询应该为我们提供前三份文档:

"hits": [{"_index": "movies","_id": "ZADvgo4BDf-WoG_MTka1","_score": 0.92932993,"_source": {"title": "The Good, The Bad and The Ugly"}},{"_index": "movies","_id": "uJ3wgo4BMlgFmHKKtFSp","_score": 0.91828954,"_source": {"title": "A Few Good Men"}},{"_index": "movies","_id": "tp15fY4BMlgFmHKK6VRV","_score": 0.90952975,"_source": {"title": "The Godfather"}}]

当我们针对片名搜索 “Good” 时,得分最高的电影是《The Good, The Bad and the Ugly》。请注意,即使结果电影不匹配,kNN 搜索也总能得到结果 - 这是 kNN 匹配的固有特性。

记下每个文档的相关性分数 (_score) - 正如预期的那样,文档是根据此分数排序的。

搜索多个 kNN 字段

我们有两个向量字段 - 电影文档中的 title_vector 和 synopsis_vector 字段 - 我们当然可以针对这两个字段进行搜索,并根据组合分数期望得到结果文档。

假设我们想在 title 中搜索 “Good”,但在 synopsis 字段中搜索 “orders”。记得从之前使用 “Good” 的单个 title 字段搜索中,我们检索到了《The Good, The Bad and the Ugly》这部电影。让我们看看根据概要的 “orders” 部分作为搜索条件,将获取哪部电影。

以下代码声明了我们的多 kNN 字段搜索:

POST movies/_search
{"knn":[{"field": "title_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "Good"}},"k": 3,"num_candidates": 100},{"field": "synopsis_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "orders"}},"k": 3,"num_candidates": 100}]
}

正如你所想象的,knn 查询可以接受多个搜索字段作为数组 - 在这里我们从两个字段中提供了搜索条件。答案是 “A Few Good Men”,因为包含 “order” 向量的概要向量就是这部电影。

何时使用多 kNN 字段进行搜索

我们可以使用多个 kNN 字段进行搜索的一些情况如下:

  • 根据图像相似性(视觉 kNN 字段)和推文相似性(文本 kNN 字段)搜索 “tweets”。
  • 根据音频特征(音频作为 kNN 字段)推荐类似的歌曲,如节奏和韵律;可能还有标题/艺术家/流派信息(文本 kNN 字段)。
  • 根据用户行为(用于用户交互的 kNN 字段)和电影/产品属性(基于这些属性的 kNN 字段)推荐电影或产品。

就这样了。在本文中,我们研究了 kNN 搜索的机制,以及当我们有多个向量化字段时如何找到最近的文档。

准备好自己尝试一下了吗?开始免费试用。

想要获得 Elastic 认证吗?了解下一次 Elasticsearch 工程师培训何时开始!

原文:Elasticsearch Scoring: Based on multiple kNN fields — Elastic Search Labs

这篇关于Elasticsearch:基于多个 kNN 字段对文档进行评分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1024342

相关文章

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

企业如何进行员工的网络安全意识培训?

企业网络安全意识培训的重要性         企业网络安全意识培训是提升员工网络安全素质的关键环节。随着网络技术的快速发展,企业面临的网络安全威胁日益增多,员工的网络安全意识和技能水平直接关系到企业的信息安全和业务连续性。因此,企业需要通过系统的网络安全意识培训,提高员工对网络安全的认识和防范能力,从而降低企业在面对潜在安全风险时的损失和影响。 企业网络安全意识培训的方法         企

基于Java医院药品交易系统详细设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W+,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码+数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人  Java精品实战案例《600套》 2023-2025年最值得选择的Java毕业设计选题大全:1000个热

工程文档CAD转换必备!在 Java 中将 DWG 转换为 JPG

Aspose.CAD 是一个独立的类库,以加强Java应用程序处理和渲染CAD图纸,而不需要AutoCAD或任何其他渲染工作流程。该CAD类库允许将DWG, DWT, DWF, DWFX, IFC, PLT, DGN, OBJ, STL, IGES, CFF2文件、布局和图层高质量地转换为PDF和光栅图像格式。 Aspose API支持流行文件格式处理,并允许将各类文档导出或转换为固定布局文件格

使用JWT进行安全通信

在现代Web应用中,安全通信是至关重要的。JSON Web Token(JWT)是一种流行的安全通信方式,它允许用户和服务器之间安全地传输信息。JWT是一种紧凑的、URL安全的表示方法,用于在两方之间传输信息。本文将详细介绍JWT的工作原理,并提供代码示例帮助新人理解和实现JWT。 什么是JWT? JWT是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSO

如何实现一台机器上运行多个MySQL实例?

在一台机器上一个MySQL服务器运行多个MySQL实例有什么好处?这里我先入为主给大家介绍这样做至少存在两个好处(看完这篇文章后理解会更透彻): (1)减轻服务器链接负担 (2)为不同的用户提供不同的mysqld服务器的访问权限以方便这些用户进行自我管理。   下面我介绍具体的实现过程: 一、准备工作     台式机一台、Windows系统、MySQL服务器(我安装的版本是MySQL

ccp之间是不可以直接进行+,-的,要用ccpSub和ccpAdd。

1.  http://www.cnblogs.com/buaashine/archive/2012/11/12/2765691.html  上面有好多的关于数学的方面的知识,cocos2dx可能会用到的 2.学到了   根据tilemap坐标得到层上物体的id int oneTiled=flagLayer->tileGIDt(tilePos);

关于word文档中目录的switch

有很多的switch,下面这篇文章介绍的比较详细,可以参考:http://word.mvps.org/FAQs/Formatting/TOCSwitches.htm