核心模块(Modules)
数据连接(DataConnection)
检索器(Retrievers)
集成(Ensemble)

集成检索器

EnsembleRetriever 接受一个检索器的列表作为输入,将它们的 get_relevant_documents() 方法的结果进行集成,并根据 Reciprocal Rank Fusion (opens in a new tab) 算法重新排序结果。

通过充分利用不同算法的优势,EnsembleRetriever 可以实现比任何单一算法更好的性能。

最常见的模式是将稀疏检索器(如BM25)与稠密检索器(如嵌入相似度)结合起来,因为它们的优势互补。这也被称为"混合搜索"。稀疏检索器根据关键词能够有效地找到相关文档,而稠密检索器则能够根据语义相似性找到相关文档。

%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检索器和FAISS检索器
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",
]
 
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")
docs

运行时配置

我们也可以在运行时配置检索器。为了做到这一点,我们需要将字段标记为可配置的。

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)
docs

注意,这里只返回了 FAISS 检索器中的一个来源,因为我们在运行时传入了相应的配置。