04 — 上下文压缩:Token 阈值与前缀缓存优化
上下文压缩:Token 阈值与前缀缓存优化
学习目标
理解 CodeWhale 的上下文压缩策略:纯 Token 触发机制、前缀缓存经济学驱动的自动地板设计,以及手动与自动压缩的协同。
前置知识
- 上下文压缩与 Token 优化 — 上下文压缩的通用策略与截断方法
下文假设你已理解上述概念,直接聚焦 CodeWhale 的具体实现。
项目实践
压缩配置结构
CompactionConfig { enabled: bool, // 是否启用(默认 true) token_threshold: usize, // Token 阈值(触发压缩) model: String, // 压缩使用的模型 cache_summary: bool, // 是否缓存摘要 auto_floor_tokens: usize, // 自动压缩地板(最低 Token 数)}纯 Token 触发(v0.8.11 改进)
在 v0.8.11 之前,压缩由两个条件触发:Token 数 或 消息数。v0.8.11 移除了消息计数触发器,原因是:
“消息计数触发器的唯一目的是在长会话小消息场景触发压缩,而这恰恰是重写 V4 前缀缓存最不划算的场景。”
改进后的触发逻辑:
- 检查总 Token 数是否 ≥
auto_floor_tokens(默认 500K) - 若通过地板检查,检查是否 ≥
token_threshold - 两者都通过才触发压缩
前缀缓存经济学:500K 自动地板
这是 CodeWhale 最独特的压缩设计。
为什么是 500K?
压缩会重写稳定的前缀——这会破坏 KV 前缀缓存。在低 Token 数时:
- 前缀缓存命中率高,大部分 tokens 以缓存命中价格计费
- 压缩导致缓存 miss,全量重新填充以 miss 价格计费
- 压缩回收的少量 Token 预算不足以抵消 miss 的成本
高于 500K 时情况反转:
- 缓存已受压,命中率下降
- 前缀已漂移(动态内容累积导致缓存边界后移)
- 回收预算变得重要
手动 vs 自动压缩
| 维度 | 自动压缩 | 手动 /compact |
|---|---|---|
| 触发条件 | Token 数 ≥ threshold 且 ≥ floor | 用户显式请求 |
| 绕过地板 | 否 | 是 |
| 使用模型 | 配置中的 compaction.model | 当前活跃模型 |
| 适用场景 | 长会话自动维护 | 用户主动管理上下文 |
每模型阈值
不同模型的上下文窗口不同,压缩阈值也不同:
| 模型 | 上下文窗口 | 自动压缩阈值(80%) |
|---|---|---|
| deepseek-v4-pro | 1M | 800K |
| deepseek-v4-flash | 1M | 800K |
| 未知模型 | 回退 128K | 102.4K(80%) |
60% 时 TUI 会建议 /compact,但自动替换压缩在 80% 时才触发——这是一个”建议早、行动晚”的策略。
问题与规避
陷阱:自动压缩在不该触发时触发
当会话包含大量工具输出(低信息密度)时,Token 数可能很快达到阈值,但实际有用的上下文并不多。
规避:CodeWhale 的 500K 地板防止了低 Token 数场景下的误触发。此外,压缩策略可以选择保留关键消息(系统提示、最近交互)而丢弃中间工具输出。
陷阱:压缩导致前缀缓存全量失效
压缩重写前缀——如果 Constitution 等稳定内容被包含在压缩后的摘要中,下次 turn 需要全量冷读。
规避:CodeWhale 的压缩策略区分”稳定前缀”(Constitution,不应被压缩)和”可变内容”(对话历史,可以压缩)。压缩只替换可变部分。
陷阱:未知模型的阈值过高
如果连接到一个 32K 窗口的模型,默认的 800K 阈值永远不会触发。
规避:CodeWhale 使用 context_window_for_model() 函数动态获取模型窗口大小,未知模型回退到 128K 的 80%(102.4K)。对于更小的模型,配置需要手动调整。
设计取舍
为什么从消息计数改为纯 Token
消息计数是 128K 时代的启发式——当时窗口小,消息数量是合理的代理。1M 窗口时代:
- 小消息长会话(如 1000 条短消息)可能只有 50K tokens
- 压缩这些会话会破坏健康的前缀缓存,回收的预算微乎其微
- Token 数是更准确的缓存压力信号
自动压缩默认关闭(v0.8.11)
虽然 CompactionConfig 的默认 enabled: true,但引擎级的 auto_compact 设置在 v0.8.11 被翻转为 OFF。原因是:
- 自动替换压缩重写前缀,用户可能不希望自动发生
- 手动
/compact给用户更精细的控制 - 60% 的建议仍然有效,用户可以自主决定时机
参考来源
crates/tui/src/compaction.rs— 压缩配置与触发逻辑- v0.8.11 CHANGELOG 条目 #665 — 自动压缩默认关闭