资讯动态

OpenHands 实战:TaoToken 跑通仓库级 Python 类型标注修复

发布时间:2026/9/20 22:27:24 来源:尧图企业网站定制
告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度1. 让 OpenHands 自己修 mypy 报错这件事比想象中省心OpenHands 是一个开源的软件工程 Agent能读写仓库文件、跑命令、看报错、再改代码适合把「仓库级」的重复劳动交给它。这次我拿一个带 mypy 报错的 Python CLI 小仓库做实验让它自动补类型标注、把 CI 里的类型检查跑绿。模型选 Kimi K2.7 Code接入走 TaoTokenbase_url 填https://taotoken.net/api。适合谁手上有中小型 Python 仓库、CI 卡在 mypy、又不想一条条手改标注的人。整条链路是拿 Key → 配 OpenHands → 给 Agent 下任务 → 看它改文件跑命令 → 验证 mypy 输出。下面把可复现的配置、命令和前后输出都摊开。2. 准备仓库与复现 mypy 报错先造一个最小可复现的 CLI 仓库。用 click 写两个子命令故意留类型问题函数没标注、返回值类型对不上、可选参数没处理 None。mkdir -p demo-cli/demo_cli cd demo-cli python -m venv .venv source .venv/bin/activate pip install click mypy目录结构demo-cli/ ├── demo_cli/ │ ├── __init__.py │ └── main.py ├── pyproject.toml └── .github/workflows/ci.ymldemo_cli/main.py故意写成有问题的版本import click def add(a, b): return a b def greet(nameNone): return Hello, name click.group() def cli(): pass cli.command() click.option(--a, typeint, requiredTrue) click.option(--b, typeint, requiredTrue) def add_cmd(a, b): click.echo(add(a, b)) cli.command() click.option(--name, defaultNone) def hello(name): click.echo(greet(name)) if __name__ __main__: cli()pyproject.toml里加上 mypy 配置方便 CI 直接调用[tool.mypy] python_version 3.11 strict true warn_unused_ignores true跑一次 mypy拿到「修复前」的基线输出mypy demo_cli典型报错会是这样版本不同行号略有差异demo_cli/main.py:4: error: Function is missing a type annotation [no-untyped-def] demo_cli/main.py:8: error: Function is missing a type annotation [no-untyped-def] demo_cli/main.py:9: error: Unsupported operand types for (str and None) [operator] demo_cli/main.py:13: error: Function is missing a type annotation [no-untyped-def] demo_cli/main.py:21: error: Function is missing a type annotation [no-untyped-def] demo_cli/main.py:26: error: Function is missing a type annotation [no-untyped-def] Found 6 errors in 1 file (checked 1 source file)CI 文件里加一步mypy demo_cli这样 Agent 改完能直接看 CI 是否通过name: ci on: [push, pull_request] jobs: typecheck: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-pythonv5 with: python-version: 3.11 - run: pip install click mypy - run: mypy demo_cli到这一步仓库和报错都齐了接下来把 OpenHands 接上模型。3. 拿 Key 并配置 OpenHands 的 LLM先去 TaoToken 官网拿 Key打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_generateutm_content 注册后在控制台创建 API Key。控制台入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_generateutm_campaigngenerate Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_generateutm_campaigngenerate 。拿到的 Key 形如sk-...先存到环境变量别写进仓库export TAOTOKEN_API_KEYsk-你的keyOpenHands 的 LLM 配置写在config.toml。关键点是把base_url指向https://taotoken.net/api模型名填 Kimi K2.7 Code 对应的标识。下面是我实测能跑通的配置[core] workspace_base ./workspace max_iterations 30 [llm] model kimi-k2.7-code api_key sk-你的key base_url https://taotoken.net/api temperature 0.2 max_output_tokens 8192如果你不想把 Key 明文写进文件OpenHands 支持从环境变量读把api_key那行换成引用即可具体字段名以你本地 OpenHands 版本的文档为准。配置好后先做一次连通性检查避免后面 Agent 跑到一半才发现鉴权失败curl -s https://taotoken.net/api/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 400返回里能看到模型列表就说明 Key 和 base_url 都对。若返回 401多半是 Key 复制时带了空格或已失效返回 404检查 base_url 是否误写成带路径的地址。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_generateutm_campaigngenerate 字段有疑问时对照一下。4. 让 Agent 跑仓库级类型修复OpenHands 的启动方式按你安装的版本走命令行入口一般是openhands。把工作目录指到仓库根让它能读写demo_clicd demo-cli openhands --config ../config.toml进入交互后把任务描述清楚。仓库级修复最怕指令含糊我用的提示词是这样的仓库根目录是当前目录。任务 1. 运行 mypy demo_cli记录所有报错。 2. 为 demo_cli/main.py 中所有函数补全类型标注保持 click 命令行为不变。 3. 修复 greet 在 name 为 None 时的类型错误不要改变默认输出语义。 4. 每改完一轮重新运行 mypy demo_cli直到 0 error。 5. 最后把 mypy 的最终输出贴出来。Agent 会自己执行命令、读报错、改文件。它改完main.py后大致长这样from typing import Optional import click def add(a: int, b: int) - int: return a b def greet(name: Optional[str] None) - str: if name is None: return Hello, stranger return Hello, name click.group() def cli() - None: pass cli.command() click.option(--a, typeint, requiredTrue) click.option(--b, typeint, requiredTrue) def add_cmd(a: int, b: int) - None: click.echo(add(a, b)) cli.command() click.option(--name, defaultNone) def hello(name: Optional[str]) - None: click.echo(greet(name)) if __name__ __main__: cli()注意greet的语义被显式定义了name为 None 时返回Hello, stranger。这是 Agent 在「不改变默认输出语义」约束下做的合理选择但你要在 review 时确认这符合预期。如果原逻辑其实不该有 None 分支应该在提示词里写清楚比如「name 为 None 时抛 ValueError」。跑完后 mypy 输出变成Success: no issues found in 1 source fileCI 里的mypy demo_cli这一步也就绿了。整个过程 Agent 大概迭代了 3 到 5 轮取决于报错数量和模型对 click 装饰器的理解。5. 验证结果与失败分支验证分三层。第一层本地 mypy 零报错上面已经看到。第二层跑一遍 CLI 确认行为没坏python -m demo_cli.main add --a 2 --b 3 python -m demo_cli.main hello --name Tao python -m demo_cli.main hello前两条分别输出5和Hello, Tao第三条输出Hello, stranger。第三层把改动推到分支触发 CI看 typecheck job 是否通过。失败分支要提前想好。如果 Agent 反复改不对常见原因是提示词没限定「不改变行为」它会顺手重构这时把约束写死或者先让它只补标注、不动逻辑。如果 mypy 报的是第三方库缺 stubAgent 可能去装types-*包你要确认这不会污染依赖必要时在提示词里禁止改pyproject.toml的依赖段。如果模型在长仓库里上下文吃紧把任务拆成「先修 main.py再修 utils.py」一次只喂一个文件范围。还有一种情况是 Agent 改了文件但没重跑 mypy 就宣布完成这时你手动跑一次mypy demo_cli就能戳破。6. 成本、模型选择与边界成本主要看 token 消耗。仓库级修复的输入包含文件内容和多轮命令输出输出是补丁和命令Kimi K2.7 Code 这类偏代码的模型在补丁生成上比较稳。具体单价和计费方式以 TaoToken 官网为准别拿别处的报价套。模型选择上纯类型标注修复对推理要求不算高代码模型够用如果仓库里有复杂泛型和协议换更强的推理模型可能更省迭代轮次但单价也更高按仓库规模权衡。限制也说清楚。OpenHands 能改文件、跑命令但它不理解你的业务语义greet的 None 分支就是例子最终 review 必须人工过一遍。mypy strict 模式下有些报错需要引入TypeVar或ProtocolAgent 未必一次写对可能要你给个示例。CI 环境里的 Python 版本、依赖版本要和本地一致否则本地绿了 CI 红。最后Key 别提交进仓库用环境变量或密钥管理config.toml里如果写了明文 Key记得加进.gitignore。 告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度

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

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

免费获取报价