【LangChain】LangChain 中的检索器(Retrievers)

该文章已生成可运行项目,

在 LangChain 中,检索器(Retrievers) 是用于从外部数据源(如文档、数据库或网页)中获取与用户查询相关内容的组件。它们是构建基于外部知识的问答系统、语义搜索或上下文增强应用的核心模块。检索器通过将用户查询与存储的数据进行匹配,返回相关文档或片段,供语言模型(LLM)进一步处理。

以下是对 LangChain 检索器的详细介绍,涵盖其定义、类型、工作原理、实现方式、应用场景、代码示例、优化建议以及与生态系统的结合。


1. 什么是 LangChain 的检索器?

检索器是 LangChain 中负责信息检索的模块,通常与 索引(Indexes) 模块(如向量存储、文档加载器)结合使用。它的核心功能是:

  • 输入:接收用户查询(通常是文本)。
  • 处理:根据查询从数据源中检索相关内容。
  • 输出:返回一组相关文档或文本片段(通常是 Document 对象列表)。

检索器在以下场景中扮演关键角色:

  • 问答系统:从文档或知识库中检索答案的上下文。
  • 语义搜索:根据查询的语义返回相关结果。
  • 上下文增强:为语言模型提供外部知识,解决其知识局限。

检索器通常与 向量存储(Vector Stores) 配合,通过嵌入模型(Embedding Models)将查询和文档转为向量,基于相似性进行检索。


2. 检索器的工作原理

检索器的工作流程可以分为以下步骤:

  1. 查询嵌入:将用户查询通过嵌入模型(如 OpenAIEmbeddings)转为向量表示。
  2. 相似性搜索:在向量存储中查找与查询向量最相似的文档向量。
  3. 文档返回:返回匹配的文档(包含内容、元数据等)。
  4. 后处理(可选):对检索结果进行排序、过滤或重新排名。

检索器的核心依赖:

  • 嵌入模型:将文本转为向量(如 OpenAIEmbeddings, HuggingFaceEmbeddings)。
  • 向量存储:存储文档向量(如 Chroma、FAISS、Pinecone)。
  • 相似性度量:如余弦相似度、欧几里得距离。

3. LangChain 检索器的类型

LangChain 提供了多种检索器,适用于不同场景。以下是主要类型的详细介绍:

(1) VectorStoreRetriever

  • 功能:基于向量存储的检索器,通过嵌入向量进行语义搜索。
  • 特点
    • 使用嵌入模型将查询和文档转为向量。
    • 支持多种向量存储(如 Chroma、FAISS、Pinecone)。
    • 默认使用余弦相似度排序结果。
  • 适用场景
    • 语义搜索。
    • 基于文档的问答系统。
  • 支持的向量存储(需单独安装):
    • langchain-chroma
    • langchain-faiss
    • langchain-pinecone
    • langchain-weaviate
    • langchain-qdrant
  • 示例
    from langchain_community.vectorstores import Chroma
    from langchain_openai import OpenAIEmbeddings
    from langchain_core.documents import Document
    
    # 创建文档
    docs = [
        Document(page_content="量子计算是一种基于量子力学的计算范式。", metadata={"source": "doc1"}),
        Document(page_content="人工智能是模拟人类智能的技术。", metadata={"source": "doc2"})
    ]
    
    # 初始化向量存储
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma.from_documents(docs, embeddings)
    
    # 创建检索器
    retriever = vectorstore.as_retriever(search_kwargs={"k": 1})  # 返回 1 个结果
    
    # 检索
    results = retriever.invoke("量子计算是什么?")
    print(results)
    
  • 输出
    [Document(page_content='量子计算是一种基于量子力学的计算范式。', metadata={'source': 'doc1'})]
    

