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

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

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

相关文章

【C++】优先级队列介绍与模拟实现

💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…

Hadoop3:MapReduce之InputFormat数据输入过程整体概览(0)

一、MapReduce中数据流向 二、MapTask并行度 1、原理概览 数据块:Block是HDFS物理上把数据分成一块一块。数据块是HDFS存储数据单位。 数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是MapRed…

哇噻,Zabbix7.0 LTS正式发布!功能又进化了!

📢📢📢📣📣📣 作者:IT邦德 中国DBA联盟(ACDU)成员,10余年DBA工作经验, Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主,全网粉丝10万 擅长主流Oracle、My…

全平台自定义小程序源码系统 一个后台控制7端 自主设计属于你的小程序 前后端带完整的安装代码包以及搭建教程

系统概述 在当今数字化时代,小程序以其轻量级、跨平台、即用即走的特点,成为企业、个人及开发者们追捧的热门工具。为了满足不同用户的需求,小编给大家分享一款全平台自定义小程序源码系统。该系统通过一套强大的后台管理系统,实…

游泳预约报名小程序开发源码案例模板之前端功能介绍

越来越多游泳馆使用线上预约报名管理系统,以此来提升游泳馆预约的便捷性以及管理的效率。馆客多小程序是一款实用、便捷的线上运动服务平台,可以让用户轻松预订游泳馆场地并享受自助线上服务,同时也减轻了游泳馆运营压力,提高游泳…

XLA - 加速线性代数

文章目录 一、关于 XLAXLA目标XLA 运作方式 二、Community沟通渠道其他资源存储库 一、关于 XLA XLA : Accelerated Linear Algebra github : https://github.com/openxla/xlaOpenXLA Community : https://github.com/openxla/communityXLA - TensorFlow : https://tensorflo…

Flink SQL查询语法部分详解(提供需求、数据练习复现)

一、Hints 动态表选择:可以在查询表的时候动态修改表的参数配置 1、读取kafka的数据建表 CREATE TABLE students (id STRING,name STRING,age INT,sex STRING,clazz STRING ) WITH (connector kafka,topic students, -- 指定topicproperties.bootstrap.servers …

高效扫码点餐:简餐茶饮外卖新体验

前言 在快节奏的现代生活中,高效便捷的扫码点餐系统正逐渐成为简餐茶饮行业的新宠。这一系统不仅提升了顾客的点餐体验,还优化了门店的运营效率,特别是基于总部多门店的连锁模式,更是将这一优势发挥得淋漓尽致。 一、这款扫码点餐…

如何通过PHP语言实现远程控制多路照明

如何通过PHP语言实现远程控制多路照明呢? 本文描述了使用PHP语言调用HTTP接口,实现控制多路照明,通过多路控制器,可独立远程控制多路照明。 可选用产品:可根据实际场景需求,选择对应的规格 序号设备名称厂…

软理复习范围

1.直觉主义逻辑常采用三值逻辑来处理命题的真值,包括以下三个真值: 真(True):表示命题是确定为真的。假(False):表示命题是确定为假的。未知(Unknown)&#…

Prism 入门02,区域介绍

一.区域概念和使用方式 什么是区域(Region)?区域,在Prism 框架中,区域是模块化的核心功能之一,其主要作用是降低应用程序和模块之间的耦合度 。使用方式:在应用程序的界面中,划分出某块区域,并为这个区域定义一个唯一的区域名称。那么通过这个区域名称,应用程序就可以…

el-tabel名称排序问题

el-tabel排序 最终实现功能如下: 排序限制为: 文件夹>普通文件 数字(0->9)->大写字母(A->Z)->小写字母(a->z)->中文拼音(a->z) 正序…

Unity开发Cosmos使用BNG Framework获取按键信息

Unity开发Cosmos使用BNG Framework获取按键信息 1、新建一个脚本&#xff0c;复制下面代码 using BNG;[Header("Input")]//[Tooltip("The key(s) to use to toggle locomotion type")]public List<ControllerBinding> locomotionToggleInput new …

处理无法拉取GitHub库的解决方案

提交和拉取github上的库总是失败&#xff0c;这里记录一下如何使用代理解决。 首先找到端口&#xff0c;记住它的端口 然后使用git命令 # HTTP/HTTPS 协议 git config ––global http.url.proxy http://127.0.0.1:port # 以 Github 为例 git config ––global http.https:/…

短网址生成原理及使用

生成短网址介绍&#xff1a; 一、定义 短网址&#xff08;Short URL&#xff09;是形式上比较短的网址&#xff0c;它通过将原始冗长的网址进行缩短&#xff0c;方便用户分享和记忆。短网址的生成主要依赖于特定的算法和服务&#xff0c;通过后端服务转向来实现网址的缩短。 …

什么是人机协同翻译

什么是人机协同翻译 序什么是人机协同翻译账号绑定服务开通文档翻译图片翻译体验感受及建议 序 什么是人机协同翻译&#xff0c;为什么会需要人机协同翻译&#xff0c;以及人机协同翻译的效果&#xff0c;应用场景等&#xff0c;本文将关于这些内容一一解答。 什么是人机协同…

大语言模型RAG-将本地大模型封装为langchain的chat model(三)

大语言模型RAG-将本地大模型封装为langchain的chat model&#xff08;三&#xff09; 往期文章&#xff1a; 大语言模型RAG-技术概览 (一) 大语言模型RAG-langchain models (二) 上一期langchain还在0.1时代&#xff0c;这期使用的langchain v0.2已经与之前不兼容了。 本期介…

【调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持】

调试笔记-系列文章目录 调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持 文章目录 调试笔记-系列文章目录调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持 前言一、调试环境操作系统&#xff1a;Ubuntu 22.04.4 LTS编译环境调试目标 二、调试步骤预…

mysql使用sorce、load 导入数据

1、本机安装mysql https://blog.csdn.net/weixin_52687711/article/details/130509902 注意&#xff1a;修改安装路径 配置环境变量 2. 使用sorce命令导入数据 https://blog.csdn.net/2301_82257317/article/details/138332048 使用mysql命令框链接目标数据库 以管理员身份运…

Echarts柱状图数据太多,自定义长度之后,自适应浏览器缩放

不知道是不是最优解&#xff0c;但是当前解决了我遇到的问题&#xff0c;如有更好的方法&#xff0c;希望看到这篇文章的同学可以不吝指导一番&#xff0c;非常感谢 1、问题描述&#xff1a; 因Ecahrts柱状图数据有时多有时少&#xff0c;所以在数据达到一定程度之后&#xff…