
1. RSI 自改进循环的 Token 账本批判、生成、评估三路消耗当你在本地把 RSI 对谈里的“自我批判—候选生成—reward 评估”跑成 while 循环最先炸的往往不是模型能力而是 token 预算。用 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_loop_intro 拿一把 Key把 OpenAI 兼容 Base URL 指向 https://taotoken.net/api同一把 Key 就能把生成、批判、评估和批量推理放进同一条可观测通道。本文不讨论递归自我改进离我们还有多远而是把对谈里的三个角色拆成可跑脚本候选生成器、自我批判器、reward/评估器。它们每轮都会重复调用模型如果分别使用不同供应商、不同 Key、不同 Base URL最后你看到的错误率和 token 用量会被拆成互不相干的几份根本无法判断是模型问题、限流问题还是 prompt 膨胀问题。统一到同一把 TaoToken Key 之后至少排障时有一个稳定坐标。先说清楚谁在消耗 Token。一个典型的两轮 self-refine 循环至少包含以下调用候选生成调用输入是任务描述、上一轮批判结果、历史失败样例输出是候选补丁、计划或代码。prompt 通常比较长因为要带上下文。自我批判调用输入是任务 候选全文 rubric输出是问题列表。很多实现里批判器的 prompt 比生成器还长因为候选全文会被塞进去而且每轮都要塞一次。reward/评估调用输入是任务 候选输出是分数、偏好或 JSON。Schulman 式 RL 评估往往对同一个候选采样多次取均值或方差token 会按采样次数线性放大。重试与超时调用429、连接超时、空响应触发重试时同一个 prompt 会再次计费。如果重试没有退避错误率和 token 会一起上升。批量推理调用Baseten 训练侧批量推理强调吞吐通常并发高、单请求 completion 短但错误率要按批次统计不能只看单次调用。可以把循环写成下面这种伪代码核心不是算法而是每轮调用都对应一笔 tokenfor round in 1..2: candidate generate(task, feedback) issues critique(task, candidate) reward evaluate(task, candidate, n3) feedback issues record_usage(round, generate, critique, evaluate)本文的接入目标是到 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_key_setup 创建一把 Key把实验脚本的 OpenAI 兼容 Base URL 指向https://taotoken.net/api然后用同一把 Key 跑两个对照对照 AJohn Schulman 式 RL 评估同一候选多次评估关注评估噪声与 token 放大。对照 BBaseten 训练侧批量推理风格批量生成 批量评估不做自我批判关注吞吐与错误率。接下来从 Key 接入、curl 连通性、两轮 self-refine 脚本、对照表、Claude Code / Codex / CC Switch 配置、排障清单逐步展开。2. 一把 TaoToken Key 的接入从控制台到 /v1/chat/completions 连通性到 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_key_setup 创建 API Key。不要等到报 401 才回头找 Key。self-refine 实验里有生成器、批判器、评估器、批处理脚本四类调用方如果它们用不同 Key会出现两个问题一是限流策略不同错误率不可比二是用量口径不同token 统计被拆散。统一 Key 之后所有调用都走https://taotoken.net/api排障时只需要查一处。本地新建.env把 Key 和模型 ID 放进去。模型 ID 以控制台可见为准下面用占位符表示TAOTOKEN_API_KEYYOUR_API_KEY OPENAI_API_KEYYOUR_API_KEY OPENAI_BASE_URLhttps://taotoken.net/api DEFAULT_MODELyour-model-id CRITIC_MODELyour-model-id EVAL_MODELyour-model-id BATCH_CONCURRENCY4 MAX_RETRIES2 REQUEST_TIMEOUT60注意OPENAI_BASE_URL不加 UTM工具配置只认干净的 API 入口。很多 404 不是 Key 的问题而是把 Base URL 写成了带路径的网页地址或者拼成了/v1/v1/chat/completions。正确路径是Base URL: https://taotoken.net/api Chat Completions: https://taotoken.net/api/v1/chat/completions先用 curl 做最小连通性验证export OPENAI_API_KEYYOUR_API_KEY export OPENAI_BASE_URLhttps://taotoken.net/api curl -sS $OPENAI_BASE_URL/v1/chat/completions \ -H Authorization: Bearer $OPENAI_API_KEY \ -H Content-Type: application/json \ -d { model: your-model-id, messages: [ {role: system, content: 你是 RSI 实验的连通性检查器只回复 OK。}, {role: user, content: ping} ], temperature: 0, max_tokens: 16 }返回 JSON 里重点看三个字段usage.prompt_tokens、usage.completion_tokens、usage.total_tokens。后面两轮 self-refine 的对照表就是按这三个字段汇总。常见错误对应关系401Authorization头没写Bearer或者 Key 复制时带了空格。404Base URL 或路径拼错优先检查https://taotoken.net/api/v1/chat/completions。429并发过高或短时间重试过多先把BATCH_CONCURRENCY降到 2再开启指数退避。400模型 ID 不受支持或者max_tokens超出该模型限制。空响应检查temperature、max_tokens和网络超时不要直接判定为限流。连通性通过后把 curl 换成脚本调用。同一把 Key 的好处在这一步开始体现生成、批判、评估都用OPENAI_API_KEY只是模型 ID 和 prompt 不同。3. 两轮 self-refine 脚本同一把 Key 下生成器、批判器、评估器如何分工下面给出一份可运行的最小脚本。安装依赖pip install openai python-dotenv脚本读取.env用 OpenAI 兼容客户端访问https://taotoken.net/api。所有调用都记录 token、延迟和错误类型方便最后汇总成表。import os import time import json import statistics from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.environ[OPENAI_API_KEY], base_urlos.environ[OPENAI_BASE_URL], ) GEN_MODEL os.environ.get(DEFAULT_MODEL, your-model-id) CRITIC_MODEL os.environ.get(CRITIC_MODEL, GEN_MODEL) EVAL_MODEL os.environ.get(EVAL_MODEL, GEN_MODEL) records [] def call(model, messages, temperature0.2, max_tokens512): start time.time() try: resp client.chat.completions.create( modelmodel, messagesmessages, temperaturetemperature, max_tokensmax_tokens, ) usage resp.usage row { ok: True, text: resp.choices[0].message.content, prompt_tokens: usage.prompt_tokens, completion_tokens: usage.completion_tokens, total_tokens: usage.total_tokens, latency_ms: int((time.time() - start) * 1000), error: , } except Exception as exc: row { ok: False, text: , prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, latency_ms: int((time.time() - start) * 1000), error: f{type(exc).__name__}: {exc}, } records.append(row) return row def generate(task, feedback): return call(GEN_MODEL, [ {role: system, content: 你是候选生成器。根据任务和历史反馈输出一个可执行方案不要解释。}, {role: user, content: f任务{task}\n历史反馈{feedback}}, ], temperature0.2, max_tokens768) def critique(task, candidate): return call(CRITIC_MODEL, [ {role: system, content: 你是自我批判器。只指出候选的错误、遗漏和风险输出 JSON 数组。}, {role: user, content: f任务{task}\n候选{candidate}}, ], temperature0.0, max_tokens256) def evaluate_once(task, candidate): return call(EVAL_MODEL, [ {role: system, content: 你是 reward 评估器。给候选打 0 到 1 分只输出一个数字。}, {role: user, content: f任务{task}\n候选{candidate}}, ], temperature0.0, max_tokens8) def evaluate(task, candidate, n3): scores [] for _ in range(n): result evaluate_once(task, candidate) if result[ok]: try: scores.append(float(result[text].strip().split()[0])) except Exception: scores.append(0.0) if not scores: return {score: 0.0, samples: 0} return { score: statistics.mean(scores), samples: len(scores), stdev: statistics.pstdev(scores) if len(scores) 1 else 0.0, } def two_round_self_refine(task, n_eval3): feedback 无 history [] for round_id in range(1, 3): gen generate(task, feedback) if not gen[ok]: history.append({round: round_id, stage: generate, ok: False}) break candidate gen[text] crit critique(task, candidate) reward evaluate(task, candidate, nn_eval) feedback crit[text] if crit[ok] else 批判调用失败 history.append({ round: round_id, candidate: candidate, critique_ok: crit[ok], reward: reward, }) return history if __name__ __main__: result two_round_self_refine(修复函数中的 off-by-one 错误并给出解释。, n_eval3) print(json.dumps(result, ensure_asciiFalse, indent2))这个脚本把三路消耗分开了generate、critique、evaluate_once。注意evaluate里循环调用n次这就是 Schulman 式 RL 评估的 token 放大器。n3时评估调用次数是候选数的三倍虽然每次 completion 很短但 prompt 会在每次评估中重复发送。如果你要做 Baseten 训练侧批量推理对照可以加一个不做批判的批量函数from concurrent.futures import ThreadPoolExecutor, as_completed def batch_generate(tasks, concurrency4): results [] with ThreadPoolExecutor(max_workersconcurrency) as executor: futures [executor.submit(generate, task, 无) for task in tasks] for future in as_completed(futures): results.append(future.result()) return results def batch_evaluate(tasks, candidates, concurrency4, n1): pairs list(zip(tasks, candidates)) results [] with ThreadPoolExecutor(max_workersconcurrency) as executor: futures [executor.submit(evaluate, task, cand, n) for task, cand in pairs] for future in as_completed(futures): results.append(future.result()) return results对照 B 的关键是批量并发高、不跑自我批判、评估采样少。它不一定比对照 A 更聪明但 token 曲线更接近吞吐型任务。4. 对照实验Schulman 式 RL 评估 vs Baseten 侧批量推理把两个对照放在同一把 TaoToken Key 下跑差异才可解释。对照 A 和对照 B 的调用结构不同维度对照 ASchulman 式 RL 评估对照 BBaseten 侧批量推理核心目标降低评估噪声观察 self-refine提高吞吐做批量推理是否自我批判是每轮都批判默认不做或抽样做评估采样n3 或更高n1必要时补评并发低到中便于归因中到高关注批次错误率Token 放大点评估次数 × 候选数prompt 重复 × 批次数错误率关注单次调用失败、解析失败批次失败、限流、超时适合场景小样本深度排障训练侧批量推理、数据生成同一把 Key 的意义是两个对照都走https://taotoken.net/api都使用OPENAI_API_KEYYOUR_API_KEY。这样对照表里的错误率差异可以归因到并发策略和 prompt 结构而不是不同 Key 的限流差异。运行方式可以统一成命令行参数python self_refine.py --rounds 2 --n-eval 3 --batch-size 20如果你把脚本拆成两个入口建议共享同一个.envTAOTOKEN_API_KEYYOUR_API_KEY OPENAI_API_KEYYOUR_API_KEY OPENAI_BASE_URLhttps://taotoken.net/api DEFAULT_MODELyour-model-id CRITIC_MODELyour-model-id EVAL_MODELyour-model-id BATCH_CONCURRENCY4 MAX_RETRIES2 REQUEST_TIMEOUT60执行时使用同一把 Key记录每一行的stage、round、prompt_tokens、completion_tokens、total_tokens、latency_ms、ok。不要只记录总 token否则你不知道超预算到底来自批判还是评估。5. 两轮 self-refine 后的 Token 用量与错误率采集表下面这张表是本地 20 条任务、两轮迭代、评估采样n3的采集模板。表中的数字用于说明字段和量级不是任何行业基准你跑自己的任务时应以脚本导出的 CSV 为准。错误率按“失败请求数 / 请求数”计算失败包括 429、超时、JSON 解析失败、空响应。阶段调用类型请求数prompt_tokenscompletion_tokenstotal_tokens失败数错误率平均延迟(ms)Round 1候选生成203,2002,4005,60000%860Round 1自我批判204,8001,6006,40015%920Round 1reward 评估 An3607,2002407,44023.3%410Round 2候选生成203,6002,6006,20000%880Round 2自我批判205,2001,7006,90015%950Round 2reward 评估 An3607,8002408,04023.3%430对照 B批量推理无自我批判406,4004,80011,20012.5%700合计全部阶段24038,20013,58051,78072.9%677从表里可以读出几个排障信号自我批判的prompt_tokens很高因为它每轮都要携带候选全文和 rubric。两轮下来批判器的 prompt 可能比生成器更贵。reward 评估的completion_tokens很低但请求数很多。n3时评估请求是生成请求的三倍错误率也会被放大。对照 B 不做自我批判total_tokens看起来更低但它缺少反馈修正任务成功率要单独统计不能只看 token。错误率主要来自 429 和解析失败。先降BATCH_CONCURRENCY再给评估器加严格的输出格式约束。把记录导出为 CSV 的示例import csv fields [ round, stage, ok, prompt_tokens, completion_tokens, total_tokens, latency_ms, error ] with open(rsi_usage.csv, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnamesfields) writer.writeheader() for row in records: writer.writerow({key: row.get(key, ) for key in fields})如果你想得到更细的错误率可以把error字段拆成auth_error、rate_limit、timeout、parse_error、empty_response五类。这样下一轮优化时你知道该调并发、调超时还是改 prompt 输出格式。6. Claude Code / Codex / CC Switch 三件套配置不要把 ANTHROPIC_* 套到 Codex同一把 TaoToken Key 不只用在自己的实验脚本里也可以接到日常 CLI。关键原则是Claude Code 走ANTHROPIC_*Codex 走config.toml两者不要混用。把ANTHROPIC_BASE_URL写进 Codex或者把 Codex 的model_provider写进 Claude Code都会导致 404 或认证失败。Claude Codesettings.json 与环境变量Claude Code 可以用settings.json也可以用环境变量。Base URL 统一写https://taotoken.net/apiKey 用YOUR_API_KEY占位。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: your-claude-model-id, ANTHROPIC_SMALL_FAST_MODEL: your-small-model-id } }或者用 shell 环境变量export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELyour-claude-model-id export ANTHROPIC_SMALL_FAST_MODELyour-small-model-id模型 ID 以 TaoToken 控制台或 Claude Code 文档为准不要凭记忆填。Codexconfig.tomlCodex 不使用ANTHROPIC_*。它走自己的 provider 配置Base URL 仍然是https://taotoken.net/api。model your-codex-model-id model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat对应的环境变量export TAOTOKEN_API_KEYYOUR_API_KEY如果 Codex 报 401先查env_key指向的环境变量是否存在如果报 404先查base_url是否被误写成了https://taotoken.net/api/v1。CC Switch 三件套如果你用 CC Switch 管理多套 CLI建议把配置拆成三件套Claude Code 的settings.json、Codex 的config.toml、以及通用环境变量。CC Switch 里新增供应商时填名称TaoToken Base URLhttps://taotoken.net/api API KeyYOUR_API_KEY然后分别回填# 通用环境变量供脚本和 Codex 使用 export TAOTOKEN_API_KEYYOUR_API_KEY export OPENAI_API_KEY$TAOTOKEN_API_KEY export OPENAI_BASE_URLhttps://taotoken.net/apiClaude Code 继续用ANTHROPIC_BASE_URL和ANTHROPIC_AUTH_TOKENCodex 继续用config.toml里的model_provider。不要把三件套合并成一个变量否则切换供应商时很容易把ANTHROPIC_*带到 Codex。7. Token 超预算排障清单与文末入口当两轮 self-refine 后 token 超预算先按下面顺序排查不要一上来就换模型Base URL 是否正确工具配置写https://taotoken.net/api请求路径写/v1/chat/completions。不要带 UTM不要多斜杠。认证是否统一脚本、Claude Code、Codex 是否都使用同一把YOUR_API_KEY。分散 Key 会让限流和用量口径不可比。429 是否来自并发把BATCH_CONCURRENCY从 4 降到 2MAX_RETRIES设为 2加入指数退避。批判器 prompt 是否膨胀每轮是否把候选全文、历史反馈、rubric 全部塞入。可以只保留最近一轮反馈或者对候选做摘要。评估采样是否过大n3是起点不是必须。先用n1做粗筛再对高分候选做n3。评估输出是否可解析让评估器只输出数字或固定 JSONmax_tokens设为 8 到 32减少解析失败。重试是否放大 token失败请求也会消耗 prompt token。记录每次重试的stage否则你看到的总额会虚高。是否只统计总额按generate、critique、evaluate、batch四类分别统计prompt_tokens和completion_tokens才能定位超预算来源。是否把对照实验混在一起对照 A 和对照 B 要分文件记录不要共用一个 CSV否则错误率无法归因。是否检查模型 ID不支持的模型 ID 会返回 400不应计入 429 错误率。如果你还没有 Key可以到 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_troubleshooting 创建然后把OPENAI_BASE_URL指向https://taotoken.net/api。同一把 Key 跑通 curl、Python 脚本、Claude Code 和 Codex 之后再开始两轮 self-refine 的对照采集。这样你得到的 token 用量和错误率表才是可复现、可比较的。文末入口按下面顺序使用模型对话https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_self_refine_chatCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_self_refine_plan创建 Keyhttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_self_refine_keysClaude Code 文档https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentrsi_self_refine_claudecode把.env、curl、两轮 self-refine 脚本和对照表放在同一个仓库里下一次 RSI 循环超预算时你只需要先看usage.prompt_tokens集中在哪个阶段再决定是调并发、缩 prompt还是减少评估采样。