跳到内容

VERL

快捷方式

您可以使用快捷方式 agl.VERL(...) 创建一个 VERL 实例。

import agentlightning as agl

agl.VERL(...)

安装

pip install agentlightning[verl]

警告

为了避免各种兼容性问题,请按照 安装指南 中的步骤设置 VERL 及其依赖项。除非您已经安装了兼容版本的 PyTorch,否则直接使用 pip install agentlightning[verl] 安装 VERL 可能会导致问题。

读者须知

VERL 在本文中指的是 Agent-lightning 提供的 VERL 框架的封装器。它是 agentlightning.Algorithm 的子类。为了与 VERL 框架区分开来,所有对 VERL 框架的引用都将使用术语“VERL 框架”,而所有对 Agent-lightning 封装器的引用都将突出显示链接。

资源

VERL 不期望任何初始资源。第一个 LLM 端点直接从 VERL 配置(.actor_rollout_ref.model.path)部署。资源键始终为 main_llm

VERL 当前不支持同时优化多个 LLM

注意

VERL 创建的资源类型实际上是一个 ProxyLLM,它是 LLM 类型的一个子类。该对象包含由 VERL 提供的 **URL 模板**,其中包含用于 rollout 和 attempt ID 的占位符。当在代理端开始 rollout 时,框架使用当前的 rollout_idattempt_id 格式化此模板,生成最终的唯一端点 URL。此 URL 指向 VERL 的内部代理,允许它拦截和记录特定 attempt 的所有流量,以便进行跟踪和负载均衡。对于使用 @rollout 装饰器创建的代理,此模板解析由自动处理(“自动剥离”)。基于类的代理需要手动解析 ProxyLLM 使用 rollout 上下文。

proxy_llm = resources["main_llm"]
proxy_llm.get_base_url(rollout.rollout_id, rollout.attempt.attempt_id)

自定义

在内部,VERL 通过 Adapter 将每个代理执行分解为 prompt-response 对,并将它们与相应的奖励信号关联为 Triplet 对象。从轨迹中的最后一个 triplet 派生的最终标量奖励,按照 相同的分配策略 传播到所有前面的 triplet。这确保了每个 triplet 接收到相同的奖励信号,并且可以作为 VERL 框架内的有效 RLHF 轨迹进行独立优化。

目前,VERL 不暴露对其奖励传播或信用分配机制的细粒度控制。需要自定义奖励塑造或轨迹分解的用户建议直接克隆和修改 VERL 源代码实现。

使用 VERL 的教程

参考 - 入口点

agentlightning.algorithm.verl

VERL

Bases: Algorithm

由 VERL PPO 运行器驱动的 VERL 算法。

警告

高级自定义目前需要复制 VERL 源代码并直接修改它。在未来的版本中将提供用于覆盖训练行为的本机钩子。

参数

  • config (dict[str, Any]) –

    字典镜像传递给 VERL CLI 的覆盖项。覆盖项通过 Hydra 与 VERL 的打包默认值合并,然后再启动训练。

  • trainer_cls (Optional[Type[AgentLightningTrainer]], default: None ) –

    训练器类的可选覆盖。实验性。

  • daemon_cls (Optional[Type[AgentModeDaemon]], default: None ) –

    守护程序类的可选覆盖。实验性。

轨迹聚合(实验性)

轨迹级别聚合将整个多轮 rollout 合并到一个单独的、masked 训练样本中,因此 GPU 时间在每个轨迹上花费一次,而不是在每个轮次上花费 N 次。通过启用它:

config["agentlightning"]["trace_aggregator"] = {
    "level": "trajectory",
    "trajectory_max_prompt_length": 4096,
    "trajectory_max_response_length": 34384,
}

保持对话结构化(消息列表而不是手动字符串连接),以便前缀匹配可以拼接轨迹。trajectory_max_prompt_length 应该设置为第一个轮次的 prompt 的最大长度,而 trajectory_max_response_length 应该设置为整个轨迹中代理响应的累积最大长度。将 debug=True 加上 mismatch_log_dir,当您需要检查重新标记或聊天模板不匹配时。有关更多详细信息,请参阅 此博客文章

示例

from agentlightning.algorithm.verl import VERL

