Prhub

#5713 [3/n][reward] feat: flowgrpo - support image-based rewards (rule-based & genrm)

原始 PR 作者 chenyingshu 合并时间 2026-03-26 15:54 文件变更 10 提交数 16 评论 12 代码增减 +590 / -19

执行摘要

添加图像奖励支持,用于 FlowGRPO 训练,扩展奖励系统以处理视觉输入。

PR body 指出这是 #4639 和 #5297 的后续工作,用于支持 FlowGRPO 训练 QwenImage。Issue 评论中 yyDing1 表示之前实现不支持图像/视频奖励模型,例如 compute_score 函数不接受 solution_image 参数,因此需要此变更来扩展功能。

推荐技术管理者和工程师精读此 PR,关注 VisualRewardManager 的设计和奖励循环的多模态扩展。值得注意的设计决策包括奖励管理器基类的扩展、异步处理实现、以及通过配置驱动的奖励函数选择,这些对于理解仓库架构演进有重要价值。

讨论亮点

review 中的核心讨论:gemini-code-assist[bot] 指出 compute_score_ocr 函数存在 ZeroDivisionError 风险(如果 ground_truth 为空字符串),建议添加边界检查;SamitHuang 提议将 ImageRewardManager 重命名为 VisualRewardManager 以覆盖图像和视频,作者采纳并修改;SamitHuang 和 zhtmike 讨论奖励函数放置位置,决定规则奖励放在 jpeg_compressibility.py,而 OCR 作为生成奖励模型示例;SamitHuang 建议通过 get_default_compute_score 函数改进 load_reward_manager 的代码结构,作者实现并更新 verl/utils/reward_score/__init__.py。

实现拆解

实现方案拆解:

1) 新增 VisualRewardManager 类(原为 ImageRewardManager),位于 verl/experimental/reward_loop/reward_manager/visual.py,作为奖励管理器基类的子类,专门处理视觉响应;
2) 修改 RewardLoopManager 和 RewardLoopWorker 的 _preprocess_reward_inputs 方法(在 verl/experimental/reward_loop/reward_loop.py),根据响应维度区分图像和文本输入;
3) 添加奖励函数 compute_score_ocr(生成奖励模型,位于 examples/flowgrpo_trainer/reward_fn.py)和 jpeg_compressibility.compute_score(规则奖励,位于 verl/utils/reward_score/jpeg_compressibility.py);
4) 新增工具函数如 pil_image_to_base64 和 prepare_query_for_multi_modal(位于 verl/utils/experimental/reward_utils.py),以支持图像转换;
5) 更新 CI 工作流(.github/workflows/reward_model_vllm.yml)添加测试,并提供单元测试脚本 tests/experimental/reward_loop/test_visual_reward_manager.py 验证功能。

文件 模块 状态 重要度
verl/experimental/reward_loop/reward_manager/visual.py reward_loop added 9.0
verl/experimental/reward_loop/reward_loop.py reward_loop modified 8.0
examples/flowgrpo_trainer/reward_fn.py examples added 7.0
tests/experimental/reward_loop/test_visual_reward_manager.py tests added 6.0
verl/utils/reward_score/__init__.py utils modified 7.0

关键符号

VisualRewardManager.run_single compute_score_ocr default_compute_score_image jpeg_compressibility.compute_score _preprocess_reward_inputs

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

评论区精华

OCR 奖励函数的 ZeroDivisionError 风险 正确性

gemini-code-assist[bot] 指出 compute_score_ocr 函数在 ground_truth 为空字符串时可能导致除以零错误,建议添加边界检查。

结论:作者未在 review 中明确修复,但提交历史显示代码更新,可能已处理此问题。 · 已解决

重命名奖励管理器以覆盖图像和视频 设计

SamitHuang 建议将 ImageRewardManager 改为 VisualRewardManager,以更全面地支持多模态输入,作者采纳建议。

结论:重命名为 VisualRewardManager,提升设计的通用性。 · 已解决

奖励函数代码结构改进 设计

SamitHuang 提议使用 reward_manager_cls.get_default_compute_score 来清理 load_reward_manager 逻辑,作者随后添加了 get_default_compute_score 函数。

结论:通过通用函数简化代码,提高可维护性。 · 已解决

风险与影响

技术风险具体包括:

1) compute_score_ocr 函数在 ground_truth 为空字符串时可能引发 ZeroDivisionError,需要额外错误处理;
2) 奖励管理器类型依赖配置字符串(如 'visual'),配置错误可能导致运行时问题;
3) 异步处理和图像转换(如 pil_image_to_base64)可能引入性能开销或内存问题;
4) 新增代码缺乏全面测试覆盖,仅提供单元测试示例,可能未覆盖所有边缘情况。

对用户:使研究人员能够使用图像奖励进行 FlowGRPO 训练,扩展了图像生成模型的应用场景;对系统:奖励循环现在支持多模态输入,增加了系统复杂性和维护负担;对团队:需要熟悉新的奖励管理器设计和多模态处理逻辑,可能影响后续开发和测试工作。

ZeroDivisionError 风险 配置字符串依赖 异步处理复杂 测试覆盖不足

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论