网站虚拟主机1g,泉州百度网站推广,学校网站建设具体分工,领地免费网站开发继续学习字节家的VeRL#xff0c;今天来看看VeRL的RL#xff0c;是VeRL系列的第三篇文章#xff08;话说近期好多大事儿#xff0c;我司发布了Longcat、韩立结婴、阿里周五发布了QWen-Next都是好东西啊#xff0c;学不过来了damn#xff09;
底层分布式能力基础Ray…继续学习字节家的VeRL今天来看看VeRL的RL是VeRL系列的第三篇文章话说近期好多大事儿我司发布了Longcat、韩立结婴、阿里周五发布了QWen-Next都是好东西啊学不过来了damn
底层分布式能力基础Ray点击查看VeRL分布式能力的基础框架RayVeRL的原理点击查看HybridFlowVeRL的使用点击查看普通RLPPOVeRL的使用Agentic RL多轮RLVeRL的魔改 前两篇文章分别介绍了VeRL的分布式基础和其底层原理下面就以RL的PPO为例同时结合源码看看具体的使用。
安装
使用docker的话verl提供了诸多版本可以使用例如纯净的只包含Verl/CUDA/PyTorch等依赖的base镜像也有整合了vLLM/SGLang/FSDP/Megatron的application镜像手动安装的话要从CUDA/cuDNN等基础库开始一定会遇到冲突嗯一定…
使用
首先在Ray的Head节点上执行 ray start --head --dashboard-host0.0.0.0之后会得到两个address
一个是集群内head/worker之间通信用的 GCS address一个是提交与查看任务/资源监控/查看日志的dashboard地址使用VSCode插件进行debug的地址也是它
然后在每个Ray Worker节点上执行 ray start --addressgcs_address最后提交job任务ray job submit --addressdashboard_address -- python3 -m verl.trainer.main_ppo trainer.n_gpus_per_node8 ... 就可以在dashboard里看到各种信息了
启动后整体架构如图前两篇文章介绍过了就不赘述了
其中driver进行代表single-controller其他的 actor/critic/rollout/ref/reward 那些 workers 代表 multi-controller均对应着各自的 resource group 下面直接看源码。
源码
首先是入口函数即main_ppo.py主要做定义、初始化
初始化 Ray cluster 环境通过 ray.remote 定义了一个 远程执行的 class TaskRunner定义 actor/rollout worker通过配置指定使用 fsdp、megatron并构建 mappingrole_worker_mapping[Role.ActorRollout] ray.remote(actor_rollout_cls)定义 criticworker将上述两个worker映射到resourece资源上mapping[Role.ActorRollout] global_pool_id、mapping[Role.Critic] global_pool_id定义 rewardworkerrole_worker_mapping[Role.RewardModel] ray.remote(RewardModelWorker) 的同时映射资源 mapping[Role.RewardModel] global_pool定义 refworkerrole_worker_mapping[Role.RefPolicy] ray.remote(ref_policy_cls) 的同时映射资源 mapping[Role.RefPolicy] global_pool执行PPO workflow加载模型、准备dataset、构建RayPPOTrainer、执行 RayPPOTrainer.init_workers()、执行 RayPPOTrainer.fit()
# Initialize the PPO trainer.
trainer RayPPOTrainer(configconfig,tokenizertokenizer,processorprocessor,role_worker_mappingself.role_worker_mapping,resource_pool_managerresource_pool_manager,ray_worker_group_clsray_worker_group_cls,reward_fnreward_fn,val_reward_fnval_reward_fn,train_datasettrain_dataset,val_datasetval_dataset,collate_fncollate_fn,train_samplertrain_sampler,
)
# Initialize the workers of the trainer.
trainer.init_workers()
# Start the training process.
trainer.fit()然后执行的是核心的RayPPOTrainer主要就是俩函数一个是init_workers()一个是fit()
先看init_workers()
根据config配置的资源创建resource pool创建hybrid_engine这是actor和rollout的 colocate的复合体
resource_pool self.resource_pool_manager.get_resource_pool(Role.ActorRollout)
actor_rollout_cls RayClassWithInitArgs(clsself.role_worker_mapping[Role.ActorRollout],configself.config.actor_rollout_ref,roleactor_rollout,
)
self.resource_pool_to_cls[resource_pool][actor_rollout] actor_rollout_cls创建critic
resource_pool self.resource_pool_manager.get_resource_pool(Role.Critic)
critic_cfg omega_conf_to_dataclass(self.config.critic)
critic_cls RayClassWithInitArgs(clsself.role_worker_mapping[Role.Critic], configcritic_cfg)
self.resource_pool_to_cls[resource_pool][critic] critic_cls创建ref
resource_pool self.resource_pool_manager.get_resource_pool(Role.RefPolicy)
ref_policy_cls RayClassWithInitArgs(self.role_worker_mapping[Role.RefPolicy],configself.config.actor_rollout_ref,roleref,
)
self.resource_pool_to_cls[resource_pool][ref] ref_policy_cls创建reward下面设置用的是reward model 非 function
resource_pool self.resource_pool_manager.get_resource_pool(Role.RewardModel)
rm_cls RayClassWithInitArgs(self.role_worker_mapping[Role.RewardModel], configself.config.reward_model)
self.resource_pool_to_cls[resource_pool][rm] rm_cls创建各自的wroker groupWorkerGroup是一组Wroker的抽象集合使得driver可以和底层的多个worker进行交互
for resource_pool, class_dict in self.resource_pool_to_cls.items():worker_dict_cls create_colocated_worker_cls(class_dictclass_dict)wg_dict self.ray_worker_group_cls(resource_poolresource_pool,ray_cls_with_initworker_dict_cls,**wg_kwargs,)spawn_wg wg_dict.spawn(prefix_setclass_dict.keys())all_wg.update(spawn_wg)if self.use_critic:self.critic_wg all_wg[critic]self.critic_wg.init_model()if self.use_reference_policy and not self.ref_in_actor: # 需要关注self.ref_policy_wg all_wg[ref]self.ref_policy_wg.init_model()if self.use_rm:self.rm_wg all_wg[rm]self.rm_wg.init_model()这里需要注意的是
actor和rollout进行colocate的目的是在rollout和train两个阶段间高效更新参数权重但是否也同样也colocate ref取决于是否用了LoRA因为ref和actor它们的base基座模型一样只不过actor lora多了一层lora的适配层也就是BA矩阵所以如果用LoRA可以把rollout/actor/ref同时colocate到一起更省资源
之后再看fit()其实就是标准的PPO实现了下面提取出关键信息
for prompt in dataloader:output actor_rollout_ref_wg.generate_sequences(prompt) # old_log_prob actor_rollout_ref_wg.compute_log_prob(output)ref_log_prob actor_rollout_ref_wg.compute_ref_log_prob(output)values critic_wg.compute_values(output)rewards reward_wg.compute_scores(output)advantages compute_advantages(values, rewards)output output.union(old_log_prob).union(ref_log_prob).union(values).union(rewards).union(advantages)actor_rollout_ref_wg.update_actor(output)critic.update_critic(output)另外关于driver和wroker的数据交互大致可以分成3步
driver把数据按DP数量进行切分把数据分发给每个worker每个worker再将执行的结果进行整合所以VeRL这里搞了一个语法糖register
class ActorRolloutRefWorker(Worker):register(dispatch_modeDispatch.DP_COMPUTE_PROTO)def generate_sequences(self, prompts: DataProto):prompts prompts.to(torch.cuda.current_device())上面的注解register装饰了方法generate_sequence包含了 dispatch_mode对应的
dispatch_func把输入dispatch到worker group中的各个workercollect_func把worker group的各个worker的response collect到一起 下篇文章介绍下如何使用VeRL进行Agentic RL也就是多轮RL。