Skip to content

Fix: propagate quantization_config to text sub-config for composite models in AutoModelForCausalLM - #45494

Merged
SunMarc merged 2 commits into
huggingface:mainfrom
lvliang-intel:fix/propagate-quantization-config-to-text-subconfig
Apr 21, 2026
Merged

SunMarc merged 2 commits into
huggingface:mainfrom
lvliang-intel:fix/propagate-quantization-config-to-text-subconfig

Conversation

@lvliang-intel

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes loading of quantized composite models (e.g. Qwen3.5-35B-A3B with AutoRound quantization) via AutoModelForCausalLM.from_pretrained.

Problem:
For composite models whose model_class.config_class maps to text_config, the from_pretrained method in auto_factory.py swaps the full composite config with the text sub-config:

if model_class.config_class == config.sub_configs.get("text_config", None):
    config = config.get_text_config()

The quantization_config is stored on the top-level composite config (from config.json), but not on the text sub-config. When modeling_utils.py later calls get_hf_quantizer, it checks hasattr(config, "quantization_config") to determine pre_quantized. Since the text sub-config lacks this attribute, pre_quantized is set to False, which causes a ValueError for quantization methods that require pre-quantized weights (e.g. AutoRound, GPTQ, AWQ).

ValueError: The quantization method QuantizationMethod.AUTOROUND does require the model to be pre-quantized.
You explicitly passed pre_quantized=False meaning your model weights are not quantized.

How to reproduce the issue:

qconfig = transformers.AutoRoundConfig()
model = transformers.AutoModelForCausalLM.from_pretrained(model_name_or_path="Intel/Qwen3.5-35B-A3B-int4-AutoRound", trust_remote_code=True, device_map="cuda", quantization_config=qconfig)

Fixes # (issue)

After swapping to the text sub-config, propagate quantization_config from the parent composite config if it exists and the text sub-config does not already have one.

@Rocketknight1

Copy link
Copy Markdown
Member

cc @SunMarc for quants

@SunMarc SunMarc 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 a lot ! Left a suggestion and a comment

…odels in AutoModelForCausalLM

Signed-off-by: lvliang-intel <liang1.lv@intel.com>
Signed-off-by: lvliang-intel <liang1.lv@intel.com>
@lvliang-intel
lvliang-intel force-pushed the fix/propagate-quantization-config-to-text-subconfig branch from aaf3b31 to c9981a2 Compare April 21, 2026 02:04
@github-actions

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: auto

@SunMarc
SunMarc enabled auto-merge April 21, 2026 12:21
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@SunMarc SunMarc 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.

Nice !

@SunMarc
SunMarc added this pull request to the merge queue Apr 21, 2026
Merged via the queue into huggingface:main with commit 85099df Apr 21, 2026
28 checks passed
jamesbraza added a commit to jamesbraza/transformers that referenced this pull request May 4, 2026
Mirror the existing from_pretrained text_config unwrap into from_config so
the composite-config -> text-only-model "VLM compatibility" mapping (e.g.
Qwen3.5 / Qwen3.5-MoE) works for meta-init paths too. Without this,
AutoModelForCausalLM.from_config(Qwen3_5MoeConfig(...)) fails with
AttributeError because the text-only model class receives the composite
config. Also propagate quantization_config from the parent so pre-quantized
detection still works, mirroring PR huggingface#45494.

Add a parametrized regression test covering both from_pretrained and
from_config in the qwen3_5 and qwen3_5_moe model test files,
and extend the existing gemma3 test_automodelforcausallm to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jamesbraza added a commit to jamesbraza/transformers that referenced this pull request May 4, 2026
Mirror the existing from_pretrained text_config unwrap into from_config so
the composite-config -> text-only-model "VLM compatibility" mapping (e.g.
Qwen3.5 / Qwen3.5-MoE) works for meta-init paths too. Without this,
AutoModelForCausalLM.from_config(Qwen3_5MoeConfig(...)) fails with
AttributeError because the text-only model class receives the composite
config. Also propagate quantization_config from the parent so pre-quantized
detection still works, mirroring PR huggingface#45494.

