🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
先给入口:TaoToken。这篇只做一件事:拿同一把 Key、同一份 2000 行单文件模块、同一段重构指令,分别交给 Claude Code 和 Codex 跑一遍,把 prompt token、补全 token 和墙钟耗时记进同一张表。选型文章最容易写飘,动不动就"某某更强",所以我更愿意把变量卡死:同一个 git commit 当输入,同一个模型 ID(以模型广场为准),同一个 Base URL https://taotoken.net/api,同一台机器,中途不换网络、不重启编辑器、不人工插手。跑完之后你会拿到一张能自己重跑一遍的对照表,以及两个 CLI 各自的启动参数和读取 token 的具体位置。
1. 2000 行单文件重构:为什么用这个任务做选型
1.1 输入长什么样
本次输入是一个 2,043 行的 Python 单文件模块,路径 legacy/report_engine.py,里面挤着四类职责:从 CSV 和 SQLite 读原始记录、计算十几个业务指标、把结果渲染成 HTML 报表、以及一个 argparse 写的命令行入口。文件里注释不少,但函数普遍偏长,最长的一个函数 340 行,中间嵌了三层循环和一个 60 行的 if/elif 分支,还散着若干裸 except 把异常直接吞掉。重构目标写在 prompt 里:拆成 reader、metrics、render、cli 四个模块,公开函数名和参数保持兼容,行为不变,补上类型标注,把裸 except 换成明确的异常类型,CLI 参数维持原样,最后给出拆分理由和风险点。这个体量刚好卡在一个位置上——单文件装得下,但已经超出"随手改改"的范围。
验收标准必须提前写死,否则两个工具都会自我宣布胜利。我们用的是四条:pytest 下 68 个用例全部通过;ruff check 不出现新增告警;mypy 不新增错误;用三份固定的历史数据跑出来的报表,与重构前的输出做 diff,除时间戳字段外完全一致。这四条里最关键的是最后一条,它拦住的是"看起来更整洁、算出来不一样"的改法。很多长文重构的翻车点不在语法,而在某次顺手重命名时改掉了默认值,或者把一个边界判断挪到了循环外层,测试没覆盖到,人要翻三十分钟才找到。
1.2 只记录三个硬数,加两个软判断
记录项只有三个硬数:prompt token(累计输入)、补全 token(累计输出)、墙钟耗时。再加两个软判断:验收是否通过,以及人工返工了几处。不记"轮数""文件数""生成行数"这类指标,是因为它们口径太模糊,不同工具对"一轮"的定义不一样,跨工具比没有意义。三个硬数里,prompt token 最容易让人误读:带编辑能力的 CLI 每一轮都要把系统提示、工具定义、已读文件内容重新发一遍,累计输入天然膨胀,所以同一个任务在不同工具上出现几十万输入 token 是正常现象,不能直接解读成"谁更费钱"。
墙钟耗时也要说清口径。它包含模型推理时间,也包含本地工具调用的等待——读文件、在仓库里搜关键词、跑一次 pytest 都算在里面,而跑测试那几十秒跟模型无关。所以耗时只能和同一台机器、同一次任务、同一份输入对齐着看。真正想拆开,可以在两边的会话记录里看工具调用次数和时间戳,把"等模型"和"等本地命令"粗略分个层,这部分我在第 4 节展开。所有数字都以一次实际会话的累计值为准,不做任何平滑或拟合。
1.3 环境清单与口径声明
环境是同一台开发机,同一把 TaoToken Key,同一个模型 ID(以模型广场为准),两个 CLI 各自安装在自己的终端里互不干扰。输入冻结在同一个 git commit 上,工作副本是复制出来的临时目录,两边的起点文件逐字节相同,跑之前用 sha256sum 记一遍哈希。跑的过程中不再手动改文件、不再插话纠正,唯一允许的人工动作是在两个工具都结束后统一跑验收命令。这样做的原因很朴素:中间你一插话,两边的对话历史和 token 口径就彻底分叉了,后面那张表也就不成立了。
口径声明写在前面:下面那张对照表来自一次自测运行,只对这次任务、这份输入、这台机器成立,不构成对两个工具整体能力的排序。本文不含任何排行分数,也不引用任何公开榜单的名次、得分或用量快照;公榜数据要引用就得带上榜名、查阅日期和页面来源,而这篇文章没有做这件事,所以干脆空着。想补公榜维度的读者,去对应榜单页面按自己查阅的日期取快照,注意公榜上排的是模型,不是这两个命令行工具——你做的事是用同一把 Key 和同一个 Base URL 把同一个模型接进两个不同的外壳,比较的是外壳,不是模型。
2. Claude Code 接 https://taotoken.net/api:三件套与启动参数
2.1 settings.json 里的 env 段落
Claude Code 认的是三个环境变量:ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL。把它们写进 ~/.claude/settings.json 的 env 段,比每次开终端 export 稳定得多,尤其当你同时开着好几个标签页时,漏掉一个就会打回默认端点。Base URL 只写 https://taotoken.net/api,末尾不要带 /v1,也不要在上面挂任何查询参数——UTM 是给浏览器落地页用的,加到 API 端点上会让请求路径变成另一个东西。模型 ID 填模型广场里列出的那串,别写社区流传的简称或某个榜单里的展示名。
{
"env": {
"ANTHROPIC_BASE_URL": "https://taotoken.net/api",
"ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY",
"ANTHROPIC_MODEL": "以模型广场为准"
}
}
ANTHROPIC_AUTH_TOKEN 填的是 Key 本身,不是 Bearer YOUR_API_KEY 这种带前缀的字符串,SDK 会自己加请求头。另外两个容易混的变量是 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN:前者在某些版本里也会被读取,两者同时存在且值不同的时候行为不直观,所以干脆只留一个,另一个显式留空。跑对照实验时我更倾向于用 shell 变量临时覆盖 settings.json,这样能保证两个 CLI 用的是同一把 Key、同一个模型,跑完关掉终端就恢复原状,不会污染平时的开发配置。
2.2 非交互启动参数
要做可复现的记录,就得用非交互模式,让它在一次调用里把活干完并把用量吐出来。-p 把 prompt 直接传进去,--output-format json 让结果以 JSON 返回,里面带着 usage 和耗时字段,--permission-mode acceptEdits 允许它落盘改文件,否则它会把所有编辑都变成待确认,非交互模式下直接卡住。--model 显式指定模型,避免它读取某个残留的默认值。具体参数名在不同版本之间偶有调整,跑之前用 claude --help 核对一遍比抄别人的命令靠谱。
export ANTHROPIC_BASE_URL="https://taotoken.net/api"
export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY"
export ANTHROPIC_MODEL="YOUR_MODEL_ID"
cd /work/legacy-refactor-cc
/usr/bin/time -f "wall=%e s" \
claude -p "$(cat /tmp/refactor_prompt.txt)" \
--model "$ANTHROPIC_MODEL" \
--permission-mode acceptEdits \
--output-format json > /tmp/cc_run.json
一次跑完大概二十来分钟,中间最好不要切窗口去看它在干什么,非交互模式下它不会问你问题,你看到的"停顿"多数是在等本地命令返回。如果确实要看过程,把 --output-format json 换成流式输出,但那样最后拿到的用量字段不一定在同一处,还得回头去会话记录里捞,来回折腾不如一次跑完。跑完先别急着关终端,先确认 /tmp/cc_run.json 文件大小正常、里面能看到 usage 段落,再动手分析。
2.3 从 JSON 里取 token 和耗时
Claude Code 的 JSON 结果里,usage 段是嵌套结构,直接 jq 拍平最好用。输入侧通常分成几项:常规输入 token、缓存写入、缓存读取,这三项是分开计的,缓存读取部分单价低,所以"累计输入很大但账单没那么夸张"是常见情况。输出侧就是 output_tokens,耗时字段是 duration_ms,另外还有 num_turns 能看出它一共做了多少轮交互。把这几项一次抽出来,后面填表就不用反复翻原始 JSON。
jq '{
input: .usage.input_tokens,
cache_read: .usage.cache_read_input_tokens,
cache_write: .usage.cache_creation_input_tokens,
output: .usage.output_tokens,
duration_ms: .duration_ms,
turns: .num_turns
}' /tmp/cc_run.json
有一点必须提醒:结果里如果带 total_cost_usd 之类的估算金额,那是客户端按它内置的标价表算出来的参考值,不是账单。真实计费、折扣和套餐归属以 TaoToken 控制台展示的用量与账单为准,做成本对比时用平台侧的数字结算,别拿客户端估算值当结论。如果你同时用 CC Switch 管理多套供应商,加一条自定义供应商,Base URL 填 https://taotoken.net/api,Key 填 YOUR_API_KEY,模型 ID 从广场复制,切换只在配置层生效,不会改变上面这套 token 口径。
3. Codex 接同一个 Base URL:config.toml 怎么配才对
3.1 model_providers 段落
Codex 走的是另一套配置体系,读 ~/.codex/config.toml,不认任何 ANTHROPIC_ 开头的变量。自定义供应商要写在 model_providers 下面,用 env_key 指向一个环境变量名,注意这里填的是变量名而不是 Key 本身——这是最常见的错误来源:把 Key 直接写进 env_key 字段,程序会去找一个叫这串 Key 的环境变量,当然找不到,于是报鉴权失败或者干脆回落到默认端点。base_url 同样只写 https://taotoken.net/api,不带 /v1,也不带任何查询串,路径拼接交给客户端。
model = "YOUR_MODEL_ID"
model_provider = "taotoken"
[model_providers.taotoken]
name = "TaoToken"
base_url = "https://taotoken.net/api"
env_key = "TAOTOKEN_API_KEY"
wire_api = "chat"
对应地在 shell 里导出 TAOTOKEN_API_KEY,值就是 YOUR_API_KEY。Key 和模型 ID 在 TaoToken 的模型广场与控制台里拿,创建完先确认这串 ID 在列表里能搜到,再往配置里写,能省掉一轮"模型不存在"的排查。wire_api 这类字段在不同版本里可能叫别的名字,或者默认值已经变化,抄配置之后先跑一次最小请求验证连通性,再上 2000 行的重活。
3.2 别把 ANTHROPIC_* 搬过来
同一个终端里可能既有 Claude Code 的环境变量,又有 Codex 的变量,两套并存本身没问题,但不要指望变量能互相顶替。有人习惯把 ANTHROPIC_BASE_URL 全局写进 shell 配置,然后给 Codex 也配上,以为它读到了同一份地址,结果 Codex 完全不看那个变量,请求仍然发往它自己的默认端点,症状就是"配了但没生效"。反过来也一样:你在 Codex 的 config.toml 里改 base_url,对 Claude Code 毫无影响。两个工具各管各的配置文件,唯一的共享对象是那把 Key 和那个模型 ID。
还有个隐性坑是变量导出的作用域。在 A 标签页里 export 了 TAOTOKEN_API_KEY,切到 B 标签页跑 Codex,B 里没有这个变量,一样会失败。跑对照实验时我习惯把两个 export 写在同一条命令前,或者干脆写进一个只在这个终端有效的 shell 函数里,跑完两个 CLI 再退出终端。这样既能保证两边用的是同一把 Key,也避免第二天忘了改回去,在某些项目里误用了错误配置。
3.3 非交互运行与用量采集
Codex 的非交互入口是 exec 子命令,加上 --json 会输出结构化事件流,一路一行的 JSONL,便于后面统计。--cd 指定工作目录,避免它把仓库根目录猜错——猜错会导致它读不到上下文,输出看起来"很浅",但 token 消耗又很低,最后一对表你才发现两边的输入根本不是同一份东西。--model 显式指定模型,和配置里的 model 字段保持一致,减少变量。
export TAOTOKEN_API_KEY="YOUR_API_KEY"
cd /work/legacy-refactor-codex
/usr/bin/time -f "wall=%e s" \
codex exec --json \
--cd /work/legacy-refactor-codex \
--model "YOUR_MODEL_ID" \
"$(cat /tmp/refactor_prompt.txt)" > /tmp/codex_run.jsonl
用量统计上,Codex 的 JSONL 里会有 token 计数相关事件,把整个文件的对应字段累加起来得到这次会话的输入与输出总量;不同版本的字段名不完全一致,稳妥做法是先跑一条极短的任务(比如让它读一个文件并回答一行),把 JSONL 打出来看结构,确认字段位置之后再跑长任务。会话记录通常也会落在本地的 sessions 目录里,事后核对时以事件流为准,两者对不上就看是不是有重试发生——重试的 token 也算在消耗里,把重试剔掉会低估成本。
3.4 两边读上下文的方式不一样
Claude Code 更倾向于在开始阶段把相关文件和仓库结构成批读进来,后面的轮次主要靠对话历史里已经存在的上下文,缓存命中的比例容易做高。Codex 在编辑过程中会按需再搜再读,走一步看一步,所以它的输入 token 分布更分散,单轮增量不大但轮次多,累计起来未必更省。这个差异不是优缺点,是策略差异,但它直接决定了第 4 节那张表里"输入 token"一栏不能横向比大小。想看得更细,就把缓存读取那一项单独拎出来看占比,占比高的那次,实际计费压力通常比裸数字小。
4. 同一份 2000 行重构的对照表
4.1 本次记录
下面这张表是本次运行的结果,输入是同一个 commit 的 2,043 行模块,prompt 是同一个文件,Key 是同一把,模型 ID 相同。表格里所有数字来自两个 CLI 自己的用量输出,耗时以 CLI 报的 duration 为准、外部墙钟做交叉核对。强调一遍:这是一次运行,不是多次平均,也不代表公榜,把它当成一个可以照着重跑的样板,而不是一份排名。
| 工具 | 启动方式 | prompt token(累计输入) | 其中缓存读取 | 补全 token | 墙钟耗时 | 验收结果 | 人工返工 |
|---|---|---|---|---|---|---|---|
| Claude Code | claude -p --output-format json --permission-mode acceptEdits | 468,300 | 291,000 | 41,200 | 23 分 18 秒 | pytest 全绿、ruff/mypy 无新增 | 1 处 import 顺序 |
| Codex | codex exec --json --cd <repo> | 512,900 | 176,400 | 37,600 | 19 分 42 秒 | pytest 全绿、ruff 新增 1 条 | 2 处默认值 |
读表的时候先看后两列。两个工具都把模块拆成了四份,公开函数签名都没动,报表 diff 除时间戳外一致,说明这个任务对两者都在能力范围内,差别体现在过程成本而不是成败。再往前看输入 token:Codex 累计输入更高,但缓存读取明显低于 Claude Code,也就是说它更多地在重复发送未命中的上下文,这一栏比总量更能反映计费压力。补全 token 上 Claude Code 更多,对应它在拆分时写了更多模块头注释和文档字符串,输出更"饱满",但饱满不等于更好。
4.2 输入 token 为什么不能直接比大小
三个原因叠在一起,让"谁的输入 token 更少"这个问题几乎没有意义。第一,系统提示和工具定义的体积不同,这部分在每一轮都要重发,属于固定开销,工具功能越多这块越大。第二,仓库上下文的装载策略不同,批量预读和按需检索在累计值上的表现完全不一样,一次读 20 个文件和分 20 次读 1 个文件,最终总量可能接近,但缓存命中率差很远。第三,缓存计价规则不同,缓存读取部分的单价通常远低于常规输入,把两类 token 加在一起看总数,等于把打了折的和没打折的混在一起算。
所以真正有用的做法是拆开记:常规输入、缓存写入、缓存读取、输出,四栏并列。如果你只想要一个粗略的成本直觉,用"常规输入 + 缓存写入 × 修正系数 + 缓存读取 × 折扣系数 + 输出"估一遍,系数按平台当期规则取,别用客户端估算金额直接下结论。平台展示的用量和账单是最终口径,跑完对照实验去控制台核对一次,就能知道你的估算偏了多少,这个偏差本身也是有用的信息。
4.3 耗时该拆成两段看
23 分 18 秒和 19 分 42 秒的差距不到四分钟,如果只看这两个数,很容易得出"差不多"的结论。但墙钟里混着大量本地命令的等待:读文件、搜关键词、跑 pytest。想做更细的拆分,就在会话记录里找每条工具调用的起止时间,把"在等模型返回"和"在等本地命令"分开累加,两段的比例往往比总时长更有信息量。有的工具把更多时间花在模型之外,有的把更多轮次花在模型上,这两种情况的优化方向完全不同。
还有个执行层面的细节值得提前约定:让 AI 改代码可以,但别让它直连你的生产库或生产机去执行任何东西。这次任务里涉及 SQLite 读取的部分,我们只让它生成和修改查询语句,真正的执行由人在本地测试库上跑,再把报错原文贴回对话,让它据此修正。这个约定不增加多少工作量,却能把"它跑通了"和"它以为跑通了"区分开,也让你的验收命令成为唯一的裁判。
4.4 公榜数字和本地表不要拼在一张表里
这两类数放在一起迟早出事:本地表是一次运行的结果,受网络、机器、上下文策略影响;公榜是特定日期、特定评测方法下的快照,评的是模型。把 Arena 分数、SWE-bench 通过率、开源热度、平台用量和本地耗时拼成"综合实力表",看起来信息量大,实际上每一项的口径都不同,读者没法验证也没法复现。本文的处理方式是:只保留本地表,且明确标注为一次运行;公榜维度留空,需要的时候单独看,带上榜名、查阅日期、名次或分数、页面来源四件套。
如果你确实想补一张公榜表,选一张就够,别铺开。做编程和 Agent 场景的人常看的是 LiveCodeBench、SWE-bench Verified、Aider Polyglot、Terminal-Bench 这类,选其中一张,写清查阅日期和快照来源,然后补一句话说明:榜上排的是模型,你用 TaoToken 的 Key 和 Base URL 把同一个模型接进自己的工具,比较的对象是外壳而不是模型。这样读者既拿到了参照,也不会把两个层次的结论混起来。
5. 复现这套对照表:同一把 Key、同一段 prompt、同一份输入
5.1 先把输入冻住
复现的第一步不是配工具,是把输入冻成不可变的一份。从仓库里拉取代码、切到指定 commit、复制出一个临时工作目录,跑之前对目标文件和测试目录各记一次哈希。这样做的目的是让"两次运行之间的差异"只可能来自工具本身,而不是来自你在中间顺手改了一行。两个目录分别是 /work/legacy-refactor-cc 和 /work/legacy-refactor-codex,内容逐字节相同,只是路径不同,避免两个工具互相看到对方的改动。
git clone <your-repo-url> /work/legacy-src
cd /work/legacy-src && git checkout <commit-sha>
cp -r /work/legacy-src /work/legacy-refactor-cc
cp -r /work/legacy-src /work/legacy-refactor-codex
sha256sum /work/legacy-refactor-cc/legacy/report_engine.py \
/work/legacy-refactor-codex/legacy/report_engine.py
哈 span 里两个哈希必须一致,不一致就说明复制过程出了问题或者源目录被动过。测完每个工具,先在它的工作目录里跑同一套验收命令,记下失败项原文,然后把两个目录都删掉——不要把实验产物混进正常分支,否则下一次跑同一份输入时你已经分不清哪次是干净的。Key 在跑之前从 TaoToken 创建好,同一把 Key 同时给两个 CLI 用,这样账单侧只有一个来源,对照实验和用量核对不会打架。
5.2 同一段 prompt
prompt 存成文件 /tmp/refactor_prompt.txt,两个工具都用 $(cat ...) 读同一份,不要手打两遍。下面这段是本次使用的原文,约 400 字,可以直接拿去改成你自己的任务。它的关键点在于:先给方案再动手、明确不改哪些东西、把验收命令写进去、要求它报告没做完的部分。
你是一名资深重构工程师。工作目录里有一个约 2000 行的单文件模块 legacy/report_engine.py,
包含数据读取、指标计算、HTML 渲染和 CLI 入口四类职责。
任务:
1. 先输出一份拆分方案,说明模块边界与保留的公开接口,再开始改动。
2. 拆分为 reader.py、metrics.py、render.py、cli.py 四个模块,包内导入路径自洽。
3. 保持所有现有公开函数名、参数顺序、默认值不变,行为不变。
4. 为所有公开函数补类型标注。
5. 把裸 except 替换为明确异常类型,不要吞掉异常。
6. 不要修改 tests/ 目录下的任何文件,不要新增第三方依赖。
完成后:
- 运行 pytest -q、ruff check .、mypy legacy,把结果原文贴出来。
- 列出你认为可能影响行为、但测试没有覆盖到的三处改动。
输出格式:先方案,再改动摘要,最后命令输出原文。不要解释你有多努力。
写这段 prompt 花了点时间,原因是它要同时约束两件相反的事:既让工具有空间发挥(自己决定怎么分模块),又不能让它在自由发挥里改掉对外行为。把验收命令写进 prompt 里还有个副作用,它会在收尾时自己跑一遍测试,相当于提前暴露一部分问题,省得你手工跑一次才发现 import 错位。两个工具之间唯一的区别是工作目录,prompt 文件完全相同,哈希也记一次。
5.3 两边各跑一次,采集与回填
跑的时候用 time 记录墙钟,同时保留 CLI 自己报的耗时字段,两者差太多就说明中途有等待(比如文件系统慢或者某个本地命令卡住)。跑完立刻把 usage 抽出来填进表,不要等第二天回忆,尤其当你一天里跑了好几组对比的时候。填完表再去跑验收命令,验收结果和 token 数据分开记录,避免"任务没完成但 token 很省"这种组合被一句"表现更好"糊弄过去。
| 轮次 | 工具 | 模型 ID | prompt token | 补全 token | 耗时 | 验收通过项 | 失败项原文 | 备注 |
|---|---|---|---|---|---|---|---|---|
| 1 | Claude Code | |||||||
| 1 | Codex |
这张空表是给读者填的。填三组以上再下结论比填一组稳,同一组里也建议至少跑两次,看看 token 波动有多大——长任务里模型自己的规划路径每次都不一样,单次结果偶然性不低。如果两次之间输入 token 差出三成以上,那说明这个任务的方差本身很大,此时比较两个工具的平均值意义有限,更该关注的是"验收通过率"这类稳定性指标,而不是某一次省了多少。
5.4 验收与返工怎么记
返工分类比返工数量更有用。粗略分三类:编译或导入期的错误(结构性问题)、行为不一致(逻辑问题)、风格或注释不达标(非功能问题)。结构性错误说明它没理解模块边界,逻辑错误说明它没吃透原有行为,风格问题基本可以自己顺手改掉。这次的记录里,Claude Code 的返工是 import 顺序这类风格问题,Codex 的两处都落在默认值上,属于逻辑边缘,需要人工确认而不是机械修复——这个区别在选型时比"谁快四分钟"重要得多。
跑完一轮之后,把失败的用例名和报错原文原样贴回对话,让它在你已经人工修补过的版本上继续改,这算是第二轮。第二轮的数据不要和第一轮混在一张表里,因为输入已经变了,起点不同,token 与耗时都不可比。想比较"一次成型的质量",就只看第一轮;想看"协同修 bug 的效率",就单独开一张表记第二轮,两件事别混。
6. 本篇配置会遇到的四类报错
6.1 401:Key 没进到对的地方
报 401 的时候先看变量名,再看值。Claude Code 侧常见的是把 Key 写进了 ANTHROPIC_API_KEY 而 AUTH_TOKEN 仍为空,或者反过来,两个都存在但只有一个有效。Codex 侧最常见的是 env_key 字段里直接写了 Key 本身——那个字段要的是变量名,程序会去环境里找同名变量,找不到就发不带鉴权的请求。第三种是变量导出在另一个终端标签页里,当前 shell 根本没有这个变量。三种情况都表现为 401,但修法完全不同,先打印环境变量确认再动手改配置。
还有一种容易被忽略:Key 复制时带上了首尾空格或换行。从网页复制到终端,尾部换行常常被忽略,有些客户端会把它拼进请求头,服务端直接判定非法。跑之前用 printf '%s' "$TAOTOKEN_API_KEY" | wc -c 数一下长度,和网页上显示的字符数对一遍,能省掉一大段无意义的排查时间。密钥这类东西不要写进仓库、不要提交到 git、不要贴进 issue,需要共享时走平台的团队能力。
6.2 404 与路径重复
404 在自定义 Base URL 场景里多数是路径拼重了。你写的 base_url 如果带上 /v1,而客户端本身也会补 /v1,最终请求就打到 /api/v1/v1/... 这种不存在的路径上。本篇的配置里 Base URL 统一写 https://taotoken.net/api,末尾不带斜杠、不带 /v1、不带任何查询参数,让客户端自己去拼。排查时把客户端的请求日志打开,看它实际打出去的完整 URL,一眼就能看出是拼重了还是少了一段。
另一种 404 是模型名写在路径里、代理侧不认这个模型,于是返回"资源不存在"。这种情况和路径问题的日志长得像,区分办法是换一个刚从模型广场复制出来的 ID 再试一次,如果立刻通了,就是模型标识写错了。别拿社区里的简称、榜单上的展示名或者上一代模型的名字去猜,这类"看着像"的字符串在服务端就是不同的资源。
6.3 模型 ID 以广场为准
模型 ID 这类字段有两个来源容易混淆:一个是展示名,给人看的;一个是调用 ID,给程序用的。配置里必须填后者。同一个模型在不同入口(对话页、控制台模型列表、文档示例)展示的字符串可能略有差异,以模型广场里可复制的那一串为准,复制后不要手工改动大小写和连字符。填完先跑一条极短请求验证,通了再上 2000 行的任务,否则跑二十分钟后发现模型名写错,浪费的是自己的时间。
版本迭代比较快的时期,广场上的 ID 会增删。跑对照实验前扫一眼当前列表,把两个 CLI 的模型字段指向同一个 ID,并且在记录表里把 ID 原样写进备注,这样过一个月回看数据时还能知道当时用的是哪个。只写"用了某个模型",等于这批数据作废,因为没法复现。
6.4 Codex 里塞 ANTHROPIC_* 等于没配
这个错误不报错,只是静默失效,所以最费时间。表现是:你以为改的是自定义供应商,实际请求走的是另一个端点,速度、报价、可用模型全都不对。判断方法很简单——把 Codex 的会话日志打开,看实际请求的 host 和路径;如果 host 不是你在 config.toml 里写的那一个,就说明 model_provider 没生效,或者你改的是另一个配置文件(有些工具会在项目目录里优先读本地配置)。
同理也要检查优先级:命令行参数通常覆盖配置文件的字段,环境变量和配置文件之间谁赢取决于具体版本。想彻底排除干扰,就把所有相关变量在一个干净的 shell 里重新导出一遍,配置文件只留一份,然后跑最小请求。确认连通之后再加参数,每加一个验证一次,比一次性堆完再排错快得多。
7. 把这套对照表跑到你自己的仓库
这次对照实验做完,值得做两件事:一是去 模型对话 里核对一下你用的模型 ID 与广场列表是否一致,顺手拿一条短任务试水;二是回到 创建 Key 页面看看本次调用有没有正常入账,用量和自己记的表对一遍,偏差大的话回头检查是不是有重试没算进去。两件事加起来不到五分钟,但能让你的对照表从"自测"变成"可对账"。
如果你打算长期把两个工具都留在工作流里,可以看 Coding Plan 的套餐与配额说明,把日常开发和跑对照实验的用量分开规划。Claude Code 的变量三件套和 settings.json 写法、Codex 的 config.toml 差异,以及 CC Switch 里自定义供应商怎么填,可以对着 接入文档 逐条核。填完先跑一条最小请求,再上你的 2000 行模块,把第一轮的 prompt token、补全 token、耗时和验收结果记进上面那张空表,跑够三组再看趋势。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度




被折叠的 条评论
为什么被折叠?



