[Bugfix][Spec Decode] Honour the draft's moe_backend on Model Runner V2 - #54788
Conversation
The draft model is loaded with the target's VllmConfig, so unless the speculative config's moe_backend is applied it silently inherits the target's --moe-backend. When the target is quantized and the draft is not, which is the normal shape of an MTP head, a quantized-only backend then rejects the draft and the server fails to start: ValueError: moe_backend='flashinfer_b12x' is not supported for unquantized MoE. Expected one of ['triton', 'batched_triton', 'flashinfer_trtllm', 'flashinfer_cutlass', ...] V1 applies this override in LLMBaseProposer._create_draft_vllm_config, but the V2 path does not: load_eagle_model already overrides kv_cache_dtype from the speculative config and simply never grew the moe_backend equivalent. Result: the same command line serves under V1 and fails under V2, which surfaced when MRV2 became the default in vllm-project#53183. Apply the override next to the existing kv_cache_dtype one. Both are scoped to the draft, and the target config is left untouched. Reproducer, on a quantized MoE target with an unquantized MTP head: --moe-backend flashinfer_b12x \ --speculative-config '{"method":"mtp","num_speculative_tokens":3, "moe_backend":"flashinfer_cutlass"}' serves with VLLM_USE_V2_MODEL_RUNNER=0 and fails with =1. Signed-off-by: Stefano Castagnetta <scastagnetta@nvidia.com>
|
Hi @njhill, could you take a look? Currently we can't specify the MoE backend for the drafter head using runner V2 |
Signed-off-by: Stefano Castagnetta <scastagnetta@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 SummarySummary by CodeRabbit
Walkthrough
ChangesEAGLE draft configuration and embedding sharing
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change lets speculative EAGLE drafts use their configured MoE backend without changing the target model configuration, resolving startup failures for differing target and draft backend requirements. No concrete current-head merge-blocking risk remains. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
/ci run |
|
✅ Triggered Buildkite CI #87322 for commit |
|
✅ @stecasta, CI is now available for this PR.
|
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
/ci run |
|
✅ Triggered Buildkite CI #87333 for commit |
|
@stecasta I think the CI failures are related |
|
Independent confirmation on a second architecture and a different backend pair — this PR's diagnosis matches what we hit today. Control (fails): Working reference (V1): stock Practical note for anyone landing here from the playbook recipe: Haven't run the treatment on this box yet; happy to if a second-hardware treatment result would help merge. |
load_eagle_model now reads speculative_config.attention_backend, so the stub needs the field or every test in this file raises AttributeError. Signed-off-by: Stefano Castagnetta <scastagnetta@nvidia.com>
Head branch was pushed to by a user without write access
|
/ci run |
|
✅ Triggered Buildkite CI #87521 for commit |
|
@njhill CI is green now, thanks! |
|
/ci run |
|
✅ Triggered Buildkite CI #87714 for commit |
|
/ci retry |
|
✅ Queued 4 failed job(s) for retry in Buildkite CI #87714. |
…V2 (vllm-project#54788) Signed-off-by: Stefano Castagnetta <scastagnetta@nvidia.com> Co-authored-by: Nick Hill <nickhill123@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Jyotirmoy Roy <jyotirmoyroy649@gmail.com>
Purpose
The draft model is loaded with the target's
VllmConfig, so--speculative-config '{"moe_backend": ...}'is ignored on Model Runner V2. When the target is quantized and the draft is not, which is the normal shape of an MTP head, a quantized-only backend rejects the draft and the engine fails to start:V1 applies this override in
LLMBaseProposer._create_draft_vllm_config. V2 never grew the equivalent:load_eagle_modeloverrideskv_cache_dtypeonly, andvllm/v1/worker/gpu/contains no reference tomoe_backendat all. The same command line therefore serves under V1 and fails under V2, which became user-visible when MRV2 was made the default in #53183.Fix
Apply the override alongside the existing
kv_cache_dtypeone inload_eagle_model. It is scoped to the draft; the target's config is left untouched. MTP reaches this path viamtp/speculator.py.Validation
Qwen3.6-35B-A3B-NVFP4 with MTP-3 on an RTX PRO 6000 Blackwell Max-Q,
--moe-backend flashinfer_b12xwith the draft onflashinfer_cutlass. Three arms on one node with identical flags, vLLMv0.28.1rc1.dev199+g7c5dc571c:ValueErroraboveApplication startup completeThe tests patch
get_modelto capture the config the draft would be built with, and assert that the override reaches the draft's kernel config, that its absence still inherits the target, and that the target's own config is not mutated. Reverting the fix fails them with the bug's signature:Why this is not a duplicate
I ran the checks in AGENTS.md. Nothing open touches the V2 draft
moe_backendpath. The nearest related work is a cluster of V2 draft-config isolation fixes (#54731, #54716), which address different fields.Model evaluation
Not applicable. This changes which MoE kernel the draft is built with, and only when the user explicitly asks for one. With no
moe_backendin the speculative config the behaviour is unchanged, which the second test pins. Affected configurations currently fail to start, so there is no baseline to regress against. Under real rejection sampling the target verifies every drafted token, so the draft's kernel choice cannot alter output.AI assistance
AI assistance was used to author this change. I have reviewed every changed line, ran the tests and linters above myself, and can defend the design.