LangChain 的"检索器"本质上是一个统一接口 :输入查询字符串,输出 Document 对象列表。它比向量库更抽象------检索器不需要能存文档,只要能"返回"文档就行,所以它可以包装向量库、搜索引擎、图数据库、关系数据库,甚至一个搜索 API。所有检索器都继承自 BaseRetriever,必须实现 _get_relevant_documents 方法,并天然具备 Runnable 能力(invoke / ainvoke / batch)。
🗂️ 检索器分类总览
| 类别 | 代表检索器 | 解决的核心痛点 |
|---|---|---|
| 1. 基础向量检索器 | vectorstore.as_retriever() |
语义相似度匹配 |
| 2. 稀疏/关键词检索器 | BM25Retriever |
精确词条、专名匹配 |
| 3. 融合检索器 | EnsembleRetriever |
稠密+稀疏互补,提升召回 |
| 4. 查询转换检索器 | MultiQueryRetriever、SelfQueryRetriever |
用户查询表述不佳 |
| 5. 上下文压缩检索器 | ContextualCompressionRetriever + CohereRerank |
检索结果冗余、需要精排 |
| 6. 父子文档检索器 | ParentDocumentRetriever |
分块导致上下文割裂 |
| 7. 外部/托管检索器 | WikipediaRetriever、ArxivRetriever、AmazonKnowledgeBasesRetriever 等 |
直接检索外部知识源 |
| 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. 外部/托管检索器
这类检索器直接对接外部知识源,不需要自己建向量库 :
- 学术/互联网 :
ArxivRetriever、WikipediaRetriever、TavilySearchAPIRetriever、ParallelSearchRetriever、PerplexitySearchRetriever - 云服务 :
AmazonKnowledgeBasesRetriever、AzureAISearchRetriever、VertexAISearchRetriever、ElasticsearchRetriever
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 系统、复杂查询、迭代精炼。
🎯 检索器选型总结
按场景对号入座:
- MVP / 原型 / 标准问答 → 基础向量检索器,
k=3~5 - 领域术语多、专名多 → 向量 + BM25 的
EnsembleRetriever(混合搜索) - 用户查询模糊、口语化 →
MultiQueryRetriever - 文档有结构化元数据(日期/来源/类别) →
SelfQueryRetriever - 检索结果太长、噪声大 →
ContextualCompressionRetriever+ 重排序模型 - 长文档、分块后上下文割裂 →
ParentDocumentRetriever - 需要查外部实时知识 →
TavilySearchAPIRetriever/WikipediaRetriever等 - 查询类型多样(事实/关系/时事/计算) → LangGraph Agentic RAG,多策略路由
- 需要多跳推理、自我纠错 → LangGraph + 检索节点 + Grader + Rewriter 闭环
生产级 RAG 的经典组合(这也是业界验证过的"黄金搭档"):
💡 ParentDocumentRetriever(父子分块)+ EnsembleRetriever(稠密+BM25)+ ContextualCompressionRetriever(重排序压缩)
这套组合同时解决了"检索精度"、"召回广度"、"上下文完整性"和"token 效率"四大问题。
⚠️ 几个常见踩坑提醒:
k不是越大越好,k=1可能漏信息,k=5以上会把噪声带进上下文,MVP 阶段k=3是甜点MultiQueryRetriever和重排序都会显著增加延迟与 LLM 调用成本,高并发场景要谨慎- BM25 必须与向量检索配合,单独使用效果有限
- LangGraph 的 Agentic 检索虽然强大,但图的状态设计(State)、路由条件、终止条件)比检索器本身更关键,否则容易陷入无限循环