algorithm = VERL(
    config={
        "algorithm": {
            "adv_estimator": "grpo",
            "use_kl_in_reward": False,
        },
        "data": {
            "train_batch_size": 32,
            "max_prompt_length": 4096,
            "max_response_length": 2048,
        },
        "actor_rollout_ref": {
            "rollout": {
                "tensor_model_parallel_size": 1,
                "n": 4,
                "log_prob_micro_batch_size_per_gpu": 4,
                "multi_turn": {"format": "hermes"},
                "name": "vllm",
                "gpu_memory_utilization": 0.6,
            },
            "actor": {
                "ppo_mini_batch_size": 32,
                "ppo_micro_batch_size_per_gpu": 4,
                "optim": {"lr": 1e-6},
                "use_kl_loss": False,
                "kl_loss_coef": 0.0,
                "entropy_coeff": 0,
                "clip_ratio_low": 0.2,
                "clip_ratio_high": 0.3,
                "fsdp_config": {
                    "param_offload": True,
                    "optimizer_offload": True,
                },
            },
            "ref": {
                "log_prob_micro_batch_size_per_gpu": 8,
                "fsdp_config": {"param_offload": True},
            },
            "model": {
                "path": "Qwen/Qwen2.5-1.5B-Instruct",
                "use_remove_padding": True,
                "enable_gradient_checkpointing": True,
            },
        },
        "trainer": {
            "n_gpus_per_node": 1,
            "val_before_train": True,
            "critic_warmup": 0,
            "logger": ["console", "wandb"],
            "project_name": "AgentLightning",
            "experiment_name": "calc_x",
            "nnodes": 1,
            "save_freq": 64,
            "test_freq": 32,
            "total_epochs": 2,
        },
    }
)
trainer.fit(algorithm, train_dataset=my_train_dataset)
get_client()

创建绑定到 VERL 管理的 Agent Lightning 服务器的客户端。

已弃用

自 v0.2 起。

run(train_dataset=None, val_dataset=None)

使用配置的运行时上下文启动 VERL PPO 入口点。

参数

  • train_dataset (Optional[Dataset[Any]], default: None ) –

    转发到 VERL 进行训练的可选数据集。

  • val_dataset (Optional[Dataset[Any]], default: None ) –

    转发到 VERL 进行评估的可选数据集。

引发

  • ValueError

    如果所需的依赖项(例如存储、LLM 代理或适配器)在使用 V1 执行模式时已被垃圾回收。

参考 - 实现

agentlightning.verl

此包包含 VERL 与 Agent Lightning 的hacky集成。

AgentLightningTrainer

基类: RayPPOTrainer

基于 Agent 的强化学习的专用 PPO 训练器。

此训练器专为模型通过 AgentLightningServer 与外部环境、工具或 API 交互的场景而设计。它简化了训练循环,去除了原始 RayPPOTrainer 中复杂的条件逻辑,并专注于 Agent 模式工作流。

与 RayPPOTrainer 的主要区别

  1. 使用 AgentModeDaemon 进行服务器通信
  2. 简化的数据流,无需 pop/union 操作
  3. 通过 Agent Daemon 直接进行批量处理
  4. 使用 Agent 模式验证进行精简的验证

AgentModeDaemon

使用 AgentLightningServer SDK 的 AgentModeDaemon。

此类管理服务器生命周期、任务队列和结果检索,同时运行 LLM 请求的代理服务器。它保留了原始接口,以与 RayPPOTrainer 兼容。

clear_data_and_server()

重置守护进程的内部状态,为下一次运行做准备。

get_test_metrics()

计算并返回验证运行的指标。

get_train_data_batch(max_prompt_length, max_response_length, device, global_steps)

处理完成的 rollout 以生成训练数据批次。

此函数重构了原始 AgentModeDaemon 中的逻辑,使用从新服务器架构检索的数据。它处理填充、截断和张量创建,用于 PPO 训练循环。

run_until_all_finished(verbose=True)

同步等待所有排队的任务完成并报告。

set_up_data_and_server(data, server_addresses, is_train=True)

设置数据和服务器资源的同步包装器。

start()

启动主 AgentLightningServer 和代理服务器。

get_left_padded_ids_and_attention_mask(ids, max_length, pad_token_id)

将 token ID 序列左侧填充(或截断)到固定长度,并构建相应的注意力掩码。

参数

  • ids (List[int]) –

    原始 token ID 列表。

  • max_length (int) –

    填充/截断后的期望总长度。

  • pad_token_id (int) –

    用于填充的 ID。

返回

  • padded_ids ( any ) –

    长度 == max_length 的列表。

  • attention_mask ( any ) –

    相同长度的列表:非填充 token 为 1,填充为 0。

get_right_padded_ids_and_attention_mask(ids, max_length, pad_token_id)

将 token ID 序列右侧填充(或截断)到固定长度,并构建相应的注意力掩码。

参数

  • ids (List[int]) –

    原始 token ID 列表。

  • max_length (int) –

    填充/截断后的期望总长度。

  • pad_token_id (int) –

    用于填充的 ID。

返回

  • padded_ids ( any ) –

    长度 == max_length 的列表。

  • attention_mask ( any ) –

    相同长度的列表:非填充 token 为 1,填充为 0。