在 RAG 流程中提高检索效果:融合传统关键词与现代向量搜索的混合式搜索技术 [译]

探讨如何结合传统关键词搜索与现代向量搜索来获得更相关的搜索结果

混合搜索栏
混合搜索栏

拥有混合搜索功能的搜索栏

最近,随着开发者们对检索增强生成(RAG)技术的兴趣激增,如何构建能达到生产级性能的 RAG 流程成了新的挑战。正如生活中的其他领域,帕累托原则(即 80/20 法则)在 RAG 流程中同样适用:初始的 80% 相对容易实现,而要让剩余的 20% 满足生产标准就比较困难了。

提升 RAG 流程检索部分性能的一个常见解决方案是采用混合搜索。

那些在构建 RAG 流程方面有经验的开发者们已经开始分享他们的心得。其中一个反复出现的主题就是通过混合搜索来增强 RAG 流程的检索部分。

本文将向您介绍混合搜索的概念,解释它如何通过提供更相关的搜索结果来增强您的 RAG 流程性能,以及在何种情况下适合使用它。

混合搜索是什么?

混合搜索是一种融合两种或更多搜索算法的先进技术,目的是提升搜索结果的相关性和准确性。通常情况下,混合搜索指的是将传统的基于关键词的搜索与现代的基于向量的搜索结合起来。

在过去,搜索引擎主要依赖于关键词搜索。但随着机器学习(ML)的发展,基于向量嵌入的新搜索技术——也就是向量或语义搜索——开始流行。这种技术让我们能够根据数据的语义意义进行跨语言和多模态的搜索。不过,这两种搜索方式都有自己的优缺点:

  • 关键词搜索: 它在匹配特定术语(如产品名或专业术语)方面表现出色,但对拼写错误和同义词较为敏感,可能会忽略一些重要的上下文信息。
  • 向量或语义搜索: 它能够基于数据的语义含义进行多语言和多模态搜索,对拼写错误具有较好的容错性,但可能会忽视关键词。此外,它的效果依赖于向量嵌入的质量,并对非专业领域的术语较为敏感。

混合搜索结合了这两种方法的优点,特别是在文本搜索方面,能够显著提高搜索结果的相关性和准确性。

比如,当搜索“如何使用 .concat() 合并两个 Pandas 数据框?”这个问题时,关键词搜索可以帮助找到涉及 .concat() 方法的相关信息。同时,由于“合并(concat)”一词有诸如“组合”、“连接”和“串联”等多种同义词,语义搜索的上下文识别功能在这里就显得非常有用(更多详情参见 何时使用混合搜索)。

此外,你还可以在这个实时 演示 中体验不同的关键词搜索、语义搜索和混合搜索查询,用来搜索电影(详细实现可参考 这篇文章)。

混合搜索是如何工作的?

混合搜索将关键词搜索和向量搜索的结果结合起来,通过重新排序这些结果来实现两种搜索技术的融合。

基于关键词的搜索

在混合搜索中,基于关键词的搜索经常利用一种称为“稀疏嵌入”的表示方式,因此也被称为稀疏向量搜索。稀疏嵌入是大部分值为零,仅少数值为非零的向量,如下所示:

[0, 0, 0, 0, 0, 1, 0, 0, 0, 24, 3, 0, 0, 0, 0, ...]

生成稀疏嵌入可以采用多种算法。最常用的算法是 BM25(最佳匹配 25),这个算法是在传统的 TF-IDF(词频 - 逆文档频率)方法的基础上进行改进的。简而言之,BM25 通过比较一个词在特定文档中的出现频率与在所有文档中的普遍频率,来确定这个词的重要性。

向量搜索

向量搜索是随着机器学习技术的发展而兴起的一种现代搜索技术。如 Transformers 等现代机器学习算法能够为各种数据对象(比如文本、图像等)生成一种数值表示形式,即向量嵌入。

这些向量嵌入通常信息密集,大部分由非零值构成(密集向量),如下例所示。这也是向量搜索被称为密集向量搜索的原因。

[0.634, 0.234, 0.867, 0.042, 0.249, 0.093, 0.029, 0.123, 0.234, ...]

在向量搜索中,搜索查询会被转化为与数据对象相同的向量空间中的一个向量。然后,系统会利用这个向量来计算哪些数据对象与其最接近,这一计算通常基于某种特定的相似度度量标准,例如余弦距离。搜索结果将按照与查询向量的相似度进行排序,展示最相似的数据对象。

融合关键词与向量搜索结果的新方法

当我们使用关键词搜索和向量搜索时,它们各自会带来一系列结果,这些结果按照它们被计算出来的相关性进行排序。这两套结果需要有效地结合起来。

根据 Benham 和 Culpepper 的研究 [1],合并这两种搜索结果的排名有很多不同的方法。

一般来讲,首先要对搜索结果进行评分。这些评分可以基于某些标准,例如余弦距离,或者仅仅是基于搜索结果的排名。

接着,我们会用一个名为 alpha 的参数来对这些分数进行加权,这个参数决定了每种搜索算法的重要性,并影响最终结果的排名。

