7-上下文压缩与摘要记忆

概述

在长对话、多轮任务规划和 Agent 执行流程中,上下文窗口是有限且昂贵的资源。上下文压缩(Context Compression)不是简单的内容删减,而是一种有目标的信息保留策略——在有限的上下文空间内,保留对当前任务最相关的信息,同时以可接受的信息损失换取可持续的对话能力。

压缩的核心矛盾在于:压缩率越高,token 成本越低,但信息损失越大;压缩率越低,信息保留越完整,但上下文耗尽越快。理解这一点,才能在工程中做出合理的权衡。


1. 为什么需要上下文压缩

1.1 长对话的困境

当对话轮次增加,历史消息会持续消耗上下文窗口。以每次交互 2,000 token 的平均对话历史计算,一个 128K 上下文窗口在约 30-40 轮对话后就会接近饱和。达到上限时,模型无法处理新输入,对话能力被迫终止。

这不只是”空间不够”的问题。在多阶段任务中,早期的中间结果、决策依据和子任务状态往往在后期才发挥作用。如果简单截断早期内容,可能导致任务无法完成。

1.2 上下文压缩的三大目标

目标含义
降低 token 成本减少每次请求的输入 token 数量,节省 API 费用
保留关键信息识别并保留对当前任务有贡献的内容
提升可持续对话能力延长对话寿命,避免上下文窗口耗尽导致的对话终止

这三个目标往往互相牵制。压缩策略的设计,本质上是在三者之间寻找当前任务可接受的平衡点。


2. 压缩的基础理论

2.1 压缩率与信息损失的关系

设原始上下文包含信息量 ,压缩后保留信息量 ,则:

  • 压缩率 ,其中 为 token 数量
  • 信息保留率

压缩率与信息保留率之间不是线性关系。不同内容的”信息密度”差异极大:

  • 一段冗余的礼貌性回复:压缩率可达 80%,信息损失接近零
  • 一段精确的数学推导中间步骤:压缩率 50% 可能就丢失了关键的推理链

工程中的经验法则:有结构的、任务相关的内容比无结构的闲聊更难压缩,因为前者中每个 token 的信息熵更高。

2.2 任务相关信息保留

不是所有历史信息都同等重要。压缩的核心任务是识别任务相关信息并优先保留。

信息相关性可从三个维度衡量:

  1. 时间衰减:近期信息通常比早期信息更重要,但早期决策前提不能丢弃
  2. 任务依赖:当前子任务的输入、约束条件和中间输出是强相关信息
  3. 语义唯一性:提供新概念、新事实或新约束的内容,比重复已有内容的片段更重要

一种简化的信息价值评分:

其中 ,权重系数根据任务类型调整。

2.3 为什么不能只按长度压缩

最简单的压缩策略是”保留最近 N 个 token”或”保留最近 M 条消息”。这种纯长度驱动的截断(Truncation)存在根本性缺陷:

  • 丢失关键前提:早期的事实陈述、用户偏好设定可能已经”过期”,但新任务可能需要回溯这些信息
  • 破坏语义连贯性:从消息中间截断可能导致指代消解失败(如”它""这个""上述”等指代词失去 antecedent)
  • 忽视信息密度差异:长消息未必信息量大,短消息未必信息量小

压缩必须基于语义判断,而非长度判断。 长度截断只适用于对信息质量要求最低的场景(如仅关心 token 成本控制)。


3. 压缩方法分类

3.1 截断(Truncation)

直接丢弃 oldest 或 relevance score 最低的内容。最简单但信息损失最大。

策略说明
Last-N 截断保留最近 N 条消息,丢弃更早的内容
时间窗口截断保留时间窗口内的所有内容,如”最近 30 分钟”
层级截断按消息层级丢弃:如先丢弃低置信度回复,再丢弃低分消息

适用场景:对早期信息依赖极低、对话结构简单的场景。作为其他压缩方法的 fallback 机制。

3.2 摘要(Summarization)

用 LLM 自身(或专用摘要模型)将一段内容压缩为简短的自然语言摘要。

摘要的优势

  • 可以跨越多段内容,提炼共同主题
  • 保留语义压缩后的核心信息
  • 可定制摘要粒度(一句话概述、多句细节摘要、条目式要点)

