🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
1. 用 OpenHands 跑 SWE-bench Verified 子集,为什么把 TaoToken 放在请求链路上
这次我用 OpenHands 跑 SWE-bench Verified 的 50 条子集时,TaoToken 放在模型请求链路上,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 。它不是被评测对象,而是 OpenAI-compatible 的 API 供应商,负责把 OpenHands 发出的 HTTP 请求转发到上游模型。这样我就不用为每个模型单独维护一套接入代码,只要把 Base URL 指过去。
OpenHands 是一个开源的自主编码代理框架,它会在一个沙箱环境里反复调用大模型,生成命令、读文件、写补丁、跑测试。SWE-bench Verified 是 SWE-bench 团队人工筛选过的 500 条真实 GitHub issue,每条带一个基准提交和一个官方补丁,用来检验代理能否自己修好 bug。完整跑 500 条对时间和令牌消耗都不小,所以我只取前 50 条作为子集,目的是观察 OpenHands 在这个子集上的修复率与平均步数,顺便验证这套统一 API 通道是否稳定。
这个通道在这个任务里更像一个“默认供应商”:OpenHands 不直接知道上游是哪个模型服务,它只认 OpenAI 格式的 /chat/completions。TaoToken 的 Base URL 就是 https://taotoken.net/api ,没有多余的 /v1 路径。我把这个地址填进 OpenHands 的 LLM 配置后,OpenHands 发出去的每个请求都会先到这个通道,再由它按模型 ID 路由到真正的上游。这样做的好处是,后续想换一个模型只改环境变量,不用重新配置 OpenHands。
我这次跑完 50 条,请求链路没有出现断连或超时。之前用临时通道时遇到过请求发到一半就 reset 的情况,而这个统一网关在同样的一批任务里表现稳定。这里有一个实际感受:统一网关的稳定性比纸面上的调价重要得多,因为你不想在半夜等一份跑了两个小时的评测时因为某个请求失败而前功尽弃。
2. 环境准备:安装 OpenHands 并抽出 50 条 Verified 实例
我直接克隆了 OpenHands 的官方仓库并按仓库里的说明安装,没有锁定特定 commit,因为这类项目迭代很快,锁定旧 commit 反而会遇到兼容问题。安装前确认本机有 Docker 环境,OpenHands 跑 agent 时要在 Docker 沙箱里执行命令。我第一次安装后直接启动,结果报错,提示 Docker 没有运行。把 Docker 服务打开后,OpenHands 才能正常创建沙箱。这一步不算配置问题,是环境依赖。
安装完成后,验证一下命令行入口:openhands --help 能打印帮助信息即可。有些安装方式会把入口放在 python -m openhands,两种都能用。接下来准备 50 条实例。我用 Hugging Face 的 datasets 库加载 SWE-bench Verified,然后取一个固定随机种子的样本。不直接用前 50 条,因为按仓库顺序排列时,某些仓库的 issue 会集中出现,导致子集偏向特定代码结构。用固定种子之后,至少每次复现得到的实例序是一样的。代码如下:
from datasets import load_dataset
dataset = load_dataset("princeton-nlp/SWE-bench_Verified", split="test")
shuffled = dataset.shuffle(seed=42)
subset = shuffled.select(range(50))
print(len(subset))
subset.save_to_disk("swebench_verified_50")
这条子集里的每条实例包含 repo、base_commit、problem_statement、gold_patch 等字段。OpenHands 实际能看到的只有 problem_statement,也就是用户写的 issue 正文。至于官方补丁和仓库地址,是我后续做验证用的,不能提前混进任务提示里,否则就失去了评测意义。我把子集保存到本地,后面用脚本逐条读取。
如果你想用不同难度的子集,可以修改 seed 或随机抽 50 条。50 条是一个权衡过的数量:太少了随机波动大,太多了时间成本和 token 开销会翻倍。以一次 OpenHands 会话平均调用几十次模型计算,50 条下来总步数已经足够用来对比两个模型。我记录的变量只有修复率和平均步数,没有去跑完整版的带工具限制的 harness,因为完整 harness 的代码和依赖需要额外配置,反而不容易讲清楚。
3. 把 TaoToken 配成 OpenHands 的默认供应商,只需要四个变量
先去 TaoToken 官网注册、登录,在控制台创建一个 API Key。创建后把它复制为 YOUR_API_KEY。注意官网是网页端入口,接口 Base URL 是 https://taotoken.net/api ,两者不要混:网页上看到的 UTM 链接不需要加进接口地址里。
在启动 OpenHands 之前,我设置下面几个环境变量:
export LLM_BASE_URL=https://taotoken.net/api
export LLM_API_KEY=YOUR_API_KEY
export LLM_MODEL=your-model-id
LLM_MODEL 的值以 TaoToken 模型广场展示的模型 ID 为准,不要凭记忆填一个非官方 ID。我这次用的模型是广场上某个支持工具调用的 ID,具体哪个先不写,因为我不想让这一篇的结论绑定在某一个上游模型上。你打开模型广场,复制你选中的 ID 填到这里就行。
设置完成后,启动 OpenHands 的命令很简单:
openhands
如果你使用 headless 模式,则用 OpenHands 自带的入口脚本,核心还是上面三个变量。OpenHands 启动后会读取这些 LLM 配置,任何需要模型回复的地方都会先请求 https://taotoken.net/api。我在界面上确认了连接状态没问题后,才开始喂任务。怎么确认?启动后先发一条普通消息,比如“请回复两个字:收到”。如果模型回复了,说明 Base URL、Key、模型 ID 三者都正确。
这一步我踩了一个坑:第一次把 Base URL 写成了 https://taotoken.net/api/v1,结果 OpenHands 报 404。原因是我习惯性以为 OpenAI 兼容端点一定挂在 /v1 下,但 TaoToken 的 OpenAI 兼容接口就挂在 /api。把 /v1 去掉后请求就正常了。另一个小坑是复制 API Key 时末尾多了一个空格,OpenHands 报认证失败,删掉空格就通过。这两个问题都只在配置阶段出现,不涉及模型本身。
除了环境变量,OpenHands 的配置文件里也有对应项。如果你更喜欢写在 ~/.config/openhands/ 下的配置文件,把 llm.base_url、llm.api_key、llm.model 三个字段填进去即可。同样,Base URL 不加 /v1。我之所以用环境变量,是为了在对比多个模型时写一个简单的 shell 脚本,每次只改 LLM_MODEL 就能跑一轮,避免手动编辑配置文件。
4. 跑 50 条实例,修复率和平均步数怎么观察
我没有跑 SWE-bench 官方评测套件的完整流程,而是自己在 OpenHands 外面套了一层循环。流程是:从刚才保存的 50 条实例中逐条取出 problem_statement,作为一条任务发送给 OpenHands;OpenHands 会在沙箱里完成读代码、改代码、跑测试等动作,最终生成一个 diff。我收集这个 diff,再回到该实例指定的 base_commit 上打补丁,然后运行与这个 issue 相关的测试。测试通过就算修复。
修复率的定义很简单:修复率 = 修复的实例数 / 50。平均步数则从 OpenHands 的日志里解析,把每条实例中 agent 执行过的工具调用次数(包括读文件、写文件、执行 shell 命令、调用模型等)加起来求平均。步数不是质量指标,但它能告诉你模型的效率:同样的修复率,步数更少意味着更少的往返开销和更少的 token 消耗。
记录表我做成下面这样,每一行对应一条实例:
| 实例ID | 仓库 | 问题摘要 | 修复状态 | 步数 | 失败原因 |
|---|---|---|---|---|---|
| 略 | 略 | 略 | 略 | 略 | 略 |
这里我不填具体数值,因为这次 50 条只是随机子集,一次运行的结果既不能代表公榜,也不适合当采购决策依据。如果你自己跑,把这五列填满就是一张可复现的观察表。想对比不同模型时,只需要改 LLM_MODEL 环境变量,再跑一遍同样的循环,把两张表放在一起看。
我在记录失败原因时做了简单分类,有助于快速定位模型行为。第一类是补丁无法应用,agent 修改了不该改的文件,或者 diff 格式与仓库当前状态不匹配;第二类是补丁能应用但测试仍然失败,说明 agent 找到了一个表面上合理的修改,但没有真正覆盖问题;第三类是超时,agent 在规定的步数内没有给出最终补丁。分类不需要太细,重点是能快速判断模型在一个子集中的失败模式是否比较集中。
需要明确一点:这篇文章里不会有 SWE-bench Verified 的公榜分数,也没有把某个模型在 500 条完整集上的数字搬过来。公榜数字需要注明查阅日期和来源才有意义;我这里没有做这个动作,所以干脆不写。本地复现的 50 条结果,我也不会宣称它和公榜有什么关系。如果你想知道某个模型在完整集上的表现,去 SWE-bench 官方仓库看,那里有持续更新的结果。
关于步数统计,我再多说一句。OpenHands 的日志通常是 JSON 事件流,每个事件带有事件类型和时间戳。我统计步数时,只筛选动作类型为工具调用的记录,排除掉 agent 的纯文本输出。这样算出来的步数能反映实际交互频率,而不是把聊天内容的长短也当作工作量。如果你想自己写解析脚本,注意不同版本的事件字段名可能不同,最好先打印几个事件看结构。
5. 从公榜到本地复现,TaoToken 在中间到底承担什么角色
SWE-bench Verified 公榜上写的每一行都是模型名,不是 API 网关名。它没有参加任何 benchmark,也不该被当成 benchmark 的参赛方。它的作用是让你用一把 Key、一个 Base URL 去接可能出现在公榜上的同一个模型。你在公榜上看到的分数,是模型官方或其他评测方在特定条件下跑出来的;你用这个统一网关接同一个模型,在本地子集上跑出来的数字可能不一样,因为模型版本、温度、采样种子、沙箱环境、测试依赖版本都会影响结果。所以正确态度是:公榜用于选型,本地复现用于验证你自己的任务类型。
跑完 50 条,我回到 TaoToken 控制台看这次评测调用是不是都入账了。控制台里能按时间筛选,能看到每次请求的模型、token 数和费用。有一个细节:OpenHands 日志里统计的 token 数比控制台里显示的偏小,因为日志只算了模型回复部分,控制台还计入了系统消息、历史消息等上下文 token。以后要对账,以控制台的账单维度为准,而不是 OpenHands 界面上的累计数字。
这种可审计性是正规 API 聚合通道和临时通道最直观的区别。临时通道只给你一个 URL 和一个 Key,请求发出去了没有明细,出了问题也找不到人。TaoToken 这边至少能查到每次调用的时间戳、模型 ID、token 和费用,也具备发票和配额管理这些企业需要的属性。对经常跑 Agent 评测的人来说,这比省几块钱重要。
控制台的配额预警也值得设置。跑 Agent 任务时,一个实例可能要来回很多步,如果外层循环没有设上限,脚本可能会在某个异常实例上反复重试,造成 token 消耗超出预期。我在跑之前设了一个消费上限,并且开启了邮件通知,这样即使半夜跑出问题,至少第二天早上能收到提醒,不会出现账单爆炸的情况。
你现在就可以打开 TaoToken,在控制台核对刚才这 50 条实例的调用记录是否入账,顺便创建一把新的 API Key,把 LLM_MODEL 改成你想对照的另一个模型,再跑一次同样的子集,生成你自己的横向对照表。这样你得到的就不是别人给的结论,而是你自己环境里的行为数据。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度




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



