mirror of
https://github.com/huggingface/diffusers.git
synced 2026-10-24 20:59:27 +03:00
* fix(torchao): route root-level tensors around safetensors reconstruction Models with parameters at the root of the module tree (e.g. Wan's `scale_shift_table`) crashed torchao's `unflatten_tensor_state_dict` when loading serialized checkpoints, since flattened tensor names are assumed to carry a module prefix. Filter such tensors and their metadata entries out of the reconstruction and merge them back unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bnb): defer 8-bit weights split from their SCB stats across shards Sharded serialization can place an 8-bit weight and its `SCB` statistics in different shard files, in which case the shard-by-shard loader failed with "Missing quantization component `SCB`". Hold the incomplete half of the pair back until its counterpart arrives with a later shard, mirroring the torchao pending mechanism, and disable parallel shard loading for prequantized 8-bit checkpoints. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [tests] extend model-level quantization tester mixins Migrate remaining model-level coverage from tests/quantization into the tester mixins so it runs for every wired model: - base: buffer-placement assertions in the device-map test, and an opt-in sharded-serialization test enabled by setting `sharded_serialization_config` - bnb: serialization across all configs (sharded included), dtype assignment and adapter training for 8-bit, device moves preserving the memory footprint, corrupted-state-dict loading error, and a fixed modules-to-not-convert test (BitsAndBytesConfig only exposes llm_int8_skip_modules; the old test passed an unsupported kwarg and only survived by being skipped) - torchao: custom device maps with cpu/disk offload, generalized from the Flux-specific test - gguf: the diffusers-format single-file loading path, wired into the Flux model tests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [tests] fix model-level quantization test wiring - SD3.5: the quantized testers reused the random-init dummy inputs (4 latent channels, fp32) while the tiny Hub checkpoint has in_channels=8 and the quantizers load the model in half precision; give them matching inputs and relax the 4-bit memory expectation for the tiny checkpoint. - QwenImage / Flux2: the quantized testers had no Hub checkpoint wired at all, so every test errored; point them at hf-internal-testing/tiny-qwenimage-pipe and tiny-flux2 with matching inputs. - NucleusMoE: no tiny checkpoint exists on the Hub yet; comment the testers out like the LTX ones. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [tests] split tests/quantization into pipeline-level and backend-level tiers Pipeline-level quantization tests (pipeline quality slices, cpu offload, LoRA loading, compile, PipelineQuantizationConfig) move to tests/pipelines/testing_utils/quantization.py, marked per backend so the nightly CI can select them with `pytest -m`. tests/quantization keeps only backend-level tests that fit neither tier: config validation, utility warnings, and GGUF CUDA kernel correctness. Tests already covered by the model-level mixins are dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [ci] select nightly quantization tests by marker across test tiers Each backend job now runs `pytest -m <marker>` over tests/models, tests/quantization, and tests/pipelines/testing_utils/quantization.py, giving the model-level mixin tests a nightly home with the backend dependencies installed. The torchao job additionally installs mslk. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: sayak@huggingface.co <sayak@ip-10-53-90-45.ec2.internal> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
# coding=utf-8
|
|
# Copyright 2026 The HuggingFace Team Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
import gc
|
|
|
|
import pytest
|
|
import torch
|
|
|
|
from diffusers import BitsAndBytesConfig
|
|
from diffusers.utils import logging
|
|
|
|
from ...testing_utils import (
|
|
CaptureLogger,
|
|
backend_empty_cache,
|
|
is_bitsandbytes,
|
|
is_bitsandbytes_available,
|
|
is_quantization,
|
|
require_accelerate,
|
|
require_bitsandbytes_version_greater,
|
|
require_torch,
|
|
require_torch_accelerator,
|
|
slow,
|
|
torch_device,
|
|
)
|
|
|
|
|
|
if is_bitsandbytes_available():
|
|
from diffusers.quantizers.bitsandbytes.utils import replace_with_bnb_linear
|
|
|
|
|
|
# Model-level BitsAndBytes tests live in `tests/models/testing_utils/quantization.py` and
|
|
# pipeline-level ones in `tests/pipelines/testing_utils/quantization.py`. This module covers
|
|
# backend behavior that fits neither: config validation, loading error paths, and utility warnings.
|
|
@is_quantization
|
|
@is_bitsandbytes
|
|
@require_bitsandbytes_version_greater("0.43.2")
|
|
@require_accelerate
|
|
@require_torch
|
|
@require_torch_accelerator
|
|
@slow
|
|
class TestBnB4BitBasic:
|
|
model_name = "stabilityai/stable-diffusion-3-medium-diffusers"
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _setup_basic(self):
|
|
gc.collect()
|
|
backend_empty_cache(torch_device)
|
|
yield
|
|
gc.collect()
|
|
backend_empty_cache(torch_device)
|
|
|
|
def test_bnb_4bit_wrong_config(self):
|
|
r"""
|
|
Test whether creating a bnb config with unsupported values leads to errors.
|
|
"""
|
|
with pytest.raises(ValueError):
|
|
_ = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_storage="add")
|
|
|
|
def test_bnb_4bit_logs_warning_for_no_quantization(self):
|
|
model_with_no_linear = torch.nn.Sequential(torch.nn.Conv2d(4, 4, 3), torch.nn.ReLU())
|
|
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
|
|
logger = logging.get_logger("diffusers.quantizers.bitsandbytes.utils")
|
|
logger.setLevel(30)
|
|
with CaptureLogger(logger) as cap_logger:
|
|
_ = replace_with_bnb_linear(model_with_no_linear, quantization_config=quantization_config)
|
|
assert (
|
|
"You are loading your model in 8bit or 4bit but no linear modules were found in your model."
|
|
in cap_logger.out
|
|
)
|