Contextual Compression
Contextual Compression 是面向 RAG 检索结果的查询条件化压缩:在注入模型上下文前,只保留与当前查询相关的文档内容;它是 Context Compression 的一个专门场景。
#concept
#evergreen
#ai
[!info] related notes
- 所属 MOC: RAG Engineering MOC
- 上位概念: Context Compression
- 相邻阶段: Reranker
Contextual Compression
一句话定义
Contextual Compression 是在注入上下文前压缩检索结果的技术。检索到的文档块可能包含很多与查询无关的内容,压缩后只保留相关的部分。
边界:它不是所有 Context Compression
Context Compression 是更宽的上位概念,可以压缩对话历史、工具输出、检索文档或其他上下文来源。Contextual Compression 只讨论其中一个稳定问题:
给定当前 query,怎样把已经检索到的文档压缩成仍能回答该 query 的证据片段?
因此:
- 压缩 conversation history,不属于本笔记;
- 为整个 prompt 做 token 预算,不属于本笔记;
- 对 RAG 文档做 query-conditioned extraction / summarization,属于本笔记;
- Reranker 决定“哪些文档更值得保留”,Contextual Compression 决定“每篇保留哪些内容”。
核心原理
压缩方式
| 方式 | 原理 | 适用场景 |
|---|---|---|
| 提取式 | 只保留相关句子 | 长文档 |
| 摘要式 | LLM 生成摘要 | 复杂文档 |
| 过滤式 | 去除不相关段落 | 混合文档 |
Python 实现
class ContextualCompressor:
def __init__(self, llm):
self.llm = llm
async def compress(self, query: str, documents: list[str]) -> list[str]:
compressed = []
for doc in documents:
prompt = f"""
从以下文档中提取与查询直接相关的内容。只保留相关部分,去除无关内容。
查询: {query}
文档:
{doc}
相关部分:
"""
result = await self.llm.chat(prompt)
if result.strip():
compressed.append(result)
return compressed
与 Reranker 的关系
检索结果 (20 个)
│
▼
Reranker → 重排序 (选 5 个)
│
▼
Contextual Compression → 压缩每个文档 (只保留相关部分)
│
▼
注入上下文
常见坑
- 不做压缩: 检索结果太长浪费 token
- 压缩太狠: 丢失了关键上下文
- 压缩增加延迟: 每个文档都调用 LLM
学习检查
- 为什么“把历史对话做摘要”属于 Context Compression,却通常不属于 Contextual Compression?
- Reranker 与 Contextual Compression 分别在“选文档”和“压文档”上负责什么?
- 如果压缩后的片段丢掉了限定条件,系统会出现哪类检索正确但回答失真的问题?
- 给定 20 个检索结果,你会先 rerank 还是先逐篇做昂贵的 LLM compression?为什么?