LangChain 中的 Retriever 检索器有哪些类型?各有什么特点?(详解RAG系统核心组件)

在构建检索增强生成(RAG)系统时,Retriever(检索器)是连接用户查询与知识库的关键桥梁。它决定了AI应用能否准确理解用户意图,并从海量文档中找到最相关的信息。LangChain框架提供了丰富多样的Retriever类型,每种都针对特定的使用场景和性能需求进行了优化。理解这些不同类型的特点和适用场景,对于构建高效的RAG系统至关重要。

基础Retriever类型

1. VectorStoreRetriever(向量存储检索器)

核心特点:

  • 语义搜索能力:基于嵌入向量进行相似度计算,能够理解查询的语义含义
  • 通用性强:支持所有主流向量数据库(Chroma、FAISS、Pinecone、Milvus等)
  • 配置灵活:支持多种检索参数调优

工作原理:
VectorStoreRetriever是最基础也是最常用的检索器类型。它将用户查询通过嵌入模型转换为向量,然后在向量数据库中执行近似最近邻(ANN)搜索,返回最相似的文档片段。

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.retrievers import BaseRetriever

# 创建向量存储
vectorstore = Chroma.from_documents(
    documents=docs,
    embedding=OpenAIEmbeddings()
)

# 创建基础向量检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",  # 相似度搜索
    search_kwargs={"k": 4}     # 返回4个最相关文档
)

# 使用检索器
results = retriever.invoke("什么是注意力机制?")

适用场景:

  • 通用的语义搜索需求
  • 需要理解查询意图而非关键词匹配
  • 大多数RAG应用的基础检索组件

局限性:

  • 对于精确关键词匹配效果不如稀疏检索
  • 可能返回冗余或不相关的文档
  • 向量计算成本较高

2. BM25Retriever(稀疏检索器)

核心特点:

  • 关键词精确匹配:基于传统的TF-IDF算法,擅长处理精确关键词查询
  • 无需向量化:直接基于文本内容进行检索,计算成本低
  • 互补性强:与向量检索形成良好互补

工作原理:
BM25Retriever实现了经典的BM25算法,这是一种改进的TF-IDF算法,能够更好地处理词频和文档长度的影响。它特别适合处理包含具体术语、代码、数字等精确信息的查询。

from langchain.retrievers import BM25Retriever

# 创建BM25检索器
bm25_retriever = BM25Retriever.from_documents(
    documents=docs,
    k=4  # 返回4个最相关文档
)

# 使用BM25检索器
results = bm25_retriever.invoke("Python中的list comprehension语法")

适用场景:

  • 包含具体技术术语、代码片段的查询
  • 需要精确关键词匹配的场景
  • 作为向量检索的补充,提高检索覆盖率

局限性:

  • 无法理解语义相似性
  • 对同义词、近义词处理能力有限
  • 不适合处理自然语言的模糊查询

高级Retriever类型

3. MultiQueryRetriever(多查询检索器)

核心特点:

  • 查询扩展:自动生成多个相关查询,扩大检索范围
  • 提高召回率:减少因查询表述不当导致的漏检
  • 智能重写:利用LLM理解查询意图并生成变体

工作原理:
MultiQueryRetriever通过LLM分析原始查询,生成多个语义相关的查询变体,然后对每个变体执行检索,最后合并和去重结果。这种方法有效解决了用户查询表述不准确或过于简单的问题。

from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI

# 创建多查询检索器
llm = ChatOpenAI(temperature=0)
multi_query_retriever = MultiQueryRetriever.from_llm(
    retriever=base_retriever,  # 基础检索器
    llm=llm
)

# 配置生成查询的数量
multi_query_retriever = MultiQueryRetriever.from_llm(
    retriever=base_retriever,
    llm=llm,
    include_original=True,  # 是否包含原始查询
    prompt=prompt_template  # 自定义提示词模板
)

适用场景:

  • 用户查询表述模糊或不完整
  • 需要提高检索召回率的场景
  • 处理复杂或多方面的查询需求

局限性:

  • 增加了LLM调用成本
  • 可能生成不相关或重复的查询
  • 执行时间相对较长

4. ContextualCompressionRetriever(上下文压缩检索器)

核心特点:

  • 结果精炼:对检索到的文档进行相关性过滤和内容压缩
  • 提高精度:去除不相关或冗余的信息
  • 节省token:减少传递给LLM的上下文长度

工作原理:
ContextualCompressionRetriever首先使用基础检索器获取候选文档,然后通过压缩器(Compressor)对每个文档进行相关性评估和内容提取。只有与查询高度相关的文档片段才会被保留。

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

# 创建LLM压缩器
compressor = LLMChainExtractor.from_llm(ChatOpenAI())

# 创建上下文压缩检索器
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=base_retriever
)

# 使用压缩检索器
results = compression_retriever.invoke("解释Transformer架构的核心组件")

适用场景:

  • 检索结果包含大量无关信息
  • 需要控制上下文长度以节省token成本
  • 提高回答质量和相关性的场景

局限性:

  • 增加了额外的LLM调用开销
  • 可能过度压缩重要信息
  • 对压缩器的质量依赖较大

5. EnsembleRetriever(集成检索器)

核心特点:

  • 混合检索策略:同时使用多种检索方法
  • 优势互补:结合不同检索器的优点
  • 鲁棒性强:降低单一检索方法的失败风险

