Agent常用检索器的详细介绍

LangChain 的"检索器"本质上是一个统一接口 :输入查询字符串,输出 Document 对象列表。它比向量库更抽象------检索器不需要能存文档,只要能"返回"文档就行,所以它可以包装向量库、搜索引擎、图数据库、关系数据库,甚至一个搜索 API。所有检索器都继承自 BaseRetriever,必须实现 _get_relevant_documents 方法,并天然具备 Runnable 能力(invoke / ainvoke / batch)。


🗂️ 检索器分类总览

类别 代表检索器 解决的核心痛点
1. 基础向量检索器 vectorstore.as_retriever() 语义相似度匹配
2. 稀疏/关键词检索器 BM25Retriever 精确词条、专名匹配
3. 融合检索器 EnsembleRetriever 稠密+稀疏互补,提升召回
4. 查询转换检索器 MultiQueryRetrieverSelfQueryRetriever 用户查询表述不佳
5. 上下文压缩检索器 ContextualCompressionRetriever + CohereRerank 检索结果冗余、需要精排
6. 父子文档检索器 ParentDocumentRetriever 分块导致上下文割裂
7. 外部/托管检索器 WikipediaRetrieverArxivRetrieverAmazonKnowledgeBasesRetriever 直接检索外部知识源
8. LangGraph Agentic 检索 路由到 Vector / Graph / Web / Direct LLM 不同类型问题需要不同工具

1. 基础向量检索器(Vector Retriever)

功能 :把查询做 embed,到向量库做相似度搜索,返回 top-k 个 Document。所有向量库(Chroma、FAISS、Pinecone、Weaviate、pgvector、InMemoryVectorStore 等)都可以通过 .as_retriever() 转成检索器 。

支持三种搜索类型

  • similarity:标准相似度
  • mmr(Maximal Marginal Relevance):兼顾相关性与多样性
  • similarity_score_threshold:带阈值过滤
python 复制代码
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_openai import OpenAIEmbeddings

vectorstore = InMemoryVectorStore.from_documents(
    documents=doc_splits,
    embedding=OpenAIEmbeddings(),
)

# 基础用法
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# MMR 搜索(多样性)
retriever_mmr = vectorstore.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 5, "fetch_k": 10, "lambda_mult": 0.5}
)

# 阈值过滤
retriever_thresh = vectorstore.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={"k": 4, "score_threshold": 0.8}
)

docs = retriever.invoke("如何申请退款?")

优点 :语义理解能力强,能匹配同义表述;接入几乎所有主流向量库。

缺点:对精确词条、产品型号、人名地名容易miss;分块策略直接影响效果;单一查询单次检索,召回上限受限 。


2. BM25 稀疏检索器

功能:基于词袋模型的关键词匹配,弥补向量检索在精确词条上的不足 。

python 复制代码
from langchain_community.retrievers import BM25Retriever

bm25_retriever = BM25Retriever.from_documents(doc_splits)
bm25_retriever.k = 5
docs = bm25_retriever.invoke("iPhone 15 Pro Max 保修政策")

优点 :对专名、型号、术语的精确匹配极佳;零成本、零延迟(不调 LLM、不调 embedding)。

缺点:完全不理解语义,"退款"和"退货"会被视为无关;单独使用效果不如稠密检索。

💡 实践中 BM25 几乎总是和向量检索配合使用,见下一节。


3. 集成检索器(EnsembleRetriever)------ 混合搜索

功能:把多个检索器的结果按权重(或 RRF 倒数排名融合)合并 。

python 复制代码
from langchain.retrievers import BM25Retriever, EnsembleRetriever

bm25_retriever = BM25Retriever.from_documents(doc_splits)
bm25_retriever.k = 5

vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})

ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.3, 0.7]   # 可调权重,也可改用 RRF
)

docs = ensemble_retriever.invoke("我们的退款政策是什么?")

优点 :稠密+稀疏互补,在领域特定查询上准确率可提升 15-25% ;是最具性价比的进阶方案。

缺点:两套检索链路都要维护;权重需要调参(RRF 可免校准 )。


4. 查询转换类检索器

4.1 MultiQueryRetriever ------ 多查询扩展

把用户的一个查询,让 LLM 生成多个不同表述的变体,分别检索后合并去重,解决"用户问得不准"的问题 。

python 复制代码
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI

multi_retriever = MultiQueryRetriever.from_llm(
    retriever=vectorstore.as_retriever(),
    llm=ChatOpenAI(temperature=0)
)
# 内部自动把 "LangChain 咋用" 扩展为多个近义查询
docs = multi_retriever.get_relevant_documents("LangChain 咋用")