Add a parametrized regression test covering both from_pretrained and
from_config in the qwen3_5 and qwen3_5_moe model test files,
and extend the existing gemma3 test_automodelforcausallm to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull Bot pushed a commit to dwongdev/transformers that referenced this pull request May 5, 2026
* Unwrap text_config in AutoModelFor*.from_config

Mirror the existing from_pretrained text_config unwrap into from_config so
the composite-config -> text-only-model "VLM compatibility" mapping (e.g.
Qwen3.5 / Qwen3.5-MoE) works for meta-init paths too. Without this,
AutoModelForCausalLM.from_config(Qwen3_5MoeConfig(...)) fails with
AttributeError because the text-only model class receives the composite
config. Also propagate quantization_config from the parent so pre-quantized
detection still works, mirroring PR huggingface#45494.

Add a parametrized regression test covering both from_pretrained and
from_config in the qwen3_5 and qwen3_5_moe model test files,
and extend the existing gemma3 test_automodelforcausallm to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert gemma3 from_config test addition

The unwrap branch in AutoModelFor*.from_config never triggers for gemma3
(its MODEL_FOR_CAUSAL_LM_MAPPING entry routes Gemma3Config to the VLM
class Gemma3ForConditionalGeneration, whose config_class is Gemma3Config
itself, not Gemma3TextConfig). The new from_config parameterization
therefore exercised only the pre-existing path and added no coverage of
the fix.

* Guard quantization_config propagation against None values

`hasattr(parent_config, "quantization_config")` returns True even when
the value is `None` (e.g. a config.json containing
`"quantization_config": null`, or a dequantization step that cleared
the attribute). The previous propagation copied that None onto the
unwrapped text sub-config, and `from_pretrained`'s downstream
`get_hf_quantizer` keys off `hasattr` to set `pre_quantized=True`, then
crashes inside `AutoHfQuantizer.supports_quant_method(None)` on
`None.get(...)`.

Switch to `getattr(parent_config, "quantization_config", None) is not
None` at both call sites so absent and None collapse into the same
"don't propagate" case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Exile333 pushed a commit to Exile333/transformers that referenced this pull request May 6, 2026
* Unwrap text_config in AutoModelFor*.from_config

Mirror the existing from_pretrained text_config unwrap into from_config so
the composite-config -> text-only-model "VLM compatibility" mapping (e.g.
Qwen3.5 / Qwen3.5-MoE) works for meta-init paths too. Without this,
AutoModelForCausalLM.from_config(Qwen3_5MoeConfig(...)) fails with
AttributeError because the text-only model class receives the composite
config. Also propagate quantization_config from the parent so pre-quantized
detection still works, mirroring PR huggingface#45494.

Add a parametrized regression test covering both from_pretrained and
from_config in the qwen3_5 and qwen3_5_moe model test files,
and extend the existing gemma3 test_automodelforcausallm to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert gemma3 from_config test addition

The unwrap branch in AutoModelFor*.from_config never triggers for gemma3
(its MODEL_FOR_CAUSAL_LM_MAPPING entry routes Gemma3Config to the VLM
class Gemma3ForConditionalGeneration, whose config_class is Gemma3Config
itself, not Gemma3TextConfig). The new from_config parameterization
therefore exercised only the pre-existing path and added no coverage of
the fix.

* Guard quantization_config propagation against None values

`hasattr(parent_config, "quantization_config")` returns True even when
the value is `None` (e.g. a config.json containing
`"quantization_config": null`, or a dequantization step that cleared
the attribute). The previous propagation copied that None onto the
unwrapped text sub-config, and `from_pretrained`'s downstream
`get_hf_quantizer` keys off `hasattr` to set `pre_quantized=True`, then
crashes inside `AutoHfQuantizer.supports_quant_method(None)` on
`None.get(...)`.

