1. 为什么长程证明的章节拆分阶段最容易卡在模型接入
在给 Stellar Colosseum 的章节拆分 Agent 设置模型 Key 时,我把 Key 的来源统一换成了 TaoToken(官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_open),并把 Base URL 写成 https://taotoken.net/api。这样做的直接原因是:长程证明一旦进入章节拆分阶段,模型调用不再是一次问答,而是“章节拆分 Agent 产出子问题、并行子问题 Agent 批量生成候选、证伪与批评 Agent 再合并”的链式流程;如果每个 Agent 各自指向不同 endpoint,401、404、429 和超时会混在一起,日志很难定位。
Google Research 近期公开的 Stellar Colosseum,面向长程数学与理论计算机科学研究,特点是与具体模型解耦,通过多智能体协作推进证明。它的运行方式可以粗略理解为几个阶段:先探索多种证明策略,达到某个就绪门槛后,把整体路线切成章节级子问题,再让多个子问题 Agent 并行生成候选方案,最后通过定向证伪和批评合并收敛。对工程侧来说,真正吃 Token、也最容易出接入问题的,恰好是章节拆分 Agent 和并行子问题 Agent:前者上下文长、调用次数不一定多,但每次都需要稳定返回结构化结果;后者并发高、单次输出可能不长,但一旦限流或超时,整个章节推进就会断掉。
很多人在本地跑 Stellar Colosseum 时,第一反应是给每个 Agent 配一个独立的模型供应商。结果常见现象是:章节拆分 Agent 能跑,但并行子问题 Agent 开始批量调用后,出现401 invalid api key、404 not found、429 rate limit,或者某些请求长时间挂起。排查时又因为 Key、Base URL、模型名、并发参数散落在多个配置文件里,很难判断到底是框架问题、网络问题,还是供应商兼容问题。更稳的做法是先统一模型入口:所有 Agent 通过同一个 OpenAI 兼容 Base URL 调用模型,Key 从 TaoToken 控制台创建,再在 Stellar Colosseum 的适配层里按 Agent 角色分模型、分并发、分重试策略。
这一步并不改变 Stellar Colosseum 的多智能体逻辑,只是把“模型从哪来”这件事收口。收口之后,章节拆分模板、跑通日志和 Token 统计才有可比性。下面按章节拆分视角,把接入、模板、日志、统计和常见排障串起来。
2. Stellar Colosseum 章节拆分流程与 Token 消耗地图
Stellar Colosseum 的长程证明不是一次性生成完整证明,而是把研究任务拆成可并行、可证伪、可合并的单元。章节拆分阶段位于“策略探索”和“并行候选生成”之间,它负责把已经通过就绪门槛的证明路线,转成一组章节级子问题。这个阶段的质量直接决定后面并行子问题 Agent 的效率:拆得太粗,子问题仍然很长,模型容易在中途丢失目标;拆得太细,Agent 数量膨胀,Token 消耗和调度复杂度都会上升。
从接入角度看,可以把流程拆成下面几层:
| 阶段 | 主要 Agent | 调用特征 | Token 消耗特征 | 接入关注点 |
|---|---|---|---|---|
| 策略探索 | strategy_agent | 少量长上下文调用 | 输入长、输出中等 | 模型长上下文能力、稳定性 |
| 就绪门槛 | readiness_gate | 判定型调用 | 输入中等、输出短 | 返回结构固定、低温度 |
| 章节拆分 | chapter_split_agent | 单次或少量调用 | 输入很长、输出结构化 JSON | 必须稳定返回可解析 JSON |
| 并行子问题 | subproblem_agent | 高并发批量调用 | 输入中等、输出中等 | 限流、重试、超时、并发控制 |
| 定向证伪 | falsifier_agent | 中等并发 | 输入中等、输出短 | 判断准确性、低温度 |
| 批评合并 | merger_agent | 少量长上下文调用 | 输入长、输出中等 | 长上下文、冲突合并 |
其中,章节拆分 Agent 的 Token 消耗主体是“长输入 + 结构化输出”。它通常要读取多份策略探索结果、就绪门槛判定理由、已有引理和约束条件,然后输出章节列表。并行子问题 Agent 的 Token 消耗主体是“调用次数 × 单次输入输出”。如果拆出 8 个章节,每个章节再生成 3 个候选,就是 24 次子问题调用;如果还有证伪和重试,调用量会继续上升。因此,接入层必须能承受并发,而不是只保证单次请求成功。
一个容易被忽略的点是:章节拆分 Agent 和并行子问题 Agent 对模型的需求并不完全相同。章节拆分 Agent 更需要长上下文和结构化输出稳定性;并行子问题 Agent 更看重吞吐、单次成本、限流恢复能力。通过 TaoToken 统一 Base URL 后,可以在配置层为不同 Agent 指定不同模型名,而不必改 Stellar Colosseum 的主体代码。这样既能保留多智能体框架的模型无关特性,也能让 Token 统计按 Agent 角色归因。
如果你还没有创建 Key,可以直接从 TaoToken 官网进入控制台:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_key。创建后把 Key 放进环境变量,不要在代码里硬编码,也不要把 Key 写进会提交到 Git 的配置文件。
3. 在 TaoToken 获取 Key 并设置 Base URL
Stellar Colosseum 是模型无关框架,实际接入方式取决于你使用的适配器。如果它通过 OpenAI SDK、OpenAI 兼容接口或 LiteLLM 调用模型,那么最关键的两个配置就是 API Key 和 Base URL。Key 从 TaoToken 控制台创建,Base URL 固定为:
https://taotoken.net/api注意,Base URL 在工具配置中不需要加 UTM 参数。UTM 只用于官网入口和文档链接的归因。最简单的环境变量配置如下:
export OPENAI_API_KEY=YOUR_API_KEY export OPENAI_BASE_URL=https://taotoken.net/api如果你的 Stellar Colosseum 适配器读取的是自定义变量名,也可以写成:
export TAOTOKEN_API_KEY=YOUR_API_KEY export TAOTOKEN_BASE_URL=https://taotoken.net/api然后在适配器初始化时把它映射到 OpenAI 兼容客户端。例如用 Python 写一个最小验证脚本,先确认 Key 和 Base URL 能通,再启动多智能体流程:
import os from openai import OpenAI client = OpenAI( api_key=os.environ["OPENAI_API_KEY"], base_url=os.environ.get("OPENAI_BASE_URL", "https://taotoken.net/api"), ) resp = client.chat.completions.create( model="gpt-4.1-mini", # 按你控制台可用的模型名替换 messages=[ {"role": "system", "content": "你是一个连通性测试助手。"}, {"role": "user", "content": "只回复 OK。"}, ], temperature=0, ) print(resp.choices[0].message.content)如果使用 curl,可以先检查模型列表或最小对话请求:
curl -s https://taotoken.net/api/v1/models \ -H "Authorization: Bearer $OPENAI_API_KEY" | headcurl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "只回复 OK"}], "temperature": 0 }'这里要特别注意路径拼接。不同 SDK 对 Base URL 的处理方式不同:有的会在 Base URL 后自动追加/v1,有的要求你手动写全/v1。Stellar Colosseum 的适配器如果基于 OpenAI SDK,通常把 Base URL 设为https://taotoken.net/api即可,由 SDK 追加/v1。如果你在日志里看到404,先检查请求 URL 是否变成了/api/v1/v1/...或/api/chat/completions这类错误拼接,而不是先怀疑模型名。
Key 创建和管理入口在 TaoToken 控制台,可以从官网进入:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_console。建议为 Stellar Colosseum 单独建一个 Key,名称里带stellar-colosseum,方便按项目统计和轮换。多人协作时,不要把同一个 Key 分发到多个本地环境;否则一旦某个并行子问题 Agent 触发限流,你无法判断是哪个环境造成的。
4. 章节拆分模板:把证明路线切成可并行子问题
章节拆分 Agent 的输出必须是结构化的,否则并行子问题 Agent 无法稳定消费。下面给一个可复现的章节拆分模板,你可以直接放进 Stellar Colosseum 的章节拆分提示词或适配层中。模板的目标不是替框架做研究判断,而是把“已通过就绪门槛的策略”转成章节列表,并给每个章节补充候选生成提示和证伪提示。
你是 Stellar Colosseum 的章节拆分 Agent。 输入: 1. 已通过就绪门槛的证明策略摘要; 2. 当前已知引理、定义、约束; 3. 不允许使用的假设或尚未证明的结论; 4. 目标定理的最终形式。 任务: 把证明路线拆成章节级子问题。每个章节必须满足: - 有明确目标,不是一个泛泛的方向; - 能独立交给一个子问题 Agent 生成候选; - 有可验证的接受条件; - 有依赖章节时,依赖关系必须显式列出; - 对高风险章节,附带定向证伪提示。 输出必须是 JSON,不要输出 Markdown,不要输出解释性前后缀。对应的 JSON 结构可以设计为:
{ "strategy_id": "strategy-001", "readiness_gate": { "passed": true, "score": 0.82, "reasons": [ "主路线与备用路线已区分", "关键引理依赖已列出", "未证明假设已标记" ] }, "chapters": [ { "chapter_id": "C1", "title": "建立基本定义与等价转化", "goal": "把目标定理转化为后续章节可使用的等价形式。", "depends_on": [], "acceptance": [ "等价转化步骤逐步可查", "每个新定义都有明确来源", "没有引入未证明假设" ], "candidate_prompt": "请给出该等价转化的完整推导,并标记每一步使用的定义或引理。", "falsify_prompt": "请尝试找出该等价转化中隐藏的方向性错误或边界条件遗漏。" }, { "chapter_id": "C2", "title": "证明核心引理 A", "goal": "证明后续主证明依赖的核心引理 A。", "depends_on": ["C1"], "acceptance": [ "引理陈述与依赖条件一致", "证明中每一步可追溯到已有结论", "极端情况已单独讨论" ], "candidate_prompt": "基于 C1 的等价形式,给出核心引理 A 的候选证明。", "falsify_prompt": "检查核心引理 A 是否在边界条件下失效,并给出反例或修补条件。" } ] }这个模板的关键点有三个。第一,readiness_gate要保留,因为它解释了为什么现在可以拆分;后续如果合并阶段发现路线有误,可以回溯到就绪门槛判定。第二,depends_on必须显式,否则并行子问题 Agent 可能在没有前置结论时提前生成候选,造成无效 Token 消耗。第三,falsify_prompt要跟着章节走,定向证伪才有目标,而不是泛泛地让模型“检查错误”。
在 Stellar Colosseum 中,章节拆分 Agent 的输出可以直接作为并行子问题 Agent 的调度输入。一个简单的调度伪代码如下:
import asyncio from collections import defaultdict async def run_subproblem_agent(chapter, sem): async with sem: # 这里调用你的模型客户端,Base URL 来自 https://taotoken.net/api return await call_model( prompt=chapter["candidate_prompt"], metadata={"chapter_id": chapter["chapter_id"], "agent": "subproblem"} ) async def run_parallel_chapters(chapters, concurrency=4): sem = asyncio.Semaphore(concurrency) tasks = [run_subproblem_agent(ch, sem) for ch in chapters] results = await asyncio.gather(*tasks, return_exceptions=True) grouped = defaultdict(list) for ch, result in zip(chapters, results): grouped[ch["chapter_id"]].append(result) return grouped并发数不要一上来就开满。建议先从 2 到 4 并发开始,观察日志中的 429 和超时比例,再逐步增加。章节拆分 Agent 本身通常不需要高并发,但并行子问题 Agent 是 Token 消耗主体,必须做并发控制、超时控制和失败重试。
5. 跑通日志:从 401 到章节拆分成功
下面是一条本地跑通日志的示例,重点展示章节拆分阶段如何确认 Base URL、Key、章节数量和并行子问题启动情况。实际日志字段会因你的 Stellar Colosseum 版本和适配器不同而变化,但排查顺序可以复用。
[10:12:03] bootstrap: load env OPENAI_BASE_URL=https://taotoken.net/api [10:12:03] bootstrap: api_key=YOUR_API_KEY length=ok prefix=sk-*** [10:12:03] adapter: provider=openai-compatible stream=false timeout=120s [10:12:04] strategy_agent: start strategy_count=3 [10:12:07] strategy_agent: done viable_strategies=2 [10:12:08] readiness_gate: evaluating strategy-001 [10:12:09] readiness_gate: passed=true score=0.82 [10:12:09] chapter_split_agent: start strategy_id=strategy-001 [10:12:11] chapter_split_agent: raw_output_chars=4820 [10:12:11] chapter_split_agent: json_parse=ok chapters=8 [10:12:11] subproblem_agent: spawn=8 concurrency=4 [10:12:13] subproblem_agent: chapter=C1 status=running [10:12:13] subproblem_agent: chapter=C2 status=running [10:12:13] subproblem_agent: chapter=C3 status=running [10:12:13] subproblem_agent: chapter=C4 status=running [10:12:16] subproblem_agent: chapter=C1 status=done tokens=prompt=6120 completion=1180 [10:12:17] subproblem_agent: chapter=C2 status=done tokens=prompt=5840 completion=1320 [10:12:19] subproblem_agent: chapter=C3 status=done tokens=prompt=6310 completion=990 [10:12:20] subproblem_agent: chapter=C4 status=done tokens=prompt=5980 completion=1450 [10:12:22] subproblem_agent: batch=1 done=4 failed=0 [10:12:22] subproblem_agent: spawn_batch=2 chapters=C5,C6,C7,C8 [10:12:29] subproblem_agent: batch=2 done=4 failed=0 [10:12:30] falsifier_agent: start candidates=8 [10:12:34] falsifier_agent: rejected=1 repaired=1 [10:12:36] merger_agent: start chapters=8 rejected=1 [10:12:39] merger_agent: merged=7 confidence=medium [10:12:39] token_summary: chapter_split=prompt=12800 completion=2600 [10:12:39] token_summary: subproblem_total=prompt=48200 completion=9800 [10:12:39] run: status=finished这条日志里,chapter_split_agent成功解析出 8 个章节,随后并行子问题 Agent 分两批执行,每批 4 个并发。真正需要盯住的指标是:json_parse是否 ok、spawn数量是否等于章节数、failed是否为 0、rejected是否被后续修复、token_summary是否按 Agent 分类。
常见错误与修复方式如下:
| 现象 | 可能原因 | 修复 |
|---|---|---|
401 invalid api key | Key 未设置、拼写错误、未带 Bearer | 重新从控制台创建 Key,确认请求头为Authorization: Bearer YOUR_API_KEY |
404 not found | Base URL 路径重复或缺少/v1 | Stellar Colosseum 适配器统一用https://taotoken.net/api,不要手写重复/v1 |
429 rate limit | 并行子问题 Agent 并发过高 | 降低concurrency,增加退避重试,按章节分批 |
timeout | 章节拆分输入过长或模型响应慢 | 拆分输入,增加超时,或给章节拆分 Agent 换长上下文模型 |
json parse error | 章节拆分 Agent 输出带解释文字 | 在提示词中强制 JSON,加入解析失败重试和截断修复 |
model not found | 模型名与 TaoToken 控制台不一致 | 在控制台确认可用模型名,再更新配置 |
建议把每次运行的失败类型计入日志,而不是只看最终成功或失败。因为章节拆分阶段的错误会放大到并行子问题阶段:一个章节 JSON 字段缺失,可能导致多个子问题 Agent 重复生成;一个依赖关系错误,可能导致后续合并阶段出现矛盾。
6. Token 统计与成本观察:谁在消耗章节拆分预算
可复现产出里最重要的一项就是 Token 统计。没有统计,你无法判断章节拆分 Agent 和并行子问题 Agent 谁在消耗预算,也无法决定哪些 Agent 该用更强模型、哪些该用更便宜的模型。下面给出一条本地样例的统计口径,不代表所有证明规模,只说明统计维度。
| 统计项 | 章节拆分 Agent | 并行子问题 Agent | 定向证伪 Agent | 批评合并 Agent |
|---|---|---|---|---|
| 调用次数 | 1 | 8 | 8 | 1 |
| 输入 Token 示例 | 12800 | 48200 | 18600 | 15200 |
| 输出 Token 示例 | 2600 | 9800 | 4200 | 3100 |
| 主要成本来源 | 长上下文 + JSON 结构 | 并发调用次数 | 候选逐个检查 | 长上下文合并 |
| 优化方向 | 精简输入、固定 schema | 限流、缓存、批处理 | 只对高风险章节执行 | 合并前去重 |
从这张表可以看出,章节拆分 Agent 单次调用输入很长,但调用次数少;并行子问题 Agent 单次输入不一定最大,但调用次数多,是整体 Token 消耗的主要放大项。实际优化时,可以这样分配模型:
- 章节拆分 Agent:使用长上下文能力更稳的模型,温度调低,强制 JSON。
- 并行子问题 Agent:使用吞吐更好、成本更低的模型,控制并发,设置最大输出长度。
- 定向证伪 Agent:只对高风险章节或候选开启,不必每个候选都全量证伪。
- 批评合并 Agent:使用长上下文模型,但输入前先去重,避免重复章节和重复候选挤占上下文。
可以用下面的 Python 片段在每次调用后记录 Token:
import json import time from pathlib import Path LOG_PATH = Path("stellar_colosseum_token_log.jsonl") def log_usage(agent, chapter_id, response): usage = getattr(response, "usage", None) record = { "ts": time.time(), "agent": agent, "chapter_id": chapter_id, "prompt_tokens": getattr(usage, "prompt_tokens", None) if usage else None, "completion_tokens": getattr(usage, "completion_tokens", None) if usage else None, "total_tokens": getattr(usage, "total_tokens", None) if usage else None, } with LOG_PATH.open("a", encoding="utf-8") as f: f.write(json.dumps(record, ensure_ascii=False) + "\n")统计后按agent聚合,就能得到类似下面的汇总:
import json from collections import defaultdict from pathlib import Path summary = defaultdict(lambda: {"calls": 0, "prompt": 0, "completion": 0}) for line in Path("stellar_colosseum_token_log.jsonl").read_text(encoding="utf-8").splitlines(): item = json.loads(line) agent = item["agent"] summary[agent]["calls"] += 1 summary[agent]["prompt"] += item.get("prompt_tokens") or 0 summary[agent]["completion"] += item.get("completion_tokens") or 0 for agent, row in summary.items(): print(agent, row)如果发现并行子问题 Agent 的calls远高于章节数,通常是因为重试或失败重放。此时不要只看总 Token,还要看failed和retry字段。很多“Token 消耗异常”并不是模型单价问题,而是章节拆分输出不稳定导致重复调用。
7. Claude Code、Codex 与 CC Switch 接入 TaoToken 的配置差异
虽然 Stellar Colosseum 的模型调用通常走 OpenAI 兼容接口,但本地开发时经常还会同时使用 Claude Code、Codex 或 CC Switch 做辅助。它们的配置方式不同,不能把ANTHROPIC_*套到 Codex,也不能把 Codex 的config.toml直接当成 Claude Code 的settings.json。下面按工具分别给出可复制配置,Base URL 统一为https://taotoken.net/api,Key 统一用YOUR_API_KEY。
Claude Code:settings.json 与 ANTHROPIC_*
Claude Code 使用ANTHROPIC_*系列环境变量。可以在项目或用户的settings.json中配置:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }如果你在 shell 里临时测试,也可以直接导出:
export ANTHROPIC_BASE_URL=https://taotoken.net/api export ANTHROPIC_AUTH_TOKEN=YOUR_API_KEY export ANTHROPIC_MODEL=claude-sonnet-4-5注意这里使用的是ANTHROPIC_AUTH_TOKEN,不是OPENAI_API_KEY。Claude Code 的模型名也要按 TaoToken 控制台实际可用的名称填写。
Codex:config.toml 与独立 provider
Codex 使用config.toml,不要混用 Claude Code 的ANTHROPIC_*。一个常见配置如下:
model = "gpt-5-codex" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"然后在环境变量中设置 Key:
export TAOTOKEN_API_KEY=YOUR_API_KEY如果你的 Codex 版本字段名不同,以本地版本为准,但核心不变:base_url指向https://taotoken.net/api,env_key指向你实际导出的 Key 变量,不要写ANTHROPIC_AUTH_TOKEN。
CC Switch:三件套配置
CC Switch 这类切换工具通常只需要三件套:Provider 名称、Base URL、API Key。可以按下面填写:
| 配置项 | 值 |
|---|---|
| Provider Name | TaoToken |
| Base URL | https://taotoken.net/api |
| API Key | YOUR_API_KEY |
| 备注 | Stellar Colosseum 共用同一入口,按 Agent 分模型 |
这样切换时不需要改 Stellar Colosseum 的主体代码,只需要确认当前激活的 Provider 是 TaoToken,且 Base URL 没有被写成带 UTM 的官网地址。UTM 链接只用于访问官网和文档,不用于 API 调用。如果你需要重新创建 Key,可以从官网进入控制台:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_ccswitch。
8. 把章节拆分跑通后,下一步做什么
当 Stellar Colosseum 的章节拆分 Agent 能稳定输出 JSON,并行子问题 Agent 能按章节调度,并且 Token 统计能按 Agent 归因,接入层就算跑通了。接下来可以继续做三件事:
第一,把章节拆分模板版本化。每次调整提示词或 JSON schema,都记录版本号,并在跑通日志里带上。这样当合并阶段出现矛盾时,可以回溯是章节拆分变化导致的,还是子问题生成变化导致的。
第二,给并行子问题 Agent 加缓存和去重。相同章节、相同候选提示词、相同模型参数,如果短时间内重复调用,可以直接复用结果。长程证明研究中很多子问题会反复出现,缓存能显著减少无效 Token。
第三,按 Agent 角色分配模型。章节拆分 Agent 用长上下文和结构化输出更稳的模型,并行子问题 Agent 用吞吐和成本更优的模型,证伪 Agent 只在高风险章节开启。TaoToken 提供统一 Base URL 和 Key 管理,方便你在同一入口下做这些切换。
如果你要直接复现本文流程,建议按下面路径操作:
- 先打开模型对话,确认模型可用:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_chat
- 如果需要长期跑 Stellar Colosseum 和本地 Coding 工具,查看 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_plan
- 创建或管理 API Key:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_keys
- 如果同时使用 Claude Code,参考 Claude Code 文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=stellar_colosseum_claudecode
最后再提醒一次配置要点:Stellar Colosseum 的模型调用 Base URL 用https://taotoken.net/api,Key 用YOUR_API_KEY,章节拆分 Agent 和并行子问题 Agent 分别统计 Token,遇到 401、404、429 时先查 Key、路径拼接和并发数。把这些基础项固定下来,长程证明的章节拆分阶段才能从“偶尔跑通”变成“可复现、可统计、可优化”的工程流程。