上下文压缩:从“选对文章”到“划出重点”

AI摘要
【知识分享】本文介绍了LangChain中上下文压缩技术的原理与实现,重点讲解ContextualCompressionRetriever组件及其两种压缩策略(提取式LLMChainExtractor和过滤式LLMChainFilter),并提供了在RAG项目中集成该技术的实操代码示例,包括如何与重排序组合使用以优化检索流水线。

🎯 上下文压缩:从“选对文章”到“划出重点”

如果说“重排序”是在一堆文档里选出最相关的几篇,那么“上下文压缩”就是在这几篇文档里,用高亮笔划出与问题最直接相关的句子,或者直接删掉不相关的段落。

LangChain 的 ContextualCompressionRetriever 是实现这一功能的核心组件。它像一个包装器,内部包含基础检索器(如你的 ensemble_retriever)和一个文档压缩器BaseDocumentCompressor)。工作流程如下:

  1. 基础检索器根据你的问题,先初步召回一批相关文档。
  2. 文档压缩器对这些文档进行压缩处理,只保留与问题最相关的信息。
  3. 压缩后的精简文档才会被送入大模型生成最终答案。

⚙️ 两种主流的压缩策略

LangChain 提供了几种不同的压缩器,主要分为两大类:

  • 提取式压缩 (LLMChainExtractor):利用大模型(LLM)智能地从每个文档中“摘抄”出最相关的句子。这会改变原始文档的内容,但能确保留下的都是精华。这种方式效果最好,但会消耗额外的 Token 和计算时间。
  • 过滤式压缩 (LLMChainFilter):利用大模型(LLM)快速判断每个文档整体是否与问题相关,然后直接丢弃不相关的文档。这种方式不改变文档内容,速度更快,但粒度较粗。

此外,还有一些更轻量的方法,如基于向量相似度的冗余过滤器EmbeddingsRedundantFilter),或者根据文档元数据(如日期、类型)进行过滤等,可以根据需求灵活组合。

🏗️ 如何在你的项目中集成(实操步骤)

在你的 my_ai_platform 项目中集成上下文压缩,核心思路是用 ContextualCompressionRetriever 将你现有的 ensemble_retriever 包装起来。

1. 安装必要的包

pip install langchain

2. 修改你的 RAG Service

在你的 src/application/services/rag_service.py 中,修改 __init__ 方法,接收并存储一个 retriever 参数。同时,在 ask 方法中,将这个 retriever 用于检索。

# src/application/services/rag_service.py
from langchain.retrievers import ContextualCompressionRetriever
# ... 其他导入 ...

class RAGService:
    def __init__(self, llm_client, retriever):
        self.llm = llm_client
        self.retriever = retriever  # 这里接收的将是压缩检索器
        # ... 其余初始化代码 ...

3. 在 main.py 中组装压缩检索器

在你的 main.py 中,创建完 ensemble_retriever 后,用 ContextualCompressionRetriever 将其包装起来。这里以 LLMChainExtractor 为例:

# main.py
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

# ... 创建 embeddings, vectorstore, ensemble_retriever, llm 的代码 ...

# 1. 创建文档压缩器(这里使用 LLM 进行提取式压缩)
compressor = LLMChainExtractor.from_llm(llm)

# 2. 用压缩器包装你的混合检索器
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=ensemble_retriever
)

# 3. 将压缩后的检索器注入 RAGService
rag_service = RAGService(
    llm_client=llm,
    retriever=compression_retriever  # 传入压缩检索器
)

之后,RAGServiceask 方法在执行 self.retriever.invoke(query) 时,就会自动完成“检索 -> 压缩”的流程。

💡 进阶策略:压缩与重排序的组合使用

你可以将“压缩”与其他后处理技术(如重排序)结合,构建更强大的检索流水线。例如,你可以先用一个基础检索器快速召回较多文档,再用重排序选出最相关的 Top-N 个,最后用上下文压缩对这些文档进行精简。

# 示例:组合使用重排序和压缩
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

# 假设 reranker_retriever 是已经封装了重排序逻辑的检索器
compression_retriever = ContextualCompressionRetriever(
    base_compressor=LLMChainExtractor.from_llm(llm),
    base_retriever=reranker_retriever  # 先重排序,再压缩
)

💎 总结与建议

上下文压缩通过提取精华或过滤噪音,让你的大模型能够更聚焦于关键信息,从而提升回答质量并节约成本。在 LangChain 中,通过 ContextualCompressionRetriever 可以方便地将这个能力集成到你现有的检索流程中。

一点建议LLMChainExtractor 会调用大模型进行压缩,因此会增加一些处理时间和成本。建议先在测试集上评估其效果和速度,再决定是否应用到生产环境。如果追求极致的性能,可以考虑 LLMChainFilter 或其它基于规则的压缩方式作为备选。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!