Codex Core

自动压缩功能源码解析

源码仓库

Auto Compaction

上下文快满时,Codex 如何把长会话压成可继续工作的短历史

自动压缩不是字节压缩,而是一次特殊的会话改写:根据 token 阈值触发,调用本地 Responses 或远端 responses/compact,生成替代历史,安装到 live session,再重新估算 token。

自动压缩 = 触发条件 + 摘要生成 + 历史替换 + token 重算

自动压缩从阈值检查到替换历史的概览图
默认触发 context window 的 90%

配置阈值存在时,也不能超过 90% 上限。

触发阶段 Pre-turn + Mid-turn

采样前检查一次,工具循环中需要继续时再检查。

执行路径 本地摘要或远端 compact

由 provider 是否支持 remote compaction 决定。

最终效果 替换历史并重算 token

持久化 Compacted marker,方便恢复和回滚。

Execution Flow

调用链拆解

Threshold Calculator

阈值计算器

History Rewrite

压缩前后历史结构

压缩真正改变的是模型下次会看到的 transcript。旧历史不会逐条保留给模型, 而是被改写成更短的替代历史;原始 rollout 仍保留压缩边界,供恢复和回滚重建使用。

压缩前

  1. prompt 层 base instructions / developer instructions
  2. session 历史中的 initial context 与当前环境信息
  3. 多轮 user / assistant 对话
  4. tool calls、function outputs、shell 结果
  5. 可能还有 ghost snapshots

压缩后

  1. 本地路径:最近真实用户消息,最多约 20k tokens
  2. 本地路径:带 SUMMARY_PREFIX 的摘要
  3. 远端路径:服务端返回的 replacement transcript
  4. mid-turn 时在模型期望的边界插回 initial context
  5. 保留 ghost snapshots 以支持 undo / rollback
  6. CompactedItem 作为 rollout 持久化边界

Two Implementations

本地路径 vs 远端路径

本地 Responses 压缩

把 compact prompt 注入当前历史,用普通 streaming 模型请求生成摘要。它是 provider 不支持 remote compaction 时使用的通用实现, 但如果 compact 请求本身超过上下文,需要删除最旧历史项后重试。

入口
run_inline_auto_compact_task()
产物
最近用户消息 + SUMMARY_PREFIX 摘要
风险控制
超窗时从历史头部裁剪,保留近期上下文。

远端 responses/compact

将格式化后的 prompt、tools、instructions、reasoning 发给专门 compact endpoint。 服务端返回压缩后的 ResponseItem 列表,客户端再过滤和安装。

入口
run_inline_remote_auto_compact_task()
产物
服务端生成的 replacement transcript
风险控制
过滤旧 developer 消息和非真实用户消息,避免重复指令。

Deep Notes

容易漏掉的实现细节

为什么 mid-turn 要特殊处理

mid-turn 压缩发生在工具循环中,模型后面还要继续工作。此时使用 BeforeLastUserMessage,把当前 turn 的 initial context 插到最后一条真实用户消息前面, 让压缩摘要仍保持模型训练期望的位置,同时不丢掉当前环境基线。

失败和降级行为

本地压缩如果遇到 ContextWindowExceeded,会从历史开头裁掉最旧 item 后重试。 远端压缩只会在估算超窗且末尾是 Codex 生成项时裁掉尾部历史;遇到非 Codex 生成项会停止裁剪。 如果远端 compact 失败,会发送 error event,当前压缩路径不会假装成功,也不会自动退回本地路径。

配置入口

model_auto_compact_token_limit 控制触发阈值; compact_promptexperimental_compact_prompt_file 可以覆盖本地压缩使用的总结 prompt。配置阈值仍会被 context window 的 90% 上限 clamp。

90% 和 effective_context_window_percent

自动压缩阈值来自 resolved context window 的 90%。而 effective_context_window_percent 是 TurnContext 计算模型可用窗口时的保守比例, 用于 prompt 与上下文预算处理。二者相关,但不是同一个开关。

远端 compact 不是简单摘要

responses/compact 返回的是 Vec<ResponseItem> replacement transcript。客户端还会过滤旧 developer 消息、非真实 user 消息、推理和工具噪声, 再把它安装为新的 live history。

CompactedItem 的意义

CompactedItem 不是普通对话消息,而是 rollout 里的语义边界。它保存摘要和 replacement_history,让 resume、rollback、trace reconstruction 能理解历史在哪里被改写。

Misconceptions

常见误解

不是压缩文件大小

它压缩的是模型可见的会话历史,把长 transcript 改写成短 replacement history。

不是超过阈值就立刻打断最终回答

mid-turn 只有在还需要 follow-up 或有 pending input 时才触发。

不是只保留最后一条消息

本地路径会保留一段最近用户消息和摘要;远端路径返回结构化替代 transcript。

手动 /compact 和自动 compact 共享核心机制

差异主要体现在 trigger、reason、phase,以及是否作为独立 turn 启动。

Glossary

术语表

replacement_history
压缩后安装进 session 的新历史,是模型后续请求真正会看到的 transcript。
initial context
当前工作目录、环境、开发者指令等上下文基线;mid-turn 压缩会把它插回关键位置。
SUMMARY_PREFIX
本地压缩摘要的前缀,用来识别这条 user-message-like item 是压缩摘要。
remote compaction
由 provider 支持的远端 responses/compact 路径,返回结构化 ResponseItem 列表。
CompactedItem
持久化到 rollout 的压缩边界,帮助恢复、回滚和 trace 重建理解历史改写。

Source Map

关键源码索引