为什么 Codex 越聊越“重”?一次讲清 Token、上下文与缓存
使用 Codex 一段时间后,很多人会遇到三个疑问:
- 为什么一个长任务越往后越容易变慢?
- 为什么明明只问了一句话,却可能消耗很多 token?
- 为什么同样的上下文,有时成本会低很多?
答案藏在三个概念里:token、上下文和 prompt caching。
先分清两套计费逻辑
使用 ChatGPT 或 Codex 产品时,通常关注套餐额度和 credits;直接调用 OpenAI API 时,通常按照输入、输出和缓存输入 token 计费。
两者不能简单混为一谈:
ChatGPT / Codex 产品侧:看计划额度与 credits
API 侧:看不同模型的 token 价格
具体价格、额度和模型可用性会变化,真正做预算时应以当前官方页面为准。
Token 不是字数
Token 是模型处理文本时的基本切分单位。它不等于汉字数,也不等于英文单词数。
代码、JSON、Markdown 表格、长文件路径、依赖锁文件和大段日志,往往比普通自然语言更占 token。工具描述、文件内容和命令输出也会进入模型上下文。
因此,“我只输入了几十个字”并不能代表这次请求很小。Codex 可能还带上了:
- 系统与项目规则;
- 当前线程的历史对话;
- 已启用工具的名称和参数结构;
- 刚刚读取的代码;
- 测试和终端输出;
- IDE 自动附带的打开文件或选区。
上下文为什么会逐轮累积
假设每轮对话新增 1,000 token:
第 1 轮:1,000
第 2 轮:2,000
第 3 轮:3,000
第 4 轮:4,000
第 5 轮:5,000
如果每一轮都需要把之前内容重新带上,那么五轮累计处理的输入并不是 5,000,而可能接近 15,000 token。
当上下文继续增长时,Codex 会进行压缩或摘要,把较早内容整理成更短的工作记录。但压缩不是完美记忆:过长的线程仍可能丢失细节、混淆阶段目标或把旧约束带到新任务里。
所以,长线程并不总比新线程更好。
Prompt caching 为什么能降低成本
Prompt caching 可以理解为:如果多次请求的开头部分足够稳定,服务端可以复用已经处理过的长前缀。
常见 token 类型可以简单理解为:
| 类型 | 内容 |
|---|---|
| Input tokens | 当前输入、历史、规则、文件与工具信息 |
| Output tokens | 模型生成的回答 |
| Cached input tokens | 命中缓存的稳定输入前缀 |
缓存的关键不是“内容大致相同”,而是前缀稳定。
容易命中的内容包括:
- 稳定的系统和项目规则;
- 长期不变的 API 说明;
- 固定工具定义;
- 格式稳定的任务模板;
- 同一项目反复使用的背景材料。
不容易命中的内容包括:
- 每轮变化的时间戳和随机 ID;
- 放在最前面的动态日志;
- 顺序不断改变的文件列表;
- 频繁切换语言和格式的同一组规则。
Codex 的上下文到底从哪里来
一个真实任务的上下文通常由多部分组成:
- 当前消息和仍被保留的历史对话;
- 全局与项目级
AGENTS.md; - 可用 Skills 的名称和描述;
- 已经触发并读取的完整 Skill;
- MCP 或其他工具的参数定义;
- Codex 实际读取过的文件;
- 测试、搜索和终端输出;
- IDE 自动提供的文件和选区;
- 子代理返回给主线程的汇总。
仓库不会自动整包塞进上下文。只有被引用、搜索、读取或工具附带的内容才会进入当前任务。
五个实用的上下文优化方法
1. 精简 AGENTS.md
保留真实命令、目录边界、测试要求和安全规则。删除“认真思考”“尽量做好”这类无法验证的空泛要求。
2. 少装不使用的工具
每个 MCP、Skill 和工具都可能增加上下文或误导匹配。工具越多不代表能力一定越强。
3. 控制日志长度
不要把几万行日志直接交给 Codex。优先保留报错附近、失败用例和关键调用链。
4. 任务阶段变化时及时开新线程
“分析架构”和“实现一个具体功能”是两种目标。如果旧上下文开始干扰新阶段,可以带着一份简短交接说明新开线程。
5. 保持固定背景的格式稳定
项目规则、输出模板和工具定义尽量保持稳定,有利于缓存命中,也有利于 Codex 形成一致行为。
写在最后
上下文管理不是单纯为了省钱,它同时影响速度、准确性和任务可控性。
真正有效的做法不是一味缩短提示词,而是区分:
- 什么信息必须长期存在;
- 什么内容只属于当前阶段;
- 什么日志只需要保留关键片段;
- 什么规则应该固化并保持稳定。
当上下文从“不断堆积的聊天记录”变成“经过设计的工作材料”,Codex 才更容易在长任务中保持方向。