@adithya_s_k: https://x.com/adithya_s_k/status/2054961319179420035

X AI KOLs Timeline 新闻

摘要

分析为什么强化学习在编程任务中因可验证奖励而受到青睐,以及新兴框架Harbor如何解决RL训练中环境复杂度的瓶颈。

https://t.co/tOnb7uElhs
查看原文
查看缓存全文

缓存时间: 2026/05/15 08:59

RL 编程环境 101:为什么 Harbor 存在

将编程作为 RL 任务正在兴起。如果你真的尝试过在编程任务上做 RL,你早就知道模型是最简单的部分。模型周围的一切才是消耗你一周时间的真正元凶。

免责声明:我使用了 Claude Code 和 Claude Opus 来帮助我整理这篇文章,但我已经在多个项目中广泛使用了 Harbor,并且认为现在是时候写下为什么我认为它是 RL 编程环境领域的正确抽象/框架了。

你需要一个真正的环境。正确的工具链、正确的系统库、锁定依赖、如果需要的话还有 GPU 驱动、以及在 rollout 之间重置状态的方法。你需要选择一个编程框架。Claude Code?Aider?OpenHands?还是你自己用 bash 和编辑器搭的脚手架?你需要初始化点。你从哪个提交开始,起始提示是什么,agent 首先看到哪些文件?你还需要一个你真正可以信任的奖励。运行测试、评分 diff、让裁判评判,或者以上所有。每一个决策都是一个兔子洞。而其中大部分会在有人发布新的编程基准或 RL 方案时被从头重新发明。

这篇博客将说明为什么这种做法不可持续,以及为什么答案的形式开始看起来像一个叫做 Harbor 的框架。

代码上的 RL 正在获胜,因为奖励大多是可验证的

过去 18 个月里代码大语言模型(LLM)的模式很难忽视。每个人都转向了同一个想法:别再假装预训练就够了,要针对能编译和运行的信号进行训练。每个前沿实验室现在都在使用某种形式的带可验证奖励的强化学习(RLVR)进行后训练,而代码是其中最干净的领域。pytest 不会说谎。

一个非详尽的参与者列表:

  • Meta 的 SWE-RL 使用基于规则的奖励(diff 与真实 PR 补丁的相似度)在数百万个合并的拉取请求上训练了 Llama3-SWE-RL-70B。它在 SWE-bench Verified 上达到了 41%,在当时是 sub-100B 模型中的最佳表现,并且即使在训练 100% 是代码的情况下,它能泛化到数学和语言推理。
  • OpenAI 的 Codex (codex-1) 是 o3 的一个版本,使用 RL 在多个环境中的真实编程任务上进行训练,“迭代运行测试直到通过”。o3 本身通过这种训练在 SWE-bench Verified 上从 48.9% 跃升至 71.7%(相较于 o1)。
  • DeepSeek-R1(Nature, 2025)表明你可以仅使用 RL 和可验证奖励获得推理能力,无需 SFT 预热。他们使用了 GRPO,并明确使用 LeetCode 问题上的编译器反馈作为信号。
  • Moonshot 的 Kimi K2(技术报告)引入了一个“类似 Gym 的可扩展框架”,用于在不同编程场景中扩展 RL。仅使用 bash/编辑器框架就在 SWE-bench Verified 上达到 65.8%。
  • Qwen3-Coder-Next(报告)明确表示:“大规模合成可验证的编程任务并搭配可执行环境”是核心训练进展,而不是模型架构。
  • Prime Intellect 的 INTELLECT-3 是一个 100B+ 的 MoE,使用大规模 RL 在数千个社区贡献的环境上训练。
  • Anthropic 的 Claude 4.x 系列在代码方面非常著名。公开训练细节较少,但据说 Anthropic 计划在 2026 年将 RL 环境投入增加 3 到 5 倍。

这个论点现在已成为共识:编程特别适合 RL,因为奖励是可验证的。你可以运行代码并检查。不需要奖励模型,不需要人工标注的偏好,没有漂移。正如 Sebastian Raschka 总结的那样,这就是为什么过去一年每一篇推理模型论文读起来都像同一篇论文。

新的瓶颈不是模型,而是环境

