From ca0b5a31bf4966d87f33245439b7eea11941174a Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Sat, 25 Oct 2025 11:17:12 -0400 Subject: [PATCH] add quantized models to reference Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 10 +- html/reference.json | 130 +++++++++++++++-------- javascript/extraNetworks.js | 4 + javascript/settings.js | 2 +- modules/sd_models.py | 23 ++-- modules/ui_extra_networks.py | 5 +- modules/ui_extra_networks_checkpoints.py | 19 +++- 7 files changed, 129 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6d270deb..9f6ef3205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,10 @@ - **Models** - [Tencent HunyuanImage 2.1](https://huggingface.co/tencent/HunyuanImage-2.1) in *full*, *distilled* and *refiner* variants HunyuanImage-2.1 is a large (51GB) T2I model capable of natively generating 2K images and uses Qwen2.5 + T5 text-encoders and 32x VAE - - networks reference section is now split into actual **Reference** models plus: - **Distilled** which shows distilled variants of base models and **Community** which shows community highlights - - Add SDNQ-SVD **pre-quantized** models to distilled models: *FLUX.1-Dev, Chroma1-HD, NoobAI-XL* - *note*: these models are pre-quantized to minimal resource usage while maintaining high quality - if you're low on vram and don't want to explore all of quantization options, these are a good starting point! - - Add additional community models: *CenKreChro, WAI-Illustrious, NoobAI, Pony-Realism* + - networks reference section is now split into actual **Reference** *Base* models plus: + - **Distilled**: distilled variants of base models, for example *Turbo or Lightning* + - **Quantized**: pre-quantized variants of the base models using SDNQ-SVD quantization for optimal quality and smallest possible resource usage + - **Community**: community highlights, for example, *Illustrious, Pony, NoobAI* - **Features** - **offline mode**: enable in *settings -> hugginface* enables fully offline mode where previously downloaded models can be used as-is diff --git a/html/reference.json b/html/reference.json index b5113b612..2022a40db 100644 --- a/html/reference.json +++ b/html/reference.json @@ -68,7 +68,7 @@ "tags": "distilled", "date": "2024 February" }, - "StabilityAI Stable Diffusion 3 Medium": { + "StabilityAI Stable Diffusion 3.0 Medium": { "path": "stabilityai/stable-diffusion-3-medium-diffusers", "skip": true, "variant": "fp16", @@ -806,28 +806,6 @@ "date": "2024 October" }, - "ShuttleAI Shuttle 3.0 Diffusion": { - "path": "shuttleai/shuttle-3-diffusion", - "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", - "preview": "shuttleai--shuttle-3-diffusion.jpg", - "tags": "community", - "skip": true - }, - "ShuttleAI Shuttle 3.1 Aesthetic": { - "path": "shuttleai/shuttle-3.1-aesthetic", - "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", - "preview": "shuttleai--shuttle-3_1-aestetic.jpg", - "tags": "community", - "skip": true - }, - "ShuttleAI Shuttle Jaguar": { - "path": "shuttleai/shuttle-jaguar", - "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", - "preview": "shuttleai--shuttle-jaguar.jpg", - "tags": "community", - "skip": true - }, - "Bria 3.2": { "path": "briaai/BRIA-3.2", "desc": "Bria 3.2 is the next-generation commercial-ready text-to-image model. With just 4 billion parameters, it provides exceptional aesthetics and text rendering, evaluated to provide on par results to leading open-source models, and outperforming other licensed models.", @@ -933,7 +911,7 @@ "preview": "Disty0--FLUX.1-dev-SDNQ-uint4-svd-r32.jpg", "desc": "4 bit (UINT4 with SVD rank 32) quantization of black-forest-labs/FLUX.1-dev using SDNQ.", "skip": true, - "tags": "distilled", + "tags": "quantized", "size": 6.8, "date": "2025 October", "extras": "" @@ -941,30 +919,76 @@ "Chroma1-HD sdnq-svd-uint4": { "path": "Disty0/Chroma1-HD-SDNQ-uint4-svd-r32", "preview": "Disty0--Chroma1-HD-SDNQ-uint4-svd-r32.jpg", - "desc": "4 bit (UINT4 with SVD rank 32) quantization of lodestones/Chroma1-HD using SDNQ.", + "desc": "quantization of lodestones/Chroma1-HD using SDNQ: sdnq-svd 4-bit uint with svd rank 32", "skip": true, - "tags": "distilled", + "tags": "quantized", "size": 5.4, "date": "2025 October", "extras": "" }, - "NoobAI-XL v1.1 sdnq-svd-uint4": { + "Wan-AI Wan2.2 A14B T2I sdnq-svd-uint4": { + "path": "Disty0/Wan2.2-T2V-A14B-SDNQ-uint4-svd-r32", + "preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg", + "desc": "quantization of Wan-AI/Wan2.2-T2V-A14B-Diffusers using SDNQ: sdnq-svd 4-bit uint with svd rank 32", + "skip": true, + "tags": "quantized", + "date": "2025 October", + "extras": "" + }, + "Wan-AI Wan2.2 A14B I2I sdnq-svd-uint4": { + "path": "Disty0/Wan2.2-I2V-A14B-SDNQ-uint4-svd-r32", + "preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg", + "desc": "quantization of Wan-AI/Wan2.2-I2V-A14B-Diffusers using SDNQ: sdnq-svd 4-bit uint with svd rank 32", + "skip": true, + "tags": "quantized", + "date": "2025 October", + "extras": "" + }, + "Qwen-Image sdnq-svd-uint4": { + "path": "Disty0/Qwen-Image-SDNQ-uint4-svd-r32", + "preview": "Qwen--Qwen-Image.jpg", + "desc": "quantization of Qwen/Qwen-Image using SDNQ: sdnq-svd 4-bit uint with svd rank 32", + "skip": true, + "tags": "quantized", + "date": "2025 October", + "extras": "" + }, + "Qwen-Image-Edit sdnq-svd-uint4": { + "path": "Disty0/Qwen-Image-Edit-SDNQ-uint4-svd-r32", + "preview": "Qwen--Qwen-Image-Edit.jpg", + "desc": "quantization of Qwen/Qwen-Image-Edit using SDNQ: sdnq-svd 4-bit uint with svd rank 32", + "skip": true, + "tags": "quantized", + "date": "2025 October", + "extras": "" + }, + "Qwen-Image-Edit-2509 sdnq-svd-uint4": { + "path": "Disty0/Qwen-Image-Edit-2509-SDNQ-uint4-svd-r32", + "preview": "Qwen--Qwen-Image-Edit-2509.jpg", + "desc": "quantization of Qwen/Qwen-Image-Edit-2509 using SDNQ: sdnq-svd 4-bit uint with svd rank 32", + "skip": true, + "tags": "quantized", + "date": "2025 October", + "extras": "" + }, + + "NoobAI-XL v1.1 epsilon sdnq-svd-uint4": { "path": "Disty0/NoobAI-XL-v1.1-SDNQ-uint4-svd-r128", "preview": "Disty0--NoobAI-XL-v1.1-SDNQ-uint4-svd-r128.jpg", - "desc": "4 bit (UINT4 with SVD rank 128) quantization of Laxhar/noobai-XL-1.1 using SDNQ.", + "desc": "quantization of Laxhar/noobai-XL-1.1 using SDNQ: sdnq-svd 4-bit uint with svd rank 128", "skip": true, - "tags": "distilled", - "size": 5.4, + "tags": "quantized", + "size": 2.56, "date": "2025 October", "extras": "" }, "NoobAI-XL v1.0 v-pred sdnq-svd-uint4": { "path": "Disty0/NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128", "preview": "Disty0--NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128.jpg", - "desc": "4 bit (UINT4 with SVD rank 128) quantization of Laxhar/noobai-XL-Vpred-1.0 using SDNQ.", + "desc": "quantization of Laxhar/noobai-XL-Vpred-1.0 using SDNQ: sdnq-svd 4-bit uint with svd rank 128", "skip": true, - "tags": "distilled", - "size": 5.4, + "tags": "quantized", + "size": 2.56, "date": "2025 October", "extras": "" }, @@ -1015,15 +1039,6 @@ "tags": "community", "extras": "width: 512, height: 512, sampler: DEIS, steps: 20, cfg_scale: 6.0" }, - "Tiwaz CenKreChro": { - "path": "Tiwaz/CenKreChro", - "preview": "Tiwaz--CenKreChro.jpg", - "skip": true, - "desc": "Based Centerfold Flux 5, trying to merge in Chroma and Krea.", - "extras": "", - "tags": "community", - "date": "2025 September" - }, "WAI Illustrious XL v15": { "path": "waiIllustriousSDXL_v150.safetensors@https://civitai.com/api/download/models/2167369", "preview": "waiIllustriousSDXL_v150.jpg", @@ -1068,5 +1083,36 @@ "size": 6.94, "date": "2025 May", "extras": "" + }, + "Tiwaz CenKreChro": { + "path": "Tiwaz/CenKreChro", + "preview": "Tiwaz--CenKreChro.jpg", + "skip": true, + "desc": "Based Centerfold Flux 5, trying to merge in Chroma and Krea.", + "extras": "", + "tags": "community", + "date": "2025 September" + }, + "ShuttleAI Shuttle 3.0 Diffusion": { + "path": "shuttleai/shuttle-3-diffusion", + "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", + "preview": "shuttleai--shuttle-3-diffusion.jpg", + "tags": "community", + "skip": true + }, + "ShuttleAI Shuttle 3.1 Aesthetic": { + "path": "shuttleai/shuttle-3.1-aesthetic", + "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", + "preview": "shuttleai--shuttle-3_1-aestetic.jpg", + "tags": "community", + "skip": true + }, + "ShuttleAI Shuttle Jaguar": { + "path": "shuttleai/shuttle-jaguar", + "desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition", + "preview": "shuttleai--shuttle-jaguar.jpg", + "tags": "community", + "skip": true } + } diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index d7affa804..aa9b71246 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -153,6 +153,10 @@ async function filterExtraNetworksForTab(searchTerm) { cards.forEach((elem) => elem.style.display = elem.dataset.tags .toLowerCase() .includes('community') ? '' : 'none'); + } else if (searchTerm === 'quantized/') { + cards.forEach((elem) => elem.style.display = elem.dataset.tags + .toLowerCase() + .includes('quantized') ? '' : 'none'); } else if (searchTerm === 'local/') { cards.forEach((elem) => elem.style.display = elem.dataset.name .toLowerCase() diff --git a/javascript/settings.js b/javascript/settings.js index f6d133a19..f82f0a692 100644 --- a/javascript/settings.js +++ b/javascript/settings.js @@ -170,7 +170,7 @@ async function initModels() { if (en.classList.contains('hide')) gradioApp().getElementById('txt2img_extra_networks_btn').click(); const repeat = setInterval(() => { const buttons = Array.from(gradioApp().querySelectorAll('#txt2img_model_subdirs > button')) || []; - const reference = buttons.find((b) => (b.innerText === 'Reference') || (b.innerText === 'Distilled') || (b.innerText === 'Community')); + const reference = buttons.find((b) => (b.innerText === 'Reference') || (b.innerText === 'Distilled') || (b.innerText === 'Community') || (b.innerText === 'Quantized')); if (reference) { clearInterval(repeat); reference.click(); diff --git a/modules/sd_models.py b/modules/sd_models.py index 9d1c978b3..534c3af58 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -1147,18 +1147,19 @@ def set_diffusers_attention(pipe, quiet:bool=False): def add_noise_pred_to_diffusers_callback(pipe): if not hasattr(pipe, "_callback_tensor_inputs"): return pipe - if pipe.__class__.__name__.startswith("StableDiffusion"): - pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access - elif pipe.__class__.__name__.startswith("StableCascade") and ("predicted_image_embedding" not in pipe._callback_tensor_inputs): # pylint: disable=protected-access + if pipe.__class__.__name__.startswith("StableCascade") and ("predicted_image_embedding" not in pipe._callback_tensor_inputs): # pylint: disable=protected-access pipe.prior_pipe._callback_tensor_inputs.append("predicted_image_embedding") # pylint: disable=protected-access - elif hasattr(pipe, "scheduler") and "flow" in pipe.scheduler.__class__.__name__.lower() and ("noise_pred" not in pipe._callback_tensor_inputs): - pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access - elif hasattr(pipe, "scheduler") and hasattr(pipe.scheduler, "config") and (getattr(pipe.scheduler.config, "prediction_type", "none") == "flow_prediction") and ("noise_pred" not in pipe._callback_tensor_inputs): - pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access - elif hasattr(pipe, "default_scheduler") and ("flow" in pipe.default_scheduler.__class__.__name__.lower()) and ("noise_pred" not in pipe._callback_tensor_inputs): - pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access - elif hasattr(pipe, "default_scheduler") and hasattr(pipe.default_scheduler, "config") and (getattr(pipe.default_scheduler.config, "prediction_type", "none") == "flow_prediction") and ("noise_pred" not in pipe._callback_tensor_inputs): - pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access + elif "noise_pred" not in pipe._callback_tensor_inputs: + if pipe.__class__.__name__.startswith("StableDiffusion"): + pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access + elif hasattr(pipe, "scheduler") and "flow" in pipe.scheduler.__class__.__name__.lower(): + pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access + elif hasattr(pipe, "scheduler") and hasattr(pipe.scheduler, "config") and (getattr(pipe.scheduler.config, "prediction_type", "none") == "flow_prediction"): + pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access + elif hasattr(pipe, "default_scheduler") and ("flow" in pipe.default_scheduler.__class__.__name__.lower()): + pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access + elif hasattr(pipe, "default_scheduler") and hasattr(pipe.default_scheduler, "config") and (getattr(pipe.default_scheduler.config, "prediction_type", "none") == "flow_prediction"): + pipe._callback_tensor_inputs.append("noise_pred") # pylint: disable=protected-access return pipe diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 50341f36f..741605c25 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -273,6 +273,7 @@ class ExtraNetworksPage: subdirs['Local'] = 1 subdirs['Reference'] = 1 subdirs['Distilled'] = 1 + subdirs['Quantized'] = 1 subdirs['Community'] = 1 subdirs[diffusers_base] = 1 if self.name == 'style' and shared.opts.extra_networks_styles: @@ -289,13 +290,15 @@ class ExtraNetworksPage: subdirs.move_to_end('Reference', last=True) if 'Distilled' in subdirs: subdirs.move_to_end('Distilled', last=True) + if 'Quantized' in subdirs: + subdirs.move_to_end('Quantized', last=True) if 'Community' in subdirs: subdirs.move_to_end('Community', last=True) subdirs_html = '' for subdir in subdirs: if len(subdir) == 0: continue - if subdir in ['All', 'Local', 'Diffusers', 'Reference', 'Distilled', 'Community']: + if subdir in ['All', 'Local', 'Diffusers', 'Reference', 'Distilled', 'Quantized', 'Community']: style = 'network-reference' else: style = 'network-folder' diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index cb21fe608..2fe4db376 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -4,6 +4,7 @@ import json import concurrent from datetime import datetime from modules import shared, ui_extra_networks, sd_models, modelstats, paths +from modules.json_helpers import readfile version_map = { @@ -36,8 +37,10 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): return any(model.endswith(url) for model in existing) if not shared.opts.sd_checkpoint_autodownload or not shared.opts.extra_network_reference_enable: + shared.log.debug(f'Networks: type="reference" autodownload={shared.opts.sd_checkpoint_autodownload} enable={shared.opts.extra_network_reference_enable}') return [] - count = { 'total': 0, 'ready': 0, 'hidden': 0, 'experimental': 0 } + count = { 'total': 0, 'ready': 0, 'hidden': 0, 'experimental': 0, 'base': 0 } + shared.reference_models = readfile(os.path.join('html', 'reference.json')) for k, v in shared.reference_models.items(): count['total'] += 1 url = v['path'] @@ -64,12 +67,22 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): path = f'{v.get("path", "")}+{v.get("subfolder", "")}' else: path = f'{v.get("path", "")}' + ready = reference_downloaded(url) if not ready and shared.opts.offline_mode: count['hidden'] += 1 continue if ready: count['ready'] += 1 + + tag = v.get('tags', '') + if tag in count: + count[tag] += 1 + elif tag != '': + count[tag] = 1 + else: + count['base'] += 1 + yield { "type": 'Model', "name": name, @@ -85,9 +98,9 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): "metadata": {}, "description": v.get('desc', ''), "version": "ready" if ready else "download", - "tags": v.get('tags', ''), + "tags": tag, } - shared.log.debug(f'Networks: type="reference" items={count["total"]} ready={count["ready"]} hidden={count["hidden"]} experimental={count["experimental"]}') + shared.log.debug(f'Networks: type="reference" items={count}') def create_item(self, name): record = None