(2) BM25Retriever

  • 功能:基于 BM25 算法的关键词检索器,适合基于词频的搜索。
  • 特点
    • 不依赖嵌入模型,使用词频和逆文档频率(TF-IDF)计算相关性。
    • 适合关键词匹配场景,计算成本低。
    • 不支持语义搜索,效果依赖文本的字面匹配。
  • 适用场景
    • 传统搜索场景。
    • 关键词驱动的问答。
  • 安装
    pip install rank_bm25
    
  • 示例
    from langchain_community.retrievers import BM25Retriever
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算是一种基于量子力学的计算范式。"),
        Document(page_content="人工智能是模拟人类智能的技术。")
    ]
    
    retriever = BM25Retriever.from_documents(docs)
    retriever.k = 1  # 返回 1 个结果
    results = retriever.invoke("量子计算")
    print(results)
    
  • 输出
    [Document(page_content='量子计算是一种基于量子力学的计算范式。')]
    

(3) TFIDFRetriever

  • 功能:基于 TF-IDF(词频-逆文档频率)的检索器,类似 BM25。
  • 特点
    • 使用 TF-IDF 向量表示文档和查询。
    • 适合关键词匹配,性能优于 BM25 在某些场景。
    • 不支持语义搜索。
  • 适用场景
    • 文本搜索。
    • 关键词提取。
  • 安装
    pip install scikit-learn
    
  • 示例
    from langchain_community.retrievers import TFIDFRetriever
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算是一种基于量子力学的计算范式。"),
        Document(page_content="人工智能是模拟人类智能的技术。")
    ]
    
    retriever = TFIDFRetriever.from_documents(docs)
    results = retriever.invoke("量子计算")
    print(results)
    

(4) MultiQueryRetriever

  • 功能:通过生成多个查询变体增强检索效果,结合向量存储。
  • 特点
    • 使用语言模型生成查询的多种表达方式。
    • 从向量存储中检索所有变体的结果并合并。
    • 提高召回率,适合复杂查询。
  • 适用场景
    • 查询表达不明确或需要覆盖多种语义。
    • 提高检索的全面性。
  • 示例
    from langchain.retrievers.multi_query import MultiQueryRetriever
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import Chroma
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算基于量子力学。"),
        Document(page_content="人工智能模拟人类智能。")
    ]
    
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma.from_documents(docs, embeddings)
    llm = ChatOpenAI(api_key="your-openai-key")
    
    retriever = MultiQueryRetriever.from_llm(
        retriever=vectorstore.as_retriever(),
        llm=llm
    )
    results = retriever.invoke("量子计算是什么?")
    print(results)
    
  • 输出:可能返回多个相关文档。

(5) ContextualCompressionRetriever

  • 功能:对检索结果进行压缩,提取最相关的内容。
  • 特点
    • 使用语言模型对检索到的文档进行重新排序或精炼。
    • 减少无关内容,提高结果质量。
    • 增加计算开销,但提升精准度。
  • 适用场景
    • 文档内容冗长,需要提取关键信息。
    • 提高问答系统的答案质量。
  • 示例
    from langchain.retrievers import ContextualCompressionRetriever
    from langchain.retrievers.document_compressors import LLMChainExtractor
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import Chroma
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算是一种基于量子力学的计算范式,涉及量子比特和量子纠缠。"),
        Document(page_content="人工智能是模拟人类智能的技术,包括机器学习和深度学习。")
    ]
    
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma.from_documents(docs, embeddings)
    llm = ChatOpenAI(api_key="your-openai-key")
    
    compressor = LLMChainExtractor.from_llm(llm)
    retriever = ContextualCompressionRetriever(
        base_compressor=compressor,
        base_retriever=vectorstore.as_retriever()
    )
    results = retriever.invoke("量子计算的核心是什么?")
    print(results)
    
  • 输出
    [Document(page_content='量子计算是一种基于量子力学的计算范式,涉及量子比特和量子纠缠。')]
    

