一、一、准备条件
·确认你已开通腾讯云,并且已创建 EMR on TKE 产品中的 Ray 服务。EMR on TKE 集群的创建详情请参见 创建集群。
·目前容器类型选择计算资源和 TKE 都支持创建 Ray 集群实例。
·实例类型:机器学习
·产品版本:EMR-TKE-AI-V1.2.0
注意:说明:
注意:使用 veRL 镜像进行后训练,在部署服务中需同步部署 JUPYTERLAB、EG、MLFLOW、TCRAY 组件。
三、使用表单创建 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. 进入任务中心查看进度:
十二、方式一:使用 WebIDE 进行大模型后训练
1. 在创建 RayCluster 时,在资源组配置中,WebIDE 将默认挂载到/home/ray/workspace。
2. 如需要开启公网访问 WebIDE,可在计算服务外网处单击开启。
3. 开启后展示确认弹窗。
4. 在控制台单击 RayCluster 后,展开即可在 head 节点看到 WebIDE。
5. 单击 WebIDE 后,外部浏览器跳转,输入集群密码。
6. 输入密码后,即展示 WebIDE,可在 WebIDE 上进行训练。
十四、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 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 None final_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 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/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
20、使用 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: