首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何把 CubeSandbox 放进 veRL 训练链路

如何把 CubeSandbox 放进 veRL 训练链路

作者头像
anzhsoft
发布2026-07-13 11:13:32
发布2026-07-13 11:13:32
1380
举报

对 coding agent 来说,环境不是背景板。它要么参与 reward,要么参与 rollout;接在哪一层,训练出来的能力就不同。 第2篇把CubeSandbox放进veRL训练链路:接在reward里只是最终评分,接进AgentLoop才会改变轨迹。文章拆清两条路径、response_mask边界和GPU/ Sandbox集群拆分,帮你看懂coding agent RL如何落地

上一篇:腾讯开源 CubeSandbox:当 AI 开始替你动手,Sandbox 就不再是可选项,从 AI Agent 进入办公和研发场景讲起,解释了 CubeSandbox 为什么不是“更快的 Docker”,而更像 AI Agent 的环境执行层。本文继续回答下一个问题:这个环境层怎么进入 veRL 训练?

先给新读者补三个概念:

  • rollout:模型根据 prompt 生成回答或动作的过程。普通 RLHF 里它通常是一次文本生成;agent RL 里它可能包含多轮工具调用。
  • reward:训练系统给这条输出打分。代码任务里,reward 往往来自真实执行,比如 patch 能否应用、测试是否通过。
  • AgentLoop:让模型、工具和环境多轮交互的循环。模型输出动作,环境返回 observation,模型再继续下一步。

本文的核心判断是:CubeSandbox 可以通过两条路径进入 veRL。第一条是 reward-only:模型生成最终答案,reward function 创建 sandbox 执行测试。第二条是 AgentLoop:模型在 rollout 中反复操作 sandbox,环境 observation 进入上下文,但 observation token 不能参与 policy loss。这两条路径解决的问题不同,不能混在一起讲。

1. 最小接法:只在 reward 阶段使用 CubeSandbox

先看最容易落地的方式:rollout 阶段仍然让模型一次性生成答案,CubeSandbox 只在评分阶段出现。读图时注意,sandbox 不改变模型生成过程,它只负责验证最终输出。

veRL 自定义 Reward 接入 CubeSandbox

这个路径适合 patch generation、代码题、SQL 题、脚本题等任务。模型输出最终代码或 patch;reward function 创建 sandbox,把答案写进去,执行测试,然后返回分数和 metadata。

veRL 文档说明,自定义 reward function 可以放在独立文件里,并通过 custom_reward_function.pathcustom_reward_function.name指定;函数参数包括 data_sourcesolution_strground_truthextra_infodocs/preparation/reward_function.rst:55-70)。配置里也有对应字段:reward.custom_reward_function.pathnameverl/trainer/config/reward/reward.yaml:7-13)。

把 CubeSandbox 接进来时,逻辑可以压成五步:

代码语言:javascript
复制
solution_str
-> create sandbox from template_id
-> write patch or code
-> run tests in sandbox
-> return score + structured metadata

这个方式的优点是侵入小。veRL 不需要先理解“代码环境”是什么,reward function 自己把真实执行包起来。缺点也很清楚:模型在生成最终 patch 前看不到 pytest输出、文件内容和命令反馈,因此训练出来的更像“一次性解题模型”,不是会探索仓库的 coding agent。

2. 真正的 coding agent:在 AgentLoop 中使用 sandbox

如果目标是训练能自己读文件、跑测试、根据错误继续修改的 agent,sandbox 就不能只出现在最后评分。它必须进入 rollout。

下面这张图展示 AgentLoop 接入 sandbox 的路径。读图时注意,环境 observation 会被追加回上下文,下一轮模型生成会看到这些 observation。

veRL Agent Loop 接入 CubeSandbox

veRL 的 AgentLoopOutput不是一段字符串,而是一组 token 级字段:prompt_idsresponse_idsresponse_mask、logprobs、reward、turn 数和 extra fields。源码注释明确写着,response_ids包含 LLM generated token 和 tool response token;response_mask对模型生成 token 是 1,对工具响应 token 是 0(verl/experimental/agent_loop/agent_loop.py:88-120)。

这就是 AgentLoop 接 sandbox 时最重要的边界。模型生成的 bash/edit/final token 要进入 loss;sandbox 返回的 stdout、stderr、文件片段和测试日志要进入上下文,但不能被当成模型自己生成的 token。generate_sequences()的 docstring 也把 multi-turn 的 token 合同写清楚:responses里既有 LLM generation,也有 observation tokens,response_mask用 1/0 区分(verl/experimental/agent_loop/agent_loop.py:450-470)。