这里有一个没人警告过你的陷阱。一旦你决定使用带可验证奖励的 RL,你的训练运行的好坏取决于你能启动的环境的质量。环境很难搞。

@PrimeIntellect 环境中心公告直言不讳:

“当前的环境生态系统是碎片化的。实现通常与特定的训练堆栈紧密耦合,使得它们难以适应、重用或共享……如果没有强大的开放替代方案,开放模型可能会落后,使用户依赖那些能力由不可访问工具塑造的闭源模型。”

Prime Intellect(发布了拥有 1000 多个开源 RL 环境的环境中心)也持同样的看法。扩展 RL 的路径不是更大的模型,而是更多、更便宜、更多样化的环境。Wing Venture 的分析直接指出:“验证,而不是模型,才是自动化的真正瓶颈。” MiniMax 的 Forge 框架在 10 万多个不同的 agent 框架和环境上运行 RL 训练,每日吞吐量达到数百万样本。这不是模型问题,而是基础设施问题。

如果你想更深入了解 RL 环境是什么,请参考这篇名为《RL 环境终极指南》的文章。

而问题的形态总是一样的。每个编程环境都需要三样东西:

  • 一个冻结的状态或快照。 一个特定的提交、一个代码库、一个数据集,或任何任务可以开始的固定位置,依赖被锁定。
  • 一种运行方式。 一个带有正确 Python/Node/Go 工具链、系统库、如果需要的话有 GPU 驱动的 Docker 镜像。
  • 一种评分 agent 输出的方式。 测试、diff 比较、裁判模型、自定义验证器。

世界上的每一个基准团队都从零重建了这个堆栈。SWE-bench 有自己的框架。R2E 有自己的。Magicoder 有自己的。结果就是 HF 所谓的“碎片化”:agent 无法在基准之间移动,数据集无法组合,每个实验室都在他们宁愿不拥有的管道工作上浪费数月时间。

这就是 Harbor

Harbor 是一个来自 Terminal-Bench 团队的编程环境框架。它与 Terminal-Bench 2.0 一起由 @Mike_A_Merrill 和 @alexgshaw 发布,他们对于为什么构建它的表述是我见过的最清晰的问题阐述:

“在容器中进行评估速度慢且难以扩展……通过训练和优化方法改进 agent 的能力有限……agent 框架和基准之间的碎片化要求每个部署都有专门的解决方案。”

Harbor 是 Terminal-Bench 自身痛点催生出的框架。作者自己的任务差异文档指出了具体的修复:指令以 markdown 而非嵌套的 YAML 存在,任务配置是类型化的(Pydantic),环境定义是强制性的且可插拔,解决方案可以是多文件的,并且(关键的是)奖励由任务产生,而不是由框架解析。最后这一点很重要。它让 Harbor 能够在不改变框架本身的情况下,支持非二元奖励、裁判评分和多标准评估。

Harbor 给出的答案是一个极简的、有主见的标准。一个任务是一个目录,一个目录有四个文件,任何能在容器中运行的 agent 都能运行任何任务。这个接口小到你一个下午就能学会,但结构足够丰富,你可以在此基础上构建严肃的训练基础设施。

我想在本文剩余部分深入探讨这一点,因为我认为 Harbor 选择的抽象正是正确的。它提供了足够的结构来实现互操作,同时不剥夺你在需要时做非常规事情的自由。

任务:四个文件,一个契约

一个 Harbor 任务在磁盘上看起来像这样:

hello-world/
├── instruction.md          # agent 应该做什么,用英文
├── task.toml               # 类型化配置:超时、资源、元数据
├── environment/
│   └── Dockerfile          # (或 docker-compose.yaml 用于多容器)
├── solution/
│   └── solve.sh            # 可选的参考解决方案
└── tests/
    └── test.sh             # 验证器:将奖励写入 /logs/verifier/

每个文件恰好回答一个问题。这就是为什么它是一个好的抽象。

  • environment/Dockerfile 回答了如何运行这个任务?
  • instruction.md 回答了 agent 应该做什么?
  • tests/test.sh 回答了如何知道它成功了?
  • task.toml 回答了这是谁构建的,为了什么,有什么限制?

