Skip to content

[Bugfix][Spec Decode] Fix multimodal embedding merge in Llama 4 and Mistral Large 3 EAGLE drafters - #57633

Merged
njhill merged 12 commits into
vllm-project:mainfrom
nishantrevur:fix/llama4-eagle-mm-embed
Oct 9, 2026
Merged

njhill merged 12 commits into
vllm-project:mainfrom
nishantrevur:fix/llama4-eagle-mm-embed

Conversation

@nishantrevur

@nishantrevur nishantrevur commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Fixes #57630.

Regression from #50417 (first released in v0.28.0): that change marked these drafters as SupportsMultiModalEmbeddings so the speculator started routing multimodal batches through their embed_input_ids, which had been an unreachable alias of SupportsMultiModal.embed_input_ids until then. cc @TQCB

EagleLlama4ForCausalLM and EagleMistralLarge3ForCausalLM implement SupportsMultiModalEmbeddings by borrowing the method object SupportsMultiModal.embed_input_ids. That method calls self._embed_text_input_ids(...) and reads self._has_oov_mm_tokens, both of which live on SupportsMultiModal, which the drafters do not inherit. Any multimodal target paired with one of these drafters fails during the first draft prefill (already in the profile run at startup):

File "vllm/v1/worker/gpu/spec_decode/autoregressive/speculator.py", line 427, in _run_model
File "vllm/model_executor/models/interfaces.py", line 507, in embed_input_ids
AttributeError: 'EagleLlama4ForCausalLM' object has no attribute '_embed_text_input_ids'. Did you mean: 'embed_input_ids'?

Reproduced on main (bf13ecc) and present in v0.28.0 and v0.29.0 with RedHatAI/Llama-4-Scout-17B-16E-Instruct-quantized.w4a16 + morgendave/EAGLE-Llama-4-Scout-17B-16E-Instruct, TP=4, --speculative-config '{"method":"eagle","model":...,"num_speculative_tokens":3}', default cudagraph mode. The same aliasing exists in EagleMistralLarge3ForCausalLM; Model Runner V1 takes the same embed_input_ids path.

Change

Replace the borrowed method with an explicit embed_input_ids in both drafters that embeds the draft input ids via self.model.embed_input_ids and merges external multimodal embeddings with _merge_multimodal_embeddings, the same shape EagleMistralForCausalLM already uses. No behavior change for text-only batches.

Test plan

.venv/bin/python -m pytest tests/v1/worker/test_gpu_autoregressive_speculator.py -v   # 21 passed (2 new)
pre-commit run --files vllm/model_executor/models/llama4_eagle.py vllm/model_executor/models/mistral_large_3_eagle.py tests/v1/worker/test_gpu_autoregressive_speculator.py

New test test_mm_capable_drafter_merges_multimodal_embeddings (parametrized over both classes) checks text-only embedding and the merge of multimodal rows; it raises AttributeError on main.

E2E (4x NVIDIA L4, TP=4, TRITON_ATTN, RedHatAI/Llama-4-Scout-17B-16E-Instruct-quantized.w4a16 + morgendave/EAGLE-Llama-4-Scout-17B-16E-Instruct, num_speculative_tokens=3, max_patches=4, 18 text + 12 image prompts, greedy, 48 new tokens):

build cudagraph_mode text AL image AL image per-pos acceptance
main @ bf13ecc FULL_AND_PIECEWISE startup crash (AttributeError: ... '_embed_text_input_ids')
main + this PR FULL_AND_PIECEWISE 2.637 (328 drafts) 2.424 (238 drafts) 0.710 / 0.445 / 0.269
main + this PR NONE 2.674 (322 drafts) 2.413 (240 drafts) 0.708 / 0.446 / 0.258

Image prompts now draft with acceptance close to text prompts, i.e. the drafter is receiving the image embeddings.

Disclosure

AI assistance (Claude) was used to investigate and draft this change; every line was reviewed and the tests were run by the submitter.

…istral Large 3 EAGLE drafters

EagleLlama4ForCausalLM and EagleMistralLarge3ForCausalLM borrowed
SupportsMultiModal.embed_input_ids, which calls self._embed_text_input_ids
and relies on SupportsMultiModal state the drafters never inherit. Any
multimodal target with one of these drafters failed at startup with
`AttributeError: 'EagleLlama4ForCausalLM' object has no attribute
'_embed_text_input_ids'` as soon as the draft prefill embedded a batch.
Embed the draft input ids directly and merge the external multimodal
embeddings, matching EagleMistralForCausalLM.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Nishant Revur <kumrfni@amazon.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify mergify Bot added llama Related to Llama models mistral Related to Mistral models speculative-decoding bug Something isn't working labels Sep 18, 2026
@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment /ci run for upstream CI or /amd-ci run for AMD CI only whenever CI signals are needed.