摘要的固有缺陷——偏差与幻觉

  1. 选择性总结偏差:摘要模型会优先保留”看起来重要”的内容,但判断重要性的标准来自摘要任务的预训练分布,与当前任务需求可能不一致
  2. 幻觉(Hallucination):摘要模型可能将源文中不存在的信息”补全”进摘要,这在关键事实、数字、名称上尤为危险
  3. 上下文丢失:摘要丢失了原文的语气、确定性程度、讨论过程,只留下”结论性”内容
  4. 累积误差:多轮摘要叠加后,信息逐渐失真,形成”电话游戏效应”

何时优先保留原文:当内容包含精确数值、专有名词、操作指令或因果链条时,应保留原文而非摘要。

何时可以用摘要:当内容是描述性、总结性的,且对精确性要求不高时(如”用户表达了不满情绪”比”用户具体说了什么”更容易安全摘要)。

3.3 结构化提炼(Structural Extraction)

将非结构化文本转换为结构化数据(如 JSON、表格、知识图谱),在相同信息量下占用更少 token。

示例对比

原文(~200 tokens):
"用户想要预订下周三从北京到上海的机票,需要上午出发,预算不超过2000元,
希望坐国航或东航的航班,如果价格合适的话也可以考虑高铁。"

结构化提炼(~60 tokens):
{
  "intent": "机票预订",
  "date": "下周三",
  "from": "北京",
  "to": "上海",
  "departure_time": "上午",
  "budget": 2000,
  "preferred_airlines": ["国航", "东航"],
  "alternative": "高铁"
}

结构化提炼的优势是信息无损(相对于原文)、可程序化处理。但需要设计合适的 schema,且对 LLM 的结构化输出能力有一定要求。

3.4 记忆槽(Memory Slot)

将关键信息存入固定槽位,上下文只保留指向这些槽位的引用。

典型设计

