@syansunyang/pi-context-prune
v1.5.3
Published
Pi coding-agent extension that summarizes finished tool-call output out of context and keeps the originals one query away. Fork of championswimmer/pi-context-prune 1.4.0, with fixes for pruned-result handling, errored turns, reload and abort.
Maintainers
Readme
English | 简体中文
pi-context-prune
上下文 token −63%,六轮 A/B 实测,被裁掉的原文随时一句话取回。
写这个是因为:长会话里模型花在反复重读自己工具输出上的钱,比花在思考上的还多。
来历。 本项目是 championswimmer/pi-context-prune(MIT)的自维护分支,基于上游 1.4.0。上游的架构、命令与工具设计均来自原作者,本分支在其上修复了若干在弱模型、错误重试与用户停止场景下会失效的行为,并按自己的版本号发布。
npm 包名
@syansunyang/pi-context-prune,从 1.5.0 起。未加作用域的pi-context-prune仍属上游。
Pi coding-agent 扩展:把已完成的工具调用批次交给摘要模型压缩,之后的请求里用摘要替代原始工具输出,原文留在会话索引里,模型随时可用 context_tree_query 取回。
解决什么问题
长会话里每一次工具调用都往上下文里堆一份输出。绝大多数输出在第一次读完之后就不再需要原文,但它们会一直占着窗口,直到触发原生压缩把整段历史重写掉。
本扩展的做法是:在模型明确用完这批结果之后,把它们换成一份简短摘要,原文不删、只是不再进入后续请求。需要细节时模型自己去取。
安装
pi install npm:@syansunyang/pi-context-prune只给当前项目装:
pi install -l npm:@syansunyang/pi-context-prune也可以从 GitHub 按标签安装(dist/ 已入库,安装时不执行构建):
pi install git:github.com/syansunyang-collab/[email protected]快速开始
装完在 Pi 里依次执行:
/pruner on
/pruner model <provider/model-id>:low
/pruner max-chars 8000第二条是关键。摘要默认用当前会话的模型,那样不省钱,应换成一个便宜的小模型。第三条决定摘要模型能看到每条工具结果的前多少字符,上游默认 2000,实测 8000 对质量更友好。
看状态与收益:
/pruner status
/pruner stats触发模式
/pruner prune-on <mode> 设置,默认 agent-message。
| 模式 | 触发时机 | 适用 |
|---|---|---|
| agent-message | 模型给出不带工具调用的回复后 | 默认。任务边界清晰,被裁的是已经用完的结果 |
| every-turn | 每个带工具结果的回合结束后 | 省得最多,但会频繁打断前缀缓存 |
| on-context-tag | 模型调用 context_checkpoint 时 | 由模型自己划分阶段 |
| agentic-auto | 模型调用 context_prune 时 | 完全交给模型决定 |
| manual | 只在 /pruner now 时 | 手动控制 |
裁剪会改变请求前缀,因此每次裁剪都会让服务端的前缀缓存失效一次。裁得越频繁,省下的窗口越多,缓存命中越少。agent-message 是这两者之间的默认折中。
配置
配置文件在 ~/.pi/agent/context-prune/settings.json,路径按用户主目录写死,不随 PI_CODING_AGENT_DIR 变化。也可用 /pruner settings 打开交互面板。
| 键 | 默认 | 说明 |
|---|---|---|
| enabled | false | 总开关,装完需要手动打开 |
| summarizerModel | default | 摘要模型,default 表示跟随会话模型 |
| summarizerThinking | default | 摘要模型的推理档位 |
| pruneOn | agent-message | 触发模式 |
| batchingMode | turn | 批次划分,turn 或 agent-message |
| summarizerMaxCharsPerResult | 2000 | 每条工具结果送进摘要模型的字符上限,0 表示不截断 |
| showPruneStatusLine | true | 底部状态行 |
| notifySkipped | true | 跳过时提示 |
工具与命令
context_tree_query:按工具调用 id 取回被裁剪的原文。模型在需要细节时自行调用,不需要人工干预。context_prune:仅agentic-auto模式下注册,让模型自己决定何时裁剪。/pruner tree:浏览已裁剪的调用树,Ctrl-O打开某条摘要。/pruner now:立即处理待裁剪队列,带进度显示。/pruner help:完整命令列表。
相对上游的改动
| 版本 | 改动 | 修复的故障 |
|---|---|---|
| 1.5.0 | 被裁剪的工具结果留一条简短的桩,不再整条删除 | 删除后工具调用不配对。pi-ai 会补一条 No result provided 的报错结果,绕过该转换层的 provider 则把不配对的调用原样发出。两种情况下模型都会认为工具坏了,能力弱的模型直接罢工 |
| 1.5.0 | 以 error / aborted 结束的回合不算最终回复 | provider 返回 503 的空回复触发裁剪,自动重试时当前任务刚读的结果已经被裁掉 |
| 1.5.0 | 索引、统计与 frontier 在 context 钩子里按需重建 | /reload 后若别的扩展在 session_start 里触发新回合,首个请求完全不裁剪 |
| 1.5.0 | 新增 summarizerMaxCharsPerResult 与 /pruner max-chars;摘要请求带 OpenCode 会话头 | 上游固定 2000 字符上限,长结果被截断后摘要质量下降 |
| 1.5.1 | 钩子里的摘要调用绑定本轮停止信号,并加 180 秒截止 | Pi 的停止要等会话空闲,而摘要在钩子里被 await,摘要期间点停止无效 |
| 1.5.1 | 构建与打包检查脚本可在 Windows 下运行 | rm -rf 与直接 spawn npm 使 npm publish 在 Windows 上失败 |
| 1.5.3 | context 钩子把会话里有、当前消息列表里缺的摘要补进请求,放在它覆盖的工具结果之后 | agent-message 与 every-turn 的摘要只写进会话文件,Pi 只在重载时读回;此前同一会话里模型只看到指向摘要的桩,看不到摘要本身 |
| 1.5.3 | turn_end 按整条分支的 assistant 消息编号 | Pi 的 event.turnIndex 每条提示词从 0 计数,frontier 按整条分支计数;从第二条提示词起,前几个工具轮被当成已处理:every-turn 不裁,agent-message 不入队 |
完整记录见 CHANGELOG.md。英文 README 末尾的 Follow-up ideas 一节是上游的路线图,不是本分支的计划。
PRUNING.md 与 .agents/ 下的开发笔记均出自上游,本分支原样保留。
实测数据
模型 openai-codex/gpt-5.6-luna,推理档 medium。每轮在同一个会话里连续解 17 道 SWE-bench Verified 的 Django 题,工作树是仓外的单提交副本、无历史、禁网,事后扫描会话确认没有越界读取。token 口径包含摘要模型的调用。
| 组 | 轮数 | token 中位数 | 解题均值 /17 | 压缩次数 | |---|---|---|---|---| | 不裁剪 | 6 | 26.0M | 12.7 | 6 | | 裁剪,上限 2000 | 6 | 9.6M(−63%) | 11.3 | 0 | | 裁剪,上限 8000 | 6 | 9.7M(−63%) | 11.7 | 0 |
token 降幅每一轮都在 53% 到 72% 之间,不裁剪的一组六轮里有五轮被压缩、共六次,裁剪组一次都没有。这里的压缩是 Pi 自带的压缩操作,由 pi-midrun-compact 扩展在上下文用到窗口的 90% 时触发。
质量上要说实话:medium 档下裁剪组平均每 17 题少解约 1 题,差距集中在三道题上,其余 14 题各组表现一致。逐会话核对后,丢分不是因为信息缺失,被裁掉的内容与这几题无关;裁剪组在首次编辑前的调查步数明显偏少,像是行为层面的影响。同样这批题把推理档提到 high 跑一轮,三组为 14 / 14 / 13,之前一直丢的三题各组全部解出,token 降幅不变。
实用结论:模型在任务上游刃有余时,裁剪基本是白赚的;模型本就吃紧时,预留一点质量损失,优先用更大的截断上限,并考虑提高推理档位。
方法、逐轮原始数据与采集脚本见 bench/。
已知限制
- 摘要模型的调用本身要花钱,
/pruner stats会累计。省下的窗口与这部分开销需要自己权衡。 - 摘要的延迟发生在触发边界上。1.5.1 起,钩子里发起的摘要绑定本轮停止信号并在 180 秒后放弃,因此不会挡住停止,放弃的批次留到下次触发。
- 每次裁剪都会让服务端前缀缓存失效一次。
- 配置路径按用户主目录写死,同一台机器上多个 agent 目录共用一份配置。
- 摘要质量取决于所选模型,太小的模型会丢掉关键标识符。
许可证
MIT。版权归上游作者与本分支各自的贡献者,见 LICENSE。
