土拨鼠日志:压缩上下文时,能丢内容,不能丢路径
这两天我们一直在干同一件事:把上下文压小。因为长任务跑起来,真正烧钱的不是模型有多聪明,而是它一遍遍把同一堆东西重新读一遍。压小本身不难,难的是压完之后还能把活干对——今天这篇就把我们踩过的坑摊开讲。
一、压缩最贵的错,不是丢内容,是丢“去哪找”
先说个很反直觉的结论:压缩时丢掉大段内容是可以接受的,丢掉“复取句柄”才是灾难。
什么叫复取句柄?就是这些东西:
- 文件路径 + 行号(
logs/20261021.log:191563) - 命令原文(不是你改写后的总结)
- 网页 URL、日志的时间戳区间
- 具体的数字与限定词(“只改第 169 行”“必须在 30 分钟窗口内”)
原因很朴素:内容丢了,模型可以按路径重新取一次;句柄丢了,模型只能重跑整件事——你把左边省下来的钱,从右边又花出去了,还多了一份不确定性。
我们现在给自己定的规矩是:任何为了省 token 而做的折叠,必须在同一处写明“已折叠,可用 X 复取”。工具输出被截断时,那一行必须写清“已截断 + 怎么取全文”,只保头尾不标注,等于制造了一个幻觉源。
二、失败痕迹别急着洗掉,它是资产
很多人(包括以前的我们)会觉得,报错堆栈、走错的弯路属于“脏数据”,重试前先清一遍上下文,看起来更干净。
但实际观察是反的:把错误观察原样留在上下文里,模型下一次会自己避开那条路;洗干净了,它会用同样优雅的姿势再撞一次墙。
所以我们现在的做法是三条:
- 记录里不清洗:报错原样留在日志和上下文里,只在给人看的汇报里做摘要。
- 重试前先写一句:“上次错在哪、这次改了什么”。不带这句的重试=同一个错花钱买第二次。
- 把“重犯率”当指标:同一类错第二次出现,就不是记一条备忘的事了,要升级成脚本或检查清单。这条比“这次修好了”硬得多。
三、长任务要靠“复述”把自己钉住
一个复杂任务跑到四五十次工具调用,很容易在中段忘掉最初的目标,或者忘掉你早上定的那个“必须满足”的约束。
低成本的解法不需要改架构:每 3 到 5 步,在上下文末尾追加一行状态回顾——目标是什么、已完成什么、当前在哪一步、下一步做什么,外加那句最容易在中段被吞掉的约束词(“不要动 X”“必须验证 Y”)。
关键在于写在末尾,不回头改开头。缓存只认从头开始匹配的前缀,你回头去改开头的计划块,等于让后面全部重算一遍——省下的那点字数,抵不上重算的账单。
四、这套东西在土拨鼠里长什么样
说点能直接感觉到的:
- 长任务会有一张进度卡,写着当前在第几步、卡在哪,你不用一直问“好了没”;
- 会话里能直接看到缓存命中与节省的账,命中率掉了会先怀疑提示开头被动过,而不是先怀疑账单算错;
- 工具输出过长时会截断并标注,随时可以按路径取回全文,不会出现“它好像看过但说不清”的情况。
如果你也在拿它跑长流程,建议先看 功能页 里关于长任务与工作区的部分;想先算一笔账,定价页 有按量与实际消耗的对照;直接上手就 下载 装一个,拿一件真事跑一遍,比看十篇介绍有用。
五、一个 30 秒自查
下次你的 AI 助手“忘了刚才做过什么”,按顺序问自己三句:
- 压缩过吗?压缩的那一版里,路径、命令、数字还在不在?
- 报错是不是被“清理”掉了?
- 开头的计划块是不是被反复改过,导致缓存整段重算?
三个问题里中任意一个,基本就能解释大部分“它今天怎么变笨了”。压缩不是删减比赛,是把能复取的东西留下。
土拨鼠 Marmot