
verl 教程体系与集群启动器实战从 Agent Loop 工具调用到 Ray/SLURM/SkyPilot 分布式训练【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl本篇技术指南围绕 verlHybridFlow灵活高效的 RL 后训练框架仓库中的 examples/tutorial/README.md 展开系统梳理 verl 官方提供的与具体算法解耦的学习型教程与启动器资源Agent Loop API 入门笔记本、Ray API 速成笔记本、Ray-on-SLURM 任务模板以及基于 SkyPilot 的云上 PPO/GRPO 训练规格。读完本文你将掌握如何在 verl 中自定义 Tool工具、实现带代码沙箱的 ReAct 智能体、用 Ray 资源池组织分布式 Worker并能在 SLURM 集群与 Kubernetes/云平台上直接拉起 verl 强化学习训练任务。一、教程与启动器总览verl 的examples/tutorial/目录专门存放学习导向的内容特点是不绑定具体算法——无论是 PPO、GRPO 还是其他策略优化算法这些教程都适用。官方将其定位为起点而可运行的完整训练脚本则位于各 trainer 目录grpo_trainer/、ppo_trainer/、sft/等下。子目录内容说明agent_loop_get_started/以 Jupyter Notebookagent_loop_tutorial.ipynb逐步演示 Agent Loop API 的使用核心是训练一个带代码沙箱的 ReAct 智能体解决数学问题ray/Ray API 速成笔记本tutorial.ipynb从 Ray 基础讲到 RayWorkerGroup 与 Megatron 并行组slurm/Ray-on-SLURM 任务模板ray_on_slurm.slurm用于在 SLURM 集群上启动 Ray 集群并运行 verl 训练skypilot/SkyPilot PPO 与 GRPO 任务规格verl-ppo.yaml、verl-grpo.yaml面向 Kubernetes 集群或云平台 GPU 节点下文按单机上手 → 分布式抽象 → 集群/云端部署的进阶路径逐一展开。二、Agent Loop 入门训练一个会调用代码沙箱的 ReAct 智能体examples/tutorial/agent_loop_get_started/agent_loop_tutorial.ipynb是本仓库中最完整的端到端 Agent 教程。它演示了如何训练一个 ReActReasoning Acting智能体解决数学问题工作流程如下给定一道数学题智能体先让 LLM 生成回复与工具调用工具调用即要在沙箱中执行的 Python 代码若有工具调用智能体在代码沙箱中执行该 Python 代码执行完毕后智能体将沙箱返回的结果追加到对话历史智能体再次询问 LLM直到不再产生工具调用或达到最大上下文长度。2.1 前置准备首先安装 verl 包git clone https://github.com/verl-project/verl cd verl pip install -e .随后在 Notebook 中初始化 Ray 并准备演示资源import ray import verl ray.init() verl_config_dir os.path.join(os.path.dirname(verl.__file__), trainer/config)教程使用Qwen/Qwen3-1.7B作为 LLM并下载verl-team/lighteval-MATH-preprocessed数学评测数据集含 AMC 10/12、AIME 等竞赛题同时从测试集中截取前 100 条作为快速验证集。rollout 服务器支持 vllm 与 sglang 两种高性能推理后端教程在两者上都验证通过用户按需选择rollout_name vllm或sglang。2.2 基础工具调用自定义 WeatherToolverl 中要使用工具需要定义一个继承BaseTool的类并实现两个方法get_openai_tool_schema以OpenAIFunctionToolSchema格式返回工具的 OpenAI 函数 Schemaexecute用给定参数执行工具并以ToolResponse格式返回结果。BaseTool定义于 verl/tools/base_tool.py其完整接口还包括create为一条轨迹创建工具实例、calc_reward依据工具状态计算奖励、release释放工具实例execute返回三元组(tool_response, tool_reward_score, tool_metrics)其中tool_reward_score可作为工具调用的步骤级奖励。从源码结构看这是 verl 将工具调用与奖励计算打通的关键抽象为 Agentic RL 提供了统一的工具协议。教程中的天气工具实现如下借助 transformers 的get_json_schema从函数签名自动生成 Schemafrom transformers.utils import get_json_schema from verl.tools.base_tool import BaseTool, OpenAIFunctionToolSchema, ToolResponse class WeatherTool(BaseTool): def get_current_temperature(self, location: str, unit: str celsius): Get current temperature at a location. Args: location: The location to get the temperature for, in the format City, State, Country. unit: The unit to return the temperature in. Defaults to celsius. (choices: [celsius, fahrenheit]) Returns: the temperature, the location, and the unit in a dict return {temperature: 26.1, location: location, unit: unit} def get_openai_tool_schema(self) - OpenAIFunctionToolSchema: schema get_json_schema(self.get_current_temperature) return OpenAIFunctionToolSchema(**schema) async def execute(self, instance_id: str, parameters: dict, **kwargs) - tuple[ToolResponse, float, dict]: try: result self.get_current_temperature(**parameters) return ToolResponse(textjson.dumps(result)), 0, {} except Exception as e: return ToolResponse(textstr(e)), 0, {} weather_tool WeatherTool(config{}, tool_schemaNone)生成的 Schema 会自动包含函数名、描述、参数类型string、枚举约束celsius/fahrenheit与必填项location。2.3 启动独立 Rollout 服务器为快速验证工具调用教程绕过较重的混合引擎用 Hydra 组合ppo_trainer配置并启动一个独立standalonerollout 服务器。这里体现了多个关键配置项from hydra import compose, initialize_config_dir from verl.workers.rollout.replica import get_rollout_replica_class with initialize_config_dir(config_dirverl_config_dir): config compose( config_nameppo_trainer, overrides[ actor_rollout_ref.rollout.name rollout_name, # vllm 或 sglang actor_rollout_ref.rollout.modeasync, actor_rollout_ref.rollout.tensor_model_parallel_size1, actor_rollout_ref.model.path model_path, actor_rollout_ref.rollout.response_length4096, actor_rollout_ref.rollout.skip_tokenizer_initFalse, # 独立服务器没有 trainer 同步权重因此必须用 auto 加载格式 actor_rollout_ref.rollout.load_formatauto, actor_rollout_ref.rollout.engine_kwargs.vllm.enable_auto_tool_choiceTrue, actor_rollout_ref.rollout.engine_kwargs.vllm.tool_call_parserhermes, actor_rollout_ref.rollout.engine_kwargs.sglang.tool_call_parserqwen25, ], ) rollout_server_class get_rollout_replica_class(config.actor_rollout_ref.rollout.name) rollout_server rollout_server_class( replica_rank0, configconfig.actor_rollout_ref.rollout, model_configconfig.actor_rollout_ref.model, ) await rollout_server.init_standalone()随后用 OpenAI 兼容客户端向其发起聊天请求注意需把工具 Schema 传给服务器以引导 LLM 生成工具调用from openai import AsyncOpenAI client AsyncOpenAI(api_keydummy, base_urlfhttp://{rollout_server._server_address}/v1) messages [{role: user, content: Hey, whats the temperature in Paris right now?}] completion await client.chat.completions.create( modelconfig.actor_rollout_ref.model.path, messagesmessages, tools[weather_tool.tool_schema.model_dump(exclude_unsetTrue, exclude_noneTrue)], extra_body{chat_template_kwargs: {enable_thinking: False}}, ) message completion.choices[0].message.model_dump(exclude_unsetTrue, exclude_noneTrue) messages.append(message)模型会正确生成get_current_temperature的调用参数为{location: Paris, France}。将工具响应以role: tool追加回对话历史后再次查询LLM 即可给出最终答案。这一生成工具调用 → 执行 → 回填 → 再生成的循环正是 ReAct 的核心。2.4 高级工具调用实现一个朴素代码沙箱真实场景中更常见的是执行 LLM 生成的 Python 代码。教程实现了一个演示用沙箱一个基于 FastAPI 的 HTTP 服务器提供/run_code端点收到请求后把代码写入临时文件、用子进程执行并返回 stdout/stderr。它被包装为 Ray Actorray.remote(num_cpus1) class Sandbox: def __init__(self): self.address ray._private.services.get_node_ip_address() self.port self._get_free_port() asyncio.create_task(self._start_fastapi_server()) async def code_execution(self, request: Request): request_json await request.json() code request_json[code] _, temp_file tempfile.mkstemp(suffix.py, prefixtemp_code, dirNone, textTrue) with open(temp_file, w) as f: f.write(code) try: process await asyncio.create_subprocess_exec( sys.executable, temp_file, stdoutasyncio.subprocess.PIPE, stderrasyncio.subprocess.PIPE ) stdout, stderr await process.communicate() response { status: Success if process.returncode 0 else Failed, run_result: {status: Finished, stdout: stdout.decode(), stderr: stderr.decode(), return_code: process.returncode}, } return JSONResponse(contentresponse) finally: try: os.unlink(temp_file) except Exception: pass注意该朴素沙箱仅用于演示严禁用于生产环境。生产部署应使用 docker/kata 容器以获得更强的隔离与安全限制。对应的SandboxTool通过aiohttp把代码片段 POST 到沙箱地址。仓库中同目录下的 examples/tutorial/agent_loop_get_started/sandbox.py 提供了同样思路的独立实现。其execute中还有两个实用细节用正则py(.*?)抽取代码块以及在脚本末尾自动补print(...)语句因为部分模型生成的脚本不会显式打印结果更优的做法是在 SFT 阶段让模型默认打印教程中省略了该阶段。import re import aiohttp class SandboxTool(BaseTool): def __init__(self, config: dict, tool_schema: OpenAIFunctionToolSchema): super().__init__(config, tool_schema) self.code_pattern re.compile(rpy(.*?), re.DOTALL) async def code_interpreter(self, code: str) - str: async with aiohttp.ClientSession() as session: async with session.post(self.config.get(sandbox_fusion_url), json{code: code}) as resp: resp.raise_for_status() result await resp.json() stdout, stderr result[run_result][stdout], result[run_result][stderr] return stdout stderr def get_openai_tool_schema(self) - OpenAIFunctionToolSchema: schema get_json_schema(self.code_interpreter) return OpenAIFunctionToolSchema(**schema) async def execute(self, instance_id: str, parameters: dict, **kwargs) - tuple[str, float, dict]: code parameters[code] matches self.code_pattern.findall(code) if matches: code matches[0].strip() lines code.split(\n) for i, line in reversed(list(enumerate(lines))): if line : continue if not lines[i].startswith(print): lines[i] fprint({line}) break code \n.join(lines) result await self.code_interpreter(code) return ToolResponse(textresult), 0.0, {}对有效代码如sympy.sqrt(3)与无效代码如未导入sympy就调用分别测试可看到沙箱正确返回 stdout 与完整 Traceback——错误信息对 LLM 非常关键它能让模型在下一轮生成中修复代码。2.5 手写 ReAct 循环验证在进入 RL 训练前教程先用一个简单的 while 循环模拟 ReAct 智能体在真实数学题上验证生成 → 执行 → 回填闭环每次聊天若finish_reason tool_calls就解析参数并调用sandbox_tool.execute把结果以role: tool追加回messages否则结束。实际运行中模型会为y 2/(x²x-6)的垂直渐近线问题写出求解x²x-60的 sympy 代码沙箱返回[-3, 2]模型据此给出\boxed{2}的最终答案。2.6 端到端 RL 训练接入内置 ToolAgentLoop工具验证通过后即可进行端到端强化学习训练。为简化 Agentic RLverl 提供 Agent Loop 抽象详见 docs/advance/agent_loop.rst允许用户自定义搜索智能体、数学智能体、SWE 智能体、GUI 智能体等并内置两个开箱即用的循环SingleTurnAgentLoop单轮对话、不调用工具ToolAgentLoop多轮对话、支持工具调用与交互。使用ToolAgentLoop时只需在 JSON/YAML 配置文件中为每个工具声明两个字段class_name工具的完整限定类名用于动态加载自定义工具类config初始化工具实例的关键字参数。把沙箱工具配置导出为tool_config.json{ tools: [ { class_name: sandbox.SandboxTool, config: { type: native, sandbox_fusion_url: http://sandbox_address/run_code } } ] }随后通过 Hydra 覆盖ppo_trainer配置接入 GRPO 算法与多轮工具调用训练。以下为教程中的完整配置覆盖项config compose( config_nameppo_trainer, overrides[ algorithm.adv_estimatorgrpo, data.train_files train_file, data.val_files test_file, data.return_raw_chatTrue, data.train_batch_size32, data.max_prompt_length1024, data.max_response_length1024, data.apply_chat_template_kwargs.enable_thinkingFalse, # actor 相关 actor_rollout_ref.model.path model_path, actor_rollout_ref.actor.ppo_mini_batch_size8, actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu8, actor_rollout_ref.actor.fsdp_config.param_offloadTrue, actor_rollout_ref.actor.fsdp_config.optimizer_offloadTrue, # rollout 相关 actor_rollout_ref.rollout.name rollout_name, actor_rollout_ref.rollout.modeasync, actor_rollout_ref.rollout.tensor_model_parallel_size1, actor_rollout_ref.rollout.n8, actor_rollout_ref.rollout.multi_turn.tool_config_path tool_config_path, actor_rollout_ref.rollout.agent.default_agent_looptool_agent, actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu8, # trainer 相关 trainer.val_before_trainTrue, trainer.log_val_generations10, trainer.n_gpus_per_node8, trainer.test_freq-1, trainer.total_training_steps5, trainer.logger[console,tensorboard, wandb], trainer.project_nameverl, trainer.experiment_name os.path.basename(model_path), ], ) from verl.trainer.main_ppo import main main(config)其中两个关键开关actor_rollout_ref.rollout.multi_turn.tool_config_path指向工具配置 JSONactor_rollout_ref.rollout.agent.default_agent_looptool_agent启用多轮工具智能体循环。演示仅训练 5 步可通过 wandb 指标验证训练过程num_turns每步对话轮数的 min/max/mean与critic rewards每步奖励的 min/max/mean。更贴近论文复现的 Agentic RL 配方如 ReTool、CollabLLM、DeepEyes 等存放在仓库之外维护的 verl-recipe 项目中本文不再展开。三、Ray API 速成从单 Actor 到 RayWorkerGroupexamples/tutorial/ray/tutorial.ipynb是 verl 底层分布式抽象SingleController见 verl/single_controller的速成教材共 4 章。3.1 Ray 基础Accumulatorray.init()在本机建立 head/worker 一体的本地 Ray 集群。把普通类标注ray.remote后其实例化即产生一个独立进程可视为 RPC 服务accumulator.add.remote(10)立即返回ObjectRef需用ray.get()获取实际结果ray.remote class Accumulator: def __init__(self): self.value 0 def add(self, x): self.value x def get_value(self): return self.value accumulator Accumulator.remote() value ray.get(accumulator.get_value.remote()) # 0 accumulator.add.remote(10) new_value ray.get(accumulator.get_value.remote()) # 103.2 资源池与 RayWorkerGroupverl 在 Ray 之上抽象出ResourcePool资源池与WorkerGroupWorker 组。RayResourcePool([4], use_gpuTrue)声明 4 个 GPU 资源RayClassWithInitArgs封装 Worker 类的构造参数RayWorkerGroup则在资源池上实例化一组 Worker。参数传递原则execute_all_sync的入参是长度为world_size的列表各元素按序分发给每个 Worker返回值同样是每个 Worker 返回值的列表from verl.single_controller.base import Worker from verl.single_controller.ray.base import RayClassWithInitArgs, RayResourcePool, RayWorkerGroup, merge_resource_pool resource_pool RayResourcePool([4], use_gpuTrue) ray.remote class GPUAccumulator(Worker): def __init__(self) - None: super().__init__() self.value torch.zeros(size(1,), devicecuda) self.rank # 初始值为 rank def add(self, x): self.value x return self.value.cpu() class_with_args RayClassWithInitArgs(clsGPUAccumulator) worker_group RayWorkerGroup(resource_pool, class_with_args) print(worker_group.execute_all_sync(add, x[1, 1, 1, 1])) # [tensor([1.]), 2, 3, 4]GPU 资源共享映射到同一资源池的多个 RayWorkerGroup 共享 GPU。merge_resource_pool(resource_pool, resource_pool_1)可合并两个资源池得到更大的组上面的 4 GPU 组再加 1新 4 GPU 组后合并为 8 GPU 组各组world_size分别为 4、4、8且运行在独立 GPU 上互不干扰。3.3 装饰器驱动的 Dispatch / Execute / Collect直接手写execute_all_sync不便编码verl 提供register(Dispatch.X)装饰器让 Worker 内的方法被 WorkerGroup 直接调用并自动完成参数分发与结果收集from verl.single_controller.base.decorator import Dispatch, Execute, register ray.remote class GPUAccumulatorDecorator(Worker): def __init__(self) - None: super().__init__() self.value torch.zeros(size(1,), devicecuda) self.rank register(Dispatch.ONE_TO_ALL) # 单个输入自动分发给所有 Worker def add(self, x): self.value self.value x return self.value.cpu() gpu_accumulator_decorator RayWorkerGroup(resource_pool_merge, class_with_args) print(gpu_accumulator_decorator.add(x10)) # 10 被自动广播到每个 Worker用户还可自定义 dispatch/collect 函数如把长度为 2 的输入按i % 2交错扩充到全组并支持仅在 rank_zero 上执行 RPCfrom verl.single_controller.base.decorator import Dispatch, collect_all_to_all, register def two_to_all_dispatch_fn(worker_group, *args, **kwargs): for arg in args: assert len(arg) 2 for i in range(worker_group.world_size - 2): arg.append(arg[i % 2]) ... return args, kwargs ray.remote class TestActor(Worker): def __init__(self, x) - None: super().__init__() self._x x def foo(self, y): return self._x y register(dispatch_modeDispatch.ALL_TO_ALL, execute_modeExecute.RANK_ZERO) def foo_rank_zero(self, x, y): return self._x y x register(dispatch_mode{dispatch_fn: two_to_all_dispatch_fn, collect_fn: collect_all_to_all}) def foo_custom(self, x, y): return self._x y x worker_group RayWorkerGroup(resource_pool, RayClassWithInitArgs(clsTestActor, x2)) assert worker_group.foo_custom(x[1, 2], y[5, 6]) [8, 10, 8, 10] assert worker_group.foo_rank_zero(x1, y2) 53.4 NVMegatronRayWorkerGroupMegatron 透明化第四章演示NVMegatronRayWorkerGroup位于 verl/single_controller/ray/megatron。受 Ray 限制目前RayResourcePool的max_colocate_count只能为 1即每块 GPU 一个进程。该组在内部创建 Megatron 并行状态并运行一个 TP4 切分的 Llama MLP 层使用复杂的Dispatch.MEGATRON_COMPUTE分发模式假设用户按 DP 维传入已切分的数据数据被分发给同一 DP 组内的所有 tp/pp rank最终只从 tp0、最后一个 pp 收集输出。这样对于只在 driver 上写代码的用户RPC 背后的 Megatron 是完全透明的。ray.remote class MLPLayerWorker(MegatronWorker): def __init__(self): super().__init__() rank int(os.environ[LOCAL_RANK]) torch.distributed.init_process_group(backendnccl) torch.cuda.set_device(rank) mpu.initialize_model_parallel(tensor_model_parallel_size4, pipeline_model_parallel_size1, ...) register(Dispatch.ONE_TO_ALL) def init_model(self, config): ... self.parallel_layer ParallelLlamaMLP(configconfig, megatron_configmegatron_config) register(Dispatch.MEGATRON_COMPUTE) def run_layer(self, x): x x.to(cuda) return self.parallel_layer(x) layer_worker_group NVMegatronRayWorkerGroup(resource_poolresource_pool, ray_cls_with_initlayer_cls) print(layer_worker_group.world_size, layer_worker_group.tp_size, layer_worker_group.pp_size, layer_worker_group.dp_size) # 4 4 1 1 x torch.rand(size(seq_len, batch_size, hidden_size), dtypetorch.float32) output layer_worker_group.run_layer([x]) # 入参必须是 size1 的列表保证输入等于 DP 维 print(output[0].shape) # torch.Size([2048, 16, 4096])四、Ray-on-SLURM在 SLURM 集群上拉起 verl 训练examples/tutorial/slurm/ray_on_slurm.slurm 是一个可直接sbatch提交的模板负责在 SLURM 分配的计算节点上先启动 Ray 集群再运行 verl 的 PPO 训练。4.1 头部参数与替换项#!/bin/bash #SBATCH --job-nameverl-ray-on-slurm #SBATCH --nodes2 #SBATCH --ntasks-per-node1 #SBATCH --mem200G #SBATCH --partitionyour-partition #SBATCH --time01:00:00 #SBATCH --accountyour-account #SBATCH --gpus-per-node4 #SBATCH --cpus-per-task64 #SBATCH --outputslurm-%j.out #SBATCH --errorslurm-%j.err # 替换为你的实际路径 verl_workdir/path/to/verl train_files/path/to/gsm8k/train.parquet val_files/path/to/gsm8k/test.parquet apptainer_image_path/path/to/verl-ngc.sif # 多网卡集群可选将 Ray 绑定到特定网卡例如 # RAY_NETWORK_INTERFACEib0 sbatch ray_on_slurm.slurm RAY_NETWORK_INTERFACE${RAY_NETWORK_INTERFACE:-}其中apptainer_image_path对应 verl 官方 NGC 容器镜像运行时通过 Apptainer 的--nv --bind挂载 GPU 与工作目录。4.2 关键机制获取节点 IPget_node_ipv4()用srun --overlap -w node在指定节点上执行ip -4 -o addr show dev iface提取 IPv4 地址未指定网卡时退化为hostname --ip-address并处理 IPv6 多地址回退。启动 Ray head在nodes_array[0]上ray start --head --node-ip-address$head_node_ip --port6379 --num-cpus --num-gpus --block。启动 Ray worker对剩余节点逐一ray start --address $ip_head ...间隔sleep 5避免并发冲突。提交训练最后在 head 节点上以PYTHONUNBUFFERED1 srun --overlap运行python3 -m verl.trainer.main_ppo通过tee verl_demo_slurm.log留存日志。4.3 训练命令行解析模板中的 PPO 训练GSM8K Qwen2.5-0.5B-Instruct2 节点 × 4 GPU展示了 verl 配置的组织结构可归纳为五大块datatrain_files/val_files、train_batch_size256、max_prompt_length512、max_response_length256actor_rollout_ref模型路径、optim.lr1e-6、ppo_mini_batch_size64、ppo_micro_batch_size_per_gpu4、log_prob_micro_batch_size_per_gpu8、tensor_model_parallel_size1、rollout 后端namevllm、gpu_memory_utilization0.4criticoptim.lr1e-5、model.path与 actor 相同、ppo_micro_batch_size_per_gpu4algorithmadv_estimatorgae、kl_ctrl.kl_coef0.001、use_kl_in_rewardFalsetrainern_gpus_per_node${SLURM_GPUS_PER_NODE}、nnodes${SLURM_NNODES}、save_freq10、test_freq10、total_epochs15、loggerconsole、val_before_trainFalse。训练脚本会随 SLURM 变量自动适配节点规模trainer.n_gpus_per_node与trainer.nnodes取自SLURM_GPUS_PER_NODE/SLURM_NNODES因此该模板可复用于不同规模的集群分配。五、SkyPilot在 Kubernetes 与云平台上跑 PPO/GRPOexamples/tutorial/skypilot/README.md 讲解如何使用 SkyPilot 在 Kubernetes 集群或 AWS/GCP/Azure 云平台的 GPU 节点上运行 verl 强化学习训练。5.1 安装与配置按目标平台选择安装方式# 仅 Kubernetes pip install skypilot[kubernetes] # AWS pip install skypilot[aws] # Google Cloud Platform pip install skypilot[gcp] # Azure pip install skypilot[azure] # 多平台 pip install skypilot[kubernetes,aws,gcp,azure]平台凭据配置完成后导出实验追踪所需的环境变量export WANDB_API_KEYyour-wandb-api-key # Weights Biases 追踪 export HF_TOKENyour-huggingface-token # 如需访问 gated Hugging Face 模型5.2 PPO 与 GRPO 任务在仓库根目录执行# PPOGSM8K 数据集 Qwen2.5-0.5B-Instruct2 节点 H100参考 examples/ppo_trainer/ sky launch -c verl-ppo examples/tutorial/skypilot/verl-ppo.yaml --secret WANDB_API_KEY -y # GRPOMATH 数据集 Qwen2.5-7B-Instruct2 节点内存优化配置参考 examples/grpo_trainer/ sky launch -c verl-grpo examples/tutorial/skypilot/verl-grpo.yaml --secret WANDB_API_KEY -yAgent Loop 与工具使用训练目前没有预置的 SkyPilot 任务官方建议先用 Agent Loop 教程 验证模型、工具与沙箱配置再适配为集群任务。5.3 任务规格解析两个 YAML 的资源配置一致infra: k8s可改为infra: aws/infra: gcp等、accelerators: H100:1、memory: 128、官方 CUDA 12.6 Docker 镜像verlai/verl:base-verl0.5-cu126-cudnn9.8-torch2.7.0-fa2.7.4、暴露 8265 端口Ray Dashboard、2 节点并通过secrets: WANDB_API_KEY声明密钥。setup阶段自动执行克隆并pip3 install -v -e .[vllm]安装 verl、安装flashinfer-python、运行examples/data_preprocess/下的数据预处理脚本下载数据集PPO 用 gsm8k.pyGRPO 用 math_dataset.py。run阶段通过 SkyPilot 注入的环境变量协调多节点SKYPILOT_NODE_IPS节点 IP 列表、SKYPILOT_NUM_NODES、SKYPILOT_NODE_RANK、SKYPILOT_NUM_GPUS_PER_NODE。head 节点rank 0启动ray start --head --port6379 --dashboard-host0.0.0.0 --dashboard-port8265并以最多 30 次、每次 10 秒的轮询等待所有节点通过ray status加入集群worker 节点则ray start --address $HEAD_IP:6379。集群就绪后在 head 节点运行python3 -m verl.trainer.main_ppo。两个任务的训练配置差异体现了 PPO 与 GRPO 的典型设置维度verl-ppo.yamlGSM8K 0.5Bverl-grpo.yamlMATH 7B算法默认 PPOalgorithm.adv_estimator未指定algorithm.adv_estimatorgrpo批大小train_batch_size256、ppo_mini_batch_size64train_batch_size32、ppo_mini_batch_size16长度限制max_prompt_length512、max_response_length256max_prompt_length256、max_response_length256内存优化—use_remove_paddingTrue、enable_gradient_checkpointingTrue、FSDP 参数/优化器卸载、gpu_memory_utilization0.4、enable_chunked_prefillTrue、max_num_batched_tokens2048损失细节—use_kl_lossFalse、entropy_coeff0、use_kl_in_rewardFalse、critic_warmup0保存/测试save_freq20、test_freq20、total_epochs2save_freq-1、test_freq-1、total_epochs1GRPO 的 7B 模型通过移除 padding 梯度检查点 FSDP 参数/优化器双卸载 vLLM 低显存利用率 chunked prefill组合将内存开销压到 2 节点可承载的水平可作为中等规模模型的参考配方。5.4 启动选项与作业监控sky launch常用选项-c name指定集群名以便管理作业--secret KEY传递 API 密钥可重复使用-y跳过确认提示。使用 gated Hugging Face 模型时需在任务的secrets段增加HF_TOKEN并用--secret HF_TOKEN传入。作业监控命令sky status # 查看集群状态 sky logs verl-ppo # 查看 PPO 作业日志 ssh verl-ppo # SSH 进入 head 节点 sky status --endpoint 8265 verl-ppo # 获取 Ray Dashboard URL sky down verl-ppo # 停止集群六、如何继续深入本文覆盖的 4 个教程资源对应 verl 使用路径上的不同阶段先用 Agent Loop 笔记本打通模型 工具 沙箱的单机验证配合 verl/tools/base_tool.py 与 docs/advance/agent_loop.rst 理解工具协议与循环抽象再通过 Ray 教程理解分布式 Worker 组织源码见 verl/single_controller最后借助 SLURM/SkyPilot 启动器将训练规模化。需要投入真实训练时以各 trainer 目录下的可运行脚本为准——例如 examples/grpo_trainer、examples/ppo_trainer 与 examples/sft 提供了覆盖 FSDP、Megatron、veomni 等多种后端与不同规模模型的启动脚本更复杂的多轮工具数据预处理可参考 examples/data_preprocess 下的gsm8k_multiturn_w_tool.py、dapo_multiturn_w_tool.py等脚本。把教程中的配置项与真实训练脚本两相对照即可快速完成从跑通 demo到复现论文级实验的过渡。【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考