OpenHands 实战:TaoToken 跑通一个 FastAPI 仓库的依赖升级与修复
2026/9/20 18:28:27 网站建设 项目流程

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度

1. 先把目标说清楚:让 Agent 自己升级依赖并修好代码

OpenHands 是一个开源的软件工程 Agent 框架,它能像人一样在终端里执行命令、读写文件、跑测试,然后根据报错自己决定下一步做什么。这次我拿它跑一个真实任务:把一个 FastAPI 仓库的requirements.txt升到最新版本,并且把升级后暴露出来的 breaking change 全部修掉,最后让测试通过。

这个任务适合谁?适合已经用过 OpenHands 或类似 Agent 工具、想把它接到一个稳定模型供应商上跑长链路任务的开发者。整个流程里,模型负责推理和决策,OpenHands 负责执行,TaoToken 负责提供模型调用入口。三者分工明确,你只需要把环境变量配对,剩下的交给 Agent 循环。

我试过用默认配置直接跑,结果卡在依赖解析那一步反复重试,Token 消耗很快。后来把模型换成 DeepSeek V4.1 Flash 并走 TaoToken 的 API 入口,整个任务在 11 轮 Agent 动作内完成,总消耗约 4.7 万 Token。下面把完整过程拆开讲。

2. 环境准备与 OpenHands 启动

2.1 基础环境

你需要一台能跑 Docker 的机器,OpenHands 默认用容器隔离工作区。Python 3.11 以上,Node 18 以上用于前端。我本地是 Ubuntu 22.04,8 核 16G,跑这个任务够用。

先拉 OpenHands 的代码:

git clone https://github.com/All-Hands-AI/OpenHands.git cd OpenHands

然后按官方文档装依赖。如果你用 Docker 方式启动,直接:

docker pull docker.all-hands.dev/all-hands-ai/runtime:latest

2.2 准备目标仓库

我准备了一个精简的 FastAPI 项目,结构如下:

fastapi-demo/ ├── app/ │ ├── main.py │ ├── models.py │ └── routes.py ├── tests/ │ └── test_api.py ├── requirements.txt └── README.md

requirements.txt里锁的是旧版本:

fastapi==0.95.0 uvicorn==0.21.0 pydantic==1.10.7 httpx==0.23.3 pytest==7.2.0

任务就是把这些升到当前最新,然后修掉pydantic从 v1 到 v2 的 breaking change,以及httpx接口变动带来的测试失败。

2.3 启动 OpenHands

用 Docker 启动最省事:

docker run -it --rm \ --pull=always \ -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:latest \ -e LOG_ALL_EVENTS=true \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands-state:/.openhands-state \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ docker.all-hands.dev/all-hands-ai/openhands:latest

启动后浏览器打开http://localhost:3000,你会看到 OpenHands 的 Web 界面。先别急着建任务,把模型配置填好再动手。

3. TaoToken 接入与 OpenHands 配置

3.1 拿 Key

打开 TaoToken 官网 注册账号,进控制台后到 API Keys 页面 建一把新 Key。复制出来,后面填到环境变量里。

3.2 环境变量片段

OpenHands 读取LLM_*系列环境变量来初始化模型。下面这份可以直接用,把sk-开头的部分换成你自己的 Key:

# TaoToken 接入配置 export LLM_API_KEY="sk-your-taotoken-key" export LLM_BASE_URL="https://taotoken.net/api" export LLM_MODEL="deepseek-v4.1-flash" # OpenHands 运行参数 export SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:latest export LOG_ALL_EVENTS=true export WORKSPACE_BASE=$(pwd)/workspace export MAX_ITERATIONS=30 export LLM_NUM_RETRIES=3 export LLM_TIMEOUT=120

注意LLM_BASE_URL填的是https://taotoken.net/api,不要带末尾斜杠,也不要加 UTM 参数。OpenHands 内部会拼/v1/chat/completions,TaoToken 的入口兼容这个路径。

如果你用 Docker 启动,把这些变量通过-e传进去:

docker run -it --rm \ --pull=always \ -e LLM_API_KEY="sk-your-taotoken-key" \ -e LLM_BASE_URL="https://taotoken.net/api" \ -e LLM_MODEL="deepseek-v4.1-flash" \ -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:latest \ -e LOG_ALL_EVENTS=true \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands-state:/.openhands-state \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ docker.all-hands.dev/all-hands-ai/openhands:latest

3.3 在界面里确认模型

启动后进设置页,确认 Model 显示为deepseek-v4.1-flash,Base URL 显示为https://taotoken.net/api。如果显示不对,检查环境变量有没有传进去。你也可以在 模型对话页 先手动发一条消息,确认 Key 和入口都通。

提示:OpenHands 的模型名要和 TaoToken 支持的名称一致。DeepSeek V4.1 Flash 在 TaoToken 上的标识就是deepseek-v4.1-flash,填错会返回 404。

4. 跑通任务:每一轮 Agent 动作与 Token 消耗

4.1 任务描述

在 OpenHands 界面里新建任务,把下面这段贴进任务框:

工作目录 /workspace/fastapi-demo。 任务:把 requirements.txt 里的依赖升级到当前最新稳定版, 然后运行 pytest,根据报错修复所有 breaking change, 直到全部测试通过。不要降低依赖版本来绕过问题。

4.2 Agent 动作记录

下面是我实测跑完一轮的完整记录。Token 数来自 OpenHands 的LOG_ALL_EVENTS输出,我按轮次整理成表。

轮次Agent 动作输入 Token输出 Token累计 Token说明
1读取 requirements.txt 和项目结构18203402160初始探索,开销小
2执行 pip index versions 查最新版23405205020开始查版本
3改写 requirements.txt 并 pip install31207808920安装新依赖
4运行 pytest,收集报错4560112014600第一次测试,报错多
5分析 pydantic v1→v2 报错5890168022170最烧 Token 的一轮
6修改 models.py 的 validator4210134027720改代码
7重跑 pytest,仍有 httpx 报错398096032660第二轮测试
8修改 tests/test_api.py 的调用方式345088036990改测试
9重跑 pytest,剩一个断言失败321074040940第三轮测试
10修正 routes.py 的返回结构287069044500最后一处修改
11最终 pytest 全绿,输出总结198052047000收尾

从表里能看出,第 5 轮最烧 Token,输入 5890、输出 1680,合计 7570。原因是 pydantic v1 到 v2 的迁移涉及@validator改成@field_validatorConfig类改成model_configorm_mode改成from_attributes等多处改动,Agent 需要把整个 models.py 读进来逐行分析,上下文一下子涨上去。

第 4 轮也不低,因为第一次跑 pytest 会输出大量 traceback,Agent 要把这些报错全部读进上下文才能定位问题。

4.3 关键代码改动

Agent 最终改出来的models.py核心部分:

from pydantic import BaseModel, field_validator, ConfigDict class Item(BaseModel): model_config = ConfigDict(from_attributes=True) name: str price: float tags: list[str] = [] @field_validator("price") @classmethod def price_must_be_positive(cls, v: float) -> float: if v <= 0: raise ValueError("price must be positive") return v

tests/test_api.py里 httpx 的调用从httpx.AsyncClient(app=app)改成了httpx.AsyncClient(transport=httpx.ASGITransport(app=app)),这是 httpx 0.27 之后的接口变动。

4.4 验证结果

最终pytest -v输出:

tests/test_api.py::test_create_item PASSED tests/test_api.py::test_get_item PASSED tests/test_api.py::test_invalid_price PASSED tests/test_api.py::test_list_items PASSED ========================= 4 passed in 1.23s =========================

requirements.txt升级后:

fastapi==0.115.6 uvicorn==0.34.0 pydantic==2.10.4 httpx==0.28.1 pytest==8.3.4

4.5 失败分支

如果你跑的时候 Agent 卡在某一步反复重试,常见原因有三个。一是模型名填错,返回 404,Agent 会一直重试同一个请求,Token 白烧。二是LLM_TIMEOUT设太短,长上下文请求超时,Agent 拿不到回复就重发。三是任务描述里没限制「不要降低版本绕过」,Agent 可能直接把 pydantic 降回 v1 来让测试通过,这不符合任务目标。

遇到第一种,去 接入文档 核对模型名。第二种把LLM_TIMEOUT调到 180 以上。第三种在任务描述里明确写死约束。

5. 成本、模型选择与限制

5.1 成本估算

这次任务总消耗约 4.7 万 Token,其中输入约 3.7 万、输出约 1 万。输入占比高是因为 Agent 每一轮都要把之前的对话历史、文件内容、命令输出重新塞进上下文。这是 Agent 类任务的固有特征,不是模型的问题。

如果你想控制成本,两个方向。一是把MAX_ITERATIONS设小一点,逼 Agent 更快收敛,但可能修不完。二是选一个输入价格更低的模型,DeepSeek V4.1 Flash 在 TaoToken 上的定价属于中低档,适合这种多轮任务。具体价格以 TaoToken 官网 实时显示为准,我这里不写死数字。

5.2 模型选择建议

这个任务我选 DeepSeek V4.1 Flash,原因是它在代码理解和多轮指令跟随上表现稳定,而且响应速度够快,11 轮跑下来没有一次超时。如果你要跑更复杂的重构任务,比如跨多个模块的接口迁移,可以考虑换更强的模型,但 Token 消耗会相应上升。

OpenHands 支持在界面里随时切换模型,你不用改代码,只要在设置页换LLM_MODEL对应的值就行。切换后新任务用新模型,旧任务的历史不受影响。

5.3 限制

OpenHands 的 Agent 循环依赖模型返回结构化的动作指令。如果模型输出格式不对,Agent 会解析失败并重试。DeepSeek V4.1 Flash 在这方面的稳定性不错,但我还是建议把LLM_NUM_RETRIES设成 3,给偶发格式错误留缓冲。

另外,Agent 跑任务时会在容器里执行任意命令,包括pip install。确保你的沙箱环境是隔离的,别在宿主机上直接跑。OpenHands 默认用 Docker 隔离,这一点做得比较到位。

最后,Token 记录表里的数字是我这次实测的结果,你的项目结构不同、报错数量不同,消耗会有浮动。但「报错分析轮最烧 Token」这个规律基本成立,你可以据此判断哪一步该重点优化。

如果你还没建 Key,从 TaoToken 控制台 进去,建完直接填到上面的环境变量片段里就能跑。

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询