slime 中基于 YAML 的 SGLang 高级引擎部署:--sglang-config 完整指南
【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime
--sglang-config是 slime(面向 RL Scaling 的 LLM 后训练框架)提供的基于 YAML 的 SGLang 引擎部署配置系统。通过一份 YAML 文件,你可以在一套训练流程中同时编排多模型服务(actor / reference / reward)、Prefill-Decode (PD) 分离、异构服务器组(不同 TP 大小、不同 worker 类型、不同 ServerArgs 覆盖),甚至将其作为复杂推理拓扑的独立 SGLang 启动器。读完本文,你将掌握--sglang-config的完整配置语法、7 种实战部署模式、router 会话亲和路由原理,以及它与旧参数(--prefill-num-servers、--rollout-external-engine-addrs)的边界与取舍。
架构概览:从单模型单 Router 到多模型多 Router
在默认配置(不使用--sglang-config)下,slime 部署单个模型,放在单个 router后面,使用统一的服务器组:
使用--sglang-config后,SGLang 部署扩展为多模型、多 router拓扑:
核心设计原则:
- 每个模型拥有独立的 router。模型在路由层隔离,支持独立的负载均衡和容错;一个模型的路由故障不会影响其他模型的流量。
- 同一模型内的服务器组可以异构。不同组可以有不同的 TP 大小、worker 类型(prefill / decode / regular / placeholder)以及独立的 SGLang ServerArgs 覆盖。
- 权重同步按模型维度。只有
update_weights: true的模型会接收来自训练的权重更新;冻结的模型(reference、reward 等)保持 checkpoint 原样服务,这避免了向只读模型推送训练权重带来的额外开销与风险。
从源码看,这一设计落实在slime/backends/sglang_utils/sglang_config.py的三层数据类上:SglangConfig(顶层,持有模型列表)→ModelConfig(单个模型的拓扑)→ServerGroupConfig(单个服务器组)。每个模型在启动后都会在args.sglang_model_routers({ model_name: (ip, port) }字典)中登记自己的 router 地址,供自定义 rollout 函数按名路由。
配置格式与字段参考
配置文件是一个 YAML 文档,顶层必须包含sglang键,其值为模型定义列表:
sglang: - name: <model_name> # 必填。模型的唯一标识符。 model_path: <path> # 可选。HF checkpoint 路径。默认使用 --hf-checkpoint。 update_weights: <bool> # 可选。是否从训练同步权重。未设置时自动推断。 num_gpus_per_engine: <int> # 可选。该模型所有组的默认 TP 大小。 server_groups: # 必填。服务器组配置列表。 - worker_type: <type> # 必填。可选:regular、prefill、decode、placeholder、encoder。 num_gpus: <int> # 必填。分配给该组的 GPU 总数(必须 > 0)。 num_gpus_per_engine: <int> # 可选。该组的 TP 大小覆盖。 overrides: <dict> # 可选。SGLang ServerArgs 字段覆盖。模型级字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name | str | 必填 | 模型唯一名称(如"actor"、"ref"、"reward")。用作args.sglang_model_routers的 key,也是自定义 rollout 中get_model_url(args, name, ...)的查找键。 |
model_path | str | args.hf_checkpoint | HuggingFace checkpoint 路径。同一模型内的所有服务器组必须共享同一个 model path(在ModelConfig.resolve()中校验)。 |
update_weights | bool | 自动推断 | 该模型是否接收训练权重更新。未设置时自动推断:有效 model path 与--hf-checkpoint匹配则为true,否则为false(同时输出 warning)。 |
num_gpus_per_engine | int | args.rollout_num_gpus_per_engine | 该模型服务器组的默认 TP 大小。各组可通过自身num_gpus_per_engine覆盖。 |
server_groups | list | 必填 | ServerGroupConfig条目列表,定义引擎拓扑。(engine_groups作为向后兼容别名仍可使用,见SglangConfig.from_yaml()的解析逻辑。) |
服务器组级字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
worker_type | str | 必填 | 引擎类型:regular(标准)、prefill(PD prefill worker)、decode(PD decode worker)或placeholder(占位,不启动引擎)。 |
num_gpus | int | 必填 | 该组的 GPU 总数。必须 > 0,否则ServerGroupConfig.__post_init__直接断言失败。 |
num_gpus_per_engine | int | 模型的num_gpus_per_engine | TP 大小覆盖。每个引擎实例占用的 GPU 数量。 |
overrides | dict | {} | SGLangServerArgs字段覆盖。优先级最高,覆盖--sglang-*CLI 参数和模型级默认值。 |
Worker 类型
| 类型 | 说明 | 使用场景 |
|---|---|---|
regular | 标准 SGLang 引擎 | 默认模式,同时处理 prefill 和 decode |
prefill | PD 分离的 prefill worker | 专门处理 prompt;与decodeworker 配对 |
decode | PD 分离的 decode worker | 专门生成 token;与prefillworker 配对 |
placeholder | 占位,不创建引擎 | 为训练共置预留 GPU 或留作未来使用 |
源码补充(encoder 类型):在
ServerGroupConfig的__post_init__校验中,合法类型集合为{"regular", "prefill", "decode", "placeholder", "encoder"}(见 sglang_config.py)。其中encoder用于 EPD(Encoder-Prefill-Decode)三级分离,encoder 引擎会最先启动,其 URL 被自动注入到 prefill 组的encoder_urls中;ModelConfig也据此暴露了has_pd_disaggregation与has_encoder_disaggregation两个属性供部署逻辑分支判断。这是比文档表格更进一步的最新能力。
使用模式:7 种实战部署
1. 基本单模型部署
最简单的配置即可复现默认行为:
# sglang_basic.yaml sglang: - name: default server_groups: - worker_type: regular num_gpus: 8python train.py \ --sglang-config sglang_basic.yaml \ --rollout-num-gpus 8 \ --rollout-num-gpus-per-engine 2 \ ...这将创建 4 个引擎(8 GPU ÷ 2 GPU/引擎),位于单个 router 之后。引擎数量 =num_gpus / num_gpus_per_engine_on_node,其中num_gpus_per_engine_on_node = min(num_gpus_per_engine, args.num_gpus_per_node)(见 engine_group.py),这意味着跨节点引擎会被正确切分。
2. PD 分离(Prefill-Decode Disaggregation)
将 prefill 和 decode 阶段分离到专用服务器组,以提升多轮和 agentic 场景的吞吐量:
# sglang_pd.yaml sglang: - name: actor server_groups: - worker_type: prefill num_gpus: 4 num_gpus_per_engine: 2 # 2 个 prefill 引擎,TP=2 - worker_type: decode num_gpus: 12 num_gpus_per_engine: 4 # 3 个 decode 引擎,TP=4python train.py \ --sglang-config sglang_pd.yaml \ --rollout-num-gpus 16 \ ...为什么需要 PD 分离?在多轮场景中,prefill 和 decode 具有完全不同的计算特性:prefill 是计算密集型(一次性处理整个 prompt 的 KV 计算),而 decode 是内存带宽密集型(逐 token 生成,受限于显存带宽)。将两者分离可以:
- 为 prefill 使用更小的 TP(每 GPU 吞吐量更高,prompt 处理并行度更充分)
- 为 decode 使用更大的 TP(单 token 延迟更低)
- 独立扩展 prefill 与 decode 的容量(例如多轮对话场景 prefill 占比高,可单独扩容)
注意:PD 分离使用 SGLang Model Gateway(sgl-router)并设置
pd_disaggregation=True。在ModelConfig中,只要任一组的worker_type是prefill或decode,has_pd_disaggregation即为true。
3. 多模型服务(Multi-Model Serving)
同时部署多个模型,每个模型拥有独立的 router:
# sglang_multi_model.yaml sglang: - name: actor update_weights: true # 接收训练权重更新 server_groups: - worker_type: regular num_gpus: 8 num_gpus_per_engine: 4 - name: ref model_path: /path/to/ref_model # 不同的模型 checkpoint update_weights: false # 冻结,不更新权重 server_groups: - worker_type: regular num_gpus: 4 num_gpus_per_engine: 2 - name: reward model_path: /path/to/reward_model update_weights: false server_groups: - worker_type: regular num_gpus: 4 num_gpus_per_engine: 2python train.py \ --sglang-config sglang_multi_model.yaml \ --rollout-num-gpus 16 \ --hf-checkpoint /path/to/actor_model \ --rollout-function-path my_rollout.generate_rollout \ ...在自定义 rollout 函数中访问模型:
from slime.rollout.sglang_rollout import get_model_url from slime.utils.http_utils import post async def my_generate(args, sample, sampling_params): # 路由到 actor 模型(默认) actor_url = get_model_url(args, "actor", "/generate") output = await post(actor_url, {"text": sample.prompt, "sampling_params": sampling_params}) # 路由到 reference 模型 ref_url = get_model_url(args, "ref", "/generate") ref_output = await post(ref_url, {"text": sample.prompt, "sampling_params": sampling_params}) # 路由到 reward 模型(如 OpenAI 兼容 API) reward_url = get_model_url(args, "reward", "/v1/chat/completions") reward_output = await post(reward_url, {...}) ...get_model_url()从args.sglang_model_routers(一个将模型名称映射到(ip, port)元组的字典)中读取,该字典在引擎启动后自动填充。从实现上看(sglang_rollout.py),若目标模型名不在字典中或字典未设置,它会优雅地回退到默认 router(args.sglang_router_ip:args.sglang_router_port),因此自定义 rollout 函数即使只写单模型逻辑也不会崩。
4. 多模型 + PD 分离
将多模型与 PD 分离结合,实现最大灵活性:
# sglang_full.yaml sglang: - name: actor update_weights: true server_groups: - worker_type: prefill num_gpus: 4 num_gpus_per_engine: 2 - worker_type: decode num_gpus: 8 num_gpus_per_engine: 4 - name: ref model_path: /path/to/ref_model update_weights: false server_groups: - worker_type: regular num_gpus: 4 num_gpus_per_engine: 25. 占位组用于 GPU 预留(Placeholder)
使用placeholder组来预留 GPU 而不创建引擎。这在训练与推理共置(co-location)场景中尤其有用——部分 GPU 需要预留给训练进程使用,SGLang 部署不应触碰:
sglang: - name: actor server_groups: - worker_type: regular num_gpus: 6 num_gpus_per_engine: 2 - worker_type: placeholder num_gpus: 2 # 预留 2 个 GPU(不创建引擎)源码细节:在
engine_group.py中,placeholder组的 GPU 槽位照常占用偏移,但引擎列表为空(all_engines=[None] * num_engines if worker_type != "placeholder" else []),且 GPU 分配时跳过引擎创建。这样后续训练进程可以安全复用这些槽位,不会与推理引擎冲突。
6. 按组覆盖 ServerArgs(overrides)
使用overrides将 SGLangServerArgs字段应用到特定服务器组,而不影响其他组:
sglang: - name: actor server_groups: - worker_type: regular num_gpus: 8 num_gpus_per_engine: 4 overrides: mem_fraction_static: 0.85 context_length: 32768 chunked_prefill_size: 4096 enable_torch_compile: true覆盖具有最高优先级:在_compute_server_args中,overrides会覆盖基础的--sglang-*CLI 参数与模型级默认值。典型应用场景:
- 不同组使用不同的显存占比(
mem_fraction_static) - prefill 与 decode 组使用不同的 context length
- 在特定组上启用实验性特性(如
enable_torch_compile),而不影响其他组稳定性
7. 独立 SGLang 启动器 / 连接外部引擎
虽然--sglang-config是为 slime 的训练流水线设计的,但通过连接外部引擎地址,它也能服务于纯推理/生产部署场景。
使用预启动的外部引擎:
# 步骤 1:外部启动 SGLang 引擎 python -m sglang.launch_server --model-path /path/to/model --port 10090 ... python -m sglang.launch_server --model-path /path/to/model --port 10091 ... # 步骤 2:将 slime 连接到外部引擎 python train.py \ --rollout-external-engine-addrs host1:10090 host2:10091 \ ...slime 会请求每个外部引擎的/server_info端点,自动推断rollout_num_gpus、单个引擎的 GPU 数、SGLang 并行参数以及 prefill/decode worker 类型。如果未提供--sglang-router-ip/--sglang-router-port,slime 会自行启动 router,并把外部引擎注册进去。
注意:
--sglang-config与--rollout-external-engine-addrs互斥:前者由 slime 管理完整引擎生命周期(创建、拉起、故障恢复),后者面向引擎已预部署的场景。选择标准很简单——是否希望 slime 接管引擎生命周期。
关于 external engine 的模型选择、update from disk 与 delta disk transport,详见 External Rollout Engines 配置路线图。
Router 配置
每个模型都有独立的 router(默认使用 SGLang Model Gateway)。router 相关 CLI 参数由add_sglang_router_arguments注册(见 arguments.py),包括--sglang-router-ip、--sglang-router-port、--sglang-router-request-timeout-secs(默认 14400 秒)等。
Router 策略
--router-policy round_robin # 简单轮询 --router-policy consistent_hashing # 多轮会话亲和 --router-policy cache_aware # 缓存感知路由(默认)多轮 Agent 的会话亲和路由(Session-Affinity Routing)
对于多轮对话和 agentic 场景,会话亲和确保同一对话的所有请求路由到同一个 backend worker。这能显著提升 prefix cache 命中率——worker 已缓存了对话历史,后续轮次的 KV 前缀直接命中,既降低时延又减少重复计算。
工作原理(结合源码验证):
- 每个 sample 通过 UUID 分配唯一的
session_id:在generate入口处,若sample.session_id is None,则赋值为str(uuid.uuid4())(见 sglang_rollout.py)。 - 每次请求时,若
router_policy == "consistent_hashing",slime 在 HTTP header 中传递X-SMG-Routing-Key: <session_id>(见 sglang_rollout.py)。 - SGLang Model Gateway 的 consistent hashing 策略将该 key 映射到特定的 worker。
- 后续轮次复用相同的
session_id,确保命中同一个 worker,实现 KV 前缀复用。
--router-policy consistent_hashing解析规则(Resolution Rules)
加载配置时,slime 按以下优先级顺序解析(核心逻辑在ModelConfig.resolve()与resolve_sglang_config(),见 sglang_config.py):
- 每引擎 GPU 数回退:组
num_gpus_per_engine→ 模型num_gpus_per_engine→args.rollout_num_gpus_per_engine。解析时还会把模型级model_path注入到各组的overrides["model_path"],供_compute_server_args统一读取。 - 模型路径回退:组
overrides.model_path→ 模型model_path→args.hf_checkpoint。 - 权重更新推断:如果
update_weights未设置:有效 model path 与--hf-checkpoint匹配则为true,否则为false(并输出 warning,建议显式设置以消除告警)。 - GPU 总数校验:所有模型所有组的
num_gpus总和必须等于--rollout-num-gpus,否则在resolve_sglang_config中直接断言失败(sglang_config total GPUs != rollout_num_gpus)。
模型路径一致性校验:resolve()还会断言同一模型内所有组的 model path 相同(取各组overrides["model_path"]的集合,长度必须为 1),这是 FAQ 中"同模型内不可混用不同 model path"的源码落点。
互斥关系(Mutual Exclusion)
--sglang-config与以下选项互斥,冲突会在参数校验阶段直接断言报错(见 arguments.py):
| 选项 | 冲突原因 |
|---|---|
--prefill-num-servers | PD 分离已通过 YAML 中的server_groups配置,二者语义重叠 |
--rollout-external-engine-addrs | 外部引擎自带拓扑;--sglang-config在内部管理生命周期 |
兼容性细节:旧参数
--prefill-num-servers内部其实等价于一个由SglangConfig.from_prefill_num_servers()生成的单模型 PD 配置——它把总 GPU 拆分为 prefill 组与 decode 组。也就是说,--prefill-num-servers是--sglang-config的一个特例;新部署应统一迁移到 YAML 配置以获得完整的模型/组编排能力。
完整示例:多模型 Agentic 训练(32 GPU)
下面是一个完整的实战示例:在 32 个 GPU 上,使用 actor(PD 分离)+ reference + reward 三模型拓扑进行 agentic RL 训练。
配置文件(sglang_agent.yaml):
sglang: - name: actor update_weights: true server_groups: - worker_type: prefill num_gpus: 4 num_gpus_per_engine: 2 overrides: chunked_prefill_size: 8192 - worker_type: decode num_gpus: 12 num_gpus_per_engine: 4 overrides: mem_fraction_static: 0.88 - name: ref model_path: /data/models/Qwen3-32B update_weights: false server_groups: - worker_type: regular num_gpus: 8 num_gpus_per_engine: 4 - name: reward model_path: /data/models/reward-model update_weights: false server_groups: - worker_type: regular num_gpus: 8 num_gpus_per_engine: 4启动命令:
python train.py \ --sglang-config sglang_agent.yaml \ --hf-checkpoint /data/models/Qwen3-8B \ --rollout-num-gpus 32 \ --rollout-function-path my_agent.rollout.generate_rollout \ --custom-rm-path my_agent.reward.reward_func \ --advantage-estimator grpo \ --n-samples-per-prompt 8 \ ...自定义 rollout 函数(my_agent/rollout.py):
from slime.rollout.sglang_rollout import get_model_url from slime.utils.http_utils import post async def generate_with_models(args, sample, sampling_params): """使用 actor 生成,用 reward 模型打分,与 reference 比较。""" # 从 actor 生成(PD 分离下的 prefill/decode 对用户透明) actor_url = get_model_url(args, "actor", "/generate") actor_output = await post(actor_url, { "text": sample.prompt, "sampling_params": sampling_params, "return_logprob": True, }) # 获取 reference logprobs 用于 KL penalty ref_url = get_model_url(args, "ref", "/generate") ref_output = await post(ref_url, { "text": sample.prompt + actor_output["text"], "sampling_params": {"max_new_tokens": 0, "temperature": 0}, "return_logprob": True, }) # 用 reward 模型打分(OpenAI 兼容接口) reward_url = get_model_url(args, "reward", "/v1/chat/completions") reward_output = await post(reward_url, { "model": "reward", "messages": [{"role": "user", "content": sample.prompt + actor_output["text"]}], }) # ... 处理输出并返回 Sample这个示例体现了--sglang-config的核心价值:actor 走 PD 分离拓扑追求吞吐与延迟平衡(prefill 组显式配置chunked_prefill_size: 8192,decode 组单独调高mem_fraction_static: 0.88),ref 与 reward 作为冻结模型各自独立部署且绝不接收训练权重更新。
FAQ
Q: 同一模型内可以混用 PD 和 regular 组吗?
不可以。PD 分离要求一个模型的服务器组要么全部是 prefill/decode 对,要么全部是 regular。不支持在同一模型内混用regular与prefill/decode。需要不同拓扑时,请拆分为独立的模型条目。
Q: 如果num_gpus不能被num_gpus_per_engine整除怎么办?
对于跨节点引擎(num_gpus_per_engine > num_gpus_per_node),引擎划分基于每节点的本地 GPU 数量:num_gpus_per_engine_on_node = min(num_gpus_per_engine, args.num_gpus_per_node),引擎数 =num_gpus // num_gpus_per_engine_on_node。例如每节点 8 个 GPU 且num_gpus_per_engine: 16时,每个引擎横跨 2 个节点。
Q: 同一模型内的不同服务器组可以使用不同的 model path 吗?
不可以。同一模型内的所有服务器组必须共享相同的model_path,这在ModelConfig.resolve()中被显式校验(各组 model path 集合必须只有一个元素)。如果需要不同模型,请定义为独立的模型条目。
Q: 运行时如何获取特定模型的 router 地址?
使用slime.rollout.sglang_rollout中的get_model_url(args, "model_name", "/endpoint")。它从args.sglang_model_routers(一个{ model_name: (ip, port) }字典)中读取,该字典在引擎启动后自动填充;若模型名不存在,则回退到默认 router 地址。
Q: 可以不训练,只用--sglang-config做推理吗?
--sglang-config是为 slime 的训练循环设计的,但你可以通过仅配置 rollout 的运行(--rollout-num-gpus等推理参数)实现纯推理场景。对于完全独立的 SGLang 推理服务,建议直接使用 SGLang 原生的python -m sglang.launch_server,或使用--rollout-external-engine-addrs连接预部署的引擎。
Q:--sglang-config和--prefill-num-servers是什么关系?
--prefill-num-servers是启用 PD 分离的旧方式——它内部构造一个带 prefill + decode 组的单模型配置(等价于SglangConfig.from_prefill_num_servers())。--sglang-config是更新、更灵活的方式,支持多模型、异构组与按组 overrides。两者互斥,推荐所有新部署迁移到--sglang-config。
延伸阅读
- 配置数据类与解析逻辑:slime/backends/sglang_utils/sglang_config.py
- 参数注册与互斥校验:slime/backends/sglang_utils/arguments.py
- 引擎组部署、placeholder 处理与故障恢复:slime/backends/sglang_utils/engine_group.py
get_model_url、session_id与路由头注入:slime/rollout/sglang_rollout.py- 外部引擎部署路线:External Rollout Engines
【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考