LangChain框架-检索器详解
摘要
检索器是一个接口,给定非结构化查询返回文档。 它比向量存储更为通用。 检索器不需要能够存储文档,只需返回(或检索)它们。 检索器可以从向量存储创建,但也足够广泛,包括维基百科搜索和亚马逊Kendra。
文本将基于LangChain 的官网文档和源码,综合介绍和总结LangChain 的检索器内容,方便学习的小伙伴快速掌握LangChain检索器相关的内容。
LangChain检索器类型
一、云服务与企业级搜索集成
-
AmazonKendraRetriever
-
集成AWS的智能搜索服务Kendra,支持自然语言理解和企业级数据源检索。
-
-
AmazonKnowledgeBasesRetriever
-
针对AWS Bedrock的Knowledge Bases,检索托管在Bedrock中的结构化知识。
-
-
AzureAISearchRetriever
-
微软Azure AI Search(原Cognitive Search)的检索接口,支持向量和全文搜索。
-
-
AzureCognitiveSearchRetriever
-
旧版Azure搜索服务兼容接口,功能与前者类似。
-
-
GoogleCloudEnterpriseSearchRetriever
-
集成Google Cloud的企业搜索API,支持自定义数据源。
-
-
GoogleDocumentAIWarehouseRetriever
-
从Google的Document AI Warehouse中检索结构化文档数据。
-
-
GoogleVertexAIMultiTurnSearchRetriever
-
基于Vertex AI的多轮对话优化搜索,适合复杂查询场景。
-
-
GoogleVertexAISearchRetriever
-
Vertex AI的通用搜索接口,支持语义和混合搜索。
-
二、学术与专业数据检索
-
ArxivRetriever
-
直接访问arXiv学术论文数据库,按关键词或元数据检索。
-
-
PubMedRetriever
-
从生物医学数据库PubMed获取文献摘要和元数据。
-
三、传统检索算法
-
BM25Retriever
-
基于BM25算法(概率加权关键词匹配),适合稀疏数据检索。
-
-
ElasticSearchBM25Retriever
-
在Elasticsearch中执行BM25算法的封装。
-
-
TFIDFRetriever
-
使用TF-IDF(词频-逆文档频率)加权的文本检索。
-
-
SVMRetriever
-
基于支持向量机(SVM)的排序模型,对检索结果重排序。
-
-
KNNRetriever
-
利用K近邻算法在向量空间中进行相似性搜索。
-
四、向量数据库与混合搜索
-
PineconeHybridSearchRetriever
-
Pinecone向量数据库的混合搜索(结合关键词和向量相似性)。
-
-
WeaviateHybridSearchRetriever
-
Weaviate数据库的混合搜索接口。
-
-
MilvusRetriever
-
专为Milvus向量数据库设计的相似性检索。
-
-
ZillizRetriever
-
兼容Zilliz(Milvus的云服务版)的检索接口。
-
-
VespaRetriever
-
针对Vespa搜索引擎的检索工具,支持复杂排序和过滤。
-
五、多策略与检索优化
-
MultiQueryRetriever
-
生成多个查询变体以扩大检索范围,提升召回率。
-
-
EnsembleRetriever
-
聚合多个检索器(如BM25+向量搜索)的结果。
-
-
ContextualCompressionRetriever
-
对检索结果压缩,保留最相关的文本片段。
-
-
TimeWeightedVectorStoreRetriever
-
根据时间权重调整结果(如优先返回最新数据)。
-
-
SelfQueryRetriever
-
将自然语言查询自动解析为结构化过滤条件(如元数据过滤)。
-
-
RePhraseQueryRetriever
-
重写用户查询以优化检索效果。
-
六、文档分块与层级检索
-
ParentDocumentRetriever
-
关联子文档块与父文档,保留上下文完整性。
-
-
MultiVectorRetriever
-
支持文档的多向量表示(如摘要、关键词、嵌入等)。
-
-
MergerRetriever
-
合并多个检索器的结果并去重(类似Ensemble但更基础)。
-
七、外部API与工具集成
-
TavilySearchAPIRetriever
-
通过Tavily API实现实时网络搜索。
-
-
WikipediaRetriever
-
直接检索维基百科内容。
-
-
WebResearchRetriever
-
自动化网络搜索与结果聚合,适合RAG应用。
-
-
ChatGPTPluginRetriever
-
兼容ChatGPT插件的检索接口(需插件支持)。
-
-
RemoteLangChainRetriever
-
远程调用其他LangChain服务的检索代理。
-
八、特定平台/数据库
-
MetalRetriever
-
专为Metal AI平台设计的语义检索工具。
-
-
ZepRetriever
-
集成Zep长时记忆存储,检索对话历史或会话数据。
-
-
NeuralDBRetriever
-
基于ThirdAI的NeuralDB,支持神经符号混合检索。
-
-
DriaRetriever
-
连接Dria知识库平台(基于区块链的知识图谱)。
-
-
ChaindeskRetriever
-
针对Chaindesk平台的定制化检索接口。
-
-
OutlineRetriever
-
集成Outline知识库工具的检索功能。
-
九、其他框架与扩展
-
LlamaIndexRetriever
-
集成LlamaIndex(原GPT Index)的文档检索。
-
-
LlamaIndexGraphRetriever
-
基于LlamaIndex的知识图谱检索。
-
-
CohereRagRetriever
-
结合Cohere的RAG模型,增强检索与生成的协同。
-
-
EmbedchainRetriever
-
使用Embedchain框架的统一检索接口。
-
-
DocArrayRetriever
-
基于DocArray的轻量级向量检索,适合原型开发。
-
-
ArceeRetriever
-
专为Arcee平台优化的领域自适应检索工具。
-
-
KayAiRetriever
-
针对Kay.ai的AI驱动搜索接口(具体功能需查证)。
-
分类总结
类别 | Retriever示例 |
---|---|
云服务/企业搜索 | AmazonKendra, AzureAI, GoogleVertexAI |
学术检索 | Arxiv, PubMed |
传统算法 | BM25, TFIDF, SVM, KNN |
向量数据库 | Pinecone, Milvus, Weaviate, Zilliz |
多策略优化 | MultiQuery, Ensemble, ContextualCompression |
文档分块 | ParentDocument, MultiVector |
外部API | Tavily, Wikipedia, WebResearch |
特定平台 | Metal, Zep, NeuralDB, Dria |
其他框架 | LlamaIndex, CohereRag, Embedchain |
检索器的基本使用
从向量存储创建检索器
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitterloader = TextLoader("state_of_the_union.txt")documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(texts, embeddings)
# 从向量存储创建检索器
retriever = vectorstore.as_retriever()
# 进行检索
docs = retriever.invoke("what did the president say about ketanji brown jackson?")
as_retriever ()方法
as_retriever主要用于将向量数据库(VectorStore
)转换为一个检索器(Retriever
)对象。这个检索器可以用来从向量数据库中检索与查询相关的文档。
as_retriever()
方法的核心作用是将向量数据库封装成一个检索器,方便后续使用不同的检索策略从数据库中获取相关文档。
参数 search_type
-
similarity
(相似度搜索)(默认值)-
原理:该策略直接依据向量之间的相似度来进行排序。通常会采用余弦相似度、欧几里得距离等计算方式,找出与查询向量最相似的向量。
-
优点:简单直接,易于理解和实现,能迅速找出与查询向量最接近的结果。
-
缺点:在某些场景下,可能会返回大量相似的结果,缺乏多样性。
-
示例代码:
-
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings# 假设已经有了向量数据库 vectorstore
embeddings = OpenAIEmbeddings()
# 以 FAISS 为例
vectorstore = FAISS.from_texts(["text1", "text2", "text3"], embeddings)# 使用相似度搜索
retriever = vectorstore.as_retriever(search_type="similarity")
results = retriever.get_relevant_documents("query text")
-
mmr
(最大边际相关性搜索,Maximal Marginal Relevance)-
原理:MMR 在兼顾结果与查询的相关性以及结果之间的多样性。它先找出与查询最相关的文档,接着在后续的检索中,会在考虑文档与查询相关性的同时,尽量选择与已选文档差异较大的文档。
-
优点:能提供既相关又多样的检索结果,避免了结果的冗余。
-
缺点:计算复杂度相对较高,因为每次选择新文档时都要考虑与已选文档的差异。
-
示例代码:
-
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings# 假设已经有了向量数据库 vectorstore
embeddings = OpenAIEmbeddings()
# 以 FAISS 为例
vectorstore = FAISS.from_texts(["text1", "text2", "text3"], embeddings)# 使用 MMR 搜索
retriever = vectorstore.as_retriever(search_type="mmr")
results = retriever.get_relevant_documents("query text")
-
similarity_score_threshold
(相似度分数阈值搜索)-
原理:此策略会设定一个相似度分数阈值,仅返回相似度分数高于该阈值的文档。
-
优点:能够精准控制检索结果的质量,过滤掉相似度较低的文档。
-
缺点:如果阈值设置不当,可能会导致返回的结果过少或者过多。
-
示例代码:
-
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings# 假设已经有了向量数据库 vectorstore
embeddings = OpenAIEmbeddings()
# 以 FAISS 为例
vectorstore = FAISS.from_texts(["text1", "text2", "text3"], embeddings)# 使用相似度分数阈值搜索
retriever = vectorstore.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.8})
results = retriever.get_relevant_documents("query text")
参数 search_kwargs
将参数传递给底层向量存储的搜索方法,上文中使用similarity_score_threshold方法时,就使用了search_kwargs={"score_threshold": 0.8},传递给向量存储一个搜索的最低阈值。
-
指定前 k:我们还可以限制检索器返回的文档数量
k
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
retriever 检索器对象核心方法
-
retriever.invoke():retriever.invoke()是一个同步方法,适合在单线程或者无需异步处理的场景中使用。在调用它时,程序会暂停执行,直至检索操作完成并返回结果。
-
retriever.ainvoke():
retriever.ainvoke()
是一个异步方法,适用于需要异步处理的场景,像在异步的 Web 应用里.使用该方法能防止阻塞事件循环,从而提升程序的并发性能。 -
invoke 和 ainvoke 方法遵循了 LangChain 的可调用对象协议,
invoke
方法在与 LangChain 的其他组件(如Chain
、Agent
等)集成时具有更好的兼容性和扩展性。可以轻松地将其嵌入到更复杂的处理流程中,实现模块化和可组合的应用开发。 -
get_relevant_documents():
功能是根据给定的查询,从检索器对应的向量数据库中获取相关的文档。该方法是同步执行的,意味着在调用它时,程序会暂停,直到检索操作完成并返回结果。 -
aget_relevant_documents():
异步版本的文档检索方法。在需要异步处理的场景中使用,能避免阻塞事件循环,提升程序的并发性能。 -
get_relevant_documents 和 aget_relevant_documents 方法
专注于文档检索功能本身。如果你的应用场景只是简单的文档检索,不涉及复杂的流程组合,使用get_relevant_documents
会更加直接和简洁。 -
batch():用于批量执行查询操作。它接收一个查询列表,然后同步地为每个查询从向量数据库中检索相关文档,最后返回一个包含所有查询结果的列表。
-
abatch():
异步版本的批量查询方法。它接收一个查询列表,然后异步地为每个查询从向量数据库中检索相关文档,最后返回一个包含所有查询结果的列表。该方法适合在需要异步处理以提高并发性能的场景中使用。 -
batch_as_completed():
该方法用于批量执行查询,并且会在每个查询完成后立即返回结果,而不是等待所有查询都完成后再返回。这样可以让你尽快处理已经完成的查询结果,提高程序的响应速度。 -
abatch_as_completed():
异步版本的batch_as_completed
方法。它会异步地批量执行查询,并在每个查询完成后立即返回结果。适合在需要异步处理以提高并发性能的场景中使用。
创建自定义检索器
要创建自己的检索器,我们可以扩展 BaseRetriever
类并实现以下方法:
方法 | 描述 | 必需/可选 |
---|---|---|
_get_relevant_documents | 获取与查询相关的文档。 | 必需 |
_aget_relevant_documents | 实现以提供异步原生支持。 | 可选 |
以下是一个自定义检索器的代码示例:
<!--IMPORTS:[{"imported": "CallbackManagerForRetrieverRun", "source": "langchain_core.callbacks", "docs": "https://python.langchain.com/api_reference/core/callbacks/langchain_core.callbacks.manager.CallbackManagerForRetrieverRun.html", "title": "How to create a custom Retriever"}, {"imported": "Document", "source": "langchain_core.documents", "docs": "https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html", "title": "How to create a custom Retriever"}, {"imported": "BaseRetriever", "source": "langchain_core.retrievers", "docs": "https://python.langchain.com/api_reference/core/retrievers/langchain_core.retrievers.BaseRetriever.html", "title": "How to create a custom Retriever"}]-->
from typing import Listfrom langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetrieverclass ToyRetriever(BaseRetriever):"""A toy retriever that contains the top k documents that contain the user query.This retriever only implements the sync method _get_relevant_documents.If the retriever were to involve file access or network access, it could benefitfrom a native async implementation of `_aget_relevant_documents`.As usual, with Runnables, there's a default async implementation that's providedthat delegates to the sync implementation running on another thread."""documents: List[Document]"""List of documents to retrieve from."""k: int"""Number of top results to return"""def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:"""Sync implementations for retriever."""matching_documents = []for document in documents:if len(matching_documents) > self.k:return matching_documentsif query.lower() in document.page_content.lower():matching_documents.append(document)return matching_documents# Optional: Provide a more efficient native implementation by overriding# _aget_relevant_documents# async def _aget_relevant_documents(# self, query: str, *, run_manager: AsyncCallbackManagerForRetrieverRun# ) -> List[Document]:# """Asynchronously get documents relevant to a query.# Args:# query: String to find relevant documents for# run_manager: The callbacks handler to use# Returns:# List of relevant documents# """
多检索器的组合使用
我们可以使用EnsembleRetriever 将多个检索器组合使用。EnsembleRetriever 支持对多个检索器的结果进行集成。它通过一组 BaseRetriever 对象进行初始化。EnsembleRetrievers 根据互惠排名融合算法对组成检索器的结果进行重新排序。
通过利用不同算法的优势,EnsembleRetriever
可以实现比任何单一算法更好的性能。
最常见的模式是将稀疏检索器(如 BM25)与密集检索器(如嵌入相似度)结合,因为它们的优势是互补的。这也被称为“混合搜索”。稀疏检索器擅长根据关键词查找相关文档,而密集检索器则擅长根据语义相似性查找相关文档。
BM25稀疏检索器结合密集检索器的代码示例:
<!--IMPORTS:[{"imported": "EnsembleRetriever", "source": "langchain.retrievers", "docs": "https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.ensemble.EnsembleRetriever.html", "title": "How to combine results from multiple retrievers"}, {"imported": "BM25Retriever", "source": "langchain_community.retrievers", "docs": "https://python.langchain.com/api_reference/community/retrievers/langchain_community.retrievers.bm25.BM25Retriever.html", "title": "How to combine results from multiple retrievers"}, {"imported": "FAISS", "source": "langchain_community.vectorstores", "docs": "https://python.langchain.com/api_reference/community/vectorstores/langchain_community.vectorstores.faiss.FAISS.html", "title": "How to combine results from multiple retrievers"}, {"imported": "OpenAIEmbeddings", "source": "langchain_openai", "docs": "https://python.langchain.com/api_reference/openai/embeddings/langchain_openai.embeddings.base.OpenAIEmbeddings.html", "title": "How to combine results from multiple retrievers"}]-->
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddingsdoc_list_1 = ["I like apples","I like oranges","Apples and oranges are fruits",
]# initialize the bm25 retriever and faiss retriever
bm25_retriever = BM25Retriever.from_texts(doc_list_1, metadatas=[{"source": 1}] * len(doc_list_1)
)
bm25_retriever.k = 2doc_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})# initialize the ensemble retriever
ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
)docs = ensemble_retriever.invoke("apples")
参考文献
使用指南 | LangChain中文网
Custom Retriever | LangChain中文网
如何结合多个检索器的结果 | LangChain中文网