帮你快速理解、总结文档立即下载
文档中心>实践教程>弹性 MapReduce>基于 Ray 使用 veRL 进行强化学习

基于 Ray 使用 veRL 进行强化学习

最近更新时间:2026-08-10 15:34:37
我的收藏

一、准备条件

确认您已开通腾讯云,并且已创建 EMR on TKE 产品中的 Ray 服务。EMR on TKE 集群的创建详情请参见 创建集群
目前容器类型选择计算资源和 TKE 都支持创建 Ray 集群实例。
实例类型:机器学习
产品版本:EMR-TKE-AI-V1.2.0
说明:
使用 veRL 镜像进行后训练,在部署服务中需同步部署 JUPYTERLAB、EG、MLFLOW、TCRAY 组件。

二、创建 RayCluster

当前支持通过表单方式和 YAML 方式 两种方式创建和管理 RayCluster。若您希望快速完成集群创建,推荐使用表单方式,通过可视化向导完成配置,若您对 Kubernetes 或 RayCluster 配置较为熟悉,可选择 YAML 方式,以获得更灵活的参数配置能力。

使用表单创建 RayCluster

登录 EMR 控制台,进入 EMR on TKE 实例详情页。在左侧导航栏中单击 RayCluster,在页面上方选择表单创建,进入 RayCluster 创建向导。


基础配置

RayCluster 名称:长度 1–53 个字符,仅支持小写字母。
命名空间:从下拉列表中选择,默认选中 KubeRay 部署所在的命名空间。

镜像配置-选择 veRL 镜像

1. 根据业务作业场景,您可以选择开启镜像配置功能。

2. 选择官方镜像,单击请选择

3. 在镜像包中选择“veRL”,选择当前 verl:0.5.0-py3.10-ray-2.52.0版本。

4. 选择完毕后回显镜像如下。


高可用

默认开启,生产环境建议保持开启。


资源组配置

RayCluster 由一个 headgroup 和若干个 workergroup 组成。
headgroup:默认创建 1 个 headgroup。您可以在 Pod 配置中设置 headgroup 的 CPU、内存、GPU(可选)、Pod 数量;同时可在参数配置中为 head Pod 配置 Labels、容忍调度、Env 以及节点调度策略(JSON),用于控制 Pod 的调度与运行环境。
workergroup:默认创建 1 个 workergroup。您可以修改 workergroup 名称,并在 Pod 配置中设置该组 Worker Pod 的 CPU、内存、GPU(可选)与 Pod 数量。workergroup 支持在 Pod 配置配置 常驻 Pod 数 以及 弹性伸缩范围(MIN/MAX)。workergroup 同样支持在参数配置中设置 Labels、容忍调度、Env 以及节点调度策略(JSON)。单个 RayCluster 最多可新增 20 个 workergroup。
说明:
为获得更好的大模型训练体验,本次示例 HeadGroup 选择8CPU、16GiB,WorkerGroup 资源规格选择16CPU、160GiB、GPU2卡、Pod2个、MIN2个、MAX2个,您也可以根据您的训练需求和购卡资源进行调整。

1. 单击编辑,弹窗展示 Headgroup 配置。

2. 高级配置支持 Ray 启动前执行的命令,与自定义 RayStartParms


资源组通用配置

开启状态:该功能默认关闭,开启后您可以进一步配置文件存储(CFS)、对象存储(COS)、高性能并行文件存储(CFS Turbo)以及缓存加速(GooseFS)。
在 CFS 中:您需要选择 CFS 实例、子目录、挂载卷。如您之前未创建过 CFS 示例,可单击 新建实例 进行创建。

在 COS 中:您需要选择 Secret、存储桶、子目录、挂载卷。如您之前未创建过 COS 示例,可单击 新建存储桶 进行创建。

在 CFSTurbo 中:您需要选择 CFS Turbo 、根目录、子目录、挂载卷。如您之前未创建过 CFS Turbo 示例,可单击 新建文件系统 进行创建。

在 GooseFS 中:您需要选择客户端版本、GooseFS 集群、命名空间等(GooseFS FUSE 与挂载选项后台已自动填入) 。前 GooseFS 使用需要开白申请,您可以通过立即申请开通试用。

WebIDE:WebIDE(Web Integrated Development Environment)是一种直接在浏览器中编写、运行、调试和管理代码的在线集成开发环境。Ray on EMR 支持 WebIDE 开发模式,输入挂载路径/home/ray/workspace,WebIDE 将默认挂载到/home/ray/workspace。

