上下文压缩
定义
上下文压缩(Contextual Compression)是 RAG 中发生在“检索之后、答案生成之前”的一层内容裁剪与重写机制。 它的做法不是重新建立索引,也不是在文档入库前做普通分块压缩,而是针对已经召回的候选 chunk,结合当前用户问题逐个判断哪些内容真正与回答任务有关,只把相关部分传给生成模型。
一句话概括:先检索出候选内容,再按 query 把无关部分“剪掉”,只留下对当前回答最有用的信息。
在本文语境中的位置
在本文语境里,上下文压缩属于标准 RAG 流程中的后检索步骤,完整链路可概括为:
- 文档文本抽取。
- 文本分块。
- 向量化。
- 相似度检索,取回 Top-K 个 chunk。
- 对每个召回 chunk 执行上下文压缩。
- 将压缩后的结果拼接为上下文。
- 交给大模型生成最终答案。
因此,它与“把长文按 1000 字切块、重叠 200 字”这类预处理动作不是一回事。 分块发生在知识入库前或检索前,属于静态处理;上下文压缩发生在 query 已知之后,属于面向当前问题的动态处理。
这一区别很重要:
- 分块解决的是“怎样让文档能被检索”。
- 上下文压缩解决的是“检索回来的内容太杂,怎样只把有用信息交给生成模型”。
要解决的问题
RAG 的典型问题不是完全检索不到,而是“检索到了,但相关和无关内容混在一起”。 原文明确指出,召回结果里经常同时包含 Relevant 与 Irrelevant 信息,真正有价值的信号会被大量“废话”包围。
这会带来几类具体后果:
- 上下文窗口浪费:有限 token 被低价值内容占满。
- 模型注意力分散:模型必须在混杂材料里自己筛重点,容易被带偏。
- 答案不聚焦:输出变得啰嗦、跑题,甚至答非所问。
一个文中的例子是:当用户问“AI 决策的伦理问题有哪些?”时,检索出的段落可能同时包含 AI 历史、AI 优点、AI 缺点等内容,而真正和“伦理问题”直接相关的部分可能只占三分之一。 如果把这些内容原样全部塞给生成模型,模型就会在大量非目标信息中消耗窗口和注意力。
核心机制
上下文压缩 的核心不是简单缩短文本长度,而是“结合 query 进行相关性导向的压缩”。 具体做法是:
- 对每个召回的 chunk 单独处理。
- 把用户 query 和 chunk 一起送入压缩模块,通常由大模型执行。
- 判断该 chunk 中哪些句子、段落、事实与当前问题直接相关。
- 删除无关内容,或把相关内容改写成更紧凑的表达。
- 将压缩后的多个 chunk 再拼接起来,作为最终生成阶段的上下文。
原文还强调可以批量压缩多个 chunk,以提高整体处理效率。
用伪代码表达,其逻辑接近:
- 先做相似度检索,取回 k 个候选 chunk。
- 对每个 chunk 调用
compress_chunk(chunk, query, compression_type)。 - 得到压缩结果后拼接上下文,再调用答案生成模型。
这里的关键判断标准不是“这段文字本身重不重要”,而是“它是否对回答当前这个 query 有帮助”。 同一 chunk 面对不同问题,压缩结果可以完全不同。
三种常见实现形态
Selective:选择性保留
Selective 的做法是只保留与问题直接相关的原文句子或段落,但不主动改写内容。 它更接近“裁剪”,不是“总结”。
特点:
- 保留原文表述,证据感较强。
- 会删除大段无关背景信息。
- 适合既希望减少噪声,又希望尽量维持原文措辞的场景。
原文给出的理解是:只保留相关句子/段落,原文照抄,不做改写。
Summary:摘要压缩
Summary 是把相关内容进一步浓缩成摘要。 它不要求完全保留原句,而是追求更高的信息密度。
特点:
- 文本最精炼。
- 在相同窗口内能容纳更多有效信息。
- 更适合问答、摘要、快速归纳等强调结果密度的场景。
原文明确指出,Summary 的特点是把相关内容浓缩成简明扼要的摘要。
Extraction:关键句抽取
Extraction 是只抽取原文里包含关键信息的句子,逐句列出。 它与 Selective 相似,但通常更偏向“关键句级别”的保留,而不是保留较完整的相关段落。
特点:
- 保留原文证据。
- 信息密度高。
- 适合法律、学术、需要引用原句支撑的场景。
原文对它的定义是:只抽取原文中最关键的句子。
三种形态的选择原则
原文给出的经验非常直接:
- 如果要“原汁原味”,优先选 Selective 或 Extraction。
- 如果要“言简意赅”,优先选 Summary。
进一步按场景可总结为:
- 需要原文证据:Extraction。
- 需要最高信息密度:Summary。
- 需要较全面覆盖相关内容:Selective。
为什么它能提升效果
上下文压缩 提升效果的原因,不是它替代了检索,而是它改善了“检索结果进入生成模型”这一段的信息质量。
主要收益包括:
- 在相同窗口内容纳更多有效信息:同样的 token 预算里,压缩后可以放入更多真正相关的知识。
- 减少噪声干扰:模型看到的无关背景更少,生成阶段更不容易跑偏。
- 答案更聚焦:因为输入材料已经围绕 query 过滤过,回答更容易直击问题。
- 推理更快、成本更低:上下文更短时,推理延迟和 API 成本通常也会下降。
- 支持更大文档:面对长文档或多 chunk 召回时,更不容易“爆窗”。
原文甚至给了一个直观收益描述:原来上下文只能塞 10 个 chunk,压缩后可能能塞 30 个,意味着同样窗口内可容纳的信息量显著提升。
实际流程细节
虽然 上下文压缩 是后检索步骤,但原文把它放进完整 RAG 流程里讨论,便于理解其边界。
1. 前置处理不是上下文压缩本身
文中示例流程先做文档预处理:
- 从 PDF 抽取文本。
- 将长文本切成 chunk。
- 示例参数为每 1000 字一块,重叠 200 字。
这些步骤是为了后续 embedding 和检索服务,不应与 上下文压缩 混为一谈。
2. 检索阶段
文中示例随后把每个 chunk 向量化,并在用户提问后做相似度检索。
示例中会取回 Top-K chunk,伪代码示例使用了 k=10。
3. 压缩阶段
核心步骤是对每个检索到的 chunk 进行压缩:
- 输入:chunk + query。
- 参数:压缩类型,可选 Selective、Summary、Extraction。
- 输出:压缩后的 chunk,以及可选的压缩比。
文中伪代码中的核心函数可概括为:
- 根据 compression_type 选择不同 prompt。
- 让 LLM 仅保留与 query 相关的内容。
- 返回压缩结果与 compression_ratio。
4. 生成阶段
压缩完成后,把多个压缩 chunk 用分隔符拼接成新的上下文,再送入生成模型回答问题。 这一步说明 上下文压缩 的直接产物不是最终答案,而是“更干净、更高密度的生成上下文”。