From 75038a87053ad96e8277b68262f35467d7310533 Mon Sep 17 00:00:00 2001 From: Yuri Khrustalev Date: Fri, 25 Sep 2026 18:33:14 -0400 Subject: [PATCH] fix: accept Hugging Face configs without a model_type in HfModel LiquidAI/LFM2.5-Audio-1.5B has no model_type in its config.json, so AutoConfig rejects it and HfModelHandler can't be built, though the ORT GenAI model builder supports it. Fall back to a plain PretrainedConfig then; unknown model types and untrusted remote-code configs still raise. --- olive/common/hf/utils.py | 24 +++++++++++++++++++++--- test/common/test_hf.py | 27 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/olive/common/hf/utils.py b/olive/common/hf/utils.py index 5d969ed16f..cd3da528b2 100644 --- a/olive/common/hf/utils.py +++ b/olive/common/hf/utils.py @@ -9,14 +9,22 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Optional, Union -from transformers import AutoConfig, AutoModel, AutoModelForSeq2SeqLM, AutoProcessor, AutoTokenizer, GenerationConfig +from transformers import ( + AutoConfig, + AutoModel, + AutoModelForSeq2SeqLM, + AutoProcessor, + AutoTokenizer, + GenerationConfig, + PretrainedConfig, +) from olive.common.hf.mappings import TASK_TO_PEFT_TASK_TYPE from olive.common.hf.mlflow import get_pretrained_name_or_path from olive.common.utils import hardlink_copy_file if TYPE_CHECKING: - from transformers import PretrainedConfig, PreTrainedModel, PreTrainedTokenizer, PreTrainedTokenizerFast + from transformers import PreTrainedModel, PreTrainedTokenizer, PreTrainedTokenizerFast logger = logging.getLogger(__name__) TEST_MODEL_MARKER_FILE = "olive_test_model.json" @@ -407,7 +415,17 @@ def get_model_config( model_name_or_path: str, test_model_config: Optional[dict[str, Any]] = None, **kwargs ) -> "PretrainedConfig": """Get HF Config for the given model_name_or_path.""" - model_config = from_pretrained(AutoConfig, model_name_or_path, "config", **kwargs) + try: + model_config = from_pretrained(AutoConfig, model_name_or_path, "config", **kwargs) + except ValueError: + # A config without a model_type (e.g. LiquidAI/LFM2.5-Audio-1.5B) is not a transformers model, but passes + # like ModelBuilder only need the config. Remote-code configs keep their error asking for trust_remote_code. + config_dict, unused_kwargs = PretrainedConfig.get_config_dict( + get_pretrained_name_or_path(model_name_or_path, "config"), **kwargs + ) + if "model_type" in config_dict or "auto_map" in config_dict: + raise + model_config = PretrainedConfig.from_dict(config_dict, **unused_kwargs) # add quantization config quantization_config = kwargs.get("quantization_config") diff --git a/test/common/test_hf.py b/test/common/test_hf.py index c51f4c9d67..dca2a9a335 100644 --- a/test/common/test_hf.py +++ b/test/common/test_hf.py @@ -15,6 +15,7 @@ TEST_MODEL_MARKER_FILE, _apply_test_model_config, _load_test_model, + get_model_config, load_model_from_task, ) @@ -43,6 +44,32 @@ def test_apply_test_model_config_reduces_nested_vision_depth(): assert reduced.vision_config.depth == 2 +def test_get_model_config_returns_plain_config_when_model_type_missing(tmp_path): + config = {"architectures": ["Lfm2AudioForConditionalGeneration"], "codebooks": 8, "lfm": {"hidden_size": 2048}} + (tmp_path / "config.json").write_text(json.dumps(config)) + + model_config = get_model_config(str(tmp_path), dtype="bfloat16") + + assert model_config.architectures == ["Lfm2AudioForConditionalGeneration"] + assert model_config.codebooks == 8 + assert model_config.lfm == {"hidden_size": 2048} + assert model_config.dtype == "bfloat16" + + +def test_get_model_config_raises_when_model_type_unknown(tmp_path): + (tmp_path / "config.json").write_text(json.dumps({"model_type": "not_a_real_model_type"})) + + with pytest.raises(ValueError, match="not_a_real_model_type"): + get_model_config(str(tmp_path)) + + +def test_get_model_config_raises_when_remote_code_not_trusted(tmp_path): + (tmp_path / "config.json").write_text(json.dumps({"auto_map": {"AutoConfig": "configuration_x.XConfig"}})) + + with pytest.raises(ValueError, match="custom code"): + get_model_config(str(tmp_path), trust_remote_code=False) + + def test_load_model_from_task(): # The model name and task type is gotten from # https://huggingface.co/docs/transformers/v4.28.1/en/main_classes/pipelines#transformers.pipeline