高级配置

依赖外部组件:开启后,可关联已有集群中部署的外部组件。由于所选组件部署在其他集群中,提供依赖组件的集群将无法直接销毁,需优先销毁所有依赖其组件的集群。详请查看组件配置共享
Token 鉴权:开启后,访问 RayCluster 时需通过系统自动生成的 Token 进行身份鉴权,该配置仅在创建阶段生效,RayCluster 创建完成后不支持开启或关闭状态变更。
说明:
在使用 veRL 架构时,不强制要求开启组件依赖,如您有其他集群部署了外部组件并有关联需求,您可选择开启。


完成创建

1. 完成上述配置并阅读勾选相关服务协议后,单击确定,提交任务。
2. 创建过程中可在右上角列表页查看进度。

3. 进入任务中心查看进度:


三、使用 veRL 进行大模型训练操作实践

方式一:使用 WebIDE 进行大模型后训练

1. 在创建 RayCluster 时,在资源组配置中,WebIDE 将默认挂载到/home/ray/workspace。

2. 如需要开启公网访问 WebIDE,可在计算服务外网处单击开启

3. 开启后展示确认弹窗。

4. 在控制台单击 RayCluster 后,展开即可在 head 节点看到 WebIDE。

5. 单击 WebIDE 后,外部浏览器跳转,输入集群密码。

6. 输入密码后,即展示 WebIDE,可在 WebIDE 上进行训练。


方式二:使用 JupyterLab 进行大模型后训练

1. 在 EG 配置环境

在实例服务中选择 EG,单击配置管理,选择 env.sh,单击编辑配置

单击新增配置项

在参数名中输入 RAY_CLUSTER_NAME ,值中 输入{rayClusterName}.{namespace},确认无误后单击保存
说明:
注意{rayClusterName}.{namespace}应替换为您所在的 rayClusterName 和所在的命名空间。

您可通过 RayCluster 列表,查看 ClusterName 和所在的命名空间。


2. 开启网络访问

登录 负载均衡,找对应实例下的安全组,单击开启

启用默认放通按钮,开启 LB 后端到 CVM 放通选项。

单击实例服务,选择 JUPYTERLAB/MLFLOW,单击更多 > 开启网络访问

选择公网 LB 访问,单击确定。CLB 的实例及 TKE 节点安全组端口需要放开53487端口。

您也可以选择内网 LB 访问,单击确定

3.访问 Jupyterlab 的 WebUI,进行模型训练
开启后单击查看信息,单击查看 WebUI,输入您的实例密码,即可访问 JUPYTERLAB/MLFLOW,开启大模型训练。

您可选择 Notebook(Ray on Kubernetes)或 Console(Ray on Kubernetes)进行模型训练。


方式三:登录 Pod 节点进行大模型后训练

除了在 JUPYTERLAB 中进行模型训练,您也可以直接登录 Pod 节点进行大模型训练。
1. 展开 RayCluster,单击登录

2. 在 Ray-head 中单击 OrcTerm 登录

3. Ray-worker 中单击 OrcTerm 登录

4. 登录后即可进行训练。


四、示例训练流程

本示例以 Qwen2.5-0.5B-Instruct gsm8k 数据集为例,展示如何提交任务并执行,您可以登录 Pod 或在 JUPYTERLAB 中执行下面的命令。

下载模型与数据

通过修改--local-dir 后的参数来配置模型的保存路径
下载模型
hf download qwen/Qwen2.5-0.5B-Instruct --local-dir /path/to/Qwen2.5-0.5B-Instruct

下载数据集并预处理:

下文所展示的代码源自 GitHub 项目,版本号 v0.5.0,具体位于该仓库的 examples/data_preprocess/gsm8k.py 文件,文件名为 gsm8k.py。

