数据截至 (上游 commit cfacd76a0bdd)
03 · 生成侧:推理副本与 AgentLoop
这一章讲什么: RL 的「采样」这一半。推理引擎怎么被部署成服务、请求怎么路由、一条轨迹的生成逻辑写在哪、多轮工具调用怎么做、生成到一半被打断怎么办。
1. 分三层看生成侧
生成这件事在 verl 里被切成三层,各管各的:
┌─────────────────────────────────────────────────────────┐
│ 第三层:AgentLoop —— 一条轨迹的业务逻辑 │
│ 单轮:发一次请求就完事 │
│ 多轮:生成→解析工具调用→执行→拼回上下文→再生成 │
└──────────────────────┬──────────────────────────────────┘
│ server_manager.generate(prompt_ids, ...)
┌──────────────────────▼──────────────────────────────────┐
│ 第二层:LLMServerClient —— 路由与容错 │
│ 粘性会话、最少在途负载均衡、被打断后自动续跑 │
└──────────────────────┬──────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────┐
│ 第一层:RolloutReplica —— 部署形态 │
│ 一个副本 = 一组 GPU 进程 + 一个 OpenAI 兼容 HTTP 服务 │
│ 三种模式:hybrid / colocated / standalone │
└─────────────────────────────────────────────────────────┘
这个分层带来的直接好处: 写一个新 agent(比如「会用搜索引擎的数学 agent」)只需要动第三层,完全不用关心 vLLM 怎么部署、请求打到哪台机器。
2. 第一层:RolloutReplica 与三种部署模式
2.1 什么是一个「副本」
RolloutReplica(verl/workers/rollout/replica.py:70)的 docstring 说得很直白:它等价于你在每个节点上手敲 python -m sglang.launch_server --node-rank i --nnode N。
副本大小由并行度算出(verl/workers/rollout/replica.py:107):
world_size = TP × DP × PP
nnodes = world_size / min(每节点GPU数, world_size)
所以一个 8 卡节点、TP=2 的配置会起 4 个副本,每个副本 2 张 卡。副本是负载均衡的最小单位。
2.2 三种模式
RolloutMode(verl/workers/rollout/replica.py:54)的三个成员,注释直接写明了使用场景:
| 模式 | 推理与训练的关系 | 何时用 | 初始化方法 |
|---|---|---|---|
HYBRID | 同一进程内融合,共享 GPU,切换要同步权重 | on-policy 训练(默认) | init_hybrid(:131) |
COLOCATED | 同一 placement group,不同进程,共享 GPU,切换不需要同步权重 | GRM(LLM 当裁判) | init_colocated(:160) |
STANDALONE | 独立 GPU 资源,训推分离 | off-policy 训练 | init_standalone(:189) |
三者的区别用一张图说清:
HYBRID COLOCATED STANDALONE
┌──────────┐ ┌──────────┐ ┌──────┐ ┌──────┐
│ GPU 0-7 │ │ GPU 0-7 │ │GPU0-7│ │GPU8-15│
│┌────────┐│ │┌───┐┌───┐│ │┌────┐│ │┌────┐│
││进程: ││ ││训练││推理││ ││训练││ ││推理││
││训练+推理││ ││进程││进程││ ││进程││ ││进程││
│└────────┘│ │└───┘└───┘│ │└────┘│ │└────┘│
└──────────┘ └──────────┘ └──────┘ └──────┘
权重同步=进程内 权重不需同步 权重跨机同步
(推理模型是别的模型) (NCCL/NIXL/Mooncake)
注意 HYBRID 模式下 init_hybrid 只是从已有的训练 WorkerGroup 里切出一段 handle(verl/workers/rollout/replica.py:138),不新起进程——推理引擎就长在训练进程里。