[记忆槽 #1] 用户偏好:{ ... }
[记忆槽 #2] 当前任务状态:{ ... }
[记忆槽 #3] 已知事实库:{ ... }

[工作上下文]
...(引用 #1 #2 #3 中的信息完成当前任务)

记忆槽的压缩效果来自于:相同信息在上下文中只出现一次(作为槽位定义),后续引用只占 1-2 个 token 的引用开销。

3.5 检索式压缩(Retrieval-based Compression)

结合检索机制,只将当前查询最相关的历史片段注入上下文。典型流程:

  1. 历史文档集合(压缩后的摘要或原文)存储在外部
  2. 当前查询到来时,用 query embedding 检索最相关的 top-K 片段
  3. 将检索结果注入上下文,而非放入全部历史

这种方法的压缩效果来自两个层面:

  • 历史本身已经过压缩(摘要或结构化)
  • 每次只注入相关性最高的子集

4. 摘要记忆的工程实践

4.1 摘要模板设计

摘要模板定义了”摘要应该包含什么”,直接影响摘要质量和后续可用性。

基础摘要模板要素

## 对话摘要

**对话主题**:[一句话描述核心话题]
**关键决策/结论**:[列出主要结论或决定]
**未解决问题**:[列出悬而未决或有待确认的事项]
**重要事实/约束**:[用户提供的关键信息,如偏好、截止日期、预算等]
**下一步行动**:[如果对话产生了待执行任务,记录之]

分级摘要模板:根据内容重要性采用不同深度的摘要模板:

内容类型摘要深度模板特点
关键决策、用户明确需求详细摘要保留原文中所有约束条件
一般性讨论标准摘要提炼要点,去除冗余表达
礼貌性/过渡性内容一句话概括仅保留核心信息
重复确认类内容直接丢弃或合并不单独摘要

4.2 滚动总结(Rolling Summarization)

滚动总结是在对话进行中持续维护一个”累积摘要”,而非等待对话结束后一次性总结。

工作流程

用户消息1 → 模型回复1
  ↓ [每 N 轮 或 上下文使用超过阈值时]
触发摘要 → 更新累积摘要
  ↓
继续对话,新消息仅注入摘要,不注入完整历史

滚动摘要的更新策略

  1. 增量更新:新摘要 = 旧摘要 + “新增内容摘要”,不重写全部历史
  2. 周期性重写:每 M 轮对话后,用 LLM 基于当前累积摘要 + 最近 N 条消息重写完整摘要(避免累积误差)
  3. 事件驱动更新:当对话中出现关键事件(决策点、任务状态变化)时立即更新

滚动总结的常见失败模式

  • 摘要陈旧:长时间不更新,旧信息被新对话稀释,导致早期重要约束被忽视
  • 重复摘要:新旧摘要表达不一致,用户或模型对同一事实产生混淆
  • 过度压缩:频繁更新导致摘要变得过于笼统,丢失具体细节

4.3 分层记忆(Hierarchical Memory)

分层记忆将信息存储在多个抽象层级,每层使用不同的压缩率和更新频率。

层级 0:工作上下文(原始消息,完整保留最近 N 条)
层级 1:当前会话摘要(每轮更新,摘要本会话内容)
层级 2:跨会话记忆(每天/每周更新,提取长期有效信息)
层级 3:长期知识库(手动维护,外部检索)

注入上下文时的层级选择

任务类型优先使用层级
单会话多轮对话层级 0 + 层级 1
跨天任务接续层级 2 摘要 + 层级 0 最近消息
需要精确回溯层级 3 外部检索 + 层级 0 原始内容

4.4 重新注入上下文

压缩后的信息需要正确地重新注入上下文才能发挥作用。常见注入方式:

方式一:摘要前置注入

[系统提示]
以下是对话历史摘要,请结合使用:
---
[累积摘要内容]
---

[当前消息]
[用户新消息]

方式二:引用式注入

根据之前对话,您提到以下关键信息:
- [引用 #记忆槽-用户偏好]
- [引用 #记忆槽-当前任务状态]

[当前消息]
[用户新消息]

方式三:检索增强注入

[外部检索结果]
相关历史片段:
1. [片段1] ...
2. [片段2] ...

[当前消息]
[用户新消息]

4.5 评估压缩是否损害任务表现

压缩效果评估是一个容易被忽视但至关重要的环节。

评估指标

指标测量方式
任务完成率压缩前后任务成功率对比
事实一致性压缩后回复中的事实与原始信息的一致率
引用准确率模型引用历史信息时,指代正确率
对话连贯性人工评估或自动化指标(如 BERTscore)
Token 节省率压缩前后 token 数量对比

渐进式评估流程

  1. 在小规模对话上 baseline(无压缩)记录任务表现
  2. 应用压缩策略,对比同一批对话的任务表现
  3. 如果表现下降超过阈值(如任务完成率下降 >5%),调整压缩策略或降低压缩率
  4. 定期抽查压缩质量,监控幻觉率

危险的信号

  • 模型开始”忘记”之前明确提供的信息(表明关键事实被过度压缩)
  • 回复中出现与历史不符的”新事实”(可能是幻觉)
  • 用户频繁需要重复之前说过的内容(摘要未捕获关键信息)
  • 任务中途失败但最终答案实际已在历史中(信息未被正确注入)

5. 对话压缩 vs 文档压缩 vs 任务状态压缩

5.1 对话压缩

特点:对话是时间序列的、多轮的、交替生成的。压缩时需要考虑:

  • 发言者身份(用户 vs 模型 vs 系统)
  • 意图和动作(用户的请求、模型的回应)
  • 对话状态变化( slots 更新、意图识别结果)

难点

  • 保留指代消解需要的信息(“它""这个”需要 antecedent)
  • 保留多轮推理链
  • 处理同一意图的重复确认和细化

5.2 文档压缩

特点:文档是静态的、结构化的(可能是多节的)。压缩时需要考虑:

  • 章节逻辑关系
  • 核心论点 vs 支撑细节的层次
  • 表格、列表、数字等结构化信息

难点

  • 不能破坏文档原有的论证链条
  • 表格和数字通常需要原文保留而非摘要
  • 跨章节的引用关系可能需要显式表达

5.3 任务状态压缩

特点:任务状态是程序化的,包含变量值、中间结果、待办事项。压缩时需要考虑:

  • 状态变量的精确值(不能有任何误差)
  • 当前执行到哪一步
  • 下一步需要什么输入

难点

  • 对精度要求极高,摘要引入的任何偏差都可能是致命的
  • 通常需要结构化压缩而非自然语言摘要
  • 状态之间的依赖关系必须完整保留

6. 长任务 Agent 的上下文维护

6.1 有限上下文的挑战

Agent 执行长任务时面临的核心问题是:任务规划、执行监控和结果汇总都需要消耗上下文,而这些内容之间存在依赖关系。

例如,一个代码生成 Agent 的任务链:

需求分析 → 技术方案设计 → 代码实现 → 单元测试 → 集成测试 → 部署

中途任何一步的错误定位和修复,都可能需要回溯之前所有步骤的上下文。

6.2 维护策略

策略一:任务看板(Task Board)

[已完成] 需求分析 - 结论:采用微服务架构
[进行中] 技术方案设计 - 结论:使用 FastAPI + PostgreSQL
[待执行] 代码实现 - 依赖:方案确定
[待执行] 测试 - 依赖:代码实现

[当前任务上下文]
技术方案设计阶段的详细结论...

任务看板本身是结构化信息,token 效率高,且清晰表达依赖关系。

策略二:检查点(Checkpoint)

每隔 N 步或每个关键里程碑,将当前完整状态序列化存入外部存储。下一步骤如果发现上下文不足,可以从最近的检查点恢复并补充新的上下文。

检查点 1 (step 10): [序列化状态]
检查点 2 (step 20): [序列化状态]
检查点 3 (step 30): [序列化状态]

恢复时:从检查点 2 加载 + 添加 step 21-35 的新内容

策略三:主动上下文回收

不要等到上下文耗尽才压缩。当上下文使用超过 60-70% 时就开始主动压缩,给后续操作留出余量,避免在紧急情况下被动截断。


附录 A:上下文压缩策略选择表

场景推荐策略压缩率目标风险
短对话(<10 轮)不压缩0%
中等对话(10-30 轮)摘要记忆(每 10 轮)40-60%早期关键事实丢失
长对话(30+ 轮)滚动摘要 + 记忆槽50-70%累积误差
多轮推理任务检查点 + 分层记忆30-50%检查点恢复开销
精确事实检索检索式压缩 + 原文保留20-40%检索召回率
结构化任务状态记忆槽 + 状态序列化60-80%结构化 schema 设计成本
对话式 QA检索增强注入50-70%检索相关性
文档理解总结结构化提炼 + 层级摘要40-60%细节丢失

附录 B:摘要记忆风险清单

信息风险

  • 幻觉风险:摘要可能包含原文不存在的信息,尤其是模型”推理补全”的内容
  • 选择性偏差:摘要优先保留摘要模型的”重要性”判断,可能偏离当前任务真正需要的信息
  • 累积误差:多轮滚动摘要后,信息逐步失真
  • 指代丢失:摘要破坏指代链,“它""这个”等词失去 antecedent

工程风险

  • 摘要触发时机不当:过于频繁的摘要浪费计算资源,过于稀疏导致上下文爆炸
  • 摘要模板设计不足:模板未覆盖任务关键信息类型,导致重要信息未被提取
  • 恢复失败:压缩后的信息在需要时无法正确恢复或检索到
  • 压缩过度:为追求低 token 成本牺牲了任务必需的信息

任务风险

  • 任务失败但信息实际存在:压缩后信息未被正确注入,模型无法访问已有信息
  • 跨任务干扰:多任务共用摘要系统时,任务 A 的摘要污染任务 B 的上下文
  • 用户期望落差:用户认为已提供的详细信息被压缩后,模型”忘记了”
  • 合规/审计问题:为节省 token 而丢弃了本应保留的交互记录

缓解措施

  • 对关键事实(数字、人名、日期)使用原文保留而非摘要
  • 定期人工审查摘要质量,建立幻觉率监控指标
  • 压缩前评估信息价值,高价值内容优先保留或提高摘要精度
  • 建立压缩前后的 A/B 测试机制,持续监控任务指标
  • 对高风险场景(金融、医疗、法律)限制压缩率,或完全不使用摘要

总结

上下文压缩的本质是在信息完整性和上下文可行性之间做有意识的权衡。没有”最优”的压缩策略,只有适合当前任务类型、精度要求和成本约束的”足够好”的策略。

工程中最重要的原则是:

  1. 压缩必须是有目标的:明确哪些信息必须保留、哪些可以损失
  2. 摘要不等于原文:摘要会引入偏差和幻觉,关键场景必须保留原文或原文引用
  3. 压缩 + 检索是更稳定的组合:压缩降低信息量,检索确保相关性,两者互补
  4. 监控压缩质量:压缩后的任务表现下降是一个需要被及时发现的故障,而非可接受的代价

上下文压缩不是一次性工程决策,而是需要持续监控、调优和迭代的系统能力。