优点 :显著提升模糊查询的召回;对口语化、非标准表述友好。

缺点 :每次检索要调 LLM 生成多查询,再检索多次,延迟和成本成倍增加

4.2 SelfQueryRetriever ------ 自查询(带元数据过滤)

让 LLM 把自然语言查询拆解为两部分:语义检索词 + 元数据过滤器。适合带结构化字段的文档库 。

python 复制代码
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_openai import ChatOpenAI

metadata_field_info = [
    {"name": "source", "type": "string", "description": "文档来源"},
    {"name": "year", "type": "integer", "description": "发布年份"},
]

self_query_retriever = SelfQueryRetriever.from_llm(
    llm=ChatOpenAI(temperature=0),
    vectorstore=vectorstore,
    document_contents="公司政策文档",
    metadata_field_info=metadata_field_info,
)

# "2024年发布的退款相关政策" -> 语义部分 + year==2024 过滤
docs = self_query_retriever.invoke("2024年发布的退款相关政策")

优点 :能利用元数据做精确过滤;复杂查询拆解能力强。

缺点:依赖 LLM 正确抽取元数据字段;元数据 schema 要预先定义好。


5. 上下文压缩检索器(Contextual Compression)

功能 :先用 base_retriever 粗召(如 top-10),再用 compressor 精排 + 压缩,只保留与查询相关的片段 。

python 复制代码
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank

# 粗召
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})

# 精排压缩
compressor = CohereRerank(top_n=3)  # 也可用 LLMChainExtractor
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=base_retriever,
)

compressed_docs = compression_retriever.invoke("如何退款?")

优点 :Cross-encoder 重排序可将准确率平均提升 33%,复杂查询甚至 +52% ;大幅节省 token。

缺点:引入重排序模型依赖(Cohere 等第三方 API 或本地 cross-encoder);增加链路延迟。


6. 父文档检索器(ParentDocumentRetriever)

功能用小分块做检索(精准匹配向量),但返回大分块/完整文档(保住上下文) 。解决了"分块小→检索准但上下文丢;分块大→上下文全但检索糙"的两难。

python 复制代码
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 小分块用于向量检索
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
# 大分块用于返回上下文
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)

retriever = ParentDocumentRetriever(
    vectorstore=child_vectorstore,      # 存小分块向量
    docstore=InMemoryStore(),           # 存父文档
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)
retriever.add_documents(docs)

优点 :兼顾"检索精度"和"上下文完整性",是生产级 RAG 的常用模式。

缺点:要同时维护向量库和文档库,架构更复杂。


7. 外部/托管检索器

这类检索器直接对接外部知识源,不需要自己建向量库 :

  • 学术/互联网ArxivRetrieverWikipediaRetrieverTavilySearchAPIRetrieverParallelSearchRetrieverPerplexitySearchRetriever
  • 云服务AmazonKnowledgeBasesRetrieverAzureAISearchRetrieverVertexAISearchRetrieverElasticsearchRetriever
python 复制代码
from langchain_community.retrievers import WikipediaRetriever
wiki_retriever = WikipediaRetriever()
docs = wiki_retriever.invoke("Transformer 模型")

优点 :开箱即用,免建索引。

缺点:受限于外部源的内容覆盖和 API 配额;可控性低。


8. LangGraph 中的 Agentic 检索

这是 LangChain 和 LangGraph 最大的分野:LangChain 检索是线性流水线(一次检索→生成),LangGraph 检索是状态机(可路由、可复盘、可循环)

LangGraph 里有两种主流接法:

8.1 直接把 Retriever 作为图节点

python 复制代码
from langgraph.graph import StateGraph, START, END

def retrieve_node(state):
    question = state["question"]
    docs = retriever.invoke(question)
    return {"context": "\n\n".join([d.page_content for d in docs])}

workflow = StateGraph(RAGState)
workflow.add_node("retrieve", retrieve_node)
workflow.add_node("generate", answer_node)
workflow.add_edge(START, "retrieve")
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", END)

8.2 把 Retriever 包装成 Tool,让 Agent 自主决策

这是 LangChain 官方 Agentic RAG 教程推荐的方式 :

python 复制代码
from langchain.tools.retriever import create_retriever_tool

