RAG 中的混合搜索:使用组合技术增强信息检索

检索器增强生成(RAG)中的混合搜索结合了不同的搜索技术,以提高从数据库或知识库中检索信息的准确性和效率。通常,混合搜索方法利用传统的基于关键字的搜索(稀疏检索)和语义搜索(密集检索),以充分利用这两种方法的优势。以下是对 RAG 中混合搜索的详细介绍。

关键部件

稀疏检索:稀疏检索通过关键字匹配进行,利用TF-IDF、BM25等技术,根据确切的关键字匹配搜索文档。对于已知确切术语的精确查询,这种方法既快速又有效。

在LangChain中实现BM25检索,你可以使用rank_bm25库来进行BM25算法的实现。以下是一个简要的示例,展示了如何将BM25检索与LangChain集成。

首先,你需要安装rank_bm25langchain库:

pip install rank_bm25 langchain
from langchain import VectorstoreRetrieverfrom rank_bm25 import BM25Okapifrom langchain.document_loaders import SimpleDocumentLoaderfrom langchain.embeddings import BM25Embeddings

假设你有一组文档,你可以将它们加载到LangChain中:

documents = [    "The quick brown fox jumps over the lazy dog.",    "Never jump over the lazy dog quickly.",    "The quick red fox leaps over the lazy dog."]
# 分词(tokenize)文档tokenized_docs = [doc.split(" ") for doc in documents]

初始化BM25模型:

bm25 = BM25Okapi(tokenized_docs)

使用BM25模型进行查询检索:

query = "quick fox"tokenized_query = query.split(" ")doc_scores = bm25.get_scores(tokenized_query)
# 获取排名最高的文档top_n = 3 # 假设获取前三个最相关文档top_docs = bm25.get_top_n(tokenized_query, documents, n=top_n)
print("Top documents:", top_docs)

为了将BM25检索与LangChain集成,可以创建一个自定义的检索器(Retriever):

class BM25Retriever(VectorstoreRetriever):    def __init__(self, documents):        self.documents = documents        tokenized_docs = [doc.split(" ") for doc in documents]        self.bm25 = BM25Okapi(tokenized_docs)
def get_relevant_documents(self, query): tokenized_query = query.split(" ") doc_scores = self.bm25.get_scores(tokenized_query) top_docs = self.bm25.get_top_n(tokenized_query, self.documents, n=3) return top_docs
# 使用自定义的BM25检索器retriever = BM25Retriever(documents)
query = "quick fox"relevant_docs = retriever.get_relevant_documents(query)print("Relevant documents:", relevant_docs)

密集检索:密集检索利用嵌入(向量表示)来理解查询和文档的上下文和含义,这使得即使查询中不存在确切的关键字,也能检索到相关信息。向量相似度则通过余弦相似度或欧几里得距离等指标来衡量查询和文档向量之间的相似性。

可以参考文章:

RAG最佳实践:用 ElasticSearch 打造AI搜索系统与RAG 应用全流程详解!

教你实现ChatPDF:从零到一的完整指南!

混合搜索的工作原理

索引:文档使用稀疏和密集方法进行索引。稀疏索引涉及传统的倒排索引,而密集索引则通过BERT或句子转换器等模型为文档创建嵌入。

查询处理:查询同时使用基于关键字的技术处理,并转换为用于语义搜索的嵌入。

检索:稀疏检索通过执行基于关键字的搜索,检索与查询词匹配的文档;而密集检索则搜索嵌入与查询嵌入相似的文档,捕获语义含义。

分数融合:结合稀疏和密集结果混合搜索的关键步骤是将稀疏和密集检索结果融合。通过将两种方法的分数归一化并结合,使用参数alpha(α)加权,决定各算法的权重并影响结果的重新排名。混合评分公式为:hybrid_score = (1−α)⋅sparse_score + α⋅dense_score。

α的取值通常介于0和1之间:

  • α = 1:纯向量搜索

  • α = 0:纯关键字搜索


这种加权组合确保同时考虑关键字相关性和语义上下文,提供一组平衡且全面的结果。

混合搜索的优点

提高召回率和精确度:通过将关键字匹配与语义理解相结合,混合搜索增加了检索到相关文档的可能性,单独使用这两种方法可能会遗漏这些文档。

处理同义词和上下文:密集检索有助于理解同义词和上下文,确保相关文档不会因词汇不匹配而被忽视。

效率:稀疏检索通常更快,可以快速缩小文档集的范围,而密集检索则可以优化此集以确保语义相关性。

