Conversation
| from slime.utils.data import Dataset | ||
| from slime.utils.eval_config import EvalDatasetConfig | ||
| from slime.utils.http_utils import get, post | ||
| from slime.utils.misc import SingletonMeta, load_function |
There was a problem hiding this comment.
Done. vllm backend runs with vllm router.
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def _nccl_bridge_worker( |
There was a problem hiding this comment.
We need to ask jason why we need a separate process to do update weights from distributed
| "Automatically disabled for MoE or compressed-tensors quantization." | ||
| ), | ||
| ) | ||
| _vllm_packed.add_argument( |
There was a problem hiding this comment.
Ao should refactor the arguments.
| """Populate ``sample.rollout_routed_experts`` from vLLM routing-replay JSON (see vLLM docs).""" | ||
| if not getattr(args, "use_rollout_routing_replay", False): | ||
| return | ||
| gen_re = choice.get("routed_experts") |
There was a problem hiding this comment.
I don't think vllm has prompt_routed_experts as return key.
|
Could you add a list listing the points that we don't support compared with sglang? like encoder-prefill-disaggregation |
| router_port = args.sglang_router_port | ||
| if router_port is None: | ||
| router_port = find_available_port(random.randint(3000, 4000)) | ||
| <<<<<<< Updated upstream |
There was a problem hiding this comment.
syntax problem
fixed
| return {"ok": True, "raw": response.text} | ||
|
|
||
| def resume_memory_occupation(self, tags: list[str] | None = None): | ||
| """``POST /wake_up`` when sleep mode is on (SGLang: ``POST /resume_memory_occupation``); else a small placeholder dict.""" |
There was a problem hiding this comment.
Codex advice, please check:
High release_memory_occupation / resume_memory_occupation 现在给 /sleep、/wake_up 发的是 JSON body(slime/backends/vllm_utils/vllm_engine.py (line 483)),但 vLLM handler 读的是 query params(vllm/entrypoints/serve/sleep/api_router.py (line 22)),所以 level/tags 会被吞掉
There was a problem hiding this comment.
Codex advice, please check: High release_memory_occupation / resume_memory_occupation 现在给 /sleep、/wake_up 发的是 JSON body(slime/backends/vllm_utils/vllm_engine.py (line 483)),但 vLLM handler 读的是 query params(vllm/entrypoints/serve/sleep/api_router.py (line 22)),所以 level/tags 会被吞掉
fixed
…LLM rollout partial continuation and choice-only routed_experts
See latest pr comment. |
| @@ -15,7 +16,6 @@ | |||
| from sglang.srt.constants import GPU_MEMORY_TYPE_CUDA_GRAPH, GPU_MEMORY_TYPE_KV_CACHE, GPU_MEMORY_TYPE_WEIGHTS | |||
There was a problem hiding this comment.
vllm might not has these keys in sglang.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This PR introduces vLLM as a rollout backend for the Slime framework. Key additions include a VLLMEngine Ray actor for managing vLLM server processes, a vllm_rollout module for handling inference and reward modeling, and support for vllm-router. To prevent NCCL conflicts between vLLM and Megatron, a _NcclBridge subprocess is implemented for weight transfers. Feedback suggests using multiprocessing.get_context("spawn") instead of global set_start_method or default process spawning to ensure safety and isolation. Additionally, bucketing parameters during weight gathering is recommended to alleviate performance bottlenecks in the new weight sync logic.
| multiprocessing.set_start_method("spawn", force=True) | ||
| p = multiprocessing.Process(target=_exec_vllm_cmd, args=(cmd, env)) | ||
| p.start() |
There was a problem hiding this comment.
Calling multiprocessing.set_start_method("spawn", force=True) inside a function is discouraged as it globally affects the start method for the entire application, which can conflict with other components (like Ray) or host applications using Slime as a library. It is safer to use multiprocessing.get_context("spawn") to create a local context for spawning processes, ensuring isolation and avoiding global state modification.
| multiprocessing.set_start_method("spawn", force=True) | |
| p = multiprocessing.Process(target=_exec_vllm_cmd, args=(cmd, env)) | |
| p.start() | |
| ctx = multiprocessing.get_context("spawn") | |
| p = ctx.Process(target=_exec_vllm_cmd, args=(cmd, env)) | |
| p.start() |
| process = multiprocessing.Process( | ||
| target=run_router, | ||
| args=(router_args,), | ||
| args=((impl, router_args),), | ||
| ) |
There was a problem hiding this comment.
Spawning a process with the default multiprocessing.Process can be unsafe on platforms where the default start method is fork, especially when CUDA contexts or multiple threads are present in the parent process. Using an explicit spawn context is more robust and consistent with other parts of the codebase (e.g., in update_weight_from_distributed.py).
| process = multiprocessing.Process( | |
| target=run_router, | |
| args=(router_args,), | |
| args=((impl, router_args),), | |
| ) | |
| ctx = multiprocessing.get_context("spawn") | |
| process = ctx.Process( | |
| target=run_router, | |
| args=((impl, router_args),), | |
| ) |
| for name, param in named_params_and_buffers(self.args, self.model): | ||
| if ".experts." in name: | ||
| continue | ||
| param = all_gather_param(name, param) | ||
| if self._is_pp_src_rank: | ||
| converted_named_tensors += convert_to_hf( | ||
| self.args, self.model_name, name, param, self.quantization_config | ||
| ) |
There was a problem hiding this comment.
The sequential all_gather_param calls for every parameter in a loop create a significant performance bottleneck, especially for large models. Each call involves a distributed collective operation and synchronization across ranks. Since this PR introduces a 'packed' weight sync mode for efficiency, consider also bucketing these parameters before gathering them to minimize the number of collective operations and synchronization points.
Code Review: vLLM 后端集成的若干问题(AI 协助评审)
Bug #2
|
| Bug | 严重度 | 是否在 PR test plan 中触发 |
|---|---|---|
| #2 cuda_graph wake_up | 高 | 否(test 没 --offload-rollout) |
| #3 shutdown DELETE 路径 | 中 | 触发但 silent |
| #6 launch_server_process 忽略 model_path | 中 | 否(单模型) |
| #8 _wait_external_config_ready 字段路径 | 低 | rollout_external 才触发 |
| #9 NewConnectionError dead code | 低 | 无功能影响 |
#2 / #6 的"silent correctness"性质比一眼可见的 crash 更危险,因为 reward 曲线还能跑出来,但跑出来的是错的。建议合入之前至少补一个端到端 sanity check(对 #6 是验 /v1/models 的 id;对 #2 是开 --offload-rollout 跑两个 step 看 vLLM log 有没有那条 wake_up warning)。
注:这是 AI 协助生成的 review,基础的"它存在不存在""它对不对"我都对照源码核过,但建议 maintainer 在合并前对 #2 / #6 自己用一个最小可复现命令验证一遍。
Changes made: Review fixes (#2, #3, #6, #8, #9)
For Gemini:
|
There was a problem hiding this comment.
Code Review
This pull request adds vLLM as a rollout backend, introducing a VLLMEngine Ray actor and a NcclBridge to prevent NCCL conflicts with the Megatron trainer. It includes a new vllm_rollout module for OpenAI-compatible generation and integrates vllm-router for request routing. Reviewers identified a potential crash in generate_and_rm when processing sample lists and recommended keeping sglang as the default backend to prevent breaking changes. Additionally, it was noted that the current vLLM server launcher lacks support for multi-node tensor parallelism.
| if args.partial_rollout and args.mask_offpolicy_in_partial_rollout and sample.response_length > 0: | ||
| sample.loss_mask = [0] * sample.response_length | ||
|
|
||
| # For samples with existing response, check if they're complete | ||
| if sample.status == Sample.Status.COMPLETED or sample.status == Sample.Status.TRUNCATED: |
There was a problem hiding this comment.
The generate_and_rm function will crash if the input sample is a list, as it attempts to access sample.response_length and sample.status before performing the type check at line 645. While current callers appear to pass a single Sample, the type hint and the logic later in the function suggest that a list of samples is a supported input/output format (e.g., for custom generation functions that might return multiple samples). The type check should be moved to the beginning of the function to safely handle both cases.
| "--rollout-backend", | ||
| type=str, | ||
| choices=["sglang", "vllm"], | ||
| default="vllm", |
There was a problem hiding this comment.
Changing the default value of --rollout-backend to vllm is a breaking change for existing users who rely on the default sglang backend. As noted in the PR description, vLLM and SGLang are not reliably co-installable in the same image due to conflicting dependencies (like flashinfer). This change could cause immediate failures for users in SGLang-only environments. It is recommended to keep sglang as the default and allow users to opt-in to vllm via the command line.
| default="vllm", | |
| default="sglang", |
There was a problem hiding this comment.
Changing the default value of
--rollout-backendtovllmis a breaking change for existing users who rely on the defaultsglangbackend. As noted in the PR description, vLLM and SGLang are not reliably co-installable in the same image due to conflicting dependencies (likeflashinfer). This change could cause immediate failures for users in SGLang-only environments. It is recommended to keepsglangas the default and allow users to opt-in tovllmvia the command line.
Keeping vllm as default for this integration; use --rollout-backend sglang when you need SGLang.
| def launch_server_process( | ||
| *, | ||
| bind_host: str, | ||
| server_port: int, | ||
| args, | ||
| rank: int, | ||
| visible_devices: str, | ||
| model_path: str, | ||
| ) -> multiprocessing.Process: | ||
| """Spawn ``vllm serve`` (OpenAI API server) in a subprocess. | ||
|
|
||
| Contrasts with SGLang's launcher, which starts the HTTP server in-process from ``ServerArgs``. | ||
| """ | ||
| env = os.environ.copy() | ||
| env.pop("PYTORCH_CUDA_ALLOC_CONF", None) | ||
| env.setdefault("NCCL_CUMEM_ENABLE", "0") | ||
| env["CUDA_VISIBLE_DEVICES"] = visible_devices | ||
| env.setdefault("VLLM_SERVER_DEV_MODE", "1") | ||
|
|
||
| host_for_subprocess = bind_host.strip("[]") | ||
| model = getattr(args, "vllm_model", None) or model_path | ||
| tp = args.rollout_num_gpus_per_engine | ||
| seed = getattr(args, "seed", 1234) + rank | ||
|
|
||
| cmd = [ | ||
| "vllm", | ||
| "serve", | ||
| str(model), | ||
| "--tensor-parallel-size", | ||
| str(tp), | ||
| "--port", | ||
| str(server_port), | ||
| "--host", | ||
| host_for_subprocess, | ||
| "--seed", | ||
| str(seed), | ||
| "--trust-remote-code", | ||
| "--gpu-memory-utilization", | ||
| str(getattr(args, "vllm_gpu_memory_utilization", 0.4)), | ||
| ] | ||
| if getattr(args, "vllm_weight_sync_mode", "auto") == "native": | ||
| cmd += ["--weight-transfer-config", '{"backend":"nccl"}'] | ||
| if getattr(args, "offload_rollout", False) or getattr(args, "vllm_enable_sleep_mode", False): | ||
| cmd += ["--enable-sleep-mode"] | ||
| if getattr(args, "vllm_enforce_eager", False): | ||
| cmd += ["--enforce-eager"] | ||
| if getattr(args, "fp16", False): | ||
| cmd += ["--dtype", "float16"] | ||
| if getattr(args, "vllm_kv_cache_memory_bytes", None) is not None: | ||
| cmd += ["--kv-cache-memory-bytes", str(args.vllm_kv_cache_memory_bytes)] | ||
| if args.rollout_max_context_len is not None: | ||
| cmd += ["--max-model-len", str(args.rollout_max_context_len)] | ||
|
|
||
| logger.info("Launching vLLM server: %s", " ".join(cmd)) | ||
|
|
||
| p = _spawn_ctx.Process(target=_exec_vllm_cmd, args=(cmd, env)) | ||
| p.start() | ||
| return p |
There was a problem hiding this comment.
The launch_server_process function currently lacks support for multi-node tensor parallelism (TP) when spawning a local vLLM server. It ignores the dist_init_addr and other distributed coordination parameters that the SGLang backend uses to synchronize TP across multiple nodes. If rollout_num_gpus_per_engine exceeds the number of GPUs available on a single node, the vLLM server will fail to launch or operate correctly because it won't be able to coordinate with other nodes. Consider adding support for vLLM's distributed environment variables (e.g., VLLM_HOST_IP, VLLM_PORT) to enable multi-node TP in future iterations.
There was a problem hiding this comment.
Out of scope for this PR—local vllm serve only; multi-node TP / dist_init_addr is a follow-up.
|
LGTM |
|
|
||
| def _sanitize_vllm_router_args(ra: Any) -> Any: | ||
| """Replace negative int fields with dataclass defaults (sglang CLI may use -1; vllm-router rejects it).""" | ||
| from vllm_router.router_args import RouterArgs as VR |
There was a problem hiding this comment.
We can make vllm import global and remove all sglang import first, or do we have to install sglang currently?
hsliuustc0106
left a comment
There was a problem hiding this comment.
Review: PR #3 vLLM Rollout Backend
Verdict: Approved
Given that SGLang will be removed later, the architecture and default choices are the right forward-looking decisions.
What is good
- NcclBridge is the right isolation strategy for the NCCL conflict (vLLM#5477). Multiprocessing + CUDA IPC avoids GPU→CPU→GPU copies.
- Packed weight sync leverages vLLM's
NCCLWeightTransferEngine.trainer_send_weightsfor dense models — meaningful optimization over per-parameter broadcast. _normalize_vllm_wake_tagscorrectly drops SGLang-only tags before they reach vLLM.model_paththreading (ServerGroup → VLLMEngine →launch_server_process) correctly supports multi-model YAML configs.- All issues from the earlier review rounds (Bug #2, #3, #6, #8, #9) are addressed.
Non-blocking observations
-
vllm_gpu_memory_utilizationdefault inconsistency: argparse default is0.55butlaunch_server_processfallback is0.4. These should agree. -
health_generateis weaker than SGLang's:GET /healthonly checks process aliveness — a GPU hang or scheduler deadlock will not be detected. Consider an optionalPOST /v1/completionswithmax_tokens=1behind a flag for stricter health checking. -
Router subprocess
daemon=True: if the main process crashes, orphaned router processes continue running and holding ports. Consideratexitcleanup or non-daemon mode. -
_restart_local_serveron reload fallback: when native weight sync is not available,continue_generationkills and reinitializes the vLLM process — adds full model load time per weight update for large models. Worth documenting the performance implication until native sync is the universal path.
None of these are blockers. The code is solid and ready to merge.
plugin-contracts failed in build #3 on tests/utils/test_hf_checkpoint_saver.py (ModuleNotFoundError: safetensors): the dep list predated the slime sync in #232 which added requests/ray/safetensors to the GHA template. Mirror it. GitHub PR labels can't trigger Buildkite jobs, so expose the run-ci-* GPU suites behind a block step instead: unblocking offers a multi-select of suites (short / vllm-config / megatron / precision / ckpt) and gpu_suites.py uploads one step per test with the same gpu_lock_exec + docker invocations and per-test DEEPEP/FP8/EVAL env combos as the GHA jobs. blocked_state: passed keeps the commit status green when the gate is left untouched. GPU steps target a new vime-gpu agent queue (self-hosted hosts; see README). https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ
plugin-contracts failed in build #3 on tests/utils/test_hf_checkpoint_saver.py (ModuleNotFoundError: safetensors): the dep list predated the slime sync in #232 which added requests/ray/safetensors to the GHA template. Mirror it. GitHub PR labels can't trigger Buildkite jobs, so expose the run-ci-* GPU suites behind a block step instead: unblocking offers a multi-select of suites (short / vllm-config / megatron / precision / ckpt) and gpu_suites.py uploads one step per test with the same gpu_lock_exec + docker invocations and per-test DEEPEP/FP8/EVAL env combos as the GHA jobs. blocked_state: passed keeps the commit status green when the gate is left untouched. GPU steps target a new vime-gpu agent queue (self-hosted hosts; see README). https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ
plugin-contracts failed in build #3 on tests/utils/test_hf_checkpoint_saver.py (ModuleNotFoundError: safetensors): the dep list predated the slime sync in #232 which added requests/ray/safetensors to the GHA template. Mirror it. GitHub PR labels can't trigger Buildkite jobs, so expose the run-ci-* GPU suites behind a block step instead: unblocking offers a multi-select of suites (short / vllm-config / megatron / precision / ckpt) and gpu_suites.py uploads one step per test with the same gpu_lock_exec + docker invocations and per-test DEEPEP/FP8/EVAL env combos as the GHA jobs. blocked_state: passed keeps the commit status green when the gate is left untouched. GPU steps target a new vime-gpu agent queue (self-hosted hosts; see README). https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai>
…move PR test on GHA (#239) * ci: add Buildkite pipeline for always-on CPU jobs Port the always-on jobs from .github/workflows/pr-test.yml.j2 (pre-commit gate, plugin contracts, agent adapter, in-image unit tests) to a single dynamically generated Buildkite pipeline targeting the vLLM elastic-stack CPU queues. GitHub Actions keeps running in parallel and stays authoritative; GPU suites are not migrated yet. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci: replace Buildkite generator with static pipeline.yml Drop generate_pipeline.py in favor of a plain static .buildkite/pipeline.yml defining the four always-on CPU steps directly (pre-commit gate, plugin contracts, agent adapter, in-image unit tests). Simpler to read and review for a first cut; the GHA workflow stays authoritative and GPU suites are still out of scope. Pass GIT_CONFIG_PARAMETERS into every container so git (in pre-commit) doesn't abort with "dubious ownership" on the host-owned checkout, and fix the depends_on typo in the README. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): fix CPU test deps; add manual gate for GPU suites plugin-contracts failed in build #3 on tests/utils/test_hf_checkpoint_saver.py (ModuleNotFoundError: safetensors): the dep list predated the slime sync in #232 which added requests/ray/safetensors to the GHA template. Mirror it. GitHub PR labels can't trigger Buildkite jobs, so expose the run-ci-* GPU suites behind a block step instead: unblocking offers a multi-select of suites (short / vllm-config / megatron / precision / ckpt) and gpu_suites.py uploads one step per test with the same gpu_lock_exec + docker invocations and per-test DEEPEP/FP8/EVAL env combos as the GHA jobs. blocked_state: passed keeps the commit status green when the gate is left untouched. GPU steps target a new vime-gpu agent queue (self-hosted hosts; see README). https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): run GPU suites on mithril-h100-pool; pin gloo to loopback Build #4's unblock test showed the CI cluster rejects uploads targeting a nonexistent queue, and rather than minting a new queue, follow the pattern vllm-omni already uses for mithril-h100-pool: each GPU job is a Kubernetes pod (agent-stack-k8s kubernetes plugin) on an H100 SXM node with nvidia.com/gpu limits (4 or 8), memory-backed /dev/shm, and /mnt/hf-cache mounted as HF_HOME. vime tests hf-download their models, so the warm HF cache replaces the GHA runners' /mnt/nvme0n1/vime_ci mounts; the docker-run wrapper goes away since the pod runs the vime CI image directly. Also pin GLOO/TP_SOCKET_IFNAME=lo in the plugin-contracts container: test_metric_report_dist hung intermittently (build #4 timed out at 30 min) because gloo can pick a non-loopback interface inside a bridge-network container. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): expandable_segments for the borderline OOM short test test_qwen3.5_0.8B_gsm8k_async_short OOMed in compute_log_probs on the mithril pool's 80 GB H100s (build #6) with 7 GiB reserved-but-unallocated — the allocator-fragmentation case PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True exists for. Scope it to this test's pod only (vLLM sleep-mode CuMemAllocator can conflict with expandable segments) via verbatim pass-through of non-VIME env overrides. The other short tests passed on H100 pods unchanged. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): soft-fail the two known-H100-incompatible GPU tests Builds #6/#7 isolated two test-level failures on the mithril 80 GB H100s, neither a pipeline issue: - gsm8k_async_short OOMs as tuned (67 GiB live on the actor GPU after expandable_segments eliminated fragmentation; its sync twin passes). - parallel_check's CP=2 grad norm diverges ~4% from the same-node baseline recording, a topology-sensitive numerical invariance question. Mark exactly these two soft_fail so they keep running and stay visible on Buildkite without failing the build; their authoritative gate remains the GHA label jobs. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): keep the two H100-incompatible GPU tests failing loudly Revert the soft_fail: per review, the gsm8k_async_short OOM and the parallel_check CP-invariance divergence should stay visible as hard failures on Buildkite until the underlying issues are fixed. Keep the diagnostic comments and the test-scoped expandable_segments setting. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * ci(buildkite): soft-fail the two H100-incompatible GPU tests after all Re-apply b334784 (reverted in 0a98010): per the follow-up decision, mark gsm8k_async_short and parallel_check soft_fail so they keep running visibly on mithril without failing the build, with the GHA label jobs as their authoritative gate until the OOM tuning and CP-invariance questions are resolved. https://claude.ai/code/session_01BSqHKH1FafdRobA7ZeRzBQ Signed-off-by: aoshen02 <aoshen@inferact.ai> * fix(ci): resolve 0.8B async OOM on H100 by reducing max-tokens-per-gpu Root cause: Qwen3.5's 248K vocab produces [T, 248320] fp32 logits tensors. calculate_log_probs_and_entropy holds 5 copies simultaneously (2 clones + 2 intermediates + original). At max-tokens-per-gpu=9216, each copy is ~8.5 GB → 42.6 GB from logits alone, exceeding H100 80 GB with activations and reserved pool fragmentation. Fix: reduce max-tokens-per-gpu from 9216 to 2048. Peak drops from 117.6 GB to 39.6 GB (measured on H200), well within H100's 80 GB. GSM8K's longest sequence is ~1200 tokens, so 2048 still fits all samples. Also removes gsm8k_async_short from SOFT_FAIL_ON_H100 (no longer needed) and the expandable_segments workaround. parallel_check remains soft-fail: ~11% flake rate on TP4+per-token-loss, confirmed same behavior in slime (Megatron FP reduction-order issue). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * style: format update_weight_from_tensor Signed-off-by: aoshen02 <aoshen@inferact.ai> * remove github workflows Signed-off-by: khluu <khluu000@gmail.com> --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Signed-off-by: khluu <khluu000@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: aoshen02 <aoshen@inferact.ai>
Purpose
vLLM is a strong, widely used inference backend (throughput, scheduling, and the OpenAI-compatible serving stack). The goal of this work is to bring that backend into Slime so teams can run the same RL / rollout training loop while choosing vLLM for generation and serving, instead of being limited to a single stack. This PR is the first step: wire vLLM into Slime with baseline engine, rollout, and router integration, and validate it on a representative dense model setup.
What’s included
VLLMEngine(Ray actor) to spawn a localvllm servechild process or attach to an external vLLM HTTP server; maps Slime expectations (health, weight version, cache flush, pause/resume, sleep/wake, etc.) onto vLLM’s HTTP control plane where it differs from SGLang.vllm_rollout(and related wiring) so training can drive rollout through a path parallel to SGLang rollout.update_weights,init_weight_transfer_engine, etc., including native vs fallback behavior as implemented on this branch.Test plan
docker env:
pkgs install:
test vllm is ok:
Megatron+SGLang E2E (cmp)
Megatron+vLLM E2E (ours)
Test result
ENV: GPU(A100/A800)
Curve compare:
TPS compare:
vLLM

SGLang

Known issue / follow-up
TODO: replace inline / hard-coded argument passing with a proper config path in a follow-up.
Features not yet supported:
PD disaggregation: The vLLM engine path drops
disaggregation_bootstrap_portand related dist args, treats non-regularworkers as warnings only, and registers workers without SGLang-stylebootstrap_portfor prefill, so prefill/decode split is not wired the same way as SGLang.EPD / encoder: Multi-stage rollout still injects
encoder_urlsandlanguage_onlythroughsglang_overridesfor Ray server groups; the vLLM launcher does not mirror that contract, so encoder-disaggregated setups are aligned with SGLang, not guaranteed for vLLM(unless you extend launch config yourself.)Offline / disk weights: SGLang updates from disk via a dedicated HTTP API with
model_path/load_format; vLLM in slime only triggerscollective_rpcreload_weights, which ignores path and format and is closer to a full reload than SGLang’s targeted disk update.Update weights via PIC/Colocate mode.