上下文压缩:从“选对文章”到“划出重点”
🎯 上下文压缩:从“选对文章”到“划出重点”
如果说“重排序”是在一堆文档里选出最相关的几篇,那么“上下文压缩”就是在这几篇文档里,用高亮笔划出与问题最直接相关的句子,或者直接删掉不相关的段落。
LangChain 的 ContextualCompressionRetriever 是实现这一功能的核心组件。它像一个包装器,内部包含基础检索器(如你的 ensemble_retriever)和一个文档压缩器(BaseDocumentCompressor)。工作流程如下:
- 基础检索器根据你的问题,先初步召回一批相关文档。
- 文档压缩器对这些文档进行压缩处理,只保留与问题最相关的信息。
- 压缩后的精简文档才会被送入大模型生成最终答案。
⚙️ 两种主流的压缩策略
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 # 传入压缩检索器
)
之后,RAGService 的 ask 方法在执行 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 协议》,转载必须注明作者和本文链接
关于 LearnKu