ToolAgentLoop的执行过程也证明了这一点。它在 PENDING -> GENERATING -> PROCESSING_TOOLS -> TERMINATED状态之间循环;工具阶段会并发调用工具,把 tool message 追加到上下文,再把这些 token 的 response_mask追加为 0(verl/experimental/agent_loop/tool_agent_loop.py:118-200273-374)。

所以,AgentLoop 接 CubeSandbox 时,真正要守住的是这条训练合同:

代码语言:javascript
复制
assistant action tokens -> response_mask = 1
sandbox observation tokens -> response_mask = 0
both enter input_ids / attention_mask / position_ids
only mask=1 tokens participate in actor loss

这也是我们第 16、17 篇已经建立过的边界:环境反馈要进轨迹,但不能污染 policy gradient。

3. reward-only 和 AgentLoop 的能力不同

这两种接法经常被混在一起,但它们训练的是不同能力。

路径

模型能看到环境反馈吗

适合任务

主要风险

reward-only

不能,只在最后被打分

一次性 patch、代码题、SQL 输出

reward 稀疏,模型无法从中间错误恢复

AgentLoop

能,stdout/stderr/文件内容进入上下文

多轮 coding agent、SWE-bench agent

轨迹变长,长尾更明显,mask 和 tokenization 更容易出错

reward-only 更像“考试后批改”;AgentLoop 更像“边做题边看反馈”。前者简单稳定,后者更接近真实 coding agent,但系统复杂度也更高。

实际工程里可以组合使用:AgentLoop 负责多轮探索,最终 reward function 仍然在干净 sandbox 中 apply patch 并跑测试,给出最终评分。

4. GPU 集群和 Sandbox 集群最好拆开

veRL 的 actor、critic、reference model、rollout backend 主要吃 GPU;CubeSandbox 主要吃 CPU、内存、磁盘 IO、网络和 KVM 能力。把两类 workload 混在同一批节点上,容易互相干扰。

下面这张图展示更清晰的部署形态。读图时注意,GPU 集群负责生成和训练,sandbox 集群负责环境执行和验证,中间通过任务请求、metadata 和 reward 结果连接。

GPU 训练集群与 CPU/KVM Sandbox 集群拆分

这种拆分让容量规划更明确:

  • GPU 侧看 token throughput、rollout latency、actor update 时间。
  • Sandbox 侧看 sandbox create QPS、并发 VM 数、测试平均耗时、模板命中率、网络策略拒绝率。
  • Reward 侧看成功率、超时率、patch apply fail、test fail、infra fail。

CubeSandbox 的 mini RL 示例里已经出现了 SWE-bench、E2B 兼容、template id、envd 注入镜像、并发运行和 pre-create 这些元素(CubeSandbox/examples/mini-rl-training/README_zh.md:1-360-91198-238)。这说明它已经把批量 agent 任务里的模板准备、并发执行和环境预创建作为工程问题暴露出来,而不只是演示一次命令执行。

5. 数据里要带环境信息

对文本任务来说,一条样本可能只有 prompt 和 answer。对 coding agent 来说,一条样本至少还要告诉训练系统:应该从哪个环境启动,仓库在哪里,运行什么测试,允许访问哪些网络,超时时间是多少。

一条简化后的样本可以这样理解:

代码语言:javascript
复制
{
  "data_source": "swebench_lite",
"prompt": "issue description and repo instructions",
"ground_truth": "test metadata",
"extra_info": {
    "template_id": "swebench-sympy-py311-v1",
    "repo_dir": "/testbed",
    "test_cmd": "python -m pytest ...",
    "timeout": 900,
    "max_steps": 30,
    "network_policy": "offline-or-allow-pypi"
  }
}

这里的 template_id很关键。它不是普通配置,而是“这条任务从什么初始世界开始”的引用。CubeSandbox 的快速开始文档也把控制面和数据面分开:Sandbox.create()负责生命周期,命令和文件操作通过数据面进入 sandbox 内的 envd;基础 SDK 示例包括创建、命令执行、文件读取、暂停恢复、网络访问控制等(CubeSandbox/examples/code-sandbox-quickstart/README_zh.md:9-12117-128)。

