Codex Compact 机制全解析:上下文压缩的两条路径与架构权衡
从我使用 API 中转站每次 compact 后都弹 warning 而登录态完全没有的困惑出发,基于 Codex 源码一路追下去:覆盖三条触发路径、provider 路由决策、local compact 的完整流式请求与历史重建流程、remote /responses/compact 的专用协议与客户端后过滤、两条路…
Codex Compact 机制全解析:上下文压缩的两条路径与架构权衡 Code Version: 基于 openai/codex commit 19702e1。 讨论范围: 只覆盖 Codex 的 compact 逻辑——manual /compact、auto compact、local compact、remote compact、compact 后的上下文恢复与会话持久化。 | 章节 | 主题 | 关键词 | |------|------|--------| | §1 | 背景与动机 | API 中转站 warning、登录态无 warning、两条路径 | | §2 | 术语与核心模型 | CompactedItem、replacement_history、rollout | | §3 | 端到端架构总览 | 触发 → 路由 → 实现 → 落地 | | §4 | 触发条件与入口 | manual、pre-turn、mid-turn、模型切换 | | §5 | 路由决策机制 | provider.is_openai()、auth mode | | §6 | Local Compact 实现详解 | 流式请求、摘要提取、历史重建 | | §7 | Remote Compact 实现详解 | /responses/compact、后过滤、opaque state | | §8 | Local 与 Remote 的架构对比 | 压缩能力、裁剪策略、产物形态、演进能力 | | §9 | Compact 后的上下文恢复与会话持久化 | AGENTS.md、baseline 重建、rollout 检查点 | | §10 | 常见误区与 Troubleshooting | 分流误解、摘要误解、约束丢失排查 | ⏭️ 如果你只关心 local 和 remote 的核心差异,可以直接跳到 §8。1. 背景与动机1.1 问题现象:API 中转站 compact 的 warning 我日常使用 API 中转站(非 OpenAI 原生 provider)接入 Codex。compact 后其实效果还行,会话也能正常继续,但每次 compact 完成后 Codex 都会弹出一条 warning: Heads up: Long threads and multiple compactions can cause the model to be less accurate. Start a new thread when possible to keep threads small and targeted. 而切到 ChatGPT 账号登录态时,compact 完全无感——没有任何 warning,会话自然延续。同一个 Codex,为什么一个有 warning 一个没有?1.2 发现路径:从外部文章到源码验证 带着这个疑问,我刷到了 Investigating How Codex Context Compaction Works 这篇文章,并把它入库做了学习。文章揭示了一个关键事实:Codex 的 compact 并非只有一条路径——登录态和 API 中转站走的是两条完全不同的实现。这一下就解释了体验差异的根源。 但文章只点到了"两条路径"这个结论,具体实现细节并没有展开。为了彻底弄清楚,我 clone 了 Codex 源码,基于 commit 19702e1 开始了完整的代码级拆解。以下就是我一路追下去的过程。1.3 技术背景:上下文窗口膨胀 在一头扎进源码之前,我需要先搞清楚 compact 到底要解决什么问题。Codex 的线程历史会随着多轮对话不断膨胀,最终逼近模型的上下文窗口上限。一旦历史过长:新一轮请求可能在发送前就已经接近或超过上下文上限多工具、多轮推理线程里,大量旧消息会持续挤占最新问题的可见预算 所以 compact 的目标不是简单"删旧消息",而是把线程状态压缩成一个更短、但仍然可继续执行的历史表示。graph LR subgraph growth["📈 历史膨胀"] T1["Turn 1<br/>user + assistant"] T2["Turn 2<br/>+ tool calls"] T3["Turn 3<br/>+ reasoning"] TN["Turn N<br/>+ more tools"] end subgraph limit["🚧 上下文窗口"] LIM["model_context_window<br/>tokens 上限"] end subgraph compact["🗜️ Compact"] CP["历史重写<br/>replacement_history"] end T1 --> T2 --> T…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行