(6) EnsembleRetriever

  • 功能:结合多种检索器(如 BM25 和向量存储),融合结果。
  • 特点
    • 结合关键词搜索和语义搜索的优点。
    • 支持加权融合,调整不同检索器的权重。
    • 提高召回率和精准度。
  • 适用场景
    • 需要综合关键词和语义的搜索。
    • 复杂查询场景。
  • 示例
    from langchain.retrievers import EnsembleRetriever
    from langchain_community.retrievers import BM25Retriever
    from langchain_community.vectorstores import Chroma
    from langchain_openai import OpenAIEmbeddings
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算基于量子力学。"),
        Document(page_content="人工智能模拟人类智能。")
    ]
    
    bm25_retriever = BM25Retriever.from_documents(docs)
    bm25_retriever.k = 1
    
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma.from_documents(docs, embeddings)
    vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
    
    ensemble_retriever = EnsembleRetriever(
        retrievers=[bm25_retriever, vector_retriever],
        weights=[0.5, 0.5]
    )
    results = ensemble_retriever.invoke("量子计算")
    print(results)
    

(7) SelfQueryRetriever

  • 功能:使用语言模型解析查询,提取结构化条件(如元数据过滤)并执行检索。
  • 特点
    • 支持复杂查询(如“2023年发布的量子计算文档”)。
    • 自动解析查询中的过滤条件。
    • 需要向量存储支持元数据查询。
  • 适用场景
    • 带元数据过滤的检索。
    • 结构化知识库查询。
  • 示例
    from langchain.retrievers.self_query import SelfQueryRetriever
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import Chroma
    from langchain_core.documents import Document
    
    docs = [
        Document(page_content="量子计算简介", metadata={"year": 2023, "category": "tech"}),
        Document(page_content="人工智能简介", metadata={"year": 2022, "category": "tech"})
    ]
    
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma.from_documents(docs, embeddings)
    llm = ChatOpenAI(api_key="your-openai-key")
    
    retriever = SelfQueryRetriever.from_llm(
        llm=llm,
        vectorstore=vectorstore,
        document_contents="技术文档",
        metadata_field_info=[
            {"name": "year", "type": "int", "description": "发布年份"},
            {"name": "category", "type": "str", "description": "类别"}
        ]
    )
    results = retriever.invoke("2023年的技术文档")
    print(results)
    

(8) WebResearchRetriever

  • 功能:从网页中检索相关内容,结合搜索引擎和向量存储。
  • 特点
    .ConcurrentHashMap - 使用外部搜索引擎(如 Google)获取网页。
    • 将网页内容存储到向量存储并检索。
    • 适合动态、实时信息检索。
  • 适用场景
    • 需要从互联网获取最新信息的问答。
    • 研究或知识收集。
  • 安装
    pip install google-api-python-client
    
  • 示例
    from langchain.retrievers.web_research import WebResearchRetriever
    from langchain_openai import ChatOpenAI, OpenAIEmbeddings
    from langchain_community.vectorstores import Chroma
    from langchain_community.utilities import GoogleSearchAPIWrapper
    
    llm = ChatOpenAI(api_key="your-openai-key")
    embeddings = OpenAIEmbeddings(api_key="your-openai-key")
    vectorstore = Chroma(embedding_function=embeddings)
    search = GoogleSearchAPIWrapper(google_api_key="your-google-key", google_cse_id="your-cse-id")
    
    retriever = WebResearchRetriever.from_llm(
        vectorstore=vectorstore,
        llm=llm,
        search=search
    )
    results = retriever.invoke("量子计算的最新进展")
    print(results)
    

(9) Custom Retriever

  • 功能:开发者可以自定义检索逻辑,适配特定数据源或算法。
  • 特点
    • 继承 BaseRetriever 类,实现 get_relevant_documents 方法。
    • 支持任意数据源(如数据库、API)。
  • 适用场景
    • 特定领域的数据源(如内部数据库)。
    • 自定义检索算法。
  • 示例
    from langchain_core.retrievers import BaseRetriever
    from langchain_core.documents import Document
    
    class CustomRetriever(BaseRetriever):
        def _get_relevant_documents(self, query: str, **kwargs):
            # 自定义逻辑(如查询数据库)
            return [Document(page_content=f"自定义结果 for {query}")]
    
    retriever = CustomRetriever()
    results = retriever.invoke("量子计算")
    print(results)
    

4. 检索器的应用场景

