上下文 5 层压缩策略
上下文 5 层压缩策略
概述
长对话场景下,上下文 token 数会逐渐逼近模型的上下文窗口限制。系统采用三层架构、五个压缩策略的级联方案,在保证对话质量的前提下智能管理上下文长度。
策略总览

| 编号 | 层级 | 策略名称 | 触发条件 | 处理方式 |
|---|---|---|---|---|
| ① | Layer 1 | 单工具结果截断 | 单个工具结果超过上下文的 50% | 截断到预算,在换行边界断点 |
| ② | Layer 1 | 旧工具结果压实 | 总输入超过上下文的 75% | 白名单工具结果替换为占位符 |
| ③ | Layer 2 | 消息历史剪枝 | LLM 返回上下文溢出错误 | 保留关键消息,剪除中间历史 |
| ④ | Layer 3 | LLM 全量摘要 | Layer 2 不足以缓解 | 分块摘要 + 合并,9 节结构化格式 |
| ⑤ | Layer 3 | 部分摘要降级 | LLM 摘要失败 | 排除超大消息后重试,最终降级为纯文本通知 |
Layer 1:预防性工具结果截断
触发时机:每次 LLM 调用前自动执行(预防性,不等溢出发生)。
策略 ① — 单工具结果截断
当单个工具结果超过上下文窗口的 50% 时,截断到预算:
原始工具输出(超长)
│
├── 保留前 N 个字符(在换行边界断点)
└── 追加标记: [truncated: output exceeded context limit]
原始工具输出(超长)
│
├── 保留前 N 个字符(在换行边界断点)
└── 追加标记: [truncated: output exceeded context limit]
此代码块在浮窗中显示
关键常量:
SINGLE_TOOL_RESULT_CONTEXT_SHARE = 0.5(单工具上限占比)
策略 ② — 旧工具结果压实
当总输入超过上下文窗口的 75% 时,从最早的工具结果开始压实:
工具调用历史(时间序列)
│
├── 最新的工具结果 → 保留完整内容
├── 较新的工具结果 → 保留完整内容
├── 较旧的工具结果 → [compacted: tool output removed to free context]
└── 最旧的工具结果 → [compacted: tool output removed to free context]
工具调用历史(时间序列)
│
├── 最新的工具结果 → 保留完整内容
├── 较新的工具结果 → 保留完整内容
├── 较旧的工具结果 → [compacted: tool output removed to free context]
└── 最旧的工具结果 → [compacted: tool output removed to free context]
此代码块在浮窗中显示
白名单机制:只对以下高输出工具执行压实:
- Read File、Bash、Grep、Glob、Search Files、Web Fetch、Edit
Write/Create 类工具的输出永远保留,因为其输出是后续操作的依据。
关键常量:
CONTEXT_INPUT_HEADROOM_RATIO = 0.75(总输入上限占比)
Layer 2:溢出检测与消息历史剪枝
触发时机:LLM 返回上下文溢出错误时被动触发。
策略 ③ — 消息历史剪枝
剪除中间历史消息,保留关键消息:
消息历史
│
├── System Prompt ← 始终保留
├── 第一条用户消息 ← 始终保留
├── _pin: true 的消息 ← 始终保留
├── ........ 中间历史 ........ ← 剪除(替换为通知)
├── [context compacted: X earlier messages removed]
├── 最近 N 条消息 ← 保留(N = min(6, ⌊总数/3⌋))
└── 当前消息 ← 保留
消息历史
│
├── System Prompt ← 始终保留
├── 第一条用户消息 ← 始终保留
├── _pin: true 的消息 ← 始终保留
├── ........ 中间历史 ........ ← 剪除(替换为通知)
├── [context compacted: X earlier messages removed]
├── 最近 N 条消息 ← 保留(N = min(6, ⌊总数/3⌋))
└── 当前消息 ← 保留
此代码块在浮窗中显示
剪枝后自动修复孤立的工具对(tool_use 无对应 tool_result,或反之),确保消息格式合法。
Layer 3:LLM 智能摘要
触发时机:Layer 2 剪枝后仍不足以缓解上下文压力时触发。
策略 ④ — 全量摘要
使用独立的 LLM 调用对历史消息进行结构化摘要:
9 节摘要格式:
- 用户意图与目标
- 关键概念与术语
- 涉及的文件与路径
- 遇到的错误与解决方案
- 问题解决思路
- 用户关键消息
- 待完成任务
- 当前工作进展
- 下一步计划
分块策略:当消息超过 50,000 字符时,分为最多 4 块分别摘要,再合并为最终摘要。
策略 ⑤ — 部分摘要降级
当全量摘要失败时,执行三级降级:
| 降级级别 | 处理方式 |
|---|---|
| Level 1 | 排除超大消息(>50,000 字符),对剩余消息重试摘要 |
| Level 2 | 添加注释 [Note: X oversized message(s) were excluded] |
| Level 3 | 返回纯文本通知 [Summary unavailable — X messages could not be summarized] |
关键常量汇总
| 常量 | 值 | 说明 |
|---|---|---|
CONTEXT_INPUT_HEADROOM_RATIO |
0.75 | Layer 1 总输入上限占比 |
SINGLE_TOOL_RESULT_CONTEXT_SHARE |
0.5 | Layer 1 单工具上限占比 |
MAX_OVERFLOW_COMPACTION_ATTEMPTS |
5 | 最大压缩重试次数 |
COMPACT_MAX_OUTPUT_TOKENS |
20,000 | 摘要 LLM 调用的输出上限 |
COMPACT_BUFFER_TOKENS |
13,000 | 压实阈值的缓冲区 |
CHARS_PER_TOKEN |
4 | 普通文本每 token 字符数 |
TOOL_RESULT_CHARS_PER_TOKEN |
2 | 工具结果(更密集)每 token 字符数 |
EMA Token 校准
系统使用指数移动平均动态校准 chars-per-token 估算:
| 阶段 | 校准方式 |
|---|---|
| 初始 | 3.0 chars/token(保守,适配中文+代码) |
| 前 3 次 LLM 调用 | 均值收敛 |
| 后续 | EMA α=0.15 平滑追踪 |
| 异常过滤 | 0.5 < observed < 8 范围外忽略 |
压缩流程图
每次 LLM 调用前
│
├── Layer 1: enforceToolResultBudget()
│ ├── 单工具截断(>50% 上下文)
│ └── 旧工具压实(总输入 >75% 上下文)
│
├── shouldPreemptiveCompact() ?
│ └── 是 → compact()(Layer 2 剪枝)
│
└── LLM 调用
│
├── 成功 → 继续
└── 溢出错误 → getRetryStrategy()
│
├── compact()(Layer 2)
│ │
│ └── 仍不足 → compactWithSummary()(Layer 3)
│ ├── summarizeMessagesFull()(策略 ④)
│ ├── 失败 → summarizeMessagesPartial()(策略 ⑤ Level 1-2)
│ └── 全失败 → bare notice(策略 ⑤ Level 3)
│
└── 重试 LLM 调用(最多 5 次)
每次 LLM 调用前
│
├── Layer 1: enforceToolResultBudget()
│ ├── 单工具截断(>50% 上下文)
│ └── 旧工具压实(总输入 >75% 上下文)
│
├── shouldPreemptiveCompact() ?
│ └── 是 → compact()(Layer 2 剪枝)
│
└── LLM 调用
│
├── 成功 → 继续
└── 溢出错误 → getRetryStrategy()
│
├── compact()(Layer 2)
│ │
│ └── 仍不足 → compactWithSummary()(Layer 3)
│ ├── summarizeMessagesFull()(策略 ④)
│ ├── 失败 → summarizeMessagesPartial()(策略 ⑤ Level 1-2)
│ └── 全失败 → bare notice(策略 ⑤ Level 3)
│
└── 重试 LLM 调用(最多 5 次)
此代码块在浮窗中显示
对用户意味着什么
上下文压缩是你在长对话中可能感受到的"Agent 忘记了之前的内容"现象的原因。 它不是 bug,而是系统在有限的上下文窗口内智能管理信息的机制。
你可能观察到的现象:
- 长对话中,Agent 突然"不记得"你在开头提到的需求 → 这是 Layer 2/3 压缩了早期消息
- Agent 说"根据之前的讨论..."但细节可能不完全准确 → 压缩后只保留了摘要
- 工具调用的历史结果变成了
[compacted]→ 这是 Layer 1 压实了旧的工具输出
你可以这样应对:
- 关键信息说"请记住":触发记忆系统存储,不受上下文压缩影响
- 重述关键需求:在长对话中,定期重述你的核心需求
- 选择大上下文模型:GPT-4.1(1M)或 Claude(200K)比 DeepSeek(64K)能保持更多上下文
- 开新对话:如果对话已经非常长且混乱,开一个新对话可能比继续更高效
相关文档
- Agent 循环引擎 — 上下文管理在循环中的位置
- 模型配置 — 各模型的上下文窗口大小
- 支持的模型列表 — 模型能力矩阵
