当前位置: 首页 > article >正文

率先实现混合搜索:使用 Elasticsearch 和 Semantic Kernel

作者:来自 Elastic Enrico Zimuel 及 Florian Bernd

混合搜索功能现在已在 .NET Elasticsearch Semantic Kernel 连接器中提供。阅读这篇博客文章了解如何开始使用。

Elasticsearch 已原生集成业内领先的生成式 AI 工具和服务提供商。欢迎观看我们的网络研讨会,了解如何突破 RAG 基础,或在 Elastic 向量数据库上构建可投入生产的应用程序。

为了为你的使用场景构建最佳搜索解决方案,现在就开始免费的云试用,或在本地机器上试用 Elastic 吧。


我们与 Microsoft Semantic Kernel 团队合作,在 .NET Elasticsearch Semantic Kernel 连接器中推出了混合搜索功能 —— 这是首个实现该功能的向量数据库。Microsoft Semantic Kernel 最近宣布支持混合搜索用例,这让客户可以将 Elasticsearch 用于更广泛的应用。Elasticsearch 从 8.8.0 版本起就已支持混合搜索,在本文中,我们将介绍如何将 Elasticsearch 与 Semantic Kernel 结合使用混合搜索。

你可以在这里找到支持混合搜索的最新版本 Elasticsearch Semantic Kernel 连接器。如果你还不熟悉在 .NET 中的 Semantic Kernel 集成 Elasticsearch,建议先阅读我们之前发布的这篇文章。

什么是混合搜索?

混合搜索是一种强大的信息检索策略,它将两种或以上的搜索技术结合进一个搜索算法中。一个典型的用例是将词法搜索(例如 BM25)与语义搜索(例如 kNN)结合使用。通过并行运行这两种策略,用户可以获得更相关的结果,从而整体提升答案质量(见图 1)。

图 1:混合搜索是词法搜索与语义搜索的交集

为了合并结果,我们可以使用不同的策略。Elasticsearch 中的每个查询结果都会生成一个相关文档列表,并按分数值排序。这个分数是一个浮点数,表示文档的相关性,分数越高,相关性越强。

如果我们有两个结果列表,一个来自词汇搜索,另一个来自语义搜索,那么我们该如何将它们合并?

一种策略是使用 RRF(Reciprocal Rank Fusion)算法。这个算法会使用以下方式重新计算每个文档的得分:

score = 0.0
for q in queries:if d in result(q):score += 1.0 / (k + rank(result(q), d))
return score

其中:

  • k 是一个排序常数

  • q 是查询集合中的一个查询(例如词法查询和语义查询)

  • d 是查询 q 返回结果中的一个文档

  • result(q) 是查询 q 的结果集

  • rank(result(q), d) 是文档 d 在查询 q 的结果中的排名位置

例如,假设我们运行一次混合搜索查询,目标是获取排名前 3 的重要文档。我们使用词法查询和语义查询,并设置 k = 1

词法查询的结果按顺序为:

  1. Doc4
  2. Doc3
  3. Doc2
  4. Doc1

这意味着最相关的文档是 Doc4,其次是 Doc3、Doc2 和 Doc1。

语义查询的结果按顺序为:

  1. Doc3
  2. Doc2
  3. Doc1
  4. Doc5

接下来我们可以使用之前提到的算法计算 RRF 分数。在下表中,我们分别计算了词法查询和语义查询的分数,然后将两者相加得到最终的 RRF 分数。

DocumentsLexicalSemanticRRF
Doc11/(1+4)1/(1+3)⅕ + ¼ = 0.4500
Doc21/(1+3)1/(1+2)¼ + ⅓ = 0.5833
Doc31/(1+2)1/(1+1)⅓ + ½ = 0.8333
Doc41/(1+1)0½ = 0.5
Doc501/(1+4)⅕ = 0.2

对 RRF 分数进行排序后,我们得到以下结果:

  1. Doc3
  2. Doc2
  3. Doc4
  4. Doc1
  5. Doc5

最后,排名前三的结果是:Doc3、Doc2 和 Doc4。

RRF 算法是 Semantic Kernel 中 Elasticsearch 混合搜索集成默认使用的算法。

Semantic Kernel 中的混合搜索集成

最新版本的 Elasticsearch Semantic Kernel 连接器在 ElasticsearchVectorStoreRecordCollection<TKey, TRecord> 类型中实现了全新的 IHybridSearch 接口。该接口在现有功能基础上新增了一个方法,定义如下:

HybridSearchAsync<TVector>(TVector vector,ICollection<string> keywords,int top,HybridSearchOptions<TRecord>? options = null,[EnumeratorCancellation] CancellationToken cancellationToken = default)

其中:

  • vector 是用于语义搜索的 TVector(使用 kNN);

  • keywords 包含一组字符串,用于 Elasticsearch 的词法搜索 terms 查询(集合中的词被视为 OR 条件);

  • top 表示返回的最大文档数;

  • options 是一些选项,比如用于向量搜索的向量属性/字段,用于词法搜索的属性/字段,或用 .NET 表达式树语法指定的额外预过滤条件;

  • cancellationToken 是用于取消异步操作的 CancellationToken;