# Copyright 2024 Bytedance Ltd. and/or its affiliates
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Preprocess the GSM8k dataset to parquet format
"""

import argparse
import os
import re

import datasets

from verl.utils.hdfs_io import copy, makedirs


def extract_solution(solution_str):
solution = re.search("#### (\\\\-?[0-9\\\\.\\\\,]+)", solution_str)
assert solution is not None
final_solution = solution.group(0)
final_solution = final_solution.split("#### ")[1].replace(",", "")
return final_solution


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--local_dir", default="~/data/gsm8k")
parser.add_argument("--hdfs_dir", default=None)

args = parser.parse_args()

data_source = "openai/gsm8k"

dataset = datasets.load_dataset(data_source, "main")

train_dataset = dataset["train"]
test_dataset = dataset["test"]

instruction_following = 'Let\\'s think step by step and output the final answer after "####".'

# add a row to each data item that represents a unique id
def make_map_fn(split):
def process_fn(example, idx):
question_raw = example.pop("question")

question = question_raw + " " + instruction_following

answer_raw = example.pop("answer")
solution = extract_solution(answer_raw)
data = {
"data_source": data_source,
"prompt": [
{
"role": "user",
"content": question,
}
],
"ability": "math",
"reward_model": {"style": "rule", "ground_truth": solution},
"extra_info": {
"split": split,
"index": idx,
"answer": answer_raw,
"question": question_raw,
},
}
return data

return process_fn

train_dataset = train_dataset.map(function=make_map_fn("train"), with_indices=True)
test_dataset = test_dataset.map(function=make_map_fn("test"), with_indices=True)

local_dir = args.local_dir
hdfs_dir = args.hdfs_dir

train_dataset.to_parquet(os.path.join(local_dir, "train.parquet"))
test_dataset.to_parquet(os.path.join(local_dir, "test.parquet"))

if hdfs_dir is not None:
makedirs(hdfs_dir)

copy(src=local_dir, dst=hdfs_dir)
运行脚本预处理训练数据:
python gsm8k.py --local_save_dir /path/to/gsm8k
根据准备好的数据和模型配置运行脚本,/cfs_data/run.sh 举例:

#!/bin/bash
MODEL_PATH=/cfs_data/verl_demo/Qwen2.5-0.5B-Instruct
GSM8K_PATH=/cfs_data/verl_demo/gsm8k


set -x
python3 -m verl.trainer.main_ppo \\
data.train_files=$GSM8K_PATH/train.parquet \\
data.val_files=$GSM8K_PATH/test.parquet \\
data.train_batch_size=1024 \\
data.max_prompt_length=512 \\
data.max_response_length=512 \\
actor_rollout_ref.model.path=$MODEL_PATH \\
actor_rollout_ref.actor.optim.lr=1e-6 \\
actor_rollout_ref.model.use_remove_padding=True \\
actor_rollout_ref.actor.ppo_mini_batch_size=256 \\
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=16 \\
actor_rollout_ref.actor.fsdp_config.param_offload=False \\
actor_rollout_ref.actor.fsdp_config.optimizer_offload=False \\
actor_rollout_ref.model.enable_gradient_checkpointing=True \\
actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=32 \\
actor_rollout_ref.rollout.tensor_model_parallel_size=2 \\
actor_rollout_ref.rollout.name=vllm \\
actor_rollout_ref.rollout.gpu_memory_utilization=0.5 \\
actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=32 \\
actor_rollout_ref.ref.fsdp_config.param_offload=True \\
critic.optim.lr=1e-5 \\
critic.model.use_remove_padding=True \\
critic.model.path=$MODEL_PATH \\
critic.model.enable_gradient_checkpointing=True \\
critic.ppo_micro_batch_size_per_gpu=32 \\
critic.model.fsdp_config.param_offload=False \\
critic.model.fsdp_config.optimizer_offload=False \\
algorithm.kl_ctrl.kl_coef=0.001 \\
trainer.critic_warmup=0 \\
trainer.logger='["console", "mlflow"]' \\
trainer.project_name='verl_example_gsm8k' \\
trainer.experiment_name='qwen2.5_0.5b_function_rm' \\
trainer.n_gpus_per_node=2 \\
trainer.nnodes=2 \\
trainer.save_freq=-1 \\
trainer.test_freq=1 \\
trainer.total_epochs=15

使用 MLFLOW 进行训练监测

在您根据前序使用说明,配置好 EG 环境、并打开 MLFLOW 公网后,您可在 MLFLOW 的 WebUI 中查看并监测模型训练效果。
1. 登录 负载均衡,找对应实例下的安全组,单击开启,启用默认放通按钮,开启 LB 后端到 CVM 放通选项。

2. 单击开启

3. 单击实例服务,选择 MLFLOW,单击更多 > 开启网络访问

4. 选择公网 LB 访问,单击确定。CLB 的实例及 TKE 节点安全组端口需要放开5000端口。

5. 您也可以选择内网 LB 访问,单击确定

6. 回到 EMR on TKE 控制台,单击 MLFLOW 服务。开启公网后,单击查看信息 > 查看 WebUI,输入实例密码,即可登录 MLFLOW 监测模型训练。

7. MLflow-Overview:

8. MLflow-metrics: