资讯动态

OpenHands 实战:TaoToken 跑通本地仓库的单测修复

发布时间:2026/9/18 11:57:37 来源:尧图企业网站定制
告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度1. 为什么用 OpenHands 修单测而不是让模型直接改文件OpenHands 是一个把「读仓库、跑命令、改文件、再跑测试」串成闭环的开源 Agent 运行时。它和纯对话式改代码最大的区别在于模型不直接给你一段 diff 让你自己贴而是先在工作区里执行pytest看到真实报错再定位到具体文件改完再跑一遍验证。这个闭环对「单测修复」这类任务特别合适因为失败信息本身就是最强的上下文。我这次要跑的任务很具体拿一个公开 Python 仓库人为制造一个失败的单测然后让 OpenHands 自己定位并提交修复 patch。模型 API 走 TaoTokenBase URL 是https://taotoken.net/api。选它当 OpenHands 的模型通道理由很实际OpenHands 对 OpenAI 兼容接口的支持最稳而 TaoToken 提供的就是统一 API 兼容通道Key 和 Base URL 一套配好换模型只改模型 ID不用动 OpenHands 的配置文件。需要先说清楚边界OpenHands 跑在本地容器或本地进程里它执行的是你自己仓库里的测试命令不是连到你的生产库上跑 SQL。模型只负责生成命令和 patch真正执行发生在你的工作区。这一点在 Agent 类工具里必须守住否则「让 AI 直接操作生产环境」就是事故。本文不含任何排行分数。我没有跑 SWE-bench Verified 全榜也没有摘录公榜快照下面所有数字都来自我这一次本地运行只代表一次运行不代表公榜。2. 环境准备OpenHands 装在哪、TaoToken Key 怎么拿2.1 OpenHands 的安装方式选择OpenHands 官方提供几种跑法Docker 镜像、pip 安装、以及从源码起。我选 Docker原因是它自带一个隔离的运行时沙箱Agent 在里面执行pytest、git、python都不会污染宿主机环境。对单测修复这种要反复跑命令的任务隔离环境能省掉很多「依赖装串了」的麻烦。docker pull docker.all-hands.dev/all-hands-ai/runtime:0.20-nikolaik docker pull docker.all-hands.dev/all-hands-ai/openhands:0.20版本号以你拉取时的实际 tag 为准我这里写的是当时用的 tag。如果你不想用 Dockerpip 方式也能起python -m venv openhands-env source openhands-env/bin/activate pip install openhands-aipip 方式下 OpenHands 会在当前目录起一个工作区Agent 的命令直接在你本机执行隔离性差一些跑之前确认仓库有 git 兜底改坏了能git checkout回来。2.2 从 TaoToken 拿 Key打开 TaoToken 官网注册后在控制台创建 API Key。Key 的占位符我统一写成YOUR_API_KEY你替换成自己那把。创建入口在 控制台 API Keys。模型 ID 不要凭记忆写。进模型广场看当前可用的 IDOpenHands 配置里填的就是广场上那个字符串。我这次用的模型 ID 以广场展示为准不同时间可选的模型会变写死一个「gpt-5」之类的名字当正式配置是错的。2.3 准备一个带失败单测的公开仓库我用的思路是clone 一个公开 Python 仓库然后在某个已有测试文件里改一行断言制造一个稳定可复现的失败。这样失败原因明确方便观察 OpenHands 能不能定位到。git clone https://github.com/psf/requests.git cd requests python -m venv .venv source .venv/bin/activate pip install -e .[dev] pytest tests/test_utils.py -x假设我在tests/test_utils.py里把某个断言从期望值改成了错误值pytest会报一条AssertionError指向具体行号。这就是交给 OpenHands 的起点。仓库选哪个不重要重要的是失败信息清晰、修复范围小。3. 把 TaoToken 接成 OpenHands 的模型 API3.1 OpenHands 的模型配置在哪OpenHands 的模型配置通过环境变量或config.toml传入。核心几个变量是LLM_MODEL、LLM_API_KEY、LLM_BASE_URL。OpenHands 用的是 LiteLLM 做底层适配所以只要 Base URL 是 OpenAI 兼容的它就能接。这里要区分清楚OpenHands 用的是LLM_*前缀不是 Claude Code 的ANTHROPIC_*也不是 Codex 的~/.codex/config.toml。三套配置别互相套用套错了就是 401 或模型找不到。3.2 启动命令Docker 方式启动把 TaoToken 的 Base URL 和 Key 传进去docker run -it --rm \ --pullalways \ -e SANDBOX_RUNTIME_CONTAINER_IMAGEdocker.all-hands.dev/all-hands-ai/runtime:0.20-nikolaik \ -e LOG_ALL_EVENTStrue \ -e LLM_MODELYOUR_MODEL_ID \ -e LLM_API_KEYYOUR_API_KEY \ -e LLM_BASE_URLhttps://taotoken.net/api \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands-state:/.openhands-state \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ docker.all-hands.dev/all-hands-ai/openhands:0.20注意LLM_BASE_URL写的是https://taotoken.net/api末尾不带/v1。OpenHands 底层 LiteLLM 会自己拼路径你多写一层/v1反而可能 404。这一点和直接 curl 调 OpenAI 接口的习惯不一样容易踩。pip 方式启动export LLM_MODELYOUR_MODEL_ID export LLM_API_KEYYOUR_API_KEY export LLM_BASE_URLhttps://taotoken.net/api openhands起来之后浏览器打开http://localhost:3000能看到 OpenHands 的对话界面。3.3 验证模型通道通不通在 OpenHands 界面里先发一条最简单的消息比如「列出当前工作区根目录的文件」。如果模型通道配对了它会返回一个ls之类的命令并执行。如果返回 401检查 Key 是不是复制时带了空格如果返回模型不存在回模型广场核对 ID如果返回 404检查 Base URL 是不是多写了/v1。这三个错误是 OpenHands 接兼容通道时最常见的排障顺序就按这个来。4. 让 OpenHands 定位失败单测并提交 patch4.1 任务描述怎么写OpenHands 的任务描述直接决定它会不会跑偏。我用的 prompt 是这样的当前仓库里有一个失败的单测。请执行以下步骤 1. 运行 pytest找到失败的那个测试用例和具体报错。 2. 定位到导致失败的源码或测试代码。 3. 提交一个最小修复只改必要的地方。 4. 重新运行该测试确认通过。 5. 用 git diff 输出你的 patch。 不要修改无关文件不要重构。关键约束是「最小修复」和「不要重构」。Agent 类工具在没有约束时容易顺手改一堆东西patch 一大就不好 review。单测修复这种任务理想 patch 就是几行。4.2 OpenHands 的执行过程OpenHands 接到任务后会先规划然后逐步执行。它第一步通常是pytest拿到失败输出。假设失败信息是FAILED tests/test_utils.py::test_to_key_val_list - AssertionError: assert a1 a:1它会读tests/test_utils.py和对应的源码文件判断是测试期望写错了还是源码实现错了。在我这次构造的场景里是测试断言被改错了所以正确修复是把断言改回期望值。OpenHands 会调用文件编辑工具改那一行然后重新跑pytest tests/test_utils.py::test_to_key_val_list看到 passed最后git diff输出 patch。4.3 拿到的 patch diff我这次运行拿到的 patch 大致是这样diff --git a/tests/test_utils.py b/tests/test_utils.py index 3f2a1b4..8c9d0e2 100644 --- a/tests/test_utils.py b/tests/test_utils.py -12,7 12,7 def test_to_key_val_list(): value to_key_val_list([(a, 1)]) - assert value a:1 assert value a1 assert to_key_val_list({a: 1}) a1一行改动测试从 fail 变 pass。这就是「最小修复」的样子。如果 OpenHands 给你的 patch 改了十几个文件说明 prompt 约束不够或者任务描述太模糊。4.4 验证 patch拿到 patch 后不要直接信。在本地手动应用再跑一遍git apply patch.diff pytest tests/test_utils.py -x确认全绿再决定要不要 commit。Agent 生成的 patch 必须经过你本地验证这是底线。模型说「已修复」不等于真的修复了只有测试通过才算。5. Token 消耗与上下文管理5.1 这次任务的 Token 大概花在哪单测修复任务的 Token 消耗主要在三块读失败输出、读相关源码文件、多轮工具调用的往返。OpenHands 每执行一个命令、每读一个文件都会把结果塞回上下文所以上下文增长比纯对话快得多。我这次任务范围小只涉及一个测试文件和一个源码文件整体往返轮数不多。如果你的仓库大、失败测试牵扯多个模块上下文会迅速膨胀这时候要么缩小任务范围要么在 OpenHands 里开上下文压缩。5.2 控制上下文膨胀的几个做法第一任务描述里明确「只修这一个测试」别让它去跑全量测试套件。全量测试的输出可能几千行全塞进上下文很浪费。第二失败信息先自己筛一遍。如果pytest输出很长你可以只把关键那段贴给 OpenHands而不是让它自己跑全量。第三模型选择上定位和改代码这类任务对模型能力有要求别用太小的模型硬扛。具体选哪个 ID 看模型广场按任务复杂度挑。5.3 用 TaoToken 看这次调用入账没有跑完任务后回 TaoToken 控制台 看用量记录。每次 OpenHands 的模型调用都会记一笔你能看到这次单测修复任务实际消耗了多少。对账的意义在于Agent 类任务的调用次数比对话多用量曲线能帮你判断任务是不是跑飞了。6. 排障OpenHands 接 TaoToken 时我遇到的坑6.1 Base URL 多写 /v1 导致 404最常见的一个。习惯性写成https://taotoken.net/api/v1结果 OpenHands 底层再拼一次路径变成/api/v1/v1/...直接 404。正确写法就是https://taotoken.net/api末尾不带/v1。6.2 模型 ID 写错导致模型不存在模型广场上的 ID 是唯一准绳。我见过有人把展示名当 ID 填进去报「model not found」。回广场复制那个字符串别自己拼。6.3 Docker 里访问不到宿主机仓库Docker 方式跑 OpenHands 时工作区在容器里。如果你想让 Agent 操作宿主机的仓库得把仓库目录挂载进去或者用 OpenHands 的工作区上传功能。挂载路径写错的话Agent 会在一个空目录里跑pytest报「no tests ran」。6.4 401 但 Key 是对的检查 Key 有没有多余空格或换行。复制粘贴时很容易带上。另外确认 Key 是从带 UTM 的官网创建的别用错环境的 Key。6.5 Agent 改了一堆无关文件这不是配置问题是 prompt 问题。在任务描述里加「只改必要文件不要重构不要动无关代码」。约束写清楚patch 就干净。7. 用同一把 Key 复现这次单测修复这次任务跑完如果你想自己复现一遍路径是这样的先在 TaoToken 官网 创建一把 Key然后按第 3 节的启动命令把LLM_BASE_URL设成https://taotoken.net/api模型 ID 从广场取。仓库随便挑一个公开 Python 项目人为改坏一个断言把第 4 节的 prompt 贴进 OpenHands看它能不能给出最小 patch。跑完回 模型对话 确认你用的模型 ID 和广场一致长期跑 Agent 任务可以看 Coding PlanKey 在 控制台 创建。Claude Code 或 CC Switch 的接入配置对照 接入文档。再强调一次边界OpenHands 执行命令发生在你的本地工作区模型只生成命令和 patch。生产库、生产机不要直接交给 Agent 执行让它生成 SQL 或命令你本地跑完把结果贴回去。这次单测修复任务全程在隔离环境里改坏了git checkout就能回退这是 Agent 类任务该有的安全姿势。 告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价