例如,假设我们重用之前文章《如何使用 Elasticsearch 向量存储连接器进行 Microsoft Semantic Kernel AI Agent 开发》中介绍的酒店数据集。

我们可以执行一次混合搜索查询,检索包含关键词 “downtown” 或 “luxury”,并结合使用向量 {1, 2, 3} 的语义搜索,返回排名前 5 的酒店:

var results = (collection as IKeywordHybridSearch<Hotel>).HybridSearchAsync(new float[] { 1, 2, 3 },["downtown", "luxury"],5).ToBlockingEnumerable().ToList();

如果我们想在执行混合搜索前应用过滤条件,可以使用 HybridSearchOptions。例如,假设我们只想考虑靠海滩的酒店,可以通过如下方式添加过滤器:Filter = x => x.Description.Contains("beachfront")。

var results = (collection as IKeywordHybridSearch<Hotel>).HybridSearchAsync(new float[] { 1, 2, 3 },["downtown", "luxury"],5,new HybridSearchOptions<Hotel>{Filter = x => x.Description.Contains("beachfront")}).ToBlockingEnumerable().ToList();

这样,搜索将只考虑靠海滩的酒店,然后应用之前的混合搜索条件(提示:基于表达式树的过滤也适用于 Semantic Kernel 中的常规向量搜索)。

最近版本的 Semantic Kernel 对基于表达式树的过滤支持,是对之前过滤 API 的很大改进。目前,Elasticsearch Semantic Kernel 连接器只支持比较操作符(=、!=、<、<=、>、>=)和布尔操作符(!、&&、||)。更多操作,如 collection.Contains(),将很快实现。

针对 .NET 应用的混合搜索,结合 Elasticsearch 和 Semantic Kernel

本文介绍了如何使用 Semantic Kernel 的混合搜索功能与 Elasticsearch 集成。展示了如何结合词法搜索和语义搜索以提升检索效果。该技术可用于改进信息检索系统,例如基于检索增强生成(RAG)。此外,我们还讲解了如何使用 HybridSearchOptions 对象应用预过滤,过滤条件可用 .NET 表达式树语法表达。

虽然 Reciprocal Rank Fusion 为结合词法和语义分数的混合搜索提供了稳健的默认方案 —— 正如本博客中使用 Semantic Kernel 展示的那样,Elasticsearch 还广泛支持其他检索器样式。这包括线性检索器(Linear Retriever)等选项,允许用户在 RRF 默认之外轻松定制组合策略,实现混合方法下的搜索相关性微调。

未来,我们将继续扩展对 Semantic Kernel 的支持,集成 Elasticsearch 的最新功能。祝你混合搜索愉快!

原文:First to hybrid search: with Elasticsearch and Semantic Kernel - Elasticsearch Labs

http://www.lryc.cn/news/2384634.html

相关文章:

  • uni-app(4):js语法、css语法
  • 基于SpringBoot的网上租赁系统设计与实现
  • kafka吞吐量提升总结
  • AI浪潮下,第五消费时代的商业进化密码
  • Vue组件开发深度指南:构建可复用与可维护的UI
  • 青少年编程与数学 02-019 Rust 编程基础 20课题、面向对象
  • Jouier 普及组十连测 R4
  • bi平台是什么意思?bi平台具体有什么作用?
  • 【机械视觉】Halcon—【二、Halcon算子全面介绍(超详细版)】
  • Redis从入门到实战 - 原理篇
  • 26考研|高等代数:线性变换
  • VSCode如何像Pycharm一样“““回车快速生成函数注释文档?如何设置文档的样式?autoDocstring如何设置自定义模板?
  • Linux(5)——再谈操作系统
  • TCP实现双向通信练习题
  • PCIe学习笔记(3)链路初始化和训练
  • Python爬虫(35)Python爬虫高阶:基于Docker集群的动态页面自动化采集系统实战
  • 运维打铁:生产服务器用户权限管理方案全解析
  • 华为云Astro前端页面数据模型选型及绑定IoTDA物联网数据实施指南
  • 【工具类】常用的工具类——CollectionUtil
  • Oracle 11g导出数据库结构和数据
  • 零基础设计模式——创建型模式 - 抽象工厂模式
  • 解锁内心的冲突:神经症冲突的理解与解决之道
  • JVM—Java对象
  • Redisson读写锁和分布式锁的项目实践
  • Https流式输出一次输出一大段,一卡一卡的-解决方案
  • SkyWalking高频采集泄漏线程导致CPU满载排查思路
  • 【HarmonyOS 5】Map Kit 地图服务之应用内地图加载
  • ld: cpu type/subtype in slice (arm64e.old) does not match fat header (arm64e)
  • sentinel核心原理-高频问题
  • 通过vue-pdf和print-js实现PDF和图片在线预览