它是一个真正的类型化模式,而不是自由格式的配置,包含 CPU/内存/GPU 部分、互联网白名单、暴露给 agent 的 MCP 服务器、容器健康检查和验证器 API 密钥。

一个简单的验证器就是一个写入数字的 bash 脚本:

#!/bin/bash
OUTPUT=$(python /workspace/hello.py 2>&1)
if [ "$OUTPUT" = "Hello, World!" ]; then
    echo "1" > /logs/verifier/reward.txt
else
    echo "0" > /logs/verifier/reward.txt
fi

对于多指标奖励,你可以写入 reward.json(例如 {"correctness": 0.75, "structure": 1.0}),Harbor 会处理聚合。在任何情况下,奖励只是已知位置的数字。这种统一性就是整个诀窍。

对于单次不够的任务,Harbor 支持多步骤任务。用 steps/ 目录替换 instruction.mdtests/,并在 task.toml 中声明它们。每步奖励通过 MEANFINAL 策略聚合,可选的 min_reward 阈值可以在某一步失败时提前终止试验。

自带你的 agent 框架

Harbor 开箱即提供 26 个内置 agent 适配器:Claude Code、Codex CLI、OpenHands、Gemini CLI、Aider、Goose、Cursor CLI、Cline CLI、Copilot CLI、OpenCode、Qwen Coder、Kimi CLI、Mini-SWE-Agent、SWE-Agent、Trae Agent(字节跳动)、Rovodev(Atlassian)、NeMo Agent(NVIDIA),以及 Harbor 自己的 Terminus-2 参考 agent 和一个用于运行 solution/solve.sh 进行健全性检查的 oracle 适配器。(来源列表)

但 Harbor 所做的最被低估的事情是将任务与 agent 框架解耦。自定义框架的契约非常小。继承 BaseAgent,实现 setup()run(),使用 --agent-import-path your.module:YourAgent 运行。这就是整个 API。只要你能在容器中安装一个二进制文件,你就有了一个 Harbor 框架。你自己的 bash 加文件编辑器的脚手架、你的自定义多 agent 系统、某人的研究原型,都一样。

反过来也一样重要。你写的任何任务都可以搭配任何 agent。用一个框架训练你的模型,用另一个进行评估,再用第三个部署。任务不知道也不关心。这就是 agent 框架的 USB-C。

超越通过/失败的奖励

奖励契约(/logs/verifier/reward.{txt,json} 中的数字)故意做得很薄。任何你能在容器内计算的东西,你都可以写成奖励。Harbor 通过一流支持来充分利用这一点:

  • 测试执行奖励。 经典情况:运行 pytest/cargo/jest,写入 1.0 或 0.0。
  • Diff 相似度。 写入 agent diff 与 oracle 之间的序列相似度,为部分修复给予部分分数(SWE-RL 方案)。
  • LLM 作为裁判。 验证器调用一个裁判模型,得到 0 到 1 的分数。API 密钥通过 task.toml 中清晰的 [verifier.env] 块传入,因此同一个任务可以由 Claude、GPT-5 等评分。仓库附带一个工作示例:一个“写一首搞笑诗”的任务,由 Claude 使用 JSON 模式评分配置进行评分。
  • 步骤级奖励。 多步骤任务为每步发出 verifier_results,通过 MEANFINAL 聚合。
  • 奖励工具包(Reward Kit)。 Harbor 还发布了 harbor-rewardkit,一个单独的包,包含 20 多个内置原语(file_existscommand_succeeds 等),以及 TOML 定义的 LLM 裁判和 agent 作为裁判的评分配置。agent 裁判在 overlayfs 隔离的工作空间副本中运行,因此它们可以探索和运行命令而不会相互污染。聚合支持加权平均、全部通过、任意通过、阈值。

一行 test.sh

uvx --with [email protected] rewardkit /tests

关键在于 Harbor 不是内置了所有奖励类型,而是奖励契约非常薄,你可以在不接触框架的情况下实现任何奖励,并且框架为常见情况提供了开箱即用的工具。这是正确的抽象级别。

统一的输出规范:ATIF

Harbor 做的另一个常被忽视的事情是:它让每个 agent 的输出看起来都一样。这种格式有一个名字:ATIF,即 Agent 轨迹交换格式(Agent Trajectory Interchange Format),以 RFC-0001(当前 v1.7)维护。

