通过 Elasticsearch 和 Go 使用混合搜索进行地鼠狩猎

作者:CARLY RICHMOND,LAURENT SAINT-FÉLIX

就像动物和编程语言一样,搜索也经历了不同实践的演变,很难在其中做出选择。 在本系列的最后一篇博客中,Carly Richmond 和 Laurent Saint-Félix 将关键字搜索和向量搜索结合起来,使用 Go 客户端在 Elasticsearch 中寻找地鼠(gopher)。

今天构建软件是对终生学习的承诺。 正如你从本系列前面的博客中看到的那样,Carly 最近开始使用 Go。

搜索经历了不同实践的演变。 在你自己的搜索用例之间做出决定可能很困难。 本系列所有代码均以第一部分中介绍的关键字和向量搜索示例为基础。 请继续阅读第 2 部分及第二部分的代码,了解本系列中的所有代码。 在本系列的第 2 部分中,我们将分享如何使用 Elasticsearch 和 Elasticsearch Go 客户端组合向量搜索和关键字搜索的示例。

先决条件

就像本系列的第一部分一样,此示例需要以下先决条件:

  • 安装 Go 版本 1.13 或更高版本
  • 使用 Go 文档中介绍的推荐结构和包管理创建您自己的 Go 存储库
  • 创建你自己的 Elasticsearch 集群,其中填充了一组基于啮齿动物的页面,包括来自维基百科的我们友好的 Gopher:

连接到 Elasticsearch

提醒一下,在我们的示例中,我们将使用 Go 客户端提供的 Typed API。 为任何查询建立安全连接需要使用以下任一配置客户端:

  • 云 ID 和 API 密钥(如果使用 Elastic Cloud)
  • 集群 URL、用户名、密码和证书

连接到位于 Elastic Cloud 上的集群如下所示:

func GetElasticsearchClient() (*elasticsearch.TypedClient, error) {
	var cloudID = os.Getenv("ELASTIC_CLOUD_ID")
	var apiKey = os.Getenv("ELASTIC_API_KEY")

	var es, err = elasticsearch.NewTypedClient(elasticsearch.Config{
		CloudID: cloudID,
		APIKey:  apiKey,
		Logger:  &elastictransport.ColorLogger{os.Stdout, true, true},
	})

	if err != nil {
		return nil, fmt.Errorf("unable to connect: %w", err)
	}

	return es, nil
}

然后,client 连接可用于搜索,如后续部分所示。

如果你是使用自己部署的 Elasticsearch 集群,你可以参考文章 “Elasticsearch:运用 Go 语言实现 Elasticsearch 搜索 - 8.x”。

手动配置 boost 参数

当组合任何一组搜索算法时,传统方法是手动配置常量来增强每种查询类型。 具体来说,为每个查询指定一个因素,并将组合结果集与预期集进行比较,以确定查询的召回率。 然后我们重复几组因素并选择最接近我们所需状态的一组。

例如,可以通过在两种查询类型中指定 Boost 字段来将增强系数为 0.8 的单个文本搜索查询与系数较低的 0.2 的 knn 查询组合起来,如下例所示:

func HybridSearchWithBoost(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	var knnBoost float32 = 0.2
	var queryBoost float32 = 0.8

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnQuery{
			Field:         "text_embedding.predicted_value",
			Boost:         &knnBoost,
			K:             10,
			NumCandidates: 10,
			QueryVectorBuilder: &types.QueryVectorBuilder{
				TextEmbedding: &types.TextEmbedding{
					ModelId:   "sentence-transformers__msmarco-minilm-l-12-v3",
					ModelText: term,
				},
			}}).
		Query(&types.Query{
			Match: map[string]types.MatchQuery{
				"title": {
					Query: term,
					Boost: &queryBoost,
				},
			},
		}).
		Do(context.Background())

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}

每个查询的 Boost 选项中指定的因子将添加到文档分数中。 通过比 knn 查询更大的因子增加匹配查询的分数,关键字查询的结果的权重更大。

手动提升的挑战是,特别是如果你不是搜索专家,则需要进行调整以找出导致所需结果集的因素。 这只是尝试随机值以查看什么能让你更接近所需结果集的情况。

倒数排序融合 - Reciprocal Rank Fusion