鲁棒性:混合搜索对不同类型的查询更具鲁棒性,无论它们是精确的基于关键字的查询,还是更抽象且依赖于上下文的查询。

在RAG中的实现

向量数据库: FAISS、Milvus、Weviate或Pinecone等工具用于高效处理密集向量搜索。

预训练模型: BERT、RoBERTa或Sentence Transformer等模型用于生成密集检索的嵌入。

搜索技术:

  • 密集检索技术: 利用嵌入和向量相似度量来查找语义相关的文档。这通常是通过预训练模型将文本转换为高维向量来实现。

  • 稀疏检索技术: 使用传统的关键字匹配和布尔运算符,根据精确的关键字匹配检索文档。可通过TF-IDF或BM25等方法实现,这些方法可以使用scikit-learn、gensim或rank_bm25库等工具。


RAG框架: 如LangChain等框架可以将这些组件整合到一个有凝聚力的RAG系统中。

#!pip install rank_bm25 langchain scikit-learn
from rank_bm25 import BM25Okapifrom langchain.vectorstores import SimpleVectorStorefrom langchain.retrievers import VectorstoreRetriever
documents = [ "向量数据库:FAISS、Milvus、Weviate或Pinecone等工具用于高效处理密集向量搜索。", "预训练模型:BERT、RoBERTa或Sentence Transformer等模型用于生成密集检索的嵌入。", "密集检索技术:利用嵌入和向量相似度量来查找语义相关的文档。", "稀疏检索技术:使用传统的关键字匹配和布尔运算符,根据精确的关键字匹配检索文档。", "RAG框架:如LangChain等框架可以将这些组件整合到一个有凝聚力的RAG系统中。",]
# 分词(tokenize)文档tokenized_docs = [doc.split(" ") for doc in documents]
bm25 = BM25Okapi(tokenized_docs)
query = "混合搜索 RAG 优势"tokenized_query = query.split(" ")doc_scores = bm25.get_scores(tokenized_query)
# 获取排名最高的文档top_n = 3 # 获取前三个最相关文档top_docs = bm25.get_top_n(tokenized_query, documents, n=top_n)
print("检索到的相关文档:")for idx, doc in enumerate(top_docs): print(f"{idx + 1}. {doc}")
class BM25Retriever(VectorstoreRetriever): def __init__(self, documents): self.documents = documents tokenized_docs = [doc.split(" ") for doc in documents] self.bm25 = BM25Okapi(tokenized_docs)
def get_relevant_documents(self, query): tokenized_query = query.split(" ") return self.bm25.get_top_n(tokenized_query, self.documents, n=3)
# 使用自定义的BM25检索器retriever = BM25Retriever(documents)
query = "混合搜索 RAG 优势"relevant_docs = retriever.get_relevant_documents(query)
print("通过LangChain集成的BM25检索到的相关文档:")for idx, doc in enumerate(relevant_docs):    print(f"{idx + 1}. {doc}")

代码的输出结果:

检索到的相关文档:1. RAG框架:如LangChain等框架可以将这些组件整合到一个有凝聚力的RAG系统中。2. 向量数据库:FAISS、Milvus、Weviate或Pinecone等工具用于高效处理密集向量搜索。3. 稀疏检索技术:使用传统的关键字匹配和布尔运算符,根据精确的关键字匹配检索文档。
通过LangChain集成的BM25检索到的相关文档:1. RAG框架:如LangChain等框架可以将这些组件整合到一个有凝聚力的RAG系统中。2. 向量数据库:FAISS、Milvus、Weviate或Pinecone等工具用于高效处理密集向量搜索。3. 稀疏检索技术:使用传统的关键字匹配和布尔运算符,根据精确的关键字匹配检索文档。

通过利用稀疏和密集检索技术,RAG系统中的混合搜索可以显著提高检索信息的质量和相关性,使其成为处理复杂信息检索任务的强大工具。

这种组合不仅提升了召回率和精确度,还确保了系统的鲁棒性和效率,从而有效应对各种类型的查询。实施混合搜索可以提升RAG系统的性能,使其在不断发展的信息检索环境中成为不可或缺的工具。

参考资料:

  1. https://www.linkedin.com/pulse/boosting-retrieval-rag-llms-power-bm25-rrf-karthikeyan-dhanakotti-rgl2f

  2. https://www.linkedin.com/pulse/hybrid-search-rag-enhancing-information-retrieval-prasanna-cn4dc

  3. https://docs.llamaindex.ai/en/stable/examples/retrievers/bm25_retriever/


    诚邀:点击关注我,进群交流和获取更多分享。


请使用浏览器的分享功能分享到微信等