hybrid_score = (1 - alpha) * sparse_score + alpha * dense_score

通常情况下,alpha 的取值在 0 和 1 之间,具体来说:

  • alpha = 1:完全基于向量的搜索
  • alpha = 0:完全基于关键词的搜索

下图是一个简单的示例,显示了在 alpha = 0.5 时,基于排名的关键词搜索与向量搜索是如何融合的。

这是一个展示关键词搜索、向量搜索与混合搜索不同排名的简单示例。
这是一个展示关键词搜索、向量搜索与混合搜索不同排名的简单示例。

这个示例简单阐述了在排名基础上,以 alpha 值为 0.5 时,关键词和向量搜索结果是如何被融合的(图片来源:作者,灵感来自混合搜索解释

如何利用混合搜索提升您的 RAG 流程性能?

RAG(检索增强生成)流程有很多调整点来提高性能。其中之一是提高检索内容的相关性,进而输入到大语言模型(LLM)中。因为如果检索内容对于回答特定问题不相关,LLM 同样难以生成相关答案。

你需要根据自己的上下文类型和查询需求,选择三种搜索技术中哪一种最适合你的 RAG 应用。因此,参数 **alpha**,用于控制基于关键词的搜索与语义搜索之间的权重,被视为一个需要调整的关键参数。

在一个典型的使用 LangChain 的 RAG 流程中,你会这样定义检索器组件:通过设置 vectorstore 组件作为检索器,并使用 .as_retriever() 方法。例如:

## 定义和填充向量存储
## 更多详情请参考 https://towardsdatascience.com/retrieval-augmented-generation-rag-from-theory-to-langchain-implementation-4e9bd5f6a4f2
vectorstore = ...
## 将 vectorstore 设置为检索工具
retriever = vectorstore.as_retriever()

但是,这种方式只能开启语义搜索功能。如果您希望在 LangChain 中启用混合搜索功能,您需要定义一个具备混合搜索功能的特定 retriever 组件,比如 WeaviateHybridSearchRetriever:

from langchain.retrievers.weaviate_hybrid_search import WeaviateHybridSearchRetriever
retriever = WeaviateHybridSearchRetriever(
alpha = 0.5, # 默认值为 0.5,意味着关键词搜索和语义搜索具有相同的权重
client = client, # 传递给 Weaviate 客户端的参数
index_name = "LangChain", # 使用的索引名
text_key = "text", # 使用的文本键名
attributes = [], # 结果中返回的属性
)

普通的 RAG 管道 其余部分保持不变。

通过这一小改动,您可以试验关键词搜索与向量搜索之间不同的权重分配。请注意,将 alpha = 1 设置为完全的语义搜索,相当于直接使用 vectorstore 组件定义检索工具 (retriever = vectorstore.as_retriever())。

何时使用混合搜索:混合搜索的实际应用场景

混合搜索特别适用于那些既需要语义搜索功能以营造更接近人类的搜索体验,又需要对特定的词语,如产品名称或序列号,进行精准匹配的场合。

一个典型的应用实例是 Stack Overflow 平台。最近,该平台借助混合搜索技术,引入了语义搜索功能,从而升级了它的搜索能力。

像人类一样提问:Stack Overflow 实施语义搜索的经验

起初,Stack Overflow 使用 TF-IDF 方法将关键词与文档匹配 [2]。但描述编程问题有时并不简单,不同的描述词汇可能导致完全不同的搜索结果(比如,合并两个 Pandas DataFrame 可以通过多种方式,如合并、连接或串联)。在这种情况下,一种更加考虑上下文的搜索方法,例如语义搜索,将更加有效。

然而,Stack Overflow 的另一个常见用途是复制粘贴错误信息。对于这种情况,精确的关键词匹配则成为首选。此外,对于方法名和参数名(例如 Pandas 中的 .read_csv()),精确匹配同样重要。

可以想见,很多类似的现实场景既需要能够理解上下文的语义搜索,也依赖于精确的关键词匹配。这些应用场景从实施混合搜索中获益良多。

概述

本文介绍了混合搜索,这是一种结合了关键词和向量搜索的方法。混合搜索融合了不同搜索算法的结果,并对这些结果进行重新排序。

在混合搜索中,参数 alpha 用于控制关键词搜索和语义搜索之间的权重分配。这个 alpha 参数可以视为在 RAG 管道中调整以提升搜索结果精准度的一个超参数。

借助 Stack Overflow [2] 的案例分析,我们展示了在某些情况下,语义搜索能够提升搜索体验,但对于特定术语,精确的关键词匹配仍然非常关键。

References

Literature

[1] Benham, R., & Culpepper, J. S. (2017). Risk-reward trade-offs in rank fusion. In Proceedings of the 22nd Australasian Document Computing Symposium (pp. 1–8).

[2] Haney, D. & Gibson, D. in Stack Overflow Blog. Ask like a human: Implementing semantic search on Stack Overflow (accessed Nov 24, 2023).