倒数排序融合 (RRF) 在 Elasticsearch 8.9 中的混合搜索技术预览版中发布。 它的目的是减少与调整相关的学习曲线,并减少尝试因素以优化结果集的时间。

  • D - 文档集
  • R - 一组排名作为 1..|D| 的排列
  • K - 通常默认设置为 60

使用 RRF,通过以下算法混合分数来重新计算文档分数:

score := 0.0
// q is a query in the set of queries (vector and keyword search)
for _, q := range queries {
    // result(q) is the results 
    if document in result(q) {
        // k is a ranking constant (default 60)
        // rank(result(q), d) is the document's rank within result(q) 
        // range from 1 to the window_size (default 100)
        score +=  1.0 / (k + rank(result(q), d))
    }
}

return score

使用 RRF 的优点是我们可以利用 Elasticsearch 中合理的默认值。 排名常数 k 默认为 60。为了在大型数据集上搜索时返回文档的相关性和查询性能之间进行权衡,每个考虑的查询的结果集的大小限制为 window_size 的值,默认为 100 如文档中所述。

k 和 windows_size 也可以在 Go 客户端的 Rank 方法中的 Rrf 配置中进行配置,如下例所示:

func HybridSearchWithRRF(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	// Minimum required window size for the default result size of 10
	var windowSize int64 = 10
	var rankConstant int64 = 42

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnQuery{
			Field:         "text_embedding.predicted_value",
			K:             10,
			NumCandidates: 10,
			QueryVectorBuilder: &types.QueryVectorBuilder{
				TextEmbedding: &types.TextEmbedding{
					ModelId:   "sentence-transformers__msmarco-minilm-l-12-v3",
					ModelText: term,
				},
			}}).
		Query(&types.Query{
			Match: map[string]types.MatchQuery{
				"title": {Query: term},
			},
		}).
		Rank(&types.RankContainer{
			Rrf: &types.RrfRank{
				WindowSize:   &windowSize,
				RankConstant: &rankConstant,
			},
		}).
		Do(context.Background())

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}

结论

在这里,我们讨论了如何使用 Elasticsearch Go 客户端在 Elasticsearch 中组合向量搜索和关键字搜索。

查看 GitHub 存储库以获取本系列中的所有代码。 如果你还没有查看本系列中的所有代码,请查看第 1 部分和第 2 部分。

快乐地鼠狩猎!

原文:Using hybrid search for gopher hunting with Elasticsearch and Go — Elastic Search Labs

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中国建设银行转账模拟器,工商农业邮政中国招商假的回执单,易语言轻松实现

用易语言的选择夹画板黑月透明标签编辑框实现了一个假的转账模拟器,当然我还是加了水印的,这个图片你也用不了,只能是学习研究一下源码的实现逻辑,知道画板是怎么对编辑框输入的内容做出反应的,然后是如何获取画板上面…

C++进阶-STL set/multiset容器和map容器的简单认识

set/multiset容器的简单认识 set基本概念set与multiset 的区别:set容器的构造和赋值set容器的大小和交换set容器的插入与删除set容器的查找和统计set容器-set和multiset的区别set容器内置类型指定排序规则set容器自定义数据类型指定排序规则 pair对组创建map容器的基…

数据拟合、参数估计、插值等数据处理算法

介绍 数据拟合: 数据拟合是通过选择或构建合适的函数模型,将给定的数据点与该函数模型进行匹配和拟合的过程。常见的数据拟合方法包括最小二乘法和非线性最小二乘法。最小二乘法通过最小化实际数据与拟合函数的残差平方和来求解最优拟合参数。非线性最小…

在AutoDL云环境上训练Stable Diffusion Lora模型

AutoDL官网: AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDLAutoDL为您提供专业的GPU租用服务,秒级计费、稳定好用,高规格机房,7x24小时服务。更有算法复现社区,一键复现算法。https://www.autodl.com/ 新建实例…

2023最新最全【Adobe After Effection 2023】下载安装零基础教程【附安装包】

AE2023下载点这里 教学 1.鼠标右击【Ae2023(64bit)】压缩包选择(win11系统需先点击“显示更多选项”)【解压到 Ae2023(64bit)】。 2.打开解压后的文件夹,鼠标右击【Set-up】选择【以管理员身份运行】。 3.点击【文件夹图标】,…

【数据结构】:红黑树

1、红黑树的简介 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构。 红黑树是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来…

