Agent 上下文压缩:从策略设计到效果评估
为什么 Agent 需要压缩上下文?如何选择滑动窗口、摘要、检索与结构化状态?又该怎样用任务表现、信息忠实度和真实成本评价方案?
随着大语言模型从单轮问答走向复杂任务执行,Agent 需要维护的上下文也越来越庞大:系统规则、用户目标、多轮对话、工具结果、执行状态、检索资料,都会在一次长任务中不断累积。
更大的上下文窗口缓解了容量焦虑,却没有消除问题。长上下文仍然意味着更高的输入成本和延迟,也可能让过期信息、重复日志与关键约束竞争模型的注意力。上下文压缩因此不只是“把文本变短”,而是一个有预算约束的信息选择问题:在有限 Token 内,保留最能支持下一步正确决策的信息。
本文围绕三个问题展开:为什么 Agent 需要上下文压缩,常见策略各自解决什么问题,以及如何科学地评价一种压缩方案。
一、为什么 Agent 需要上下文压缩
一个典型的 Agent 上下文可以抽象为:
Agent Context
├── System Instructions 系统指令与安全约束
├── Task Definition 当前目标与验收条件
├── Conversation History 历史对话
├── Tool Results 工具调用结果
├── Working State 计划、进度与当前问题
└── Retrieved Knowledge 外部检索资料
任务每推进一步,这个集合都可能继续增长。最终会暴露出三个核心问题。
1. 上下文窗口始终有限
Coding Agent 可能反复读取代码、执行测试、分析日志并修改文件。即使单次工具调用只返回几千 Token,多次迭代后也会积累出庞大的轨迹。一旦逼近模型的窗口上限,系统只能删除、转移或压缩部分信息,否则任务无法继续。
窗口更大,只是推迟了这个时刻。只要任务能够持续运行,历史增长速度最终仍可能超过可用容量。
2. 容量不等于利用率
把信息放进上下文,不代表模型一定能正确使用它。Lost in the Middle 的实验表明,相关信息位于长输入的不同位置时,模型表现可能明显不同;至少对论文测试的模型与任务而言,位于输入中部的信息往往更难被利用。
在 Agent 场景中,这类问题会表现为:
- 忘记用户早期提出的约束;
- 重复已经完成的步骤;
- 忽略工具返回的关键结果;
- 根据已经过时的状态继续决策。
因此,上下文管理既要解决容量问题,也要提高有效信息的密度、位置与可访问性。
3. 累计成本会随历史增长
假设第 n 轮请求的上下文长度为:
Lₙ = L₀ + ∑ᵢ₌₁ⁿ⁻¹ ΔLᵢ
其中,L₀ 是初始上下文长度,ΔLᵢ 是第 i 轮新增的上下文。若每轮都携带完整历史,累计输入量为:
Tₙ = ∑ₙ₌₁ᴺ Lₙ
即使最终一轮尚未触及窗口上限,整个任务也可能已经为同一段历史重复付费多次。提示缓存可以降低部分成本,但实际收益取决于缓存命中、消息前缀是否稳定、服务商计费方式和部署架构,不能替代上下文治理。
二、五类常见压缩策略
不存在适用于所有任务的最优策略。不同方法对“什么值得保留”的回答并不相同。
1. 滑动窗口:相信最近的信息
滑动窗口只保留最近 N 轮或最近 B 个 Token,丢弃更早的内容。
压缩前:[M1][M2][M3][M4][M5][M6][M7][M8]
窗口 = 4
压缩后: [M5][M6][M7][M8]
它不需要额外模型,速度快、成本低,也很容易实现。但时间接近不等于任务相关。用户第一轮提出的“必须兼容 Python 3.12”,可能在几十轮后仍是硬约束。
因此,滑动窗口适合做兜底裁剪或保留近期工作区,不适合独自承担长期任务记忆。
2. 摘要压缩:相信语义提炼
摘要压缩让模型把较早的对话、工具结果和执行记录整理为更短的表示,再用摘要替换原文。高质量摘要通常会显式区分:
- 当前目标与验收条件;
- 用户硬约束;
- 已确认的事实与架构决策;
- 已完成、待完成和失败的步骤;
- 仍需保留的文件、错误与原始证据引用。
摘要比截断更能保留跨轮次关系,但它是有损变换。事实可能被遗漏,建议可能被写成决定,尚未验证的状态可能被写成完成。摘要再次被摘要时,误差还会累积。
工程上应避免把摘要当成新的绝对事实源。更稳妥的做法是保留摘要对应的原始区间或引用,使系统在需要时能够回溯。
3. 重要性筛选:相信价值评分
重要性筛选为上下文片段打分,在预算内优先保留高价值信息。一个启发式评分可以写成:
Sᵢ = αRᵢ + βIᵢ + γDᵢ + δFᵢ
其中:
Rᵢ:与当前任务的相关性;Iᵢ:信息本身的重要性;Dᵢ:后续步骤对它的依赖程度;Fᵢ:新鲜度或时效性;α、β、γ、δ:各维度权重。
这不是行业统一公式,而是一种可实现的思考框架。真实系统可以结合确定性规则、关键词、Embedding、依赖图和 LLM Judge。
它的优势是预算分配更精细,难点则在于评分错误具有隐蔽性:被删掉的信息不会主动提醒系统“我其实很重要”。对安全规则、用户硬约束等内容,更适合使用不可淘汰的固定优先级,而不是完全交给相关性模型。
4. 检索式压缩:相信按需召回
检索式方案不要求所有历史始终出现在模型输入中,而是把历史对话、工具结果和任务产物存入外部系统,需要时再召回。
原始历史 → 分块与索引 → 长期存储
↓
当前任务 → 生成查询 → 检索与重排 → 注入本轮上下文
它把“系统是否保存信息”和“本轮模型是否看到信息”分开,适合长周期任务与跨会话记忆。但它把风险从压缩器转移给了检索器:索引粒度、查询表达、权限过滤、Top-K 和重排质量都会影响最终召回。
向量相似度也不等于任务依赖。一次技术决策的理由可能分散在多轮对话中,单次相似度检索未必能恢复完整因果链。
5. 结构化状态:相信显式字段
对状态流转明确的任务,可以把历史转化为结构化状态:
{
"goal": "实现用户认证模块",
"constraints": ["使用 FastAPI", "使用 JWT"],
"completed": ["数据库模型", "登录接口"],
"pending": ["Token 刷新", "单元测试"],
"current_issue": "Token 过期处理尚未完成"
}
这种表示紧凑、可校验,也方便程序消费,尤其适合 Coding Agent、工作流与自动化运维。代价是必须提前设计 Schema、更新规则和冲突语义。若实际操作已经失败,而状态仍写着“完成”,结构化只会让错误看起来更确定。
策略比较
| 策略 | 压缩能力 | 主要优势 | 主要风险 | 典型场景 |
|---|---|---|---|---|
| 滑动窗口 | 中 | 简单、快速、确定 | 丢失早期关键约束 | 短对话、近期工作区 |
| LLM 摘要 | 高 | 保留跨轮语义 | 遗漏、失真、误差累积 | 多轮对话、任务交接 |
| 重要性筛选 | 中至高 | 预算分配灵活 | 评分错误难察觉 | 任务型 Agent |
| 检索式压缩 | 高 | 存储与即时上下文解耦 | 漏检、错检、依赖恢复困难 | 长期记忆、跨会话任务 |
| 结构化状态 | 高 | 紧凑、可校验、可编程 | Schema 与状态同步成本 | Coding、Workflow |
成熟系统通常会混合使用:固定保留系统规则与当前目标,用结构化状态维护任务进度,用滑动窗口保留近期交互,把旧轨迹压成摘要,同时让原始记录可以被检索和追溯。
三、压缩的终点是分层上下文管理
把上下文压缩理解为“缩短一段文本”仍然过于狭窄。更合理的架构是分层管理:
L0 System Instructions 不可丢失的系统规则与安全边界
L1 Current Task 当前目标、约束、计划与状态
L2 Working Memory 近期对话、关键工具结果与决策
L3 Long-term Memory 用户偏好、历史任务、知识与经验
L4 Raw History 完整对话、原始日志与任务产物
L0 和 L1 应优先保证完整性;L2 可以组合窗口、筛选与摘要;L3 通过结构化存储或检索动态召回;L4 用于恢复、审计和重新压缩,不必常驻模型输入。
这里最重要的区分是:压缩不应等同于永久删除。 系统可以保存完整证据,只在本轮推理时构造一个更小、更可信、更相关的工作集。
四、如何评价一种压缩方案
假设框架 A 把 20,000 Token 压到 5,000,框架 B 压到 8,000。A 是否更好?不能只看长度,因为把全部历史压成“用户要完成一个开发任务”也有极高压缩率,却几乎没有任务价值。
科学评估至少要同时覆盖压缩效率、信息质量、下游任务和系统开销。
1. 压缩率与 Token 减少率
定义压缩后长度占原始长度的比例:
CR = 压缩后 Token 数 ÷ 原始 Token 数
对应的 Token 减少率为:
TR = 1 − CR
若 20,000 Token 压到 5,000 Token,则 CR = 0.25,TR = 0.75。需要明确口径:有些资料会把原始长度除以压缩后长度,称为“4 倍压缩”,不能与这里的 CR 直接混用。
2. 关键信息召回率
先为原始上下文标注关键事实集合:
K = {k₁, k₂, …, kₙ}
再检查压缩结果保留了多少:
Rₖ = 保留下来的关键事实数 ÷ 关键事实总数
如果五条关键事实保留了四条,则 Rₖ = 0.8。检测时应接受语义等价表达,并同时检查事实之间的关系、条件和状态,而不是只做字符串匹配。
更重要的是给关键事实分级。一条安全限制或用户硬约束的丢失,可能无法被几十条普通事实的正确保留所抵消。
3. 忠实度与事实精度
压缩不仅会遗漏,也可能引入原文没有的信息,或者改变事实的确定性。例如:
原文:团队正在评估 Redis,尚未确定。
摘要:项目使用 Redis。
这里保留了关键词,却把候选方案改写成了最终决策。忠实度评估至少要检查:
- 是否出现原文不存在的事实;
- 是否改变条件、时间、否定或确定性;
- 是否混淆用户要求、Agent 建议和已经执行的结果;
- 是否错误合并了新旧冲突信息。
可以使用人工标注、规则和 LLM Judge 组合评估,但 Judge 本身也需要抽样复核与一致性测试。
4. 下游任务表现
这是最有业务意义的指标。压缩的目标不是生成一段漂亮摘要,而是让 Agent 在更少上下文中继续正确工作。
一组公平的对照实验应当固定任务、原始历史、底层模型、System Prompt、工具 Schema、采样参数和运行环境,只替换上下文方案:
同一任务与历史
│
┌───────────────┼───────────────┐
│ │ │
原始上下文 压缩方案 A 压缩方案 B
│ │ │
└───────────────┼───────────────┘
│
相同底层模型
│
比较任务结果与执行轨迹
Coding Agent 可以关注单元测试通过率、任务完成率、约束遵循率、修复成功率和额外工具调用次数;问答 Agent 可以关注答案准确率、历史事实恢复率、多轮指令遵循率和幻觉率。
5. 端到端成本与延迟
LLM 摘要、Embedding、检索、重排和存储都不是免费的。完整任务成本应写成:
总成本 = 压缩成本 + 推理成本 + 检索成本 + 存储成本
若各阶段串行,端到端延迟可以近似表示为:
总延迟 = 压缩延迟 + 检索延迟 + 推理延迟 + 其他延迟
实际存在并行或缓存时,应记录真实墙钟时间及 P50、P95 等分位数,而不是机械相加。一个方案即使减少 80% 输入 Token,如果额外压缩调用抵消了节省,也不具备工程优势。
五、如何设计一组可靠的对照实验
1. 使用接近真实的长任务
测试集不应只是随机拼接长文本,至少应覆盖:
- 早期事实记忆:从很早的对话中恢复关键事实;
- 长期约束遵循:任务运行很久后仍遵守初始限制;
- 多步骤执行:后续操作依赖前面多个工具结果;
- 任务切换与恢复:从任务 A 切到 B,再回到 A;
- 信息更新与冲突:旧决定被新决定明确替换;
- 失败与回滚:区分“尝试过”“失败了”和“已经完成”。
LongBench 可以提供长文本理解任务,但完整 Agent 框架还需要补充工具调用、状态恢复和多轮执行等测试。
2. 在多个预算点比较
只测一个压缩比例无法展示方案的退化曲线。可以设置 75%、50%、25% 和 10% 等保留预算,观察事实召回与任务成功率如何变化。
比较时应同时回答两个问题:
- 同预算比效果:保留相同 Token 时,谁的任务表现更好?
- 同效果比成本:达到相同成功率时,谁需要的 Token、延迟和费用更少?
第二个问题往往更接近生产决策。
3. 多次运行并报告分布
模型输出具有随机性。应对每个条件重复运行,报告均值、方差或置信区间,而不是用一次成功样例下结论。还应记录失败类型:遗漏约束、召回错误、摘要幻觉、状态过期和工具使用错误,可能需要完全不同的修复手段。
4. 使用硬门槛,而不只看综合分
可以构造归一化综合分数:
Score = w₁E + w₂Q + w₃P + w₄C,其中 w₁ + w₂ + w₃ + w₄ = 1
其中 E 是压缩效率,Q 是信息质量,P 是下游任务表现,C 是工程效率。但单一分数容易让极高压缩率掩盖严重信息损失。
更稳妥的方式是先设置硬门槛,例如关键约束召回率和任务成功率必须达标;再在合格方案中比较成本、延迟与压缩率。高风险任务还应对关键约束采用“任何一次丢失都不合格”的规则。
下面是一组仅用于说明分析方法的假设数据:
| 指标 | 不压缩 | LLM 摘要 | 筛选 + 检索 |
|---|---|---|---|
| 上下文 Token | 20,000 | 5,000 | 5,000 |
| 关键事实召回率 | 100% | 84% | 94% |
| 任务成功率 | 90% | 76% | 87% |
| 平均总成本 | $0.20 | $0.09 | $0.11 |
| 平均端到端延迟 | 8.0s | 6.5s | 7.0s |
这组演示结果中,摘要方案最便宜,但任务损失最大;混合方案成本略高,却更接近基线。哪一个更好,最终取决于准确性要求、预算和错误代价,而不是某个孤立指标。
六、研究与工程实践
LLMLingua 系列 表明,Prompt Compression 不必局限于让大模型写摘要:LLMLingua 使用由粗到细的 Token 级压缩,LongLLMLingua进一步考虑长上下文中的问题相关性,LLMLingua-2 则将压缩建模为 Token 分类任务。
这类方法主要处理给定 Prompt 的压缩,而 Agent 上下文管理还要面对持续更新、工具结果、跨任务恢复和状态冲突。两者目标相近,但系统边界不同。
Microsoft Agent Framework 的 Compaction 文档 也展示了工程侧的不同策略:截断、摘要工具调用组,或在不破坏原始存储历史的情况下只压缩本次请求上下文。这个区分很重要——模型看到的工作上下文可以被压缩,原始会话仍可以完整保留。
七、结语:把压缩看成信息选择策略
上下文压缩真正要优化的不是摘要长度,而是 Agent 在预算约束下的决策质量。给定候选信息集合:
X = {x₁, x₂, …, xₙ}
每个片段 xᵢ 具有 Token 成本 cᵢ。系统要在预算 B 内选择信息子集 S,最大化它对当前任务 q 的效用:
在 S ⊆ X 的范围内,最大化 U(S, q)
满足:
同时满足:S 中所有信息片段的 Token 成本之和 ≤ B
现实中的效用并不容易直接计算,还存在信息依赖、冲突、新鲜度、权限和不可压缩约束。但这个视角能够提醒我们:更短不一定更好,保留更多也不一定更好。
一套成熟的上下文系统,应当做到信息分层、动态压缩、按需检索、状态维护、原始证据可追溯,并持续用真实任务验证。最终评价标准很朴素:在相同预算下,Agent 是否更可靠;在相同可靠性要求下,系统是否更省成本、更低延迟。
这才是上下文压缩从技巧走向工程的分界线。