Switch to `getattr(parent_config, "quantization_config", None) is not
None` at both call sites so absent and None collapse into the same
"don't propagate" case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mvafin added a commit to mvafin/openvino that referenced this pull request Oct 1, 2026
….0.30, support aten.meshgrid in FX (openvinotoolkit#38443)

### Details:
- Nightly Scope1 has been crashing with runner OOM since openvinotoolkit#33706.
`filter_timm` sorted size tokens alphabetically (`enormous` < `giant` <
... < `small`) and didn't recognize `7b`/`so400m`, so it picked the
*largest* variants (e.g. `vit_7b_dinov3`, 26.9 GB). Several of these
were loaded at the same time under `-n 4`.
- `filter_timm` now keeps the smallest variant of each architecture.
Size tokens are ordered by size, parameter counts and bare `t`/`h` sizes
are recognized, and width-multiplier variants (`resnetv2_50x3`,
`resnext101_32x8d`) are folded into their base architecture (they use
the same ops).
- timm updated to 1.0.30. `timm_models` is regenerated: 517 models, down
from 532. The largest model is now 4.05 GB, and total weights drop from
~248 GB to ~108 GB. New failing models are marked xfail: `iformer_*`
(numpy<2 load error) and `gemma4_vit_167m*` in export mode.
- `aten::meshgrid` is now converted during translation for both
TorchScript and FX. `PrimListUnpackReplacer` is still the fallback when
the input list is unknown at that point. This fixes export mode for 9
new timm models and meshgrid outputs used directly by
`stack`/`cat`/`[i]`.
- Nightly Scope2 fails because
`DunnBC22/efficientformer-l3-300-Brain_Tumors_Image_Classification` was
removed from HF Hub. That failure also skips the LLM, Detectron2 and
Torchbench steps. The model is replaced with
`snap-research/efficientformer-l1-300`.
- LLM nightly test `qwen3_compressed_tensors`
(`cyankiwi/Qwen3.5-4B-AWQ-4bit`, a multimodal checkpoint) is marked
xfail. With the pinned transformers 5.5.3, `AutoModelForCausalLM` drops
its `quantization_config` (fixed in 5.8,
huggingface/transformers#45494). Newer versions still don't match the
checkpoint's ignore list to the text-only module names, so
`linear_attn.in_proj_a/b` are initialized randomly.
- Torchbench: all models failed in `install.py`, which requires
torchaudio. torchaudio was dropped from the requirements in openvinotoolkit#36098 and
doesn't support torch 2.14. The test removes torchaudio from
torchbench's `TORCH_DEPS`, pins `setuptools<81` for sdist builds
(`visdom` needs `pkg_resources`), and sets `PIP_USE_PEP517=1`. With pip
24, legacy `setup.py` packages are built in the test venv, where the
`egg_info` hook of `kernels` (installed for LLM tests) crashes against
the older `huggingface_hub` installed by torchbench. The maml models'
inputs, pickled with numpy<2, now load with numpy 2.
 - Scope1 failures that existed before this PR:
- `convit_tiny` (trace): the model fills a cache on its first forward,
so the test runs one warm-up forward first.
- torchvision segmentation models (export): FX model outputs are now
named after their dict keys, which for `ExportedProgram` are taken from
`out_spec`. A key is skipped if it's ambiguous (one tensor under several
keys, or the same key in several nested dicts) or matches the name of
another graph node or input.
   - `efficientvit_b0` (export): fixed by openvinotoolkit#38396, now passes.
 - Documented how to run model hub tests with a model cache.
- The nightly `PyTorch Models Nightly Scope1/Scope2 tests` jobs in
`ubuntu_22.yml` now also run for PRs that change
`tests/model_hub_tests/pytorch`,
`tests/model_hub_tests/models_hub_common` or
`job_pytorch_models_tests.yml`. The `Smart_CI` job checks the PR's
changed files with `git diff` on the merge commit, without extra API
calls. The jobs also run on manual dispatch with the new
`pytorch-models-nightly` input. They use the same runner and settings as
the nightly, and aren't part of `Overall_Status`, so a failure doesn't
block merge. This PR runs them itself. Moved from openvinotoolkit#38457.

### Tickets:
 - N/A

### AI Assistance:
 - AI assistance used: yes
- AI analyzed the CI logs, implemented the changes and ran local
validation (torch 2.14.0+cpu, timm 1.0.30):
- New timm models and the timm models that use meshgrid: pass or xfail
in trace and export mode.
   - `test_models_list_complete`: passes.
- Full layer suites: 0 failures, with TorchScript (16533 passed) and
with export (12969 passed, including the new dict output name tests).
- Torchbench, convit, efficientvit and torchvision segmentation models:
pass.
   - New efficientformer HF test: passes.
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.

4 participants