基于LDA主题分析的《老友记》情景喜剧数据集的建模分析(文末送书)

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

进程状态和优先级

文章目录 进程状态Linux中具体的进程状态僵尸进程孤儿进程 进程优先级 正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通俗易懂,风趣幽默,忍不住分享一下给大家。 点击跳转到网站。 进程状态 进程在操…

图解算法数据结构-LeetBook-数组03_除本身之外乘积

为了深入了解这些生物群体的生态特征,你们进行了大量的实地观察和数据采集。数组 arrayA 记录了各个生物群体数量数据,其中 arrayA[i] 表示第 i 个生物群体的数量。请返回一个数组 arrayB,该数组为基于数组 arrayA 中的数据计算得出的结果&am…

AI驱动的软件测试,何时可以信赖?

综合编译|TesterHome社区 作者|Yuliya Vasilko,数据工程师 以下为作者观点: 越来越多的组织转向人工智能(AI)驱动的测试解决方案,以简化质量保证流程并提高软件可靠性。 随着对人工智能的依赖程…

动态规划题解

文章目录 杨辉三角杨辉三角2爬楼梯最小花费爬楼梯斐波那契数列比特位计数不同路径 杨辉三角 var generate function(numRows) {//先定义一个空数组var ret[];//遍历行数for(let i 0;i<numRows;i){var cownew Array(i1).fill(1)//定义行内数组数&#xff0c;有多少numrows&a…

[N-133]基于springboot,vue小说网站

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatis-plus 本项…

幼教早教内容付费预约小程序的效果如何

很多家庭对孩子的重视程度很高&#xff0c;尤其加之如今激烈竞争的市场&#xff0c;孩子从小便需要各种提前教育&#xff0c;而相关教培企业也比较多&#xff0c;基于服务高需求度&#xff0c;线下教育与线上课程教育同样重要。 在实际经营中&#xff0c;幼教早教培训机构也面…

关于我用半个月过了软件设计师这件事

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 前言 有关考取软件设计师证书的好处我就不在…

JAIN SIP API详解与GB28181服务器实现

目录 JAIN SIP API 摘要 关于JAIN SIP API API概述 maven坐标 类/接口 Message接口 Request接口 Response接口 即时通讯程序 TextClient代码概述 Message Processor SIP协议栈 发送SIP请求 发送会话消息 接收SIP响应 接收SIP请求 处理错误 总结 GB28181SIP…

HDRP图形入门:HDRP渲染管线depth翻转

新项目开坑HDRP渲染管线&#xff0c;花了些时间把项目开发框架和图形工作流更新到最新版本&#xff0c;其间发现HDRP中深度信息和buildin渲染管线翻转了。 以前的buildin渲染管线&#xff0c;距离摄像机越近depth->0&#xff0c;越远depth->1&#xff0c;这也很好理…

2.3 CE修改器:浮点数扫描

本关需要使用 Cheat Engine 工具对浮点数进行扫描&#xff0c;完成修改任务。浮点数是一种带有小数点的数值&#xff0c;通过“浮点数”扫描方式进行修改。本关中&#xff0c;健康值为单精度浮点数&#xff0c;弹药值为双精度浮点数&#xff0c;需要将这两项数值都修改为 5000 …

【Linux】八、进程通信

进程通信的介绍 目的 数据传输&#xff1a;一个进程将它的数据发送给另一个进程&#xff1b; 资源共享&#xff1a;多个进程间共享资源&#xff1b; 通知事件&#xff1a;一个进程向另一个或一组进程发送消息&#xff0c;同时事件如&#xff0c;进程终止时要通知父进程&#xf…

web前端开发第一次Dreamweave课堂练习/html练习代码《社会主义核心价值观》

目标图片&#xff1a; 文字素材&#xff1a; 社会主义核心价值观 Socialist Core Values 富强、民主、文明、和谐是国家层面的价值目标。 自由、平等、公正、法治是社会层面的价值取向。 爱国、敬业、诚信、友善是公民个人层面的价值准则。 Core socialist values are the…

联系作者方式的教程

首先你应该目前是在付费资源运行效果的展示文章页面&#xff0c;如下所示 然后一直往下滑&#xff0c;滑到这个文章的最下面&#xff0c;就可以看到我的推广名片&#xff0c;最后点击这个名片就可以获取到我的联系方式了~