Skip to content

[EXPERIMENT][WIP] Fix Eagle3 VLM draft model export/load (qwen3_vl_eagle3) - #1901

Draft
mlukasze wants to merge 1 commit into
huggingface:mainfrom
mlukasze:enable/AngelSlim-Qwen3-VL-4B-Instruct_eagle3
Draft

[EXPERIMENT][WIP] Fix Eagle3 VLM draft model export/load (qwen3_vl_eagle3)#1901
mlukasze wants to merge 1 commit into
huggingface:mainfrom
mlukasze:enable/AngelSlim-Qwen3-VL-4B-Instruct_eagle3

Conversation

@mlukasze

Copy link
Copy Markdown
Contributor

⚠️ AUTOMATICALLY GENERATED BY OMEGA AGENT — REQUIRES HUMAN REVIEW ⚠️
This PR was created by an AI agent as part of automated model enablement.
A human maintainer must review and approve it before it can be considered for merge.
Do NOT merge without human review and sign-off.

What does this PR do?

Fixes two regressions that block exporting/loading the Eagle3 speculative-decoding draft
model AngelSlim/Qwen3-VL-4B-Instruct_eagle3
for Qwen/Qwen3-VL-4B-Instruct, as reported in
openvinotoolkit/omega#78.

Bug 1 — KeyError: 'input_ids' at export time

OpenVINOConfigWithPast.generate_dummy_inputs (in optimum/exporters/openvino/base.py)
assumed the dummy input dict always contains input_ids, and only ran its attention-mask
padding logic for task == "text-generation". The Eagle3 draft model exports as a VLM
component with task == "image-text-to-text" and produces inputs_embeds instead of
input_ids. Fix: fall back to inputs_embeds when input_ids is absent, and extend the
task check to include "image-text-to-text".

Bug 2 — KeyError: 'llama' at load time

OVModelForVisualCausalLM._from_pretrained (in optimum/intel/openvino/modeling_visual_language.py)
does a direct MODEL_TYPE_TO_CLS_MAPPING[config.model_type] lookup. The Eagle3 draft model's
config.json sets model_type to the target model's type ("llama"/"qwen3_vl" family)
rather than a VLM-registered type, causing an opaque KeyError. Fix: add a pre-check that
raises a clear ValueError explaining that Eagle3 draft models should be loaded with
OVModelForCausalLM, not OVModelForVisualCausalLM (matching the exact error reported in
the ticket, now actionable instead of an opaque KeyError).

Testing

Added test_exporters_cli_eagle3_vlm_quantization to tests/openvino/test_exporters_cli.py,
covering fp16/int8/int4 export + load + the new error message, using the existing tiny CI
fixture optimum-intel-internal-testing/tiny-random-qwen3-vl-eagle3. All 3 variants pass.

Verified no regression on the existing non-VLM eagle3 export/load test.

Full end-to-end validation performed downstream (VLM + Eagle3 speculative decoding via
openvino_genai.VLMPipeline, on CPU/iGPU/dGPU, fp16/int8/int4, WWB accuracy + TTFT/TPOT
perf) — see openvinotoolkit/omega#78 for the full report.

Scope

Minimal, surgical fix — no unrelated changes. Both hunks are guarded by narrow conditions
(inputs_embeds fallback only when input_ids missing; VLM model_type pre-check only
triggers before the existing dict lookup).

Fixes reported issue in openvinotoolkit/omega#78

Before submitting

  • Did you write any new necessary tests?
  • Did you make sure to update the documentation with your changes? (not applicable — internal export/load fix, no public API change)

Two distinct bugs affected VLM-flavored Eagle3 speculative-decoding
draft models (e.g. AngelSlim/Qwen3-VL-4B-Instruct_eagle3), reported in
openvinotoolkit/omega#78:

1. Export (`optimum-cli export openvino`, any weight format) failed
   with `KeyError: 'input_ids'` in
   `OpenVINOConfigWithPast.generate_dummy_inputs`. VLM Eagle3 configs
   replace `input_ids` with `inputs_embeds` in dummy inputs, but the
   attention-mask padding branch only looked up `input_ids` and only
   triggered for `task == "text-generation"`, missing
   `image-text-to-text` (the task under which `qwen3_vl_eagle3`
   registers). Restored the `.get()` fallback and task condition that
   existed prior to the base.py export-config refactor.

2. Loading an exported VLM Eagle3 model via `OVModelForVisualCausalLM`
   failed with a cryptic `KeyError: 'llama'` in `_from_pretrained`,
   because these checkpoints self-report `model_type="llama"` (not a
   key in `MODEL_TYPE_TO_CLS_MAPPING`) while carrying VLM-oriented
   `modal_type`/`target_model_type` fields. These models are standalone
   draft causal LMs and must be loaded with `OVModelForCausalLM`
   instead. Added a pre-check that raises a clear, actionable
   `ValueError` pointing at the correct class.

Added `test_exporters_cli_eagle3_vlm_quantization` covering fp16/int8/
int4 export + load for `qwen3_vl_eagle3`, using the existing tiny CI
fixture, and asserting the improved error message from bug #2.
Comment on lines +898 to +910
if config.model_type not in MODEL_TYPE_TO_CLS_MAPPING:
archs = getattr(config, "architectures", None) or []
if archs and "eagle3" in archs[0].lower():
raise ValueError(
f"Model with architecture '{archs[0]}' (model_type='{config.model_type}') is a standalone "
"Eagle3 speculative-decoding draft model, not a multi-component VLM, even though its "
"config declares a VLM-oriented `modal_type`/`target_model_type`. Please load it with "
"`OVModelForCausalLM` instead of `OVModelForVisualCausalLM`."
)
raise ValueError(
f"Unsupported model_type '{config.model_type}' for `OVModelForVisualCausalLM`. Supported "
f"model types are: {sorted(MODEL_TYPE_TO_CLS_MAPPING)}."
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not needed

del expected_int8["decoder_with_past"]
check_compression_state_per_model(self, model.ov_models, expected_int8)

@parameterized.expand(["fp16", "int8", "int4"])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

fix tests

and self.use_cache_branch is not False
and "attention_mask" in dummy_inputs
and self.task == "text-generation"
and self.task in ("text-generation", "image-text-to-text")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

risky change because we have other vlm models. It can affect them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants