Codex 用完一个月的额度只用了一个上午这种事在开发者群里越来越常见。很多人以为是任务太复杂其实往往是同一个原因每次请求时塞进模型的上下文太大了。Codex 并不会凭空把你的 Token 烧掉它只是把你给它的每一段历史对话、每一份重复粘贴的代码、每一条啰嗦的说明都忠实地计了费。这篇文章要聊的不是“少用 Codex”那是因噎废食。真正的方向是用同样的功能让每次请求携带更少冗余内容让模型更快进入有效工作状态。在长上下文重复型任务里把 Token 消耗降低 80% 并不是夸张的说法而是上下文管理做到位以后的自然结果。读完这篇文章你会掌握 Codex 的 Token 消耗构成、会话清理方法、System Prompt 精简技巧、增量式任务描述方法、模型与输出预算控制以及一套可以落地的成本排查与监控方案。1. 为什么 Codex 的 Token 消耗总是“看不见上限”先纠正一个常见误解很多人以为 Codex 的 Token 消耗等于“模型解答问题时生成的文字量”。实际上模型收费的对象不只是输出内容还包括每一次请求时发送给模型的全部输入内容。举个例子。你在终端里执行一次 Codex 任务告诉它“帮我看看这个项目里登录模块的 bug”。Codex 收到的不只是这句话它可能还要附带上系统内置的指令和工具说明你当前工作区的文件列表、Git 状态、相关代码片段前面几轮对话已经产生的历史记录模型检测到的项目配置、AGENTS.md 或类似的项目级提示文件。这些内容加起来往往比你的问题本身大几十倍。一次两次看不出问题但如果一个任务需要连续迭代 10 轮每一轮都会把之前所有的对话内容重新发送一遍。Token 的消耗是指数级叠加的不是线性的。从材料来看很多 Codex 用户遇到的问题并不只是“用量大”还包括登录态失效、Token 刷新失败、403 地区限制提示等。这些属于认证与网络层面的问题后面会单独讲。但绝大多数“Token 不够用”的核心原因其实是使用习惯问题会话开得太久不清理代码反复粘贴任务描述一次说太多无关细节。所以省 Token 的第一步不是心疼模型而是先看清钱到底花在了哪里。2. 前置认知Token、上下文窗口与 Prompt 缓存2.1 Token 到底是什么Token 是语言模型处理文本的基本单位。它可以是一个单词的一部分、一个标点、一个汉字甚至一个空格。对于英文文本通常一个 Token 约等于 0.7 到 1 个单词对于中文文本一个汉字大约对应 0.6 到 0.8 个 Token具体取决于模型使用的分词器。对于 Codex 这种编程场景代码里的缩进、换行、括号、注释都会被拆分。看起来不起眼的空行和大段注释累计起来会消耗大量 Token。2.2 上下文窗口的三种角色模型处理文本的空间叫做上下文窗口Context Window它分为三个部分部分说明Token 消耗特征System Prompt系统级指令决定模型行为方式每次请求都会计入且通常不可压缩用户输入与工具结果你提供的任务、代码、文件内容、命令输出这部分是变量最大的来源模型输出模型生成的回答、代码、修改建议可以通过限制输出长度来控制上下文窗口不是“无限聊天记录”而是每一轮都会完整发送的数组。这是许多人忽略的关键你以为在“继续对话”实际上是在不断复制粘贴全部历史。2.3 利用 Prompt 缓存省钱主流模型接口普遍支持 Prompt Caching 机制如果多次请求使用相同的前缀内容服务商可以对该部分缓存缓存命中的输入 Token 费用通常显著低于未命中。这意味着如果你能让对话的前缀保持不变或者让多轮请求共享相同的系统提示符和项目说明那么大量 Token 会以更便宜的价格计费。反过来如果每次请求前都无意义地调整 System Prompt 或重新贴一段内容缓存就永远命不中成本自然居高不下。3. 技巧一从会话层面控制上下文膨胀3.1 一个任务一个会话别让 Codex “带病工作”Codex 的长期会话会积累大量历史。假设你上午 10 点开始排查一个 bug过了两个小时又把 Codex 叫来写一个新模块此时它还记得上午的排错过程。这些老内容不仅没有帮助还会抢占上下文窗口让模型在无关信息里找重点。最朴素也最有效的做法是换任务就换会话。如果你是重度终端用户不要舍不得关掉当前会话。重新开一个会话的成本比让模型带着几十轮历史继续工作低得多。# 查看当前 Codex 会话状态 codex status # 启动一个新会话具体命令以你安装的版本为准 codex # 如果某次任务已经结束直接退出并重启会话 exit3.2 主动清理历史与压缩上下文如果任务确实很长、不适合完全重开可以采用分段会话策略把一个大任务拆成几个阶段每个阶段完成后清空上下文只保留必要的结论。很多 Codex 工具支持会话压缩或重置命令实际使用前可以先执行codex --help查看自己的版本支持哪些命令。清理历史时可以遵循一个原则只把与当前步骤直接相关的文件和描述喂给模型。比如刚完成了登录模块的 bug 修复下一步要写单元测试就应该把登录模块的核心代码路径传给 Codex而不是把整个项目的全部文件都丢进去。3.3 少闲聊多下指令Codex 不是聊天机器人它更适合被当作“执行具体任务的工程师”。每次对话里加入“你觉得怎么样”“帮我分析一下原因”“你明白我的意思吗”这类模糊表达不仅不会提高回答质量还会让模型输出大量过渡性内容白白消耗 Token。在实操中更推荐直接用动词开头的短句告诉它要做什么在 src/auth/login.ts 中修复登录超时未抛出自定义异常的问题 不要修改其他文件 完成后运行 npm test 验证相比之下这种描述比“我这边登录超时了你帮我看看是什么原因然后看看能不能改一下顺便跑一下测试”少消耗很多 Token而且结果更可控。4. 技巧二精简 System Prompt 与项目说明文件4.1 AGENTS.md 写太多反而费钱现在很多 AI 编程工具支持项目级说明文件比如AGENTS.md。这个文件里的内容会随每次请求一起发送给模型也就是说它里面的每一行都会变成 Token 账单上的数字。很多团队会把 AGENTS.md 写得像一本手册公司历史、团队文化、编码规范全抄进来、甚至还有几十条“禁止事项”。这些内容模型虽然能读但属于稀缺的上下文资源。一个比较合理的 AGENTS.md 应该只回答三个问题这个项目的构建、测试、运行命令是什么项目结构和约定有哪些模型必须知道的硬约束有哪些文件绝对不能动、有哪些目录是生成出来的。优化前# 项目说明 这是一个电商系统的前端仓库。 我们团队使用 React 18由前端架构组统一维护状态管理方案。 所有组件都放在 src/components 下面页面放在 src/pages 下面。 如果遇到任何问题请优先查看 README.md 或者联系 前端负责人。 请注意我们使用 pnpm 而不是 npm也不要用 yarn。 构建命令是 pnpm build测试命令是 pnpm test类型检查是 pnpm typecheck。 不要修改 src/constants 下任何文件这些是业务常量。 如果有 ESLint 报错先看是不是自动修复能解决。优化后# 项目说明 - 包管理器pnpm不要使用 npm / yarn - 构建pnpm build - 测试pnpm test - 类型检查pnpm typecheck - 禁止修改src/constants 下 的常量文件 - 组件路径src/components页面路径src/pages同样一份信息后者的 Token 消耗可能只有前者的三分之一。能直接给结论就不要给背景故事。4.2 系统提示词也要做减法如果你通过 Codex API 或自定义配置调用模型系统提示词同样影响每次请求的成本。系统提示词可以精简为三层角色层一句话说明模型的职责范围操作层只写输出格式、禁止行为等硬性要求信息层不放具体代码只放路径索引。一个容易踩的坑是有人为了让模型“更懂项目”把一大段业务背景写进系统提示词结果每次请求都背着这份背景。背景知识如果只在个别任务里用得到就应该放进任务描述而不是全局提示词。5. 技巧三改用“增量式任务描述”避免重复粘贴代码5.1 一次只让它读该读的文件初级用户最常见的浪费是把整个文件甚至整个目录的代码复制粘贴到对话里然后说“帮我改”。这种方式不仅消耗大量 Token而且会让模型面对过多无关代码反而降低修改质量。推荐的做法是用文件路径代替代码全文让 Codex 自己去读。Codex 本身具备文件读取能力只要项目文件在它的访问范围内你给出路径和明确的修改目标即可。codex 修改 src/services/order.ts 中的 createOrder 方法加入库存校验逻辑如果任务是让 Codex 搜索代码同样不需要把搜索到的内容全部贴回来。让它直接修改目标文件并汇报改动点而不是把大段代码复制到对话里讨论这样更省。5.2 任务描述要“增量”不要“全量重述”很多人在多轮任务里会重复描述背景。比如第一轮已经说了“我在做一个订单管理系统使用 React 和 TypeScript”第二轮又开始说一遍。这种重复对模型理解没有帮助却会让 Token 消耗翻倍。正确的增量式描述应该默认 Codex“还记得”上一轮的结论只补充当前步骤的变化继续现在给 createOrder 增加一个订单状态字段默认值为 pending这样一句话就够了。背景信息只在会话开头给一次后续都以“继续”开头而不是重新叙述背景。5.3 不要用“长对话”对抗“短记忆”有一种错误用法用户担心 Codex 忘记需求于是不断在每轮请求里复述需求。这会让上下文越来越长、成本越来越高但模型“记得住”的能力并不会变得更好。更合理的做法是把核心需求写进项目级说明文件或者一个独立的需求文档然后在任务描述里直接引用文件路径。这样即使会话中途换模型或清理上下文需求也不会丢。6. 技巧四选对模型、限制输出、利用前缀缓存6.1 模型选择直接影响成本不同模型的价格差异很大。对于简单任务使用轻量级模型往往已经足够只有处理复杂推理、架构设计和多文件重构时才需要调用更强的模型。如果你只是让 Codex 补全函数、写单元测试或格式化代码却默认使用最强模型成本会明显偏高。从社区讨论看Codex 接入第三方模型如 DeepSeek也是不少开发者尝试的方向这样可以用更低的单价完成类似任务。但需要注意兼容性问题不是所有模型都支持 Codex 的工具调用格式接入前要先确认模型对 function calling 的支持情况。6.2 用输出限制防止“废话连篇”模型生成完代码后往往会惯性输出一段“这段代码实现了以下功能”之类的总结。这些输出同样消耗 Token。可以通过配置或提示词约束输出格式。# config.toml 示例字段以你使用的 Codex 版本为准 model gpt-5.4 # 换成你实际可用的模型名称 model_provider openai approval_policy on-request在配置或提示词中明确要求“不要输出解释只输出代码”可以有效减少模型生成无意义文字的比例。只输出修改后的文件内容不要解释、不要总结、不要给出额外建议6.3 前缀稳定缓存才能命中前面提到过 Prompt Caching。要让缓存生效需要保持系统提示词和项目说明稳定。换句话说不要每次请求都调整 AGENTS.md 的措辞多轮会话中前缀尽量保持不变避免在会话中途插入大段与任务无关的对话。一个常见的反模式是用户每轮在对话开头加一句“忽略我上面说的话现在开始新任务”。这相当于强制让缓存前缀发生变化不仅不能省钱还可能让模型更困惑。7. 实战示例一次代码重构任务的优化前后对比7.1 优化前的做法假设现在要完成一个任务重构src/utils/format.ts中的日期格式化函数让它支持时区参数。优化前的任务描述可能是这样我这边有一个日期格式化工具文件路径是 src/utils/format.ts。 里面有个 formatDate 函数现在不支持时区参数。 我想让它支持传入 timezone然后根据时区输出对应的时间。 这个函数很多地方在用所以不能破坏原来的功能。 另外有测试文件在 src/utils/__tests__/format.test.ts你改完之后记得跑一下测试。 哦对了项目用的是 Jest测试命令是 npm test -- format。 如果你看到别的地方也用了这个函数能不能也检查一下有没有受影响 如果时间充裕顺便把文档注释也更新一下。这段描述包含了大量冗余信息文件路径重复出现、额外附带“如果时间充裕”这类模糊指令、还让模型自行决定检查范围。这会导致模型不必要地读取多个文件、输出更多解释Token 消耗自然偏高。7.2 优化后的做法同样任务可以拆成两步第一步codex 修改 src/utils/format.ts 中的 formatDate新增可选参数 timezone默认值为 UTC不能改变现有调用方式的返回值格式。只改这一个文件。第二步codex 补充 src/utils/__tests__/format.test.ts 中关于 timezone 参数的测试用例运行 npm test -- format 验证通过。两步分开任务边界清晰模型不需要在一轮里同时处理修改、测试、全局影响分析和文档更新。Token 节省不是来自少干活而是来自不干多余的活。7.3 为什么在某些场景下能接近 80%80% 这个数字并不是在所有场景下都能达到。当你执行的任务是“长历史会话 重复上下文 模型额外输出”的组合时优化空间巨大。比如一个会话持续了 30 轮每轮都携带 2 万 Token 的历史背景用户每轮重新粘贴 300 行代码而实际上只需要其中 20 行模型每轮都生成大段解释性文字。这种情况下从会话清理、提示压缩、输出限制三个方向同时优化80% 是合理的期望。但如果你的任务是单轮短对话、模型输出本身就很少那能省的空间就没有那么夸张。把 80% 理解为一个方向而不是一张保证达到的支票。8. Codex 登录、Token 失效与网络报错排查8.1 为什么明明 Token 失效的不是 API Key很多用户把开发中遇到的 “Token Exchange Failed” 和模型计费里的 Token 混在一起其实这是两回事。Codex 登录时的 Token 是 OAuth 认证令牌用于确认用户身份模型计费里的 Token 是文本切分单位。从社区反馈看这些报错信息出现频率比较高token exchange failed: error sending requesttoken endpoint returned status 403 forbidden: countryfailed to refresh token: 400 bad requestsign-in could not be completed token exchange failed这类问题的核心是认证流程无法完成与对话内容的 Token 消耗无关。出现这些问题时优先检查的不是“是不是我说太多了”而是登录态和网络环境。8.2 常见认证失败排查表问题现象可能原因排查方式解决方案登录时报error sending request网络连通性异常无法访问认证服务检查当前网络能否访问官方登录域名切换网络环境或检查系统代理设置是否正确返回 403提示forbidden: country所在地区不在服务允许范围内查看认证服务返回的错误码和地区限制说明确认所在地区是否在官方支持范围内或联系团队管理员确认合规访问方式failed to refresh token本地保存的刷新令牌过期或失效查看本地认证缓存文件确认登录时间手动退出后重新登录重新走一遍 OAuth 流程登录成功但无法加载组织设置组织权限或会话缓存异常检查账号是否有对应组织访问权限重新登录并确认组织授权范围8.3 一个稳妥的重置流程遇到认证问题时最稳妥的做法是按顺序逐步重置而不是反复点击登录按钮# 1. 查看当前登录状态 codex login status # 2. 退出当前账号命令以你的 Codex 版本为准 codex logout # 3. 清除本地残留缓存后重新登录 codex login如果退出重新登录后仍然报错检查一下系统的日期时间是否准确。OAuth 令牌对时间偏差很敏感本机时间不准确会导致令牌签名验证失败。这里要特别提醒不要为了绕过地区限制而使用未经授权的访问工具。更合理的做法是查看官方支持地区列表结合团队实际部署情况选择合规的使用方式。9. 工程化建议把 Token 消耗纳入开发流程管理9.1 用脚本估算输入 Token在生产实践中可以在调用 Codex 前先对任务描述做一次 Token 估算提前发现“这条 prompt 太重”的问题。使用tiktoken库可以快速估算文本的 Token 数量# estimate_tokens.py import tiktoken def estimate(text: str, model: str cl100k_base) - int: enc tiktoken.get_encoding(model) return len(enc.encode(text)) if __name__ __main__: prompt open(prompt.txt, encodingutf-8).read() print(f估算 Token 数{estimate(prompt)})这个脚本的价值不在于精确计费而在于让开发者对“一句话到底值多少 Token”有一个体感。当你把一段 500 字的任务描述压缩到 100 字时就能直观看到 Token 数量的下降。9.2 记录每次请求的用量如果是通过 API 调用 Codex响应结果里通常包含usage字段。把它记录下来按项目和会话维度聚合就能看清哪个模块消耗最多。# 示例在脚本中保存响应信息伪代码 codex run 你的任务 --output-format json | jq .usage通过长期记录你会发现 Token 消耗往往集中在少数几个高密度任务里。针对这些任务做专项优化比全面压缩所有对话更有效。9.3 团队协作层面的省钱规范如果团队多人使用 Codex建议在项目说明里加一条使用规范每个任务必须对应一个新会话不要粘贴超过 50 行的代码块改用文件路径模型输出指定为“只输出代码”或“只输出结论”每周检查一次 Token 用量统计寻找异常高的会话。这些规范不需要强制执行只要让每个使用者意识到“上下文是有成本的”就能大幅降低整体消耗。10. 总结回头看Codex 省 Token 的核心不是玄学而是四件事控制会话长度、精简系统提示词、使用增量式任务描述、限制模型输出。这四件事单独拿出来都不复杂但组合起来足以在常见的多轮开发场景里省下大量 Token。需要承认的是80% 是一个在特定条件下成立的目标不是每个任务都能达到。真正值得做的是建立“上下文成本”意识把省 Token 从偶尔一次的操作变成一套使用习惯。如果你下次打开 Codex 时发现额度又不够用了先别急着换模型或开新账号。检查一下自己的会话历史有多长看看自己是不是又把整份代码贴进了对话里。答案往往就在那里。