1. 先定口径:Codex/Pi 的 Token 账单不是“模型单价”一个变量
Arena 那组 21 个模型-harness 组合的评测里,真正让账单分析者头疼的并不是“哪个模型更强”这一件事,而是同一批模型换到 Codex、Pi、Claude Code 后,成功率看起来差不太多,Token 消耗却可能完全不是一条曲线。要用 TaoToken 做统一供应商时,先到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_intro 拿 Key,Base URL 固定写成 https://taotoken.net/api。这篇不讨论谁排第一,而是把 Codex 与 Pi 的 Token 账单拆成可复现的表:谁在消耗 Token、消耗在什么阶段、失败任务有没有把预算吃掉、成功率与成本是否背离。
原文的测试设计是 7 个模型分别放进 Claude Code、Codex、Pi 三种 harness,形成 21 个模型-harness 组合。这个设计对账单分析非常有用,因为它把“模型”和“harness”拆成了两个维度:模型决定单次推理的输入输出规模与工具调用倾向,harness 决定一轮任务里到底要推理多少次、重试多少次、塞多少上下文、调用多少轮工具。很多团队只盯着模型单价,最后发现账单失控往往不是模型贵,而是 harness 让同一个任务跑了更多轮。
所以本文的口径是:所有 Codex 与 Pi 的调用都走 TaoToken,Base URL 使用 https://taotoken.net/api,Key 用 YOUR_API_KEY 占位;每次运行都打上 harness、模型、任务 ID、运行 ID 四个标签;账单按“总 Token、成功任务 Token、失败重试 Token、Token/成功任务”拆分;最后输出 Codex/Pi 的 Token 账单对比表和成功率表。这样你得到的不是一句“harness 影响成本”的结论,而是一套能在本地复跑的账单分析流程。
2. 在 TaoToken 统一 Key 与 Base URL:Codex、Pi、Claude Code 各走各的字段
第一步不是改模型,而是统一供应商入口。去 TaoToken 官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_getkey 注册并创建 API Key,Key 填到各工具时不要写死在博客示例里,用环境变量或本地配置文件保存,再用 YOUR_API_KEY 作为占位符替换。所有工具的 Base URL 都指向:
https://taotoken.net/api注意,Base URL 后面不要带 UTM 参数。UTM 只用于官网和 deep link 的跳转追踪,工具配置里只认干净地址。下面这张表先明确边界,避免把 Claude Code 的 ANTHROPIC_* 变量套到 Codex 或 Pi 上。
| 工具 | 配置入口 | 关键字段 | 不要混用 |
|---|---|---|---|
| Claude Code | settings.json | ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL | 不要把ANTHROPIC_*写到 Codex 的config.toml |
| Codex | config.toml | model_provider、base_url、env_key、model | 不要用ANTHROPIC_*冒充 Codex 的供应商变量 |
| Pi | Pi 自身的 provider/环境变量配置 | OpenAI 兼容的 Base URL、API Key、模型名 | 不要假设 Pi 会读取 Claude Code 的配置 |
| CC Switch | 供应商、密钥、模型别名三件套 | 切前检查 Base URL、Key、模型 ID | 不要只切 Key 不切 Base URL |
这里的核心是:Codex 与 Pi 使用 TaoToken 时,去官网拿 Key,Base URL 用 https://taotoken.net/api;Claude Code 只是对照组,它可以用settings.json和ANTHROPIC_*,但不能反过来污染 Codex 和 Pi。账单分析最怕“看起来走了 TaoToken,实际上某个 harness 还在走默认供应商”,那样导出的 Token 数要么缺失,要么混入其他平台的计费口径。
建议为这次 Arena 复现专门建一个目录,例如arena-billing/,里面放三样东西:Codex 配置、Pi 配置、Claude Code 对照配置。每次运行前先打印当前环境变量,确认没有串线。下面这段命令只读本地环境,不连接生产库,也不触碰任何远端数据库:
mkdir -p arena-billing cd arena-billing # 只查看当前 shell 里与模型供应商相关的变量,确认没有混用 env | grep -E 'ANTHROPIC|OPENAI|TAOTOKEN|CODEX' || true如果你看到同一个终端里同时存在ANTHROPIC_BASE_URL和 Codex 的env_key,就很容易出现“Claude Code 正常、Codex 报 401”或者“Pi 走了另一套 Key”的问题。最稳妥的做法是:一个 harness 一个终端,或者用 CC Switch 明确切换。
3. Codex:config.toml 接入 TaoToken 的可复制写法
Codex 的接入关键在config.toml。不要把 Claude Code 的ANTHROPIC_*写进来,Codex 走的是自己的 provider 配置。你可以先把 Key 放进环境变量,再让config.toml通过env_key读取。下面是一个可复制的模板,模型 ID 先用YOUR_MODEL_ID占位,你需要替换成 TaoToken 控制台里实际可用的模型名。
export TAOTOKEN_API_KEY="YOUR_API_KEY"# ~/.codex/config.toml 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"这段配置只做三件事:告诉 Codex 默认模型是谁、默认供应商是taotoken、到TAOTOKEN_API_KEY环境变量里取 Key。wire_api字段是否必须、值是否写chat,以你本地 Codex 版本为准;如果版本不识别这个字段,删掉即可,但base_url和env_key必须指向 TaoToken。不要写ANTHROPIC_AUTH_TOKEN,也不要写ANTHROPIC_BASE_URL,否则 Codex 会按错误协议发请求。
配完之后,先在本地做一次连通性检查。下面命令只发一个最小请求,目的在于确认 Base URL 和 Key 能被识别;如果你的 Codex 版本没有run子命令,可以用它自己的交互模式启动一次空任务,观察是否报 401 或 404。
# 检查环境变量是否可读 test -n "$TAOTOKEN_API_KEY" && echo "TAOTOKEN_API_KEY is set" # 启动 Codex 时指定刚才的 provider,具体参数以本地版本为准 codex --config ~/.codex/config.toml如果 Codex 报 401,优先检查YOUR_API_KEY是否真的被替换、环境变量是否在同一个终端生效、env_key名字是否写错。如果报 404,优先检查base_url是否被手滑写成https://taotoken.net/api/v1或带了多余路径。产品事实给出的 Base URL 是https://taotoken.net/api,工具配置里保持这个值即可。
Codex 的账单特征通常与“工具循环”绑定:它可能为了完成一个编码任务多次读文件、跑命令、改代码、再验证。每一次循环都可能产生输入 Token 和输出 Token,如果失败后自动重试,失败轮次也会计费。因此做账单对比时,不能只记录最终成功的一次,而要把同一RUN_ID下的所有请求聚合起来。
4. Pi:把 harness 的供应商指向 TaoToken,账单才能归因
Pi 是原文里的第三种 harness。它和 Codex、Claude Code 最大的不同在于:Pi 可能不直接读取你熟悉的settings.json或config.toml,而是有自己的 provider 配置或环境变量约定。这里不能编造插件名或内部 API,只能写通用做法:如果 Pi 通过 OpenAI 兼容接口调用模型,就把 Base URL 指向https://taotoken.net/api,Key 用YOUR_API_KEY;如果 Pi 只接受 provider 配置文件,就在它的供应商设置里填同样的 Base URL 和 Key。
一个常见的 OpenAI 兼容配置模板如下。注意这只是通用变量名,Pi 是否读取OPENAI_BASE_URL、OPENAI_API_KEY,要以你本地 Pi 版本的文档和实际配置项为准。不要因为 Pi 看起来像 Agent,就把 Claude Code 的ANTHROPIC_*直接复制过去。
export OPENAI_BASE_URL="https://taotoken.net/api" export OPENAI_API_KEY="YOUR_API_KEY" export ARENA_HARNESS="pi" export ARENA_RUN_ID="pi-$(date +%Y%m%d-%H%M%S)"为了让账单可归因,建议在 Pi 的任务入口统一注入三个标签:ARENA_HARNESS=pi、ARENA_MODEL=YOUR_MODEL_ID、ARENA_RUN_ID=...。这些标签不会自动出现在 TaoToken 的账单里,但你可以把它们写入本地运行日志,再与导出的 Token 用量按时间窗口对齐。否则你只知道“今天 Pi 消耗了很多”,却不知道是哪一个模型、哪一个任务、哪一次重试吃掉的。
Pi 的账单分析重点看两个指标:第一是“每成功任务 Token”,第二是“失败任务 Token 占比”。如果 Pi 的成功率与 Codex 接近,但 Token/成功任务明显更高,就要继续拆:是系统提示更长,还是工具调用轮数更多,还是失败重试没有及时熔断。下面这个本地日志格式可以作为中间层,字段保持简单,方便后续用 SQLite 或 Python 汇总。
{ "run_id": "pi-20250101-120000", "harness": "pi", "model": "YOUR_MODEL_ID", "task_id": "arena-task-001", "success": true, "input_tokens": 0, "output_tokens": 0, "retry_count": 0, "error_class": null }注意,input_tokens和output_tokens先留 0,等从 TaoToken 控制台或本地请求日志导出后再回填。不要在示例里写具体消耗数字,因为不同模型、不同任务、不同上下文长度都会让数字失真。本文要的是账单对比方法,不是伪造一个好看的表。
5. Claude Code:settings.json / ANTHROPIC_* 只用于 Claude Code 对照
Claude Code 在这组评测里更适合作为对照 harness。它的配置入口是settings.json,关键变量是ANTHROPIC_*,而不是 Codex 的config.toml。如果你要把 Claude Code 也接到 TaoToken,可以这样写:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "YOUR_MODEL_ID" } }这段配置只对 Claude Code 生效。不要把它复制到 Codex 的config.toml,也不要在 Pi 的 provider 配置里写ANTHROPIC_BASE_URL。账单分析时,Claude Code 的价值是提供一条基准线:同一个模型在 Claude Code 下的成功率、Token/成功任务是多少,再拿 Codex 和 Pi 与之对比,就能看出 harness 到底把成本推高在哪些环节。
如果你使用 CC Switch 做多供应商切换,Claude Code 侧要特别检查三个值是否同时切换:ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL。只切 Key 不切 Base URL,可能导致请求仍然发往默认地址;只切 Base URL 不切模型,可能拿到不存在的模型 ID。对账单来说,最隐蔽的问题是“切了但没完全切”,请求看似成功,实际计费口却不是你预期的那个。
Claude Code 的对照数据建议单独建表,不要和 Codex/Pi 混在同一张原始日志里。混在一起后,后续按 harness 聚合时很容易把 Claude Code 的 Token 算进 Codex 或 Pi。你可以用harness字段区分,但在采集阶段就分开文件更稳。
6. CC Switch 三件套:供应商、密钥、模型别名
多 harness 切换时,最容易出错的地方不是配置写得不对,而是切换不完整。这里把 CC Switch 场景简化为“三件套”:供应商 Base URL、密钥、模型别名。无论切到 Codex、Pi 还是 Claude Code,这三项必须同步变化。TaoToken 的官网入口可以放在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_ccswitch ,需要创建 Key 时从控制台完成。
| 三件套 | Codex 侧 | Pi 侧 | Claude Code 侧 |
|---|---|---|---|
| 供应商 Base URL | base_url = "https://taotoken.net/api" | OpenAI 兼容 Base URL 或 provider 配置 | ANTHROPIC_BASE_URL = "https://taotoken.net/api" |
| 密钥 | env_key = "TAOTOKEN_API_KEY" | API Key / 环境变量 | ANTHROPIC_AUTH_TOKEN = "YOUR_API_KEY" |
| 模型别名 | model = "YOUR_MODEL_ID" | Pi 配置中的模型名 | ANTHROPIC_MODEL = "YOUR_MODEL_ID" |
切换完成后,用下面命令检查当前终端环境,确认没有把 Claude Code 的变量带进 Codex 会话。这个命令只读本地环境:
env | sort | grep -E 'ANTHROPIC|OPENAI|TAOTOKEN|CODEX|ARENA' || true如果输出里同时出现ANTHROPIC_BASE_URL和TAOTOKEN_API_KEY,而你又准备启动 Codex,就要明确 Codex 到底读哪个变量。最稳的方式是每个 harness 使用独立终端,或者在启动前显式unset不属于该 harness 的变量。账单分析最怕“配置漂移”:上午用 Pi 跑,下午切 Codex,晚上导出账单时发现供应商字段已经变了,却不知道哪一段属于哪个 harness。
CC Switch 三件套还应该加一条“运行标签”检查:每次运行前打印ARENA_HARNESS、ARENA_MODEL、ARENA_RUN_ID。这三个标签不参与模型调用,但决定你后面能不能把 Token 账单对齐到具体任务。没有标签,账单只能看到总量;有了标签,才能算出 Codex 与 Pi 的 Token/成功任务。
7. 复现 Codex/Pi Token 账单对比与成功率表
现在进入可复现产出。目标不是写一个复杂的计费系统,而是用本地文件把 Codex 与 Pi 的账单和成功率拼成两张表。第一张是 Token 账单对比表,第二张是成功率表。原始数据可以来自 TaoToken 控制台导出、请求日志或你自己的埋点,但必须包含run_id、harness、model、task_id、input_tokens、output_tokens、success、retry_count这些字段。
先在本地建一个 SQLite 表。下面 SQL 只在你自己的机器上执行,不连接任何生产库或远端数据库:
CREATE TABLE arena_runs ( run_id TEXT NOT NULL, harness TEXT NOT NULL, model TEXT NOT NULL, task_id TEXT NOT NULL, input_tokens INTEGER NOT NULL DEFAULT 0, output_tokens INTEGER NOT NULL DEFAULT 0, success INTEGER NOT NULL DEFAULT 0, retry_count INTEGER NOT NULL DEFAULT 0, error_class TEXT, PRIMARY KEY (run_id, task_id) );把 Codex 和 Pi 的运行记录导入后,先做账单对比。下面 SQL 按 harness 和模型聚合,计算总 Token、成功任务 Token、失败任务 Token、Token/成功任务。注意SUM里的 Token 字段来自你自己的导出数据,示例不写死具体数字。
SELECT harness, model, COUNT(*) AS total_tasks, SUM(input_tokens + output_tokens) AS total_tokens, SUM(CASE WHEN success = 1 THEN input_tokens + output_tokens ELSE 0 END) AS success_tokens, SUM(CASE WHEN success = 0 THEN input_tokens + output_tokens ELSE 0 END) AS failed_tokens, CASE WHEN SUM(success) = 0 THEN NULL ELSE 1.0 * SUM(CASE WHEN success = 1 THEN input_tokens + output_tokens ELSE 0 END) / SUM(success) END AS tokens_per_success FROM arena_runs WHERE harness IN ('codex', 'pi') GROUP BY harness, model ORDER BY harness, model;这张表可以直接映射成 CSDN 博客里的 Markdown 表格。你可以这样呈现:
| harness | 模型 | 总任务 | 总 Token | 成功任务 Token | 失败 Token | Token/成功任务 |
|---|---|---|---|---|---|---|
| codex | YOUR_MODEL_ID | <int> | <int> | <int> | <int> | <float> |
| pi | YOUR_MODEL_ID | <int> | <int> | <int> | <int> | <float> |
第二张是成功率表,按 harness 和模型计算成功率,同时带上重试次数。成功率不要只看最终通过率,还要看重试率。一个 harness 可能最终成功率不低,但靠大量重试堆出来,Token 账单会明显更厚。
SELECT harness, model, COUNT(*) AS total_tasks, SUM(success) AS success_tasks, ROUND(1.0 * SUM(success) / COUNT(*), 4) AS success_rate, AVG(retry_count) AS avg_retry, SUM(retry_count) AS total_retry FROM arena_runs WHERE harness IN ('codex', 'pi') GROUP BY harness, model ORDER BY harness, model;对应表格:
| harness | 模型 | 总任务 | 成功任务 | 成功率 | 平均重试 | 总重试 |
|---|---|---|---|---|---|---|
| codex | YOUR_MODEL_ID | <int> | <int> | <float> | <float> | <int> |
| pi | YOUR_MODEL_ID | <int> | <int> | <float> | <float> | <int> |
如果你不想用 SQL,也可以用 Python 做本地汇总。下面脚本只读本地 JSONL 文件,输出按 harness 聚合的账单和成功率。字段名保持和前面一致,方便你从 Codex/Pi 日志映射。
import json from collections import defaultdict stats = defaultdict(lambda: { "total_tasks": 0, "success_tasks": 0, "total_tokens": 0, "success_tokens": 0, "failed_tokens": 0, "retry_count": 0, }) with open("arena_runs.jsonl", "r", encoding="utf-8") as f: for line in f: if not line.strip(): continue row = json.loads(line) harness = row["harness"] if harness not in ("codex", "pi"): continue tokens = int(row.get("input_tokens", 0)) + int(row.get("output_tokens", 0)) key = (harness, row["model"]) stats[key]["total_tasks"] += 1 stats[key]["total_tokens"] += tokens stats[key]["retry_count"] += int(row.get("retry_count", 0)) if row.get("success"): stats[key]["success_tasks"] += 1 stats[key]["success_tokens"] += tokens else: stats[key]["failed_tokens"] += tokens for (harness, model), s in sorted(stats.items()): success_rate = s["success_tasks"] / s["total_tasks"] if s["total_tasks"] else 0 tps = s["success_tokens"] / s["success_tasks"] if s["success_tasks"] else None print(harness, model, { "success_rate": round(success_rate, 4), "total_tokens": s["total_tokens"], "failed_tokens": s["failed_tokens"], "tokens_per_success": tps, "total_retry": s["retry_count"], })这套流程跑完,你就能回答原文那个结论背后的账单问题:harness 选择对成功率影响可能不大,但对成本影响是否显著、显著在哪里、是失败重试还是成功任务本身更贵。对于 Codex 和 Pi,重点对比tokens_per_success和failed_tokens两项,而不是只比较总 Token。
8. 读账单时优先看的 6 个异常信号
第一,重试次数高但成功率没有同步提高。这说明 harness 可能在无意义重试,失败任务也在消耗 Token。第二,输入 Token 远大于输出 Token。编码任务里如果输入长期偏高,通常是上下文注入过多、文件读入过大或系统提示过长。第三,工具循环轮数异常。Codex 和 Pi 都可能因为验证步骤过多而反复调用模型,账单会随轮数线性上涨。
第四,模型别名写错。YOUR_MODEL_ID如果被替换成不存在的模型,可能表现为 404 或直接回退到默认模型,账单归属会乱。第五,Claude Code 的ANTHROPIC_*串到了 Codex 或 Pi。这种问题不一定报错,但会导致请求协议不匹配,最终要么失败,要么走了非预期端点。第六,失败任务 Token 占比过高。如果失败任务消耗了总 Token 的很大一部分,先修 harness 的错误处理与重试上限,再谈模型选择。
这六个信号都可以从第 7 节的 SQL 里读出来。建议每次跑完 Arena 的 21 个模型-harness 组合后,至少保留两张表:按 harness 的账单对比、按 harness 的成功率表。不要只截一张总量图,因为总量会掩盖 Codex 与 Pi 的结构差异。
9. 本地排障:401、404、超时、账单不更新怎么查
401 最常见的原因是 Key 没替换、环境变量不在当前终端、或者把YOUR_API_KEY原样写进了配置。检查顺序是:先env | grep TAOTOKEN,再检查config.toml的env_key是否和实际变量名一致,最后确认 Key 没有多余空格或换行。
404 通常和 Base URL 路径有关。工具配置里应使用https://taotoken.net/api,不要在后面自行拼/v1、/chat/completions或带 UTM 参数。不同工具对路径的拼接方式不同,最稳的做法是只填产品事实给出的 Base URL,让工具自己拼接端点。
超时问题先查本地网络、DNS 和请求超时设置。不要在不了解链路的情况下改全局代理配置,也不要把排障步骤写成绕过网络合规的方式。对账单分析来说,超时不仅意味着任务失败,还可能意味着失败前已经产生了输入 Token。把超时单独标记为error_class=timeout,后面统计失败 Token 时才能区分。
账单不更新时,先确认请求是否真的走了 TaoToken。检查 Codex 的base_url、Pi 的 provider 配置、Claude Code 的ANTHROPIC_BASE_URL是否都指向https://taotoken.net/api。如果某个 harness 还在用默认地址,导出的账单自然缺一块。此时不要急着重新跑全部 21 个组合,先跑一个最小任务验证链路,再补跑缺失的 harness。
10. 文末 CTA:从模型对话到 Coding Plan,再到创建 Key
如果你准备复现 Codex 与 Pi 的 Token 账单对比,可以按下面路径走一遍。先用模型对话快速确认模型 ID 和基础连通性:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_chat 。如果你要长期跑 Arena 这类多 harness 评测,再看 Coding Plan 是否适合你的用量:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_plan 。接着到控制台创建 API Key,把YOUR_API_KEY替换掉:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_keys 。Claude Code 侧的settings.json和ANTHROPIC_*写法可以对照文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_claudecode 。
最后再强调一次配置边界:Codex 用config.toml,Base URL 用https://taotoken.net/api,Key 从 TaoToken 获取并用YOUR_API_KEY占位;Pi 用自己的 provider 或 OpenAI 兼容配置,同样指向 TaoToken;Claude Code 才使用settings.json和ANTHROPIC_*。把这三套配置分开,把每次运行打上 harness、模型、任务、运行 ID 标签,再用本地 SQL 或 Python 汇总,你就能得到 Codex 与 Pi 的 Token 账单对比与成功率表。官网入口放在这里,需要创建 Key 或查看控制台时从这里进入:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=arena_codex_pi_final 。