检索器在以下场景中广泛应用:

  1. 基于文档的问答
    • 从公司文档、PDF 或知识库中检索答案。
    • 示例:RetrievalQA 链结合 VectorStoreRetriever
  2. 语义搜索
    • 根据查询的语义返回相关内容。
    • 示例:使用 VectorStoreRetriever 实现产品搜索。
  3. 上下文增强
    • 为语言模型提供外部知识,解决知识截止问题。
    • 示例:结合 WebResearchRetriever 获取最新信息。
  4. 结构化查询
    • 从带元数据的文档中检索特定内容。
    • 示例:SelfQueryRetriever 按年份过滤文档。
  5. 混合搜索
    • 结合关键词和语义搜索。
    • 示例:EnsembleRetriever 融合 BM25 和向量存储。
  6. 实时信息检索
    • 从网页或 API 获取动态数据。
    • 示例:WebResearchRetriever 检索新闻。

5. 检索器的实现与代码示例

综合示例:RetrievalQA 链

以下是一个基于 VectorStoreRetriever 的问答系统:

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain.chains import RetrievalQA
from langchain_core.prompts import PromptTemplate

# 创建文档
docs = [
    Document(page_content="量子计算是一种基于量子力学的计算范式。", metadata={"source": "doc1"}),
    Document(page_content="人工智能是模拟人类智能的技术。", metadata={"source": "doc2"})
]

# 初始化向量存储和检索器
embeddings = OpenAIEmbeddings(api_key="your-openai-key")
vectorstore = Chroma.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})

# 初始化语言模型
llm = ChatOpenAI(api_key="your-openai-key")

# 创建 RetrievalQA 链
prompt = PromptTemplate.from_template("根据以下上下文回答问题:{context}\n问题:{question}")
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True,
    chain_type_kwargs={"prompt": prompt}
)

# 查询
result = qa_chain.invoke({"query": "量子计算是什么?"})
print(result["result"])
print("来源:", result["source_documents"])

输出

量子计算是一种基于量子力学的计算范式。
来源:[Document(page_content='量子计算是一种基于量子力学的计算范式。', metadata={'source': 'doc1'})]

6. 检索器的优化建议

(1) 提高检索质量

  • 嵌入模型选择
    • 使用高质量嵌入模型(如 text-embedding-ada-002SentenceTransformers)。
    • 针对特定领域微调嵌入模型。
  • 文档分割
    • 使用 RecursiveCharacterTextSplitter 分割长文档,保留语义。
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    
    splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    chunks = splitter.split_documents(docs)
    
  • 查询优化
    • 使用 MultiQueryRetriever 生成查询变体。
    • 规范化查询(如小写化、去噪)。

(2) 提高性能

  • 向量存储优化
    • 使用高效的向量存储(如 FAISS 适合本地,Pinecone 适合云)。
    • 索引优化(如 FAISS 的 HNSW 索引)。
  • 缓存检索结果
    • 结合 LangChain 的缓存机制。
    from langchain.globals import set_llm_cache
    from langchain.cache import SQLiteCache
    
    set_llm_cache(SQLiteCache(database_path="cache.db"))
    
  • 批量检索
    • 使用 batch 方法处理多个查询。
    results = retriever.batch(["query1", "query2"])
    

(3) 后处理

  • 重新排名
    • 使用 ContextualCompressionRetriever 精炼结果。
  • 过滤
    • 根据元数据(如日期、类别)过滤结果。
    retriever = vectorstore.as_retriever(search_kwargs={"filter": {"year": 2023}})
    

(4) 监控与调试

  • 回调
    • 使用回调记录检索器的输入输出。
    from langchain_core.callbacks import BaseCallbackHandler
    
    class RetrieverCallback(BaseCallbackHandler):
        def on_retriever_start(self, serialized, query, **kwargs):
            print(f"检索查询:{query}")
        def on_retriever_end(self, documents, **kwargs):
            print(f"检索结果:{documents}")
    
  • LangSmith
    • 分析检索器的召回率和精准度。
    from langsmith import Client
    retriever.invoke(query, config={"callbacks": [Client(api_key="your-langsmith-key")]})
    