Once the PR is approved or has the ready label, the PR author can also use the corresponding /ci run, /ci retry, and /ci cancel commands, or their /amd-ci variants. New commits do not start upstream CI automatically.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban.

🚀

@nishantrevur

Copy link
Copy Markdown
Contributor Author

@njhill @TQCB gentle ping, since this has been open about two weeks without review.

This fixes a startup regression introduced by #50417. That PR marked EagleLlama4ForCausalLM and EagleMistralLarge3ForCausalLM as SupportsMultiModalEmbeddings, which made their aliased SupportsMultiModal.embed_input_ids reachable. The alias calls _embed_text_input_ids, which these drafters don't inherit, so any multimodal target paired with them crashes during the profile run. Repro and traceback are in #57630.

It still reproduces on main as of today (edaf3e7), and the branch applies cleanly. The fix is ~40 lines with a unit test, and it was verified end to end on 4x L4 with Llama 4 Scout + EAGLE.

@njhill njhill left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nishantrevur

@njhill njhill added the ready ONLY add when PR is ready to merge/full CI is needed label Oct 6, 2026
@njhill

njhill commented Oct 6, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

✅ @nishantrevur, CI is now available for this PR.

  • /ci run starts upstream CI; /amd-ci run starts AMD CI only.
  • Your branch must contain every commit currently on its upstream target branch. Merge or rebase onto the latest target branch, then rerun the command. Append --allow-stale to a run command to test an outdated branch at your own risk.
  • /ci retry retries failed jobs in the CI build for the current PR head. If the current head has no CI build, it starts a new CI build for the current head containing only jobs that failed in the latest earlier CI build for this PR.
  • /amd-ci retry retries failed jobs in AMD CI for the current PR head. Use /amd-ci run when the current head has no AMD CI build.
  • /ci cancel cancels scheduled or running CI builds for this PR branch; /amd-ci cancel does the same for AMD CI only.

@njhill
njhill enabled auto-merge (squash) October 6, 2026 22:32
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93194 for commit 3bfa43db6fb9.

@vllm-agent

vllm-agent commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

CI selector (shadow): 8 test steps (28 jobs) instead of 62 (94 jobs)

Shadow mode: this changes nothing about what CI runs. It shows what the evidence-based selector would pick for this PR, next to today's rules. How it works.

Feedback welcome: reply here if it would skip a step this change needs, or runs something unrelated.

steps (jobs) Today's rules Selector Would skip Would add
NVIDIA, CPU and others 62 (94) 8 (28) 56 (73) 2 (7)
AMD mirrors 58 (85) 4 (17) 54 (68) 0 (0)
Selector would run (8)
  • arm-cpu-test ×3
  • basic-models-tests-extra-initialization ×14
  • basic-models-tests-other
  • cpu-language-generation-and-pooling-model-tests ×3
  • cpu-multi-modal-model-tests-n ×4
  • cpu-spec-decode-tests
  • model-executor
  • v1-executor-worker