@tool
def retrieve_blog_posts(query: str) -> str:
    """Search and return information about Lilian Weng blog posts."""
    retriever = _get_retriever()
    retrieved_docs = retriever.invoke(query)
    return "\n\n".join([doc.page_content for doc in retrieved_docs])

retriever_tool = retrieve_blog_posts

8.3 多策略路由检索(Agentic RAG 的高级形态)

LangGraph 的真正威力是让 LLM 决定用哪种检索策略

python 复制代码
def router(state):
    """把查询分类为 vector / graph / web / direct"""
    classification = llm.with_structured_output(RouteDecision).invoke(
        f"Classify: {state['question']}"
    )
    return classification.type  # "vector" | "graph" | "web" | "direct"

workflow = StateGraph(AgentState)
workflow.add_node("router", router)
workflow.add_node("vector_retrieve", vector_node)
workflow.add_node("graph_retrieve", graph_node)
workflow.add_node("web_retrieve", web_node)
workflow.add_conditional_edges(
    "router", router,
    {
        "vector": "vector_retrieve",
        "graph": "graph_retrieve",
        "web": "web_retrieve",
        "direct": "direct_llm",
    }
)

完整 Agentic RAG 还会加入 Grader(文档相关性评分)→ Rewriter(查询改写)→ Hallucination Check(幻觉检查) 节点,形成"检索→评分→不行就改写重写→再检索"的闭环 。

📌 LangChain vs LangGraph 检索的本质区别

  • LangChain:单次检索、线性流水线、无状态。适合标准问答、文档搜索、简单聊天机器人。
  • LangGraph:多次检索、带状态、可条件分支和回环。适合多跳推理、Agent 系统、复杂查询、迭代精炼。

🎯 检索器选型总结

按场景对号入座:

  1. MVP / 原型 / 标准问答 → 基础向量检索器,k=3~5
  2. 领域术语多、专名多 → 向量 + BM25 的 EnsembleRetriever(混合搜索)
  3. 用户查询模糊、口语化MultiQueryRetriever
  4. 文档有结构化元数据(日期/来源/类别)SelfQueryRetriever
  5. 检索结果太长、噪声大ContextualCompressionRetriever + 重排序模型
  6. 长文档、分块后上下文割裂ParentDocumentRetriever
  7. 需要查外部实时知识TavilySearchAPIRetriever / WikipediaRetriever
  8. 查询类型多样(事实/关系/时事/计算) → LangGraph Agentic RAG,多策略路由
  9. 需要多跳推理、自我纠错 → LangGraph + 检索节点 + Grader + Rewriter 闭环

生产级 RAG 的经典组合(这也是业界验证过的"黄金搭档"):

💡 ParentDocumentRetriever(父子分块)+ EnsembleRetriever(稠密+BM25)+ ContextualCompressionRetriever(重排序压缩)

这套组合同时解决了"检索精度"、"召回广度"、"上下文完整性"和"token 效率"四大问题。

⚠️ 几个常见踩坑提醒

  • k 不是越大越好,k=1 可能漏信息,k=5 以上会把噪声带进上下文,MVP 阶段 k=3 是甜点
  • MultiQueryRetriever 和重排序都会显著增加延迟与 LLM 调用成本,高并发场景要谨慎
  • BM25 必须与向量检索配合,单独使用效果有限
  • LangGraph 的 Agentic 检索虽然强大,但图的状态设计(State)、路由条件、终止条件)比检索器本身更关键,否则容易陷入无限循环
相关推荐
小柯南敲键盘1 小时前
图片翻译API接入与自动化实现指南
运维·python·自动化
旅僧2 小时前
Q-learning(自用)
python·机器学习
ThatMonth2 小时前
Langchain 入门教程五:提示词Prompts
langchain
Python大数据分析@2 小时前
曝梁文锋称「一度不想维护C端用户,奈何赶不走」,DeepSeek真不需要C端用户吗?可能会有啥影响吗?
python
中微极客3 小时前
用LangChain 0.3构建生产级RAG与Agent:从API集成到Streamlit部署
数据库·人工智能·langchain
海上彼尚3 小时前
Nodejs也能写Agent - 22.LangGraph篇 - 上下文工程
前端·javascript·人工智能·langchain·node.js
艾斯特_3 小时前
工作流与多Agent协作:LangGraph、MCP和A2A的应用分层
人工智能·python·ai
IT小盘3 小时前
04-大模型流式输出原理-SSE与Python实现
开发语言·网络·人工智能·python
我叫黑大帅4 小时前
add()和 __add__() 写法哪个更好呢?
后端·python·面试