作者:来自 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)。

为了合并结果,我们可以使用不同的策略。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。
词法查询的结果按顺序为:
- Doc4
- Doc3
- Doc2
- Doc1
这意味着最相关的文档是 Doc4,其次是 Doc3、Doc2 和 Doc1。
语义查询的结果按顺序为:
- Doc3
- Doc2
- Doc1
- Doc5
接下来我们可以使用之前提到的算法计算 RRF 分数。在下表中,我们分别计算了词法查询和语义查询的分数,然后将两者相加得到最终的 RRF 分数。
Documents | Lexical | Semantic | RRF |
---|---|---|---|
Doc1 | 1/(1+4) | 1/(1+3) | ⅕ + ¼ = 0.4500 |
Doc2 | 1/(1+3) | 1/(1+2) | ¼ + ⅓ = 0.5833 |
Doc3 | 1/(1+2) | 1/(1+1) | ⅓ + ½ = 0.8333 |
Doc4 | 1/(1+1) | 0 | ½ = 0.5 |
Doc5 | 0 | 1/(1+4) | ⅕ = 0.2 |
对 RRF 分数进行排序后,我们得到以下结果:
- Doc3
- Doc2
- Doc4
- Doc1
- 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