将上下文压缩移出关键路径:面向长时智能体的两阶段预触发与恢复提示
内容提要
长时智能体上下文管理采用两阶段预压缩:用量达90%时后台摘要前缀,达100%时仅合并摘要与尾部增量,减少主循环阻塞。压缩保留原始记录与本地JSONL恢复指针,并冻结系统提示以维持缓存命中。优先裁剪旧工具输出,避免不必要的LLM摘要。实测每轮输入token降低40%,上下文稳定在约28万。
延伸解读
两阶段预压缩如何避免主循环卡顿
传统单次压缩在达到阈值时暂停主循环,将全部历史发送给LLM总结,导致数秒至数十秒的等待。本文方案将重活拆成两阶段:用量达90%时后台异步摘要最旧95%的消息生成NOTE1并缓存指纹,主循环继续运行;达100%时仅合并NOTE1与尾部增量,大幅减少压缩时发送的token,主线程等待降至毫秒级。
压缩不等于删除:恢复指针保留原始细节
摘要会丢失精确行号、文件路径等细节,导致模型重新查询或幻觉。本文强调所有原始消息、参数和完整输出持续写入本地JSONL文件且永不删除,压缩摘要块中嵌入恢复提示标签,包含会话JSONL绝对路径。后续需要精确信息时,模型可直接用读取工具检查该文件,兼顾上下文精简与细节可追溯。
先裁剪旧工具输出,再考虑LLM摘要
上下文膨胀常源于工具输出过大,如git diff或构建日志。本文建议在完整压缩前先执行trim_old_tool_results,将旧轮次的冗长输出截断为短预览。若释放足够token,则设置context_changed并立即重试,省去昂贵的LLM摘要调用。这能减少不必要的摘要开销,并更快恢复上下文空间。
实测效果与缓存命中权衡
在47小时连续会话、1000次请求的测试中,每轮平均输入token从496,806降至299,625,降幅40%,上下文稳定在约28万而非膨胀至175万。提示缓存命中率从99.11%变为96.91%,包含冷重启影响,但压缩后仅约2万token的短暂未命中,后续轮次维持99%至100%命中。说明将摘要作为独立对话轮次注入、冻结系统提示,能有效保护缓存。
Q&A
长时智能体的上下文压缩为什么要采用两阶段预触发,而不是一次性压缩?
一次性压缩需要暂停主循环,把整个历史发给LLM做全局摘要,往往耗时数秒到数十秒,导致输入框卡在加载状态;同时会丢失精确的错误行号、文件路径等细节,还会因修改System Prompt前缀而破坏Prompt Caching,推高TTFT和API成本。两阶段预触发把重活放到后台,主循环不阻塞,压缩时只发送NOTE1加尾部增量,主线程等待降到毫秒级。
两阶段预压缩的两个阶段分别是什么,触发条件是什么?
第一阶段是前缀预触发(Pass 1):当上下文用量达到阈值90%时,主循环继续运行,后台任务切出最旧的95%消息(严格保护tool_use和tool_result边界),生成结构化摘要NOTE1并缓存前缀的哈希指纹。第二阶段是增量压缩(Pass 2):当后续轮次把总token推过100%阈值时,校验指纹,若匹配且后台任务已完成,就只把NOTE1加上Pass 1之后产生的少量尾部消息发给模型;若指纹漂移或Pass 1失败,则回退到标准单次压缩。
压缩后原始的执行细节(如错误行号、命令输出)还能找回吗?
能。压缩不等于删除:所有原始消息、参数和完整输出都持续写入本地会话JSONL文件,永不删除。压缩摘要块中会自动包含一个<recovery_hint>标签,给出该会话JSONL的绝对路径,提示后续步骤如果需要精确行号、错误堆栈或命令输出,可以直接用读取工具查看该文件。
为什么压缩摘要不放进System Prompt,而是作为独立对话轮次注入?
因为把摘要塞进System Prompt会改变提示前缀,导致服务端的Prompt Caching完全失效,从而推高TTFT和API成本。将摘要作为独立的对话轮次注入,System Prompt保持冻结不变,可以维持较高的服务端Prompt Caching命中率。
在调用LLM做摘要之前,有没有更省成本的做法?
有。在运行完整压缩之前,先执行trim_old_tool_results,把较早轮次中冗长的工具输出截断成简短预览。如果裁剪释放了足够的token,就设置context_changed = true并立即重试,从而省下一次昂贵的摘要调用。很多情况下上下文膨胀只是因为某个工具输出了巨大的git diff或构建日志,裁剪旧工具输出就能回收数万token,根本不需要LLM摘要。
这套两阶段压缩方案的实际效果如何,有数据支撑吗?
有。在连续47小时、1000次请求、4.9亿输入token的测试中:平均每轮输入token从496,806降到299,625,下降40%;上下文形态从1.75M的完整重放(膨胀)变为约250K基线/280K稳态,保持有界;Prompt缓存命中率从99.11%变为96.91%(含冷重启),但压缩重启后除约20K的短暂缓存未命中外,后续轮次持续保持99%到100%的命中率。