Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions optimum/exporters/openvino/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,11 @@ def generate_dummy_inputs(self, framework: str = "pt", **kwargs):
and self.PAD_ATTENTION_MASK_TO_PAST
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

):
seq_len = dummy_inputs["input_ids"].shape[1]
# VLM Eagle3 uses inputs_embeds instead of input_ids
main_input = dummy_inputs.get("input_ids", dummy_inputs.get("inputs_embeds"))
seq_len = main_input.shape[1]
past_seq_len = dummy_inputs["past_key_values"][0][1].shape[-2]
dummy_inputs["attention_mask"] = DummyInputGenerator.pad_input_on_dim(
dummy_inputs["attention_mask"], desired_length=past_seq_len + seq_len, dim=1
Expand Down
13 changes: 13 additions & 0 deletions optimum/intel/openvino/modeling_visual_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,19 @@ def _from_pretrained(
trust_remote_code (`bool`, *optional*, defaults to `False`):
Whether to trust remote code when loading model tokenizer/processor during quantization.
"""
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)}."
)
Comment on lines +898 to +910

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

model_cls = MODEL_TYPE_TO_CLS_MAPPING[config.model_type]
model_file_names = model_cls._all_ov_model_paths.copy()
for k in tuple(model_file_names):
Expand Down
26 changes: 26 additions & 0 deletions tests/openvino/test_exporters_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,32 @@ def test_exporters_cli_int8(self, task: str, model_type: str):
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

def test_exporters_cli_eagle3_vlm_quantization(self, weight_format: str):
# Regression test: exporting the VLM-flavored Eagle3 draft model (e.g. AngelSlim's
# Qwen3-VL eagle3 checkpoints) with any weight format used to fail with
# `KeyError: 'input_ids'` in `generate_dummy_inputs` because `eagle3_vlm` configs
# replace `input_ids` with `inputs_embeds` (see model_configs.py LlamaOpenVINOConfig).
model_type = "qwen3_vl_eagle3"
task = "text-generation-with-past"
with TemporaryDirectory() as tmpdir:
add_ops = "--group-size 16" if weight_format == "int4" else ""
subprocess.run(
f"optimum-cli export openvino --model {MODEL_NAMES[model_type]} --task {task} "
f"--trust-remote-code --weight-format {weight_format} {add_ops} {tmpdir}",
shell=True,
check=True,
)
# Must be loaded with OVModelForCausalLM: it is a standalone draft causal LM,
# not a multi-component VLM, even though its config carries VLM-oriented fields.
model = OVModelForCausalLM.from_pretrained(tmpdir, use_cache=True)
self.assertTrue(model.stateful)

# Loading the same export with OVModelForVisualCausalLM must raise a clear,
# actionable error instead of a bare `KeyError: 'llama'`.
with self.assertRaisesRegex(ValueError, "OVModelForCausalLM"):
OVModelForVisualCausalLM.from_pretrained(tmpdir, use_cache=True)

@parameterized.expand(SUPPORTED_SD_HYBRID_ARCHITECTURES)
def test_exporters_cli_hybrid_quantization(
self, model_type: str, expected_fake_nodes: int, expected_int8_nodes: int
Expand Down