无论你运行的是 Claude Code、OpenHands、Codex、Mini-SWE-Agent、Gemini CLI 还是你自己的自建脚手架,Harbor 的适配器都会将轨迹转换为统一的 JSON 形状。逐步骤记录包含 sourcemodel_namemessagereasoning_contenttool_callsobservation,以及包含 token 数量、缓存 token 和美元成本的指标块。根级元数据涵盖会话 ID、agent 身份和最终聚合指标。

为什么这很重要?因为一旦你的轨迹统一了,它们就是训练数据。ATIF 的作者明确指出了这一点:

  • v1.3 添加了 completion_token_ids “以实现无需重新分词漂移的 RL 训练”
  • v1.4 出于同样原因添加了 prompt_token_ids
  • v1.5 为 SFT 流水线添加了 tool_definitions

你可以反向阅读这个版本历史,看作 Harbor 在公开场合逐步弄清楚 RL 流水线真正需要从轨迹格式中得到什么。结果是一个可以作为一流训练输入的 JSON 规范。Harbor 有专门的 SFT 和 RL 工作流文档,并提供了一个 SkyRL 集成,其中 rollout 接口直接返回 Rollout(reward=..., token_ids=..., mask_ids=...),直接来自 Harbor 的一次试验。

这就构成了完整的闭环。相同的任务规范 → 相同的执行沙箱 → 相同的奖励信号 → 相同的轨迹格式 → 可训练。你可以并行在五个不同的 agent 框架上运行数千次 rollout,将它们倒入同一个桶中,然后直接送入后训练。无需重塑数据,无需胶水代码。没有其他人能把这四件事都做对。

入门指南

最小的端到端循环:

# 安装 uv
tool install harbor

# 使用 Claude Code 运行真实基准,4 个并行容器
export ANTHROPIC_API_KEY=
harbor run \
  --dataset [email protected] \
  --agent claude-code \
  --model anthropic/claude-opus-4-1 \
  --n-concurrent 4

或者使用 oracle 在本地运行单个任务,以确认你的验证器没问题:

uv run harbor run --agent oracle --path ./tasks/hello-world
# Mean: 1.000 ✓

想在 Modal 或 Daytona 上运行?添加 --env modal--env daytona,你就能在云端拥有上千个并行容器。Harbor 支持 10 多个沙箱后端,只需一个标志:Local Docker、Daytona、Modal、E2B、Runloop、Apple Container、GKE、Tensorlake、Islo、Singularity。相同的任务规范,相同的奖励信号,相同的轨迹输出。

之后用 harbor view 检查所有内容,这是一个本地 Web UI,可以渲染轨迹、每个标准的奖励分解以及收集的工件。

如果你不想从头写任务,Harbor 已经提供 50 多个基准适配器:SWE-Bench 系列、Aider Polyglot、LiveCodeBench、GAIA、BFCL、MedAgentBench、ML-Dev-Bench 等等。每个主要的编程/agent 基准,都被归一化到相同的 harbor run 流程。

这就是全部要点。

为什么现在这很重要

未来一年前沿编程模型的工作将主要由谁能最快地搭建最多的环境、具备最高的验证保真度所主导。瓶颈是共享基础设施,而我们没有时间一直重建它。

Harbor 是那种不输的共享基础设施的最简版本。四个文件,任何 agent,10 多个沙箱,统一的可训练轨迹。如果你曾经重复搭建过相同的评估脚手架两次,这就是选择它的理由。

来源:

  • 实验室 RL 工作:SWE-RL · Codex/o3 · DeepSeek-R1 · Kimi K2 · Qwen3-Coder-Next · INTELLECT-3
  • 环境讨论:HF Environments Hub 博客 · Prime Intellect 环境 · Wing VC 分析 · Sebastian Raschka,RL 现状 · RL 环境终极指南
  • Harbor:GitHub · 文档 · Terminal-Bench 2.0 公告 · ATIF (RFC-0001) · LLM 作为裁判教程 · Reward Kit 示例 · 多步骤任务 · Tessl 介绍

PS:如果你发现任何事实上不准确的地方,请告诉我。反馈和建议总是受欢迎的。谢谢!

相似文章