7. 注意事项

  • 检索质量
    • 嵌入模型的质量直接影响检索效果。
    • 关键词检索(BM25/TFIDF)和语义检索(向量存储)各有优劣,需根据场景选择。
  • 数据规模
    • 大规模文档需要高效的向量存储(如 Pinecone、Weaviate)。
    • 定期更新索引以反映数据变化。
  • 隐私与安全
    • 文档可能包含敏感信息,需加密存储或限制访问。
    • 避免将用户查询存储在公共向量存储中。
  • 成本管理
    • 云向量存储(如 Pinecone)可能产生费用,需优化查询频率。
    • 嵌入模型的 API 调用也需监控。
  • 调试
    • 检查检索结果是否相关,必要时调整嵌入模型或分割策略。
    • 使用 LangSmith 分析检索器的性能。

8. 与其他模块的结合

  • 链(Chains)
    • 结合 RetrievalQAConversationalRetrievalChain 实现问答。
    from langchain.chains import ConversationalRetrievalChain
    from langchain.memory import ConversationBufferMemory
    
    memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
    qa_chain = ConversationalRetrievalChain.from_llm(llm, retriever, memory=memory)
    
  • 回调(Callbacks)
    • 监控检索过程。
  • 缓存(Cache)
    • 缓存检索结果,减少重复查询。
  • 代理(Agents)
    • 结合 WebResearchRetriever 为代理提供动态知识。
  • LangSmith
    • 分析检索器的性能和命中率。

9. 学习资源


10. 总结

  • 定义:检索器用于从外部数据源获取与查询相关的内容,是问答和搜索系统的核心。
  • 类型
    • VectorStoreRetriever:语义搜索。
    • BM25Retriever/TFIDFRetriever:关键词搜索。
    • MultiQueryRetriever:多查询增强。
    • ContextualCompressionRetriever:结果压缩。
    • EnsembleRetriever:混合搜索。
    • SelfQueryRetriever:结构化查询。
    • WebResearchRetriever:网页检索。
    • 自定义检索器:特定需求。
  • 工作原理:查询嵌入 → 相似性搜索 → 文档返回。
  • 应用场景:问答、语义搜索、上下文增强、结构化查询。
  • 优化点:嵌入模型、文档分割、缓存、后处理、监控。
  • 注意事项:质量、规模、隐私、成本、调试。
本文章已经生成可运行项目
### LangChain检索器实现与使用 #### 实现细节 LangChain的`runnables`包提供了构建可执行组件的能力,这些组件可以用于创建复杂的流水线和工作流。对于检索器而言,其实现主要依赖于向量数据库和其他索引结构来高效地查找最相似的数据项[^1]。 在具体实践中,检索器通常会集成诸如FAISS、ChromaDB或其他类似的库来进行高效的近似最近邻搜索(Approximate Nearest Neighbor Search, ANN)。这使得即使面对大规模数据集也能保持良好的性能表现。当用户查询到来时,检索器负责将输入转换成适合ANN算法处理的形式,并返回一系列潜在的相关文档或片段给下游模块进一步分析处理[^2]。 #### 使用方法 为了利用LangChain中的检索功能,在编写代码之前应当先准备好要被索引的内容以及相应的元数据。下面给出了一段Python代码作为示例: ```python from langchain.retrievers import Retriever import faiss # 或者其他支持的向量存储引擎 # 初始化Faiss索引并加载已有的向量集合 index = faiss.read_index("path/to/index") retriever = Retriever( index=index, input_transformer=lambda query: transform_query_to_vector(query), ) results = retriever.retrieve("example user query", top_k=5) for result in results: print(f"Document ID: {result['id']}, Score: {result['score']}") ``` 这段脚本展示了如何设置一个基于Faiss的检索实例,并通过简单的lambda表达式定义了从自然语言查询到向量表示之间的映射关系。最后调用了`retrieve()`函数获取前五个匹配度最高的条目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值