-
Notifications
You must be signed in to change notification settings - Fork 7.3k
[Quantization] Add support for Comfy-Kitchen / Comfy-Quants #14747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
PrakshaaleJain
wants to merge
24
commits into
huggingface:main
Choose a base branch
from
PrakshaaleJain:feat/comfy-quant-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
2dd589f
adding comfy_quant methods
PrakshaaleJain 78054ff
feature: add aupport for comfy-kitchen quantization
PrakshaaleJain eb4811c
feat: add support for INT8 and INT4 formats to comfy-kitchen quantizer
PrakshaaleJain b185a13
fix: register comfy-kitchen dummy objects correctly for check_dummies.py
PrakshaaleJain a8b2e12
docfix: deleted suggestion for installing latest version of comfy-kit…
PrakshaaleJain 0317874
test: add comfy-quant unit tests and fix layout passing
PrakshaaleJain 65587a0
Merge branch 'huggingface:main' into feat/comfy-quant-support
PrakshaaleJain 0c97d8d
test: refine invalid format test
PrakshaaleJain e38bf7f
style fixes
PrakshaaleJain 2452aa8
docs: add comfy_quant usage tutorial
PrakshaaleJain e9bca91
Merge branch 'main' into feat/comfy-quant-support
PrakshaaleJain 97c216d
Merge branch 'main' into feat/comfy-quant-support
PrakshaaleJain 6e450d5
Merge branch 'huggingface:main' into feat/comfy-quant-support
PrakshaaleJain 2b6f56e
fix: wrong dummy object name
PrakshaaleJain 5eb91a7
fix: avaliability guard logic
PrakshaaleJain c680d23
fix: revert unrelated ltx2 change
PrakshaaleJain b7f7536
Merge branch 'main' into feat/comfy-quant-support
PrakshaaleJain 0ff5c5e
fix: confy_kitchen import check
PrakshaaleJain a1e71c7
fix: moved layout resolution to init, removed QuantizedTensor check
PrakshaaleJain 47a77d1
feat: add check for unsupported passed format
PrakshaaleJain 69f29fa
test: add ComfyQuantConfigMixin and ComfyQuantTesterMixin
PrakshaaleJain 99d5ca6
add: tests for comfy_quant
PrakshaaleJain 310990a
Merge branch 'main' into feat/comfy-quant-support
PrakshaaleJain 4844cc9
Merge branch 'main' into feat/comfy-quant-support
PrakshaaleJain File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| <!--Copyright 2026 The HuggingFace Team. All rights reserved. | ||
|
|
||
| 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. | ||
|
|
||
| --> | ||
|
|
||
| # Comfy Quant | ||
|
|
||
| The [Comfy Quant](https://github.com/Comfy-Org/comfy-quants) toolkit provides state-of-the-art quantization techniques. While `comfy-quants` is used for exporting and quantizing models, Diffusers natively supports running inference on these models using the [comfy-kitchen](https://github.com/Comfy-Org/comfy-kitchen) library. | ||
|
|
||
| `comfy-kitchen` provides highly optimized GPU kernels that allow you to seamlessly run quantized layers. By passing a `ComfyQuantConfig` to Diffusers, the library will dynamically intercept parameters and wrap them in a `QuantizedTensor` that maps directly to the optimized `comfy-kitchen` layouts. | ||
|
|
||
| Before starting, please install `comfy-kitchen` in your environment: | ||
|
|
||
| ```shell | ||
| pip install comfy-kitchen | ||
| ``` | ||
|
|
||
| ## Loading a Comfy Quant Model | ||
|
|
||
| To load a model prequantized with Comfy Quant, use the [`~FromSingleFileMixin.from_single_file`] method and pass in the [`ComfyQuantConfig`]. | ||
|
|
||
| The configuration requires you to specify the `quant_format` that the model was quantized in, and the `compute_dtype` for active inference calculations. | ||
|
|
||
| The following example demonstrates how to load a quantized FLUX transformer: | ||
|
|
||
| ```python | ||
| import torch | ||
| from diffusers import FluxPipeline, FluxTransformer2DModel, ComfyQuantConfig | ||
|
|
||
| ckpt_path = "path/to/comfy_quant_checkpoint.safetensors" | ||
|
|
||
| # Initialize the config with your desired format and compute dtype | ||
| quantization_config = ComfyQuantConfig( | ||
| quant_format="fp8", | ||
| compute_dtype=torch.bfloat16 | ||
| ) | ||
|
|
||
| # Load the transformer directly from the safetensors file | ||
| transformer = FluxTransformer2DModel.from_single_file( | ||
| ckpt_path, | ||
| quantization_config=quantization_config, | ||
| dtype=torch.bfloat16, | ||
| ) | ||
|
|
||
| # Pass the quantized transformer into the pipeline | ||
| pipe = FluxPipeline.from_pretrained( | ||
| "black-forest-labs/FLUX.1-dev", | ||
| transformer=transformer, | ||
| dtype=torch.bfloat16, | ||
| ) | ||
| pipe.enable_model_cpu_offload() | ||
|
|
||
| prompt = "A cat holding a sign that says hello world" | ||
| image = pipe(prompt, generator=torch.manual_seed(0)).images[0] | ||
| image.save("flux-comfy-quant.png") | ||
| ``` | ||
|
|
||
| ## Supported Quantization Formats | ||
|
|
||
| Diffusers currently maps the following Comfy Quant formats to `comfy-kitchen` layouts: | ||
|
|
||
| - **FP8** (`fp8`): Maps to `TensorCoreFP8Layout` (E4M3/E5M2) | ||
| - **INT8** (`int8`): Maps to `TensorWiseINT8Layout` (W8A8, tensorwise) | ||
| - **MXFP8** (`mxfp8`): Maps to `TensorCoreMXFP8Layout` | ||
| - **NVFP4** (`nvfp4`): Maps to `TensorCoreNVFP4Layout` | ||
| - **INT4 SVD** (`int4_svd`): Maps to `TensorCoreSVDQuantW4A4Layout` (SVDQuant W4A4) | ||
| - **INT4 AWQ** (`int4_awq`): Maps to `TensorCoreAWQW4A16Layout` (AWQ W4A16) | ||
|
|
||
| When using optimized layouts, `comfy-kitchen` automatically dispatches the operations to the best available backend (HIP, CUDA, Triton, or Eager). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from .comfy_quantizer import ComfyQuantizer |
121 changes: 121 additions & 0 deletions
121
src/diffusers/quantizers/comfy_quant/comfy_quantizer.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| from ...utils import get_module_from_name, is_comfy_kitchen_available, is_torch_available, logging | ||
| from ..base import DiffusersQuantizer | ||
|
|
||
|
|
||
| if is_comfy_kitchen_available(): | ||
| import comfy_kitchen.tensor as ck_tensor | ||
|
|
||
| if TYPE_CHECKING: | ||
| from ...models.modeling_utils import ModelMixin | ||
|
|
||
| if is_torch_available(): | ||
| import torch | ||
|
|
||
|
|
||
| logger = logging.get_logger(__name__) | ||
|
|
||
|
|
||
| class ComfyQuantizer(DiffusersQuantizer): | ||
| """ | ||
| Quantizer for comfy-kitchen formats (FP8, INT8, etc.). | ||
| """ | ||
|
|
||
| use_keep_in_fp32_modules = True | ||
| requires_calibration = False | ||
| required_packages = ["comfy_kitchen"] | ||
|
|
||
| def __init__(self, quantization_config, **kwargs): | ||
| super().__init__(quantization_config, **kwargs) | ||
| self.quant_format = getattr(quantization_config, "quant_format", "fp8") | ||
| self.compute_dtype = quantization_config.compute_dtype | ||
| self.modules_to_not_convert = quantization_config.modules_to_not_convert or [] | ||
| if not isinstance(self.modules_to_not_convert, list): | ||
| self.modules_to_not_convert = [self.modules_to_not_convert] | ||
|
|
||
| if is_comfy_kitchen_available(): | ||
| # Resolve the layout class once since quant_format is constant. | ||
| layout_map = { | ||
| "fp8": getattr(ck_tensor, "TensorCoreFP8Layout", None), | ||
| "nvfp4": getattr(ck_tensor, "TensorCoreNVFP4Layout", None), | ||
| "mxfp8": getattr(ck_tensor, "TensorCoreMXFP8Layout", None), | ||
| "int8": getattr(ck_tensor, "TensorWiseINT8Layout", None), | ||
| "int4_svd": getattr(ck_tensor, "TensorCoreSVDQuantW4A4Layout", None), | ||
| "int4_awq": getattr(ck_tensor, "TensorCoreAWQW4A16Layout", None), | ||
| } | ||
| self.layout = layout_map.get(self.quant_format.lower()) | ||
| if self.layout is None: | ||
| supported = list(layout_map.keys()) | ||
| raise ValueError( | ||
| f"The layout for '{self.quant_format}' was not found in `comfy_kitchen`. " | ||
| f"Supported formats are: {supported}." | ||
| ) | ||
| else: | ||
| self.layout = None | ||
|
|
||
| def validate_environment(self, *args, **kwargs): | ||
| if not is_comfy_kitchen_available(): | ||
| raise ImportError( | ||
| "Loading Comfy Quant weights requires `comfy-kitchen`. " | ||
| "Please install it with: `pip install comfy-kitchen`." | ||
| ) | ||
|
|
||
| def check_if_quantized_param( | ||
| self, | ||
| model: "ModelMixin", | ||
| param_value: "torch.Tensor", | ||
| param_name: str, | ||
| state_dict: dict[str, Any], | ||
| **kwargs, | ||
| ) -> bool: | ||
| # Based on comfy_kitchen, we will likely wrap tensors based on some config layout. | ||
| # For now, we assume all linear weights that aren't excluded are quantized. | ||
| # This will be refined based on comfy-kitchen's actual detection logic. | ||
| if any(m in param_name.split(".") for m in self.modules_to_not_convert): | ||
| return False | ||
| return True | ||
|
|
||
| def create_quantized_param( | ||
| self, | ||
| model: "ModelMixin", | ||
| param_value: "torch.Tensor", | ||
| param_name: str, | ||
| target_device: "torch.device", | ||
| state_dict: dict[str, Any] | None = None, | ||
| unexpected_keys: list[str] | None = None, | ||
| **kwargs, | ||
| ): | ||
| module, tensor_name = get_module_from_name(model, param_name) | ||
|
|
||
| quantized_weight = ck_tensor.QuantizedTensor.from_float(param_value.to(target_device), self.layout.__name__) | ||
|
|
||
| if tensor_name in module._parameters: | ||
| module._parameters[tensor_name] = quantized_weight.to(target_device) | ||
| if tensor_name in module._buffers: | ||
| module._buffers[tensor_name] = quantized_weight.to(target_device) | ||
|
|
||
| def update_torch_dtype(self, torch_dtype: "torch.dtype") -> "torch.dtype": | ||
| if torch_dtype is None: | ||
| torch_dtype = self.compute_dtype | ||
| return torch_dtype | ||
|
|
||
| def _process_model_before_weight_loading( | ||
| self, | ||
| model: "ModelMixin", | ||
| device_map, | ||
| keep_in_fp32_modules: list[str] = [], | ||
| **kwargs, | ||
| ): | ||
| pass | ||
|
|
||
| def _process_model_after_weight_loading(self, model, **kwargs): | ||
| pass | ||
|
|
||
| @property | ||
| def is_serializable(self): | ||
| return False | ||
|
|
||
| @property | ||
| def is_trainable(self): | ||
| return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # This file is autogenerated by the command `make fix-copies`, do not edit. | ||
| from ..utils import DummyObject, requires_backends | ||
|
|
||
|
|
||
| class ComfyQuantConfig(metaclass=DummyObject): | ||
| _backends = ["comfy_kitchen"] | ||
|
|
||
| def __init__(self, *args, **kwargs): | ||
| requires_backends(self, ["comfy_kitchen"]) | ||
|
|
||
| @classmethod | ||
| def from_config(cls, *args, **kwargs): | ||
| requires_backends(cls, ["comfy_kitchen"]) | ||
|
|
||
| @classmethod | ||
| def from_pretrained(cls, *args, **kwargs): | ||
| requires_backends(cls, ["comfy_kitchen"]) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.