在训练之前,最好把仓库 checkout、依赖安装、envd ready、测试缓存等步骤尽量固化到 template 或 snapshot。训练阶段只做“启动/克隆、执行动作、评分、清理”。这能减少环境抖动,也让 reward 更可复现。

6. 并发和生命周期要显式设计

Agent RL 里的 sandbox 不是一个个孤立请求,而是一批并发环境。一个 batch 可能包含多个 prompt,每个 prompt 还可能采样多条 trajectory。环境层如果没有生命周期设计,很容易出现泄漏、超时堆积、日志爆炸和 GPU 空等。

下面这张图展示批量 rollout 的 sandbox 生命周期。读图时重点看 pre-create、acquire、run、release/rollback/kill 这几个阶段。

批量 rollout 的 sandbox 生命周期

工程上建议把这些规则写死在系统里,而不是散落到 reward 脚本里:

  • template_id分组创建环境,提升模板本地性。
  • reward worker 数量受 sandbox 集群容量约束,不直接等于 batch size。
  • 所有 sandbox 都有 TTL。
  • cleanup 放进 finally语义,失败也要释放。
  • stdout/stderr 截断保存,避免 metadata 失控。
  • timeout、patch apply fail、test fail、sandbox crash、API error 分开计数。
  • 网络默认收紧,只开放任务需要的域名或 CIDR。

CubeSandbox 快照示例展示了 create_snapshot()clone(n=...)rollback()和从快照启动新 sandbox 的接口(CubeSandbox/examples/snapshot-rollback-clone/README_zh.md:48-69)。这些能力在训练系统里的价值不是“API 好看”,而是让同一初始环境可以被批量复用和重放。

7. reward 不能只保存一个 float

代码任务如果只返回 01,训练很难诊断。失败可能来自模型,也可能来自环境。

建议至少拆出这些字段:

字段

含义

是否应该惩罚模型

patch_apply

patch 是否能应用

是,通常可作为格式/动作质量反馈

selected_tests

相关测试通过数量

是,任务质量反馈

full_tests

全量目标测试结果

是,主 reward

timeout

命令或 rollout 超时

视情况,可能是模型死循环,也可能是环境过慢

sandbox_error

envd 不通、VM crash、创建失败

通常不应直接惩罚模型

policy_error

访问未授权网络或 secret

取决于任务设计,通常要强约束

infra_error

CubeAPI、CubeMaster、Redis、网络异常

不应写成模型负反馈,应重试或丢样本

veRL 的 reward 路径已经支持把 extra info 带回 batch:extract_reward()会从 batch.non_tensor_batch里提取 reward_extra_keys对应字段(verl/trainer/ppo/reward.py:160-167)。AgentLoop 的 _postprocess()也会把 reward_extra_infoturn_scorestool_rewards等字段放入 non-tensor batch(verl/experimental/agent_loop/agent_loop.py:895-986)。

这就是为什么环境执行层要有结构化 metadata。没有这些字段,训练曲线掉了,你很难判断是模型变差、题目变难、sandbox 变慢,还是网络策略误拦了依赖下载。

小结:环境层决定 agent RL 是否可训练

把 CubeSandbox 放进 veRL 之后,可以得到一条清晰的系统图:

代码语言:javascript
复制
dataset extra_info
-> template / sandbox lifecycle
-> reward-only or AgentLoop
-> observation / score / metadata
-> DataProto / rm_scores / response_mask
-> advantage and actor update

如果只是做一次性代码评分,先从 reward-only 开始,路径短、风险低。如果要训练真正的 coding agent,就必须进入 AgentLoop,并认真处理 response_mask、上下文长度、工具等待、环境并发和失败归因。

到这里,CubeSandbox 不再只是一个外部项目介绍。它补上的是 train/serve 系统里越来越重要的一层:当模型开始行动,环境本身就成为训练数据流的一部分。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 1. 最小接法:只在 reward 阶段使用 CubeSandbox
  • 2. 真正的 coding agent:在 AgentLoop 中使用 sandbox
  • 3. reward-only 和 AgentLoop 的能力不同
  • 4. GPU 集群和 Sandbox 集群最好拆开
  • 5. 数据里要带环境信息
  • 6. 并发和生命周期要显式设计
  • 7. reward 不能只保存一个 float
  • 小结:环境层决定 agent RL 是否可训练
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档