工作原理:
EnsembleRetriever将多个不同的检索器组合在一起,对每个检索器的结果进行加权融合。通常会结合向量检索和稀疏检索,既保证语义理解能力,又保持关键词匹配的精确性。

from langchain.retrievers import EnsembleRetriever

# 创建集成检索器
ensemble_retriever = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.5, 0.5]  # 权重分配
)

# 使用集成检索器
results = ensemble_retriever.invoke("机器学习中的梯度下降算法")

适用场景:

  • 需要兼顾语义搜索和关键词匹配
  • 提高检索系统的整体鲁棒性
  • 处理多样化的查询类型

局限性:

  • 计算成本较高(需要执行多次检索)
  • 权重调优需要经验和实验
  • 结果融合策略可能影响最终效果

6. ParentDocumentRetriever(父文档检索器)

核心特点:

  • 分块策略优化:小块用于检索,大块用于上下文
  • 保持上下文完整性:避免因分块过小丢失重要上下文
  • 灵活性强:支持不同的分块大小配置

工作原理:
ParentDocumentRetriever采用两层分块策略:将文档分割成较小的子块用于向量检索,但存储和返回的是较大的父块。这样既能保证检索的精确性,又能提供足够的上下文信息。

from langchain.retrievers import ParentDocumentRetriever
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 创建不同大小的文本分割器
child_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)

# 创建父文档检索器
parent_retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=InMemoryStore(),  # 存储父文档
    child_splitter=child_splitter,
    parent_splitter=parent_splitter
)

# 添加文档
parent_retriever.add_documents(docs)

适用场景:

  • 文档内容较长且需要保持上下文完整性
  • 小块检索但大块使用的场景
  • 技术文档、法律文件等结构化内容

局限性:

  • 存储开销较大(需要存储两种粒度的文档)
  • 配置复杂度较高
  • 对内存要求较高

特殊用途Retriever类型

7. TimeWeightedVectorStoreRetriever(时间加权检索器)

核心特点:

  • 时间衰减:较新的文档获得更高权重
  • 动态更新:支持文档的时间戳管理
  • 时效性优先:适合处理时效性强的内容

工作原理:
这种检索器在计算相似度时,除了考虑向量距离外,还考虑文档的时间戳。较新的文档会获得更高的最终得分,确保用户优先看到最新的信息。

8. SelfQueryRetriever(自查询检索器)

核心特点:

  • 元数据过滤:自动从查询中提取过滤条件
  • 结构化查询:支持基于元数据的复杂查询
  • 智能解析:利用LLM理解查询中的结构化信息

工作原理:
SelfQueryRetriever能够分析用户查询,自动识别其中的元数据过滤条件(如日期范围、作者、类别等),并将这些条件应用到检索过程中。

from langchain.retrievers.self_query.base import SelfQueryRetriever

# 定义文档元数据结构
metadata_field_info = [
    AttributeInfo(
        name="category",
        description="文档类别",
        type="string"
    ),
    AttributeInfo(
        name="date",
        description="发布日期",
        type="integer"
    )
]

# 创建自查询检索器
self_query_retriever = SelfQueryRetriever.from_llm_and_vectorstore(
    llm=llm,
    vectorstore=vectorstore,
    document_contents="文档内容",
    metadata_field_info=metadata_field_info
)

适用场景:

  • 文档具有丰富的元数据信息
  • 用户查询包含明确的过滤条件
  • 需要支持复杂的结构化查询

Retriever选择与优化策略

性能对比与选择指南

Retriever类型 语义理解 关键词匹配 计算成本 适用场景
VectorStoreRetriever ⭐⭐⭐⭐⭐ ⭐⭐ 中等 通用RAG应用
BM25Retriever ⭐ ⭐⭐⭐⭐⭐ 低 精确匹配需求
MultiQueryRetriever ⭐⭐⭐⭐⭐ ⭐⭐⭐ 高 模糊查询场景
ContextualCompression ⭐⭐⭐⭐ ⭐⭐⭐ 高 结果精炼需求
EnsembleRetriever ⭐⭐⭐⭐ ⭐⭐⭐⭐ 高 综合性能要求
ParentDocumentRetriever ⭐⭐⭐⭐ ⭐⭐ 中等 长文档处理

组合使用最佳实践

在实际应用中,往往需要组合多种Retriever来达到最佳效果:

# 复合检索策略示例
def create_optimized_retriever():
    # 基础向量检索器
    vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
    
    # 多查询扩展
    multi_query_retriever = MultiQueryRetriever.from_llm(
        retriever=vector_retriever,
        llm=ChatOpenAI(temperature=0)
    )
    
    # 集成BM25检索
    bm25_retriever = BM25Retriever.from_documents(docs, k=10)
    ensemble_retriever = EnsembleRetriever(
        retrievers=[multi_query_retriever, bm25_retriever],
        weights=[0.7, 0.3]
    )
    
    # 上下文压缩
    compressor = LLMChainFilter.from_llm(ChatOpenAI())
    final_retriever = ContextualCompressionRetriever(
        base_compressor=compressor,
        base_retriever=ensemble_retriever
    )
    
    return final_retriever

这种复合策略结合了多种Retriever的优势:多查询扩展提高了召回率,集成检索保证了语义和关键词的双重覆盖,上下文压缩确保了结果的精确性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
其AI的头像其AI普通用户

相关推荐

返回顶部