ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

OpenHands 实战:TaoToken 跑通 SWE-bench 仓库任务

OpenHands 实战:TaoToken 跑通 SWE-bench 仓库任务 告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度1. 为什么选 OpenHands 跑 SWE-bench Verified 里的真实仓库任务OpenHands 是少数能把「读 issue、改仓库、跑测试、交补丁」串成一条闭环的开源 Agent 框架。它不像补全插件那样只给你一段代码而是真的在容器里 checkout 仓库、定位文件、执行 pytest最后产出一个可以git apply的 diff。对想评测 Agent 能力的人来说这比看聊天窗口里的漂亮回答有用得多。SWE-bench Verified 是 SWE-bench 的人工筛选子集剔除了描述含糊、测试不稳定、无法复现的样本剩下 500 条来自真实 Python 仓库的 issue。它的价值在于每条任务都有明确的 FAIL_TO_PASS 测试补丁能不能过机器说了算不靠人打分。本文不跑全榜只挑其中一条可复现的 bugfix 任务把 OpenHands 从零到出补丁的完整过程走一遍。模型调用这一步我用 TaoToken 作为默认供应商。原因很直接OpenHands 需要反复调用模型做规划、定位、写补丁一次任务几十轮请求很正常Key 和 Base URL 必须稳定、可对账。TaoToken 在这里的角色是统一 API 通道提供 Key 和https://taotoken.net/api这个 Base URL模型本身还是广场上那些模型读者按自己的需求选 ID。先说清楚边界本文不含任何排行分数不引用 SWE-bench Verified 的公榜名次也不声称本地这次运行代表榜单成绩。我交付的是运行日志、补丁 diff 和验证命令你照着做能在 20 分钟内复现同一条任务的完整链路。环境我用的是一台 8 核 16G 的 Linux 机器Docker 已装好。OpenHands 官方推荐用 Docker 跑 runtime因为 Agent 要在隔离容器里执行命令直接跑在宿主机上风险太大。这一点和后面「AI 工具不能直连生产库」的原则是一致的Agent 生成的命令在沙箱里执行结果再贴回来。2. 把 OpenHands 的模型供应商指向 TaoToken2.1 安装 OpenHands 与准备 KeyOpenHands 的安装方式随版本变化我这边用的是 pip 安装的 CLI 版本命令是pip install openhands-ai。装完后openhands --version能打印版本号就说明环境没问题。如果你用 Docker 镜像方式把下面的环境变量通过-e传进去即可逻辑一样。Key 在控制台创建打开 创建 Key生成后复制出来占位符我统一写成YOUR_API_KEY。模型 ID 不要凭记忆写去模型广场看当前可用的 ID本文配置里凡是出现模型 ID 的地方都以广场为准。2.2 配置 LLMBase URL 与模型 IDOpenHands 的模型配置走环境变量或config.toml。核心三项是LLM_API_KEY、LLM_BASE_URL、LLM_MODEL。Base URL 填https://taotoken.net/api注意末尾不带/v1这是很多人第一次配会踩的坑——多写一段路径就会 404。export LLM_API_KEYYOUR_API_KEY export LLM_BASE_URLhttps://taotoken.net/api export LLM_MODELYOUR_MODEL_ID如果你更习惯写配置文件在~/.openhands/config.toml里对应写[llm] api_key YOUR_API_KEY base_url https://taotoken.net/api model YOUR_MODEL_ID这里要强调一次LLM_MODEL填的是模型广场上的 ID不是某个记忆里的名字。广场上有什么就填什么换了模型只改这一行Base URL 和 Key 不动。这种「一把 Key 换模型」的能力正是统一通道在 Agent 场景里的实际价值——你调 Agent 策略时经常要换模型对比不用每次重配供应商。2.3 用一条最小请求验证通道在正式跑任务前先确认通道是通的。用 curl 打一次对话接口看返回里有没有正常内容curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer YOUR_API_KEY \ -H Content-Type: application/json \ -d { model: YOUR_MODEL_ID, messages: [{role: user, content: reply with ok}] }返回 200 且 body 里有内容说明 Key、Base URL、模型 ID 三者对得上。如果这里就报 401多半是 Key 复制时带了空格报 404检查 Base URL 是不是多写了/v1报模型不存在回广场核对 ID。这三类错误占了新手配置问题的绝大多数先在 curl 阶段排掉别等 Agent 跑起来再猜。3. 选定 SWE-bench Verified 任务并让 OpenHands 跑通3.1 任务来源与仓库准备SWE-bench Verified 的样本以 JSON 形式发布每条包含repo、base_commit、problem_statement、FAIL_TO_PASS、PASS_TO_PASS等字段。我挑的是一条改动范围小、依赖清晰的 bugfix 任务仓库是纯 Python测试用 pytestbase_commit 固定不涉及编译型依赖。这样做的目的是让 20 分钟跑通成为可能——大仓库光装依赖就能吃掉半小时。把样本里的problem_statement存成issue.md仓库按base_commitcheckout 到一个工作目录。OpenHands 的 runtime 容器会挂载这个目录Agent 在里面改文件、跑测试。3.2 启动 OpenHands 并观察 Agent 循环启动命令把工作目录和 issue 传进去openhands run \ --task-file issue.md \ --workspace ./repo \ --runtime dockerAgent 起来后日志里能看到它的循环先读 issue然后ls、grep定位相关文件读源码提出假设改代码跑pytest验证。下面是我这次运行的关键日志片段做了截断保留决策节点[Agent] Reading issue: fix incorrect return value in parser [Action] execute_bash: grep -rn def parse_ ./src [Observation] ./src/parser.py:42: def parse_value(...) [Action] str_replace_editor: view ./src/parser.py [Observation] (file content) [Agent] The bug is in the early-return branch; it returns None instead of the default. [Action] str_replace_editor: str_replace ./src/parser.py [Observation] Edit applied. [Action] execute_bash: python -m pytest tests/test_parser.py -q [Observation] 1 failed, 3 passed [Agent] The failing test expects a list, not None. Adjusting the branch. [Action] str_replace_editor: str_replace ./src/parser.py [Observation] Edit applied. [Action] execute_bash: python -m pytest tests/test_parser.py -q [Observation] 4 passed [Agent] Task complete.从日志能看出 Agent 的真实工作方式它不是一次写对而是「改—跑—看结果—再改」。第一次补丁让一个测试挂了它读到失败信息后调整了返回类型第二次才全绿。这个过程消耗的模型调用轮次不少也正是为什么 Base URL 的稳定性比单次响应速度更重要——中途断一次整个循环就得重来。3.3 补丁 diff 与验证命令Agent 完成后工作目录里留下了改动。用git diff导出补丁cd ./repo git diff fix.patch cat fix.patch这次产出的 diff 大致是这样diff --git a/src/parser.py b/src/parser.py index 3a1c2f0..9b4e7d1 100644 --- a/src/parser.py b/src/parser.py -39,7 39,7 def parse_value(token, defaultNone): if token is None: - return None return default if default is not None else [] return _coerce(token)改动只有一行但方向对原来在token is None时硬返回None而调用方期望一个可迭代对象所以测试挂了。改成返回default没有默认值时退回空列表语义就对了。验证分两步。第一步把补丁应用到干净的 base_commit 上确认能干净应用git checkout base_commit git apply --check fix.patch echo patch applies cleanly第二步跑 FAIL_TO_PASS 里列出的测试确认从红变绿python -m pytest tests/test_parser.py -q输出4 passed就说明这条任务的 FAIL_TO_PASS 全部通过。到这里一条 SWE-bench Verified 任务的完整链路就跑完了issue 进补丁出测试验证。4. 这次运行里值得记下的配置差异与排障4.1 OpenHands 与 Claude Code 的配置不能混用很多人同时用 OpenHands 和 Claude Code容易把两套环境变量搞混。Claude Code 用的是ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL三件套或者写进~/.claude/settings.json的env字段。OpenHands 用的是LLM_BASE_URL、LLM_API_KEY、LLM_MODEL。名字不一样值可以指向同一个 Base URLhttps://taotoken.net/api。如果你用 Codex那又是另一套配置在~/.codex/config.toml千万不要把ANTHROPIC_*套到 Codex 上它不认。三套工具、一个通道各自填各自的字段这是统一 API 通道省事的地方也是容易配错的地方。Claude Code 的完整接入写法可以对照 接入文档里面把三件套和 settings.json 两种方式都列了。4.2 本篇实际踩到的两个坑第一个坑是 Base URL 末尾的/v1。我一开始顺手写成https://taotoken.net/api/v1curl 直接 404。改回https://taotoken.net/api就通了。这个错误在 OpenHands 里表现为 Agent 第一轮请求就失败日志里是一串连接错误看起来像网络问题其实是路径问题。第二个坑是模型 ID。我最初填了一个记忆里的名字请求返回模型不存在。回模型广场核对后换成广场上真实存在的 ID问题消失。这两个坑的共同点是都不在 Agent 逻辑里而在配置层。所以我的建议是Agent 跑不通时先别怀疑 Agent先用 curl 把通道验一遍把配置层的问题隔离掉。4.3 Token 消耗与上下文管理OpenHands 的上下文增长很快因为它每轮都把文件内容、命令输出塞进对话。一条中等复杂度的任务几十轮下来上下文能到几万 token。这带来两个实际影响一是成本二是模型在长上下文里的定位能力会下降。我的做法是给 Agent 设一个合理的步数上限别让它无限循环同时在 issue 描述里把范围写清楚减少它到处乱翻的概率。这次任务改动只有一行但 Agent 读了三个文件才定位到说明定位阶段的 token 消耗往往比写补丁阶段还大。用统一通道的好处是这些消耗在控制台里能按 Key 对账跑完一批任务后你能清楚看到每条任务花了多少而不是一笔糊涂账。5. 用同一把 Key 复现对照表跑完这条任务后如果你想横向对比不同模型在同一个 issue 上的表现最省事的做法是保持 Base URL 和 Key 不变只改LLM_MODEL。同一把 Key、同一个 issue、同一套验证命令换模型重跑把每次的轮数、是否通过、补丁行数记下来就是一张属于你自己的对照表。对照表跑完后打开 模型对话 确认你用的模型 ID 与广场一致长期跑 Agent 任务可以看 Coding Plan。Key 在 控制台 创建Claude Code 与 CC Switch 的三件套写法对照 接入文档。想先确认这次评测调用有没有正常入账去控制台看用量明细即可想复现本文的对照表创建一把新 Key把LLM_BASE_URL指向https://taotoken.net/api从模型广场挑 ID 开跑。 告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度
返回列表