Prhub

#1923 [examples] add coding_agent_rl: agent-in-sandbox RL minimal demo

原始 PR 作者 jingshenghang 合并时间 2026-05-26 23:34 文件变更 6 提交数 44 评论 15 代码增减 +2502 / -0

执行摘要

新增编码代理 RL 示例,E2B 沙盒 + Claude Code 集成

提供一个最小且可读的编码代理 RL 示例,展示如何将真实编码工具(Claude Code)与沙盒执行和基于测试的奖励集成到 slime 训练循环中。PR body 描述了完整的端到端流程,强调无需事后重新标记化。

值得精读,尤其关注 middleware.py 的设计模式:如何通过 Chain/Session 实现多对话链跟踪、raw token 拼接保证 TITO、以及 generate.py 的容错设计。对于希望实现类似代理 RL 管线的工程师有很强参考价值。

讨论亮点
  1. 文件重命名:zhuzilin 建议将 bridge.py 重命名为 middleware.py,以避免与 slime 已有的 mbridgemegatron bridge 混淆。作者采纳。
  2. asyncio 锁的必要性:zhuzilin 质疑单线程下是否需要 session 锁。作者解释 _run_turn 包含 await _post_generate(HTTP 调用),同一 session 并发请求会交错修改状态,导致 TITO 校验失败;锁是 per-session 的。
  3. session_id 唯一性:作者将 sid 改为 f'cagent-{instance_id}-{sample.index}-{sample.group_index}',确保在 rollout 步骤内唯一。
  4. TITO 校验失败处理:讨论确认会 mask 整条 response 的 loss_mask,代码为 target.loss_mask[-n:] = [0] * n
  5. 流式请求同步化:作者解释 _post_generate 调用同步 sglang 接口获取完整 output_ids,再一次性流式返回,避免增量流式损坏 TITO。
  6. 客户端取消处理:通过 handler_cancellation/abort_request 避免已取消生成与 release_memory_occupation 竞争。

实现拆解

  1. Sandbox 层 (sandbox.py):封装 E2B API,提供 execuploadwrite_textread_text 等 5 个原语,并实现 _is_transient_rpc_error_rpc_retry 以应对网络波动。
  2. LLM 中间件 (middleware.py):实现 Anthropic Messages API ↔ SGLang /generate 协议转换;核心数据类 ChainSession 维护对话链与会话状态;_select_chain 决定延续主链还是子代理链;_build_prompt 通过 chat template 加 raw token 拼接避免重新分词;_generate 调用 SGLang 并验证 TITO;_build_reply 将 output_ids 翻译回 Anthropic SSE 块。
  3. 样本生成 (generate.py):实现 slime custom-generate 入口 generate();每个样本:启动 Agent 沙盒 → 安装 Node 与 Claude Code → 执行代理 → 捕获 git diff → 启动评估沙盒 → 应用 diff 并运行测试 → 从中间件拉取 token 段 → 折叠或扇出为 Sample 对象;包含墙钟超时保护、失败软降级等容错设计。
  4. aiohttp 线程工具 (aiohttp_threaded.py):在后台 daemon 线程中运行 aiohttp 应用,用于中间件的 HTTP 服务。
  5. 启动脚本与文档run_qwen36_35b_a3b_swe_8nodes.sh 展示完整的模型并行与 rollout 配置;README.md 说明环境设置、数据集格式和运行指南。
文件 模块 状态 重要度
examples/coding_agent_rl/middleware.py 中间件 added 9.08
examples/coding_agent_rl/generate.py 样本生成 added 9.08
examples/coding_agent_rl/sandbox.py 沙盒 added 8.89
examples/coding_agent_rl/aiohttp_threaded.py 网络服务 added 8.56
examples/coding_agent_rl/run_qwen36_35b_a3b_swe_8nodes.sh 启动脚本 added 5.62
examples/coding_agent_rl/README.md 文档 added 4.43

关键符号

generate _boot_agent_sandbox _write_segment_to_sample _fan_out_to_samples _handle_request _select_chain _build_prompt _generate _build_reply _strip_cache_control _hash Chain Session _make_segment _flatten _translate_anthropic _parse_sandbox_metadata _is_transient_rpc_error _rpc_retry E2BSandbox run_app_in_thread AppHandle

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

文件重命名:bridge → middleware 设计

zhuzilin 建议将 file bridge.py 改名为 middleware.py,避免与 slime 已有的 mbridge 和 megatron bridge 混淆。

结论:作者采纳,将 bridge.py 更名为 middleware.py,并更新所有导入。 · 已解决

asyncio 锁的必要性 正确性

zhuzilin 质疑 Python asyncio 单线程下是否需要 session 锁。作者解释 _run_turn 中 await _post_generate 被切换后,同一 session 并发请求会交错修改状态,破坏 TITO 校验。锁是 per-session 的,不同 session 仍完全并发。

结论:作者坚持锁的必要性,解释合理,保留锁。 · 已解决

session_id 唯一性 正确性

zhuzilin 指出需要提示 session_id 不能重复。作者回应将 sid 改为 `f'cagent-{instance_id}-{sample.index}-{sample.group_index}'`,确保在 rollout 步骤内唯一。

结论:作者修改实现,确保唯一性。 · 已解决

TITO 校验与 loss_mask 策略 正确性

zhuzilin 询问当 TITO 不匹配时是否 mask 整条 response。作者确认并提供代码:`target.loss_mask[-n:] = [0] * n`。

结论:确认策略,不匹配时置零当前 response 的 loss_mask。 · 已解决

流式请求同步化 性能

zhuzilin 想确认流式请求是否变为同步。作者解释:_post_generate 调用 sglang 非流式接口获取完整 output_ids,然后一次性以 SSE 流式返回给 claude-code,避免增量流式导致的 TITO 损坏。

结论:设计确认:攒齐后再流式发送。 · 已解决

风险与影响

  • 外部服务依赖:E2B 沙盒和 Claude Code 均为外部系统,网络波动或版本升级可能导致训练故障。_rpc_retry 和超时提供部分容错,但仍无离线方案。
  • Token 捕获正确性:中间件的 TITO 验证关键;当前设计在失败时静默置零 loss_mask,可能丢失训练信号。
  • 环境一致性:运行脚本中硬编码的 Node 和 Claude Code tarball 路径需与集群同步,否则沙盒环境不匹配。
  • 资源开销:沙盒启动与销毁涉及 I/O 和网络,每个样本延迟高;扇出模式可能使样本数激增,导致显存压力。
  • 模型适配:示例针对 Qwen3.5 配置,切换模型需调整 chat template、tool parser 和 reasoning parser。
  • 用户:提供了一个开箱即用的编码代理 RL 示例,只需配置 E2B 和 Claude Code 路径即可实验。
  • 系统:未修改 slime 核心模块,仅通过 --custom-generate-function-path 挂钩;不影响现有训练流程。
  • 团队:为后续复杂代理 RL 工作流提供了可扩展的参考架构,middleware 的设计模式可直接复用。
  • 维护成本:作为示例代码,需与主仓库同步更新;环境变量接口的变更可能破坏现有脚本。
外部服务依赖 token 捕获正确性 环境一致性 资源开销 模型适配

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论