Prhub

#1957 Minor refactor for coding agent rl logic and remove SWE_LIST_TRAJECTORY

原始 PR 作者 zhuzilin 合并时间 2026-05-27 12:04 文件变更 3 提交数 2 评论 0 代码增减 +172 / -173

执行摘要

重构 agent RL 生成逻辑并移除 SWE_LIST_TRAJECTORY 配置

移除已弃用的 SWE_LIST_TRAJECTORY 配置(该配置允许将多个 segment 折叠为单个 Sample),现在始终生成每个 segment 对应的 Sample,避免配置混乱并减少维护成本。同时将 generate() 函数模块化以提高可读性和可测试性。

值得精读 generate.py 的模块化拆分方式,以及如何将单体生成函数重构为管道式编排。同时注意配置移除可能对现有实验脚本的影响,建议运行 fan-out 测试验证。

讨论亮点

无公开 review 讨论或评论。

实现拆解

  1. 重构 generate.py:将原 generate() 中的步骤提取为 _run_claude_code、_get_diff、_merge_samples 等辅助函数,引入 dataclass RewardResult 作为中间数据载体。删除所有与 SWE_LIST_TRAJECTORY 相关的条件分支,generate() 现在始终返回 list[Sample]。
  2. 修改 shell 启动脚本:移除 SWE_LIST_TRAJECTORY 的 export 和注释,调整 fan-out 语义说明。
  3. 更新 README:从环境变量表中移除 SWE_LIST_TRAJECTORY 行,简化 Fan-out 章节描述。
文件 模块 状态 重要度
examples/coding_agent_rl/generate.py 代理 RL modified 8.65
examples/coding_agent_rl/run_qwen36_35b_a3b_swe_8nodes.sh 部署脚本 modified 2.99
examples/coding_agent_rl/README.md 文档 modified 1.82

关键符号

generate _run_claude_code _get_diff _merge_samples _pop_segments _start_session

关键源码片段

examples/coding_agent_rl/generate.py dependency-wiring

核心重构文件,涉及 generate() 函数拆分、SWE_LIST_TRAJECTORY 移除、新增辅助函数和 RewardResult 数据结构。

# 文件 : examples/coding_agent_rl/generate.py
# 重构后的 generate() 使用四个辅助函数组织流程,并通过 RewardResult 传递中间状态@dataclass
class RewardResult:
    """保存 reward 评估结果,供后续合并使用"""
    reward: float
    metadata: dictasync def _run_claude_code(sample, state) -> middleware.Session:
    """阶段1: 启动 E2B 沙箱,安装 Node + Claude Code,运行 agent"""
    # 根据 sample 的 metadata 创建 sandbox,返回 session 对象
    ...async def _get_diff(session) -> str:
    """阶段2: 在 agent 运行结束后捕获 git diff 补丁"""
    ...async def _merge_samples(session, reward_result, state) -> list[Sample]:
    """阶段4: 从 middleware 拉取 token segment,结合 reward 组装为 Sample 列表"""
    segments = await middleware.pop_session_split(session.uid)
    # 每个 segment 对应一个 Sample,reward 均分
    samples = []
    for seg in segments:
        samples.append(Sample(
            prompt_ids=seg.prompt_ids,
            response_ids=seg.response_ids,
            loss_mask=seg.loss_mask,
            reward=reward_result.reward / len(segments),
            rollout_id=sample.rollout_id,
        ))
    return samplesasync def generate(samples, args) -> AsyncIterator[Sample]:
    """四阶段编排器: agent -> diff -> evaluate -> merge"""
    state = _State(args)
    async for sample in samples:
        try:
            session = await _run_claude_code(sample, state)
            diff = await _get_diff(session)
            reward_result = await sandbox.evaluate(diff, sample.metadata)
            async for merged in _merge_samples(session, reward_result, state):
                yield merged
        except Exception:
            logger.exception("sample failed, skipping")
            continue

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

主要风险在于 SWE_LIST_TRAJECTORY=0 的 collapsed 模式被移除,若外部工作流依赖该模式则行为改变。此外,新引入的 _merge_samples 等函数若未正确处理 reward 分割可能导致 reward 计算错误。建议确认所有依赖方已迁移到 fan-out 模式。

影响范围限于 coding_agent_rl 示例的用户。用户需要删除 SWE_LIST_TRAJECTORY 设置(原 shell 中默认已设为 1,所以影响较小)。代码重构提升了可读性和模块性,便于后续扩展。

移除旧配置可能破坏依赖 collapsed 模式的工作流

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论