一、准备条件
确认您已开通腾讯云,并且已创建 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

基础配置
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
下载数据集并预处理:
# 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 argparseimport osimport reimport datasetsfrom verl.utils.hdfs_io import copy, makedirsdef extract_solution(solution_str):solution = re.search("#### (\\\\-?[0-9\\\\.\\\\,]+)", solution_str)assert solution is not Nonefinal_solution = solution.group(0)final_solution = final_solution.split("#### ")[1].replace(",", "")return final_solutionif __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 iddef make_map_fn(split):def process_fn(example, idx):question_raw = example.pop("question")question = question_raw + " " + instruction_followinganswer_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 datareturn process_fntrain_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_dirhdfs_dir = args.hdfs_dirtrain_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/bashMODEL_PATH=/cfs_data/verl_demo/Qwen2.5-0.5B-InstructGSM8K_PATH=/cfs_data/verl_demo/gsm8kset -xpython3 -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:
