上下文窗口是生产级的第一成本
大语言模型有上下文窗口上限。会话一长,旧内容会占满窗口、成本飙升。Compaction(压缩)就是 pi 用来「总结旧内容、保留近期工作」的机制。对跑长任务的 md-tools 来说,这一课直接关系到你能跑多久、烧多少钱。
md-tools 处理长文档、跑长会话时,上下文窗口会被 markdown 内容迅速撑满。**这一节学会 compaction 的设置和触发逻辑,你就能为 md-tools 配置合理的 reserveTokens / keepRecentTokens,让长任务自动压缩、不会爆上下文。** 这是生产级「持续跑」的能力保证。两种总结机制
pi 有两种总结机制,注意别搞混:
| 机制 | 触发 | 目的 |
|---|---|---|
| Compaction | 上下文超阈值,或 /compact |
总结旧消息、腾出上下文 |
| 分支总结 | /tree 导航 |
切换分支时保留上下文 |
两者都用同一套结构化总结格式,并累积跟踪文件操作。
Compaction 什么时候触发
自动压缩的触发条件是:
contextTokens > contextWindow - reserveTokens
默认 reserveTokens 是 16384 tokens(可在 settings 里改)——给 LLM 的响应留位置。你也可以手动触发:
/compact [instructions]
可选的 instructions 能让总结更有针对性。
它是怎么工作的
流程可以概括为「找切点 → 摘消息 → 生成总结 → 追加条目 → 重建上下文」:
- 找切点:从最新消息往回走,累加 token 估算,直到
keepRecentTokens(默认 20k)被满足 - 摘消息:收集上一个保留边界(或会话开始)到切点之间的消息
- 生成总结:用结构化格式调 LLM 总结,有前一个总结就作为迭代上下文传入
- 追加条目:保存
CompactionEntry(含 summary 和 firstKeptEntryId) - 重建上下文:下一次请求用「总结 + 从 firstKeptEntryId 往后的消息」重建
被压缩的内容不会发给 LLM,LLM 只看到总结 + 保留的近期消息。
切点规则
合法的切点是:用户消息、assistant 消息、BashExecution 消息、自定义消息。
绝对不能切在工具结果上——工具结果必须跟它的工具调用待在一起。如果单个回合太大超过 keepRecentTokens,会形成「切分回合」(split turn),pi 会生成两份总结再合并。
设置:三个旋钮
在 ~/.pi/agent/settings.json 或 /.pi/settings.json 配置:
{
"compaction": {
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000
}
}
| 设置 | 默认 | 作用 |
|---|---|---|
enabled |
true |
是否启用自动压缩 |
reserveTokens |
16384 | 给 LLM 响应预留的 token |
keepRecentTokens |
20000 | 保留(不总结)的近期 token |
enabled: false 会关掉自动压缩,但你仍能手动 /compact。
结构化总结格式
压缩和分支总结用同一套格式,让总结可读、可续接:
## Goal
[用户想完成什么]
## Constraints & Preferences
- [用户提到的要求]
## Progress
### Done
- [x] [已完成任务]
### In Progress
- [ ] [进行中的工作]
## Key Decisions
- **[决策]**: [理由]
## Next Steps
1. [接下来该做什么]
## Critical Context
- [要继续需要的关键数据]
文件清单会被单独跟踪,跨多次压缩累积保留 read / modified 文件的完整历史。
落地练习:调一次 compaction 并观察触发
让 compaction 在你的会话里实际跑起来:
- 在 settings 里把
reserveTokens或keepRecentTokens调小(比如keepRecentTokens: 8000) - 起一个会话,发足够长的上下文,或直接
/compact "重点保留 md-tools 的脚本改动" - 观察会话重建后:旧内容被总结成一块,近期消息仍在
怎么判断做对了?——能看到 compaction 发生(或手动
/compact成功返回总结);重建后 LLM 仍能回答「之前做了什么」,说明总结没丢关键信息。
卡住了怎么办? 不触发?阈值还没到,把 keepRecentTokens 调小更容易触发。想确认有没有压缩?RPC / JSON 模式里能看 compaction_start / compaction_end 事件。
常见坑:关掉 auto-compaction,然后长会话直接爆
有人为了「省钱」或「怕总结丢内容」,把 enabled 设成 false 关掉自动压缩——然后长会话一路涨到超上下文,请求直接失败。
关掉自动压缩 ≠ 没有压缩。正确姿势是:enabled 保持 true,通过调 reserveTokens / keepRecentTokens 来控制触发点;真要关,也要知道手动 /compact 还能救。别为了省小钱,让生产任务在关键时刻爆掉。
小结
- compaction 总结旧内容、保留近期工作,缓解上下文成本
- 触发条件:
contextTokens > contextWindow - reserveTokens - 默认
reserveTokens: 16384、keepRecentTokens: 20000 - 切点规则:不切在工具结果上
enabled: false只关自动,手动/compact仍可用
下一节,模块 05 的收口:贯穿项目 md-tools 打包含发布。