大型语言模型(LLMs) 在检索增强生成(RAG)领域 占主导地位,高效的可扩展搜索机制是关键。虽然向量搜索已经变得流行,特别是在语义搜索 中,但在应用于大规模实际场景时,这些方法仍面临挑战。
这篇文章深入探讨了混合搜索,一种结合关键字搜索和向量搜索的搜索方法,利用LanceDB作为核心数据库,以提供精准且符合用户期望的搜索体验。
混合搜索技术结合了基于关键词的传统搜索与先进的技术,包括自然语言处理(NLP)、语义搜索和机器学习,提供更准确和相关的结果。为何要局限于一种方法,而不能利用多种方法的长处呢?通过结合这些技术,混合搜索技术可以理解查询的上下文和含义,超越简单的关键词匹配,提供符合用户意图的信息。
这对实际应用有什么影响?在工作中,企业搜索引擎使用混合搜索技术,可以让员工快速在庞大的知识库中找到特定信息。电子商务平台也受益于混合搜索,即使顾客不确定商品的确切名称,也能帮助他们找到合适的产品。传统的网络搜索引擎也在采用这种方法,提高他们提供给用户的搜索结果的准确性和相关性。
混合搜索通过结合传统的基于关键词的搜索(使用稀疏向量)和现代的基于密集向量的语义搜索来运行,从而提供更加细腻且准确的检索体验。那么它是如何做到这一点的呢?让我们来拆解一下。
图片来源:混合搜索是如何工作的?
在现代应用中,最终混合搜索通常是最佳选择,因为它能够利用关键词和语义搜索的各自优点,为用户提供最相关和最精确的结果。
为什么选择混合搜索?
现在我们已经讨论了为什么要考虑使用混合搜索,现在我们来看看在不同平台上的混合搜索实例。每个平台都有其独特的特性和能力,来提高搜索的准确性和相关性。
亚马逊 Kendra 是一款全文搜索服务,帮助您轻松查找和访问存储在不同来源中的信息。
您的混合搜索应用程序的项目结构: 为了搭建您的混合搜索应用程序,您可以参考以下布局:
HybridSearch/ │ ├── data/ │ └── BEIR/ (请将您的数据集放在这里) │ ├── db/ │ └── (LanceDB数据库文件) │ ├── scripts/ │ ├── setup.py (配置环境) │ ├── load_data.py (加载并预处理数据集) │ ├── hybrid_search.py (实现混合搜索功能) │ └── rerankers.py (自定义重排序器和过滤器脚本) │ └── README.md (项目概览和说明)
设置 LanceDB 环境: 要开始实现混合搜索,您需要设置您的环境。LanceDB 是一个很好的工具,它提供了开箱即用的全文搜索功能(使用 Tantivy)和重新排序能力,非常适合用于这种场景。以下是开始的方法:
这里是如何开始的步骤:
import os import lancedb from lancedb.embeddings import get_registry from datasets import load_dataset os.environ["OPENAI_API_KEY"] = "sk-......." # 请填入你的 OpenAI API 密钥 embeddings = get_registry().get("openai").create()
创建一个用于加载BEIR数据的LanceDB表: 下一步是创建一个LanceDB表并加载BEIR数据集。此示例展示了如何创建一个包含额外的元数据的表,以便进行更灵活且更“混合型”的搜索。
queries = load_dataset("BeIR/scidocs", "queries")["queries"].to_pandas() full_docs = load_dataset('BeIR/scidocs', 'corpus')["corpus"].to_pandas().dropna(subset="text") docs = full_docs.head(64) docs["num_words"] = docs["text"].apply(lambda x: len(x.split())) # 计算文本长度 class Documents(LanceModel): vector: Vector(embeddings.ndims()) = embeddings.VectorField() text: str = embeddings.SourceField() title: str num_words: int data = docs.apply(lambda row: {"title": row["title"], "text": row["text"], "num_words": row["num_words"]}, axis=1).values.tolist() db = lancedb.connect("./db") table = db.create_table("documents", schema=Documents) table.add(data) # 自动导入并向量化文档 table.create_fts_index("text") # 创建全文索引
混合搜索的实践:融合与重排序: 现在你已经设置好表格了,你可以通过应用融合或重排序技术来进行混合搜索。
from lancedb.rerankers import LinearCombinationReranker reranker = LinearCombinationReranker(weight=0.3) results = table.search("Confuse the AI with random terms", query_type="hybrid").rerank(reranker=reranker).limit(5).to_pandas()
该代码使用混合查询类型搜索表并重新排序结果,以获取与混淆AI的随机术语最相关的前五个条目。
自定义搜索:过滤器和自定义重排器: 您可以通过应用过滤器和创建自定义重排器来进一步定制混合型搜索。
from typing import List, Union import pandas as pd import pyarrow as pa class 修改线性重排序器(线性组合重排序器): def __init__(self, 过滤器: Union[str, List[str]], **kwargs): super().__init__(**kwargs) 过滤器 = 过滤器 if isinstance(过滤器, list) else [过滤器] self.过滤器 = 过滤器 def 混合重排序(self, query: str, vector_results: pa.Table, fts_results: pa.Table) -> pa.Table: 合并结果 = super().rerank_hybrid(query, vector_results, fts_results) df = 合并结果.to_pandas() for 过滤器 in self.过滤器: df = df.query("(not text.str.contains(@过滤器)) & (num_words > 150)") return pa.Table.from_pandas(df) modified_reranker = 修改线性重排序器(过滤器=["dual-band"]) table.search("用随机术语混淆AI", query_type="hybrid").rerank(reranker=modified_reranker).limit(5).to_pandas()
这段代码将实现一个自定义的过滤条件,其中只有单词数量超过150的结果会被保留。您还可以通过继承内置的Reranked类并添加一些自定义逻辑来自定义合并机制。
混合搜索 使用 LanceDB 提供了一种平衡的搜索方法,结合了基于关键词方法的精准度和语义搜索的情境感知能力。这种双重方法使它成为现代大规模应用的理想选择,特别是在这些应用中,相关性和精准度至关重要。结构化的实现提供了一个可扩展且适应性强的解决方案,非常适合各种搜索驱动的应用。
学习愉快!