Would skip (today's rules run them) (56)
  • amd-lm-eval-small-models-harness
  • amd-qwen3-next-mtp-async-eplb-accuracy
  • ascend-npu-test
  • async-engine-inputs-utils-worker
  • basic-correctness ×2
  • basic-correctness-cpu-offload
  • basic-correctness-cumem
  • basic-correctness-prefetch-offload
  • basic-correctness-sleep-mode
  • basic-models-test-other-cpu
  • basic-models-tests-initialization
  • benchmarks-cli-test
  • distributed-model-tests-2-gpus ×3
  • entrypoints-integration-api-server ×4
  • entrypoints-integration-api-server-generate
  • entrypoints-integration-api-server-openai-chat_completion
  • entrypoints-integration-api-server-openai-completion
  • entrypoints-integration-llm
  • entrypoints-integration-multimodal
  • entrypoints-integration-pooling
  • entrypoints-integration-responses-api
  • entrypoints-integration-speech_to_text
  • fusion-e2e-quick-h100
  • fusion-e2e-tp2-b200
  • fusion-e2e-tp2-quick-h100
  • kernels-fla-ops-test-b200
  • kernels-mhc-test-b200
  • kernels-root-misc-test-b200
  • language-models-tests-extra-standard ×2
  • language-models-tests-granite-l4-compatibility
  • language-models-tests-hybrid ×2
  • language-models-tests-standard
  • metrics-tracing-2-gpus
  • multi-modal-models-standard-1-qwen2
  • multi-modal-models-standard-2-qwen3-gemma
  • multi-modal-models-standard-3-llava-qwen2-vl
  • multi-modal-models-standard-4-other-whisper
  • multi-modal-processor ×4
  • multi-modal-processor-cpu ×4
  • pipeline-context-parallelism-4-gpus
  • pytorch-compilation-dynamic-shapes
  • pytorch-compilation-passes-unit-tests
  • pytorch-compilation-unit-tests
  • pytorch-compilation-unit-tests-h100
  • pytorch-fullgraph-cudagraph-l4-compatibility
  • pytorch-fullgraph-test
  • regression
  • rl-entrypoints-tests
  • v1-core
  • v1-kv-connectors ×4
  • v1-kv-offload
  • v1-logits-oracle
  • v1-metrics-lmeval
  • v1-others-cpu
  • v1-sample
  • v1-spec-decode
Would add (today's rules do not run them) (2)
  • arm-cpu-test ×3 (code map)
  • cpu-multi-modal-model-tests-n ×4 (code map)
AMD mirrors: would skip (54)
  • async-engine-inputs-utils-worker
  • basic-correctness ×2
  • basic-correctness-cpu-offload
  • basic-correctness-cumem
  • basic-correctness-prefetch-offload
  • basic-correctness-sleep-mode
  • basic-models-tests-initialization
  • benchmarks-cli-test
  • distributed-model-tests-2-gpus ×3
  • entrypoints-integration-api-server ×4
  • entrypoints-integration-api-server-generate
  • entrypoints-integration-api-server-openai-chat_completion
  • entrypoints-integration-api-server-openai-completion
  • entrypoints-integration-llm
  • entrypoints-integration-multimodal
  • entrypoints-integration-pooling
  • entrypoints-integration-responses-api
  • entrypoints-integration-speech_to_text
  • fusion-e2e-quick-h100
  • fusion-e2e-tp2-ar-rms-config-sweep-h100
  • fusion-e2e-tp2-b200
  • fusion-e2e-tp2-quick-h100
  • kernels-fla-ops-test-b200
  • kernels-mhc-test-b200
  • kernels-root-misc-test-b200
  • language-models-tests-extra-standard ×2
  • language-models-tests-granite-l4-compatibility
  • language-models-tests-hybrid ×2
  • language-models-tests-standard
  • lm-eval-small-models
  • metrics-tracing-2-gpus
  • mrcr-eval-small-models
  • multi-modal-models-standard-1-qwen2
  • multi-modal-models-standard-2-qwen3-gemma
  • multi-modal-models-standard-3-llava-qwen2-vl
  • multi-modal-models-standard-4-other-whisper
  • multi-modal-processor ×4
  • pipeline-context-parallelism-4-gpus
  • platform-tests
  • pytorch-compilation-dynamic-shapes
  • pytorch-compilation-passes-unit-tests
  • pytorch-compilation-unit-tests
  • pytorch-compilation-unit-tests-h100
  • pytorch-fullgraph-cudagraph-l4-compatibility
  • pytorch-fullgraph-test
  • regression
  • rl-entrypoints-tests
  • v1-core
  • v1-kv-connectors ×4
  • v1-kv-offload
  • v1-logits-oracle
  • v1-metrics-lmeval
  • v1-sample
  • v1-spec-decode
AMD mirrors: would add (0)

none

3 changed files · base 554340f3d3 · head d073559efa · Python record: build 93039 at 1e5d0ea888 · kernel record: table 43b4aae (build 93244), map 43b4aae · not counted: 10 build steps, 5 A100 steps the generator no longer emits, 8 optional steps the selector would also run

@njhill

njhill commented Oct 7, 2026

Copy link
Copy Markdown
Member

/ci retry

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93356 for commit 7e91e9036d4a, running 1 failed step(s) from Buildkite CI #93194.

@mergify

mergify Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @nishantrevur.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Oct 7, 2026
@mergify mergify Bot removed the needs-rebase label Oct 8, 2026
@njhill

njhill commented Oct 9, 2026

Copy link
Copy Markdown
Member

/ci retry

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93734 for commit b5e49b84c572, running 1 failed step(s) from Buildkite CI #93356.

@njhill
njhill merged commit 581692c into vllm-project:main Oct 9, 2026
13 checks passed
michael-gpu pushed a commit to practical-inference/vllm-ampere-extended that referenced this pull request Oct 20, 2026
…istral Large 3 EAGLE drafters (vllm-project#57633)

Signed-off-by: Nishant Revur <kumrfni@amazon.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working llama Related to Llama models mistral Related to Mistral models ready ONLY add when PR is ready to merge/full CI is needed speculative-decoding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Spec Decode] Llama 4 / Mistral Large 3 EAGLE drafters crash at startup with a multimodal target: no attribute _embed_text_input_ids

3 participants