ms-swift GRPO 多任务训练指南:用任务列 + 分任务奖励函数实现 Math/Code 混合强化学习

发布时间:2026/9/14 15:14:54

ms-swift GRPO 多任务训练指南:用任务列 + 分任务奖励函数实现 Math/Code 混合强化学习 ms-swift GRPO 多任务训练指南用任务列 分任务奖励函数实现 Math/Code 混合强化学习【免费下载链接】swiftUse PEFT or Full-parameter to CPT/SFT/DPO/GRPO 600 LLMs (Qwen3.6, DeepSeek-V4, GLM-5.1, InternLM3, Llama4, ...) and 300 MLLMs (Qwen3-VL, Qwen3-Omni, InternVL3.5, Ovis2.5, GLM4.5v, Gemma4, Llava, Phi4, ...) (AAAI 2025).项目地址: https://gitcode.com/GitHub_Trending/swift1/swift本篇技术指南基于 SWIFTms-swift仓库中的 GRPO 开发者文档 Multi-Task Training讲解如何在一次 GRPO 训练中混合不同领域的数据如数学与代码任务通过在数据集里添加task任务标记列编写只对目标任务计分、对非目标任务返回 None的奖励函数从而让不同任务各自使用最合适的奖励逻辑。读完本文你将掌握多任务 GRPO 数据集的构造方式、按任务分发奖励的插件写法以及该机制在swift/rl_core/grpo_algorithm.py与swift/rlhf_trainers/grpo_trainer.py中的底层实现链路。为什么需要多任务训练GRPO 的奖励信号来自奖励函数或奖励模型。当训练集只包含单一任务例如只有数学题时一个accuracy奖励函数足以胜任但当同一个数据集里同时包含数学题和编程题时正确答案的判定标准完全不同数学答案通常用math_verify之类的符号化校验SWIFT 内置的accuracy即基于此而代码任务更依赖单元测试通过率、沙箱执行等判定方式。用同一个奖励函数去评所有样本要么数学侧不准要么代码侧失效。SWIFT 官方 FAQ 对这一问题给出的答案就是本文档本身若训练集包含不同任务请参考 Multi-Task Training 文档。核心方案只有两句话在数据集中加一列如task标记任务类型在奖励函数或奖励模型插件中读取这一列对属于当前任务的样本计算奖励对不属于的样本返回None。数据集构造添加 task 任务标记列按 multi_task.md 的示例一个同时包含数学和编程任务的 GRPO 数据集可以写成如下 JSON[ {query: Solve the equation x 2 5, solution: 3, task: math}, {query: Write a function to calculate the Fibonacci sequence, solution: xxx, task: code}, {query: What is the integral of x^2?, solution: xxx, task: math}, {query: Implement a sorting algorithm in Python, solution: xxx, task: code} ]关键点query/solution之外的额外列不会进入模型 prompt而是作为额外列原样保留供奖励函数读取。关于各列的具体语义query、response、solution等如何映射到messages可参见 自定义数据集文档。task列的取值math、code等由你自己约定奖励函数里只需按相同的字符串判断即可。注意文档中的提醒与模型输入相关的列如query、response会被转换成messages键数据集中的原始 assistant 回复会被丢弃因此像solution这类需要保留的信息应放在额外列里。编写按任务分发的奖励函数multi_task.md 给出的核心思路是数据集的列会被完整传入奖励函数因此可以在函数签名里直接声明task参数对每个样本判断它属于哪个任务属于则计算真实奖励不属于则返回None。原文给出的示例如下原文风格保留from swift.rewards import ORM, orms import random # Math-specific reward function class MathRandomReward(ORM): def __call__(self, completions, task, **kwargs): rewards [] for completion, t in zip(completions, task): if t math: # Implement math accuracy logic reward random.random() rewards.append(reward) else: # Return None for non-math tasks rewards.append(None) return rewards # Coding-specific reward function class CodeRandomReward(ORM): def __call__(self, completions, task, **kwargs): rewards [] for prompt, completion, t in zip(prompts, completions, task): if t code: # Implement coding accuracy logic reward random.random() rewards.append(reward) else: # Return None for non-coding tasks rewards.append(None) return rewards orms[math_reward] MathRandomReward orms[code_reward] CodeRandomReward说明以上代码忠实保留原文档示例。实际落地时有两处建议修正/替换CodeRandomReward.__call__中引用了未声明的prompts实现时建议只保留completions与task两个参数如数学示例所示示例中的random.random()是占位逻辑真实训练应替换为具体判定数学侧可直接复用 SWIFT 内置的accuracy奖励基于math_verify见 orm.py 中的MathAccuracy代码侧可参考仓库自带的沙箱执行示例 plugin.py 中的CodeRewardE2B 沙箱或CodeRewardByJudge0Judge0 端点。最后将奖励函数注册进orms字典如orms[math_reward] MathRandomReward注册名即可在训练参数--reward_funcs中引用。None 的语义非本任务样本不参与该奖励列对不属于当前任务的样本返回None是整套机制的枢纽。从源码看这一行为在 compute_rewards_per_func 中有明确处理每个奖励函数的输出会被逐元素转换——output reward_func(completions, **reward_kwargs) output [reward if reward is not None else torch.nan for reward in output] rewards_per_func[:, i] torch.tensor(output, dtypetorch.float32, devicedevice)也就是说None会被写入NaN形成一张[样本数, 奖励函数数]的稀疏奖励矩阵。后续在计算 advantage 时SWIFT 按列加权求和并跳过NaN因此数学奖励列只对task math的样本生效代码奖励列只对task code的样本生效两者互不干扰。同一函数里还有一道防线如果某个样本被所有奖励函数都返回None整行全NaN训练器会打印一条告警提示至少要让一个奖励函数对该样本给出有效奖励——这正是多任务分发的正确性约束每个样本必须恰好被某个奖励函数认领。数据集列是如何流进奖励函数的列会被传给奖励函数并非约定俗成而是有明确实现链路。在 GRPOSample.to_reward_row 中每个样本被压平成奖励函数可见的字典其中extra字段即数据集中不属于协议字段的额外列如task、solution会被展平到顶层随后 compute_rewards_per_func 用RowPreprocessor.rows_to_batched把逐行字典转成批量的键值对task变成与completions等长的列表与completions、trainer_state一起作为 kwargs 传给每个奖励函数。这也解释了为什么可以在__call__签名里直接写def __call__(self, completions, task, **kwargs)——参数名与列名一致即可自动绑定。补充两点实用信息若不想显式声明列名也可以从kwargs中取值task kwargs.get(task)训练步数则可通过kwargs.get(trainer_state).global_step获取见 Reward Function 文档。与模型输入相关的列会被转成messages因此奖励函数里拿到的问题文本应通过messages列访问query这类原始列名可能不再存在。训练配置external_plugins reward_funcs自定义奖励函数放在外部插件文件中通过--external_plugins加载、--reward_funcs指定参考仓库示例脚本 run_external_reward_func.shswift rlhf \ --rlhf_type grpo \ --model Qwen/Qwen2.5-3B-Instruct \ --external_plugin examples/train/grpo/plugin/plugin.py \ --reward_funcs math_reward code_reward \ --dataset 你的多任务数据集 \ --num_generations 8 \ --learning_rate 1e-6 \ ...相关参数在 GRPOConfig 中的定义参数说明默认值reward_funcs奖励函数名列表内置可选accuracy、format、cosine、repetition、soft_overlong见 orm.py自定义函数需在orms中注册[]reward_weights各奖励源的权重长度须等于奖励函数数外加外部奖励模型None时全部等权1.0None多任务场景下reward_funcs通常就是按任务拆分的多个函数如math_reward code_reward。需要留意两点组内同质性GRPO 的 advantage 是在同一 prompt 的num_generations条生成内做组内标准化奖励只作用在同任务样本上不会破坏该性质但应避免同一 prompt 的不同 completion 因任务判定不一致而部分得None。每步都要雨露均沾若某个 batch 恰好全是math数据则code_reward列整列为NaN且该列贡献为 0这是预期行为但若整行全NaN没有任何奖励函数认领该样本说明任务判定逻辑有漏洞会触发前述告警。结合内置奖励与奖励模型的多任务组合多任务机制不限于两个自定义 ORM内置奖励可直接参与分发例如数学任务直接复用内置accuracy要求安装math_verify实现见 MathAccuracy无需自己写判定逻辑代码任务再配一个沙箱执行类奖励。异步奖励兼容若某个任务的奖励涉及 I/O沙箱、API 调用可继承AsyncORM训练器会自动用asyncio.gather并行执行见 reward_function.md 与 compute_rewards_per_func 中async_indices分支仓库中的CodeReward示例本身就用了 E2B 异步沙箱。奖励模型插件同样适用文档提到reward functionor reward model plugin——在 GRPOTrainer._prepare_rewards 中--reward_model会通过rm_plugins注册为额外的奖励源。你同样可以让自定义 RM 插件在__call__里读取task列对非目标任务样本返回None奖励模型的输出在 compute_rewards_per_func 中同样经过None - NaN转换。小结SWIFT 的 GRPO 多任务训练方案可以归纳为三步数据侧为数据集添加task标记列math/code等自定义取值奖励侧按任务各写一个 ORM或 RM 插件签名里声明task参数对本任务样本计算真实奖励对非本任务样本返回None配置侧用--external_plugins加载插件文件--reward_funcs列出所有任务奖励函数必要时用--reward_weights调权。底层由 GRPOSample.to_reward_row 将数据集列透传为奖励函数的 kwargs由 compute_rewards_per_func 完成None - NaN的稀疏奖励矩阵组装最终保证每个样本只被对应的任务奖励打分。这套机制使一次 GRPO 训练即可覆盖多个领域的可验证奖励无需为每个任务单独起一轮训练。【免费下载链接】swiftUse PEFT or Full-parameter to CPT/SFT/DPO/GRPO 600 LLMs (Qwen3.6, DeepSeek-V4, GLM-5.1, InternLM3, Llama4, ...) and 300 MLLMs (Qwen3-VL, Qwen3-Omni, InternVL3.5, Ovis2.5, GLM4.5v, Gemma4, Llava, Phi4, ...) (AAAI 2025).项目地址: https://gitcode.com/GitHub_Trending/swift1/swift创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/14 15:14:54

