Mini Context Compaction¶
从 services/compact 12 个文件(~5000 行)提炼到 ~150 行 的滑动窗口 + 摘要压缩。 3 策略 + 5 场景:drop-middle / keep-first-last / summarize-middle + 阈值对比。
文件¶
mini-context-compaction/
├── src/
│ ├── compaction.ts Compactor + 3 策略 + mock summarizer(~120 行)
│ └── cli.ts 5 场景
└── README.md
跑¶
真实代码对照¶
| Demo | 真实文件 | 简化 |
|---|---|---|
estimateTokens |
真实用 tiktoken | char/4 简化 |
dropMiddle |
compact/window.ts:200 |
简化 |
keepFirstLast |
同上 | 简化 |
summarizeMiddle |
compact/summarize.ts:100 (~800 行) |
mock LLM |
| 触发器 | compact/compact.ts:30 (~300 行) |
单阈值 |
核心 4 件套¶
1️⃣ Token 估算 char/4¶
function estimateTokens(messages) {
return Math.ceil(messages.reduce((sum, m) => sum + m.content.length, 0) / 4);
}
2️⃣ 3 策略按需选¶
| 策略 | 优点 | 缺点 |
|---|---|---|
drop-middle |
零开销、简单 | 丢上下文信息 |
keep-first-last |
系统 prompt + 最近消息保留 | 完全丢中间 |
summarize-middle |
保留语义 | 调 LLM 慢 + 贵 |
真实 CC 默认用 summarize-middle(保留语义对长对话关键)。
3️⃣ Mock Summarizer = 1 行¶
真实 CC 调 LLM(opus / sonnet)做摘要。本 demo 用占位符展示接口形态。4️⃣ 阈值触发 = O(1) 检查¶
每次 setState 后调一次(或每 N 次)。O(1) 计算 + O(N) 压缩。5 场景输出¶
📌 Test 1: small conversation (no trigger)
triggered? false
📌 Test 2: large conversation + drop-middle
reduction: 615 → 100 (16%)
📌 Test 3: large conversation + keep-first-last
reduction: 545 → 82 (15%)
📌 Test 4: large conversation + summarize-middle
summary: "[Summary of 34 messages, 463 tokens compressed]"
📌 Test 5: threshold comparison
maxTokens=2000: triggered=false
maxTokens=200: triggered=true (14%)
进阶练习¶
- 接真实 LLM summarizer:用 fetch 调 Claude API
- 加 sliding window 优化:不要 hard cut,而是按 token 滑
- 加 importance scoring:基于关键词/工具调用标记"重要消息"不丢
- 加 hierarchical compaction:多轮压缩,每轮总结上一轮
- 加 compaction history:记录每次压缩前的快照(可回滚)
- 接真实 tokenizer:用 @anthropic-ai/tokenizer 精确算 token
相关阅读¶
- topics/context-compaction.md —— 跨阶段专题
- topics/deep-dive-compact.md —— compact 12 文件分析
- docs/PERFORMANCE.md —— 性能相关
- Anthropic 上下文管理文档
- tiktoken 库