[XPU] Fix Eagle3 initialization on XPU (#43957)

Signed-off-by: Chaojun Zhang <chaojun.zhang@intel.com> Co-authored-by: Andreas Karatzas <akaratza@amd.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Kunshang Ji <kunshang.ji@intel.com>

Chaojun Zhang committed Jul 6, 2026 at 08:46 UTC d2ec433e3795ad3ef7314c8c0f87f03d24d47960
3 files changed +44 -1
.buildkite/intel_jobs/misc_intel.yaml
+20
@@ -76,6 +76,26 @@ steps:
76 pytest -v -s v1/sample/test_logprobs.py &&
77 pytest -v -s v1/sample/test_logprobs_e2e.py'
78
79 +- label: Basic Models Tests (Initialization)
80 + timeout_in_minutes: 60
81 + device: intel_gpu
82 + no_plugin: true
83 + working_dir: "."
84 + env:
85 + REGISTRY: "public.ecr.aws/q9t5s3a7"
86 + REPO: "vllm-ci-test-repo"
87 + VLLM_TEST_DEVICE: "xpu"
88 + source_file_dependencies:
89 + - vllm/
90 + - tests/models/test_initialization.py
91 + - tests/models/registry.py
92 + commands:
93 + - >-
94 + bash .buildkite/scripts/hardware_ci/run-intel-test.sh
95 + 'export VLLM_XPU_FUSED_MOE_USE_REF=1 &&
96 + cd tests &&
97 + pytest -v -s models/test_initialization.py::test_can_initialize_large_subset[Eagle3MiniMaxM2ForCausalLM]'
98 +
99 - label: XPU CPU Offload
100 timeout_in_minutes: 60
101 device: intel_gpu
vllm/model_executor/models/llama_eagle3.py
+4 -1
@@ -233,7 +233,10 @@ class LlamaModel(nn.Module):
233 ) -> tuple[torch.Tensor, torch.Tensor]:
234 if input_embeds is None:
235 input_embeds = self.embed_input_ids(input_ids)
236 - assert hidden_states.shape[-1] == input_embeds.shape[-1]
236 + torch._assert(
237 + hidden_states.shape[-1] == input_embeds.shape[-1],
238 + "hidden_states and input_embeds must have the same last dimension",
239 + )
240
241 residual = None
242 for layer in self.layers:
vllm/v1/spec_decode/llm_base_proposer.py
+20
@@ -1468,6 +1468,26 @@ class SpecDecodeBaseProposer:
1468 "Sharing target model embedding weights with the draft model."
1469 )
1470
1471 + if share_embeddings:
1472 + draft_embed = self.model.model.embed_tokens
1473 + # Only share when both models use the same embedding width.
1474 + # Guard with isinstance so non-Tensor weights (e.g. in tests)
1475 + # are not affected — mirrors the weight-equality check above.
1476 + if isinstance(target_embed_tokens.weight, torch.Tensor) and isinstance(
1477 + draft_embed.weight, torch.Tensor
1478 + ):
1479 + target_dim = target_embed_tokens.weight.shape[-1]
1480 + draft_dim = draft_embed.weight.shape[-1]
1481 + if target_dim != draft_dim:
1482 + share_embeddings = False
1483 + logger.info(
1484 + "Target embedding dim (%d) differs from draft "
1485 + "embedding dim (%d). Keeping separate embedding "
1486 + "weights.",
1487 + target_dim,
1488 + draft_dim,
1489 + )
1490 +
1491 if share_embeddings:
1492 if hasattr(self.model.model, "embed_tokens"):
1493 del self.model.model.embed_tokens