Android Studio安装配置全攻略:从依赖关系到环境变量,一次跑通

装 Android Studio 这件事,我前前后后折腾过不下几十次,给自己装、给学生装、给同事远程排错,每次都能碰到新花样。市面上的安装教程多如牛毛,但大多只告诉你“点下一步”,没告诉你为什么这一步非点不可、哪一步选错了…

2026/9/14 16:10:05

布隆过滤器原理与应用:高效海量数据去重方案

1. 布隆过滤器概述布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,由Burton Howard Bloom在1970年提出。它专门用于快速判断一个元素是否存在于某个集合中,特点是可能存在误判(false positive&#xff0…

2026/9/14 16:10:05

Discourse开源论坛部署与SSO集成实战:Docker+泛微OA单点登录

1. 项目概述:为什么Discourse不是“又一个论坛”,而是开源社区基建的分水岭Discourse 新一代开源论坛——这名字里藏着三个容易被忽略但极其关键的定语:“Discourse”是具体技术实体,不是泛指;“新一代”不是营销话术&…

2026/9/14 16:10:04

Seata TCC模式实战:分布式事务解决方案详解

## 1. 项目概述第一次接触分布式事务时,我被这个看似简单实则复杂的领域深深吸引。作为从单体架构转型微服务的必经之路,分布式事务问题就像悬在架构师头顶的达摩克利斯之剑。在电商系统中,用户支付成功后需要同时更新订单状态、扣减库存、增…

2026/9/14 16:10:04

二维区域和问题的动态优化与工程实践

1. 面试高频题解析:二维区域和(可变)问题第一次在技术面遇到这道题时,我盯着白板上的矩阵愣了足足十秒钟。面试官轻描淡写地说:"这不就是个二维前缀和的变形吗?"后来我才明白,这道题之…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码