diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e3ab6ded..433208b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ For full details, see [ChangeLog](https://github.com/vladmandic/automatic/blob/m - [HiDream-O1-Image](https://huggingface.co/HiDream-ai/HiDream-O1-Image) pixel-level unified transformer model support HiDream-O1 is based on a single custom *Qwen3-VL* 8.8B 35GB component includes both **HiDream-O1-Image** *(base)* and **HiDream-O1-Image-Dev** *(distilled*)* variants + includes *sdnq-svd-dynamic-int8* pre-quantized variants for both base and dev models includes *T2I* and *I2I edit* capabilities and resolutions up to 2048px *note*: use steps:50 for base and steps:28 for dev variants - [JoyAI Image Edit](https://huggingface.co/jdopensource/JoyAI-Image-Edit-Diffusers) image-editing model support @@ -33,10 +34,13 @@ For full details, see [ChangeLog](https://github.com/vladmandic/automatic/blob/m primarily image-editing model, but supports t2i as well, uses multi-scale resolution binning up to 2048px - [AlphaVLLM Lumina-DiMOO](https://huggingface.co/Alpha-VLLM/Lumina-DiMOO) unified multimodal diffusion model includes *T2I*, *I2I edit*, and *MMU* capabilities in a single pipeline - *note* in addition to normal prompt-based image editing, model also supports special prompts: *dense, canny_pred, control, subject, edit, ref_transfer, multi_view* + *note* model also supports special prompts: *dense, canny_pred, control, subject, edit, ref_transfer, multi_view* *note* as with most multi-modal/unified models, it needs higher step count (recommended is 64 steps) and uses quite a lot of VRAM, so use with caution! - [Owen777 UltraFlux-v1](https://huggingface.co/Owen777/UltraFlux-v1) native 4K text-to-image model based on *FLUX.1-dev* *note*: UltraFlux is capable of rendering images up to 4K resolution, but it doesnt mean it will do that on any hardware - it will depend on your VRAM! + - [Anima Preview-v3](https://huggingface.co/circlestone-labs/Anima) + add *turbo* variant with [turbo-LoRA](https://civitai.com/models/2560840/anima-turbo-lora) pre-merged + add *sdnq-svd-dynamic-int8* pre-quantized variant - **Features** - **Multi-image** workflows! for models that support multiple images as inputs, you can now add multiple stages in Kanvas diff --git a/data/reference-quant.json b/data/reference-quant.json index edeb0dbf2..67254baf4 100644 --- a/data/reference-quant.json +++ b/data/reference-quant.json @@ -242,7 +242,7 @@ "desc": "ERNIE-Image is a text-to-image diffusion transformer model that combines a Mistral3 text encoder with a FlowMatch transformer and Flux2-style VAE for 1024px image generation.", "skip": true, "extras": "sampler: Default, cfg_scale: 4.0, steps: 50", - "size": 23.93, + "size": 7.52, "date": "2026 April" }, "Baidu ERNIE-Image-Turbo sdnq-dynamic-int4": { @@ -251,8 +251,44 @@ "desc": "ERNIE-Image-Turbo is a distilled ERNIE-Image variant optimized for fast generation with fewer denoising steps.", "skip": true, "extras": "sampler: Default, cfg_scale: 1.0, steps: 8", - "size": 23.37, + "size": 7.52, "tags": "distilled", "date": "2026 April" + }, + "Anima Preview 3 sdnq-dynamic-int8": { + "path": "vladmandic/Anima-Preview-3-diffusers-SDNQ-8bit-dynamic", + "preview": "CalamitousFelicitousness--Anima-Preview-3-sdnext-diffusers.jpg", + "desc": "Anima Preview V3 with extended 1024-resolution training and expanded dataset coverage for less common artists. A 2B parameter anime-focused text-to-image model based on modified Cosmos-Predict-2B with Qwen3-0.6B text encoder, created by CircleStone Labs and Comfy Org.", + "tags": "community", + "date": "2026 April", + "size": 3.19, + "skip": true + }, + "Anima Preview 3 Turbo sdnq-dynamic-int8": { + "path": "vladmandic/Anima-Preview-3-turbo-diffusers-SDNQ-8bit-dynamic", + "preview": "CalamitousFelicitousness--Anima-Preview-3-sdnext-diffusers.jpg", + "desc": "Anima Preview V3 with extended 1024-resolution training and expanded dataset coverage for less common artists. A 2B parameter anime-focused text-to-image model based on modified Cosmos-Predict-2B with Qwen3-0.6B text encoder, created by CircleStone Labs and Comfy Org.", + "tags": "community", + "date": "2026 April", + "size": 3.19, + "skip": true + }, + "HiDream-O1 Image sdnq-dynamic-int8": { + "path": "vladmandic/HiDream-O1-Image-SDNQ-8bit-dynamic", + "desc": "HiDream-O1-Image is an 8B pixel-level unified transformer model for text-to-image generation, instruction editing, and multi-reference personalization up to 2048x2048.", + "preview": "HiDream-ai--HiDream-O1-Image.jpg", + "skip": true, + "extras": "sampler: Default", + "size": 10.34, + "date": "2026 May" + }, + "HiDream-O1 Image Dev sdnq-dynamic-int8": { + "path": "vladmandic/HiDream-O1-Image-Dev-SDNQ-8bit-dynamic", + "desc": "HiDream-O1-Image is an 8B pixel-level unified transformer model for text-to-image generation, instruction editing, and multi-reference personalization up to 2048x2048.", + "preview": "HiDream-ai--HiDream-O1-Image.jpg", + "skip": true, + "extras": "sampler: Default", + "size": 10.34, + "date": "2026 May" } } diff --git a/modules/sdnq/loader.py b/modules/sdnq/loader.py index 6fb9f2d9b..fa7ce30dd 100644 --- a/modules/sdnq/loader.py +++ b/modules/sdnq/loader.py @@ -25,6 +25,31 @@ def unset_config_on_save(quantization_config: SDNQConfig) -> SDNQConfig: return quantization_config +def normalize_tied_weights_keys_for_save(model: ModelMixin, is_pipeline: bool = False) -> list[tuple[torch.nn.Module, object]]: + normalized_modules = [] + modules_to_walk = [] + if is_pipeline: + for module_name in get_module_names(model): + module = getattr(model, module_name, None) + if isinstance(module, torch.nn.Module): + modules_to_walk.append(module) + elif isinstance(model, torch.nn.Module): + modules_to_walk.append(model) + + for root_module in modules_to_walk: + for submodule in root_module.modules(): + tied_weights_keys = getattr(submodule, "_tied_weights_keys", None) + if isinstance(tied_weights_keys, list): + normalized_modules.append((submodule, tied_weights_keys)) + submodule._tied_weights_keys = {key: key for key in tied_weights_keys} # pylint: disable=protected-access + return normalized_modules + + +def restore_tied_weights_keys_after_save(normalized_modules: list[tuple[torch.nn.Module, object]]) -> None: + for submodule, tied_weights_keys in normalized_modules: + submodule._tied_weights_keys = tied_weights_keys # pylint: disable=protected-access + + def save_sdnq_model(model: ModelMixin, model_path: str, max_shard_size: str = "5GB", is_pipeline: bool = False, sdnq_config: SDNQConfig | None = None) -> None: if is_pipeline: for module_name in get_module_names(model): @@ -39,7 +64,11 @@ def save_sdnq_model(model: ModelMixin, model_path: str, max_shard_size: str = "5 if hasattr(model, "quantization_config") and isinstance(model.quantization_config, SDNQConfig): model.quantization_config = unset_config_on_save(model.quantization_config) - model.save_pretrained(model_path, max_shard_size=max_shard_size) # actual save + normalized_modules = normalize_tied_weights_keys_for_save(model, is_pipeline=is_pipeline) + try: + model.save_pretrained(model_path, max_shard_size=max_shard_size) # actual save + finally: + restore_tied_weights_keys_after_save(normalized_modules) quantization_config_path = os.path.join(model_path, "quantization_config.json") if sdnq_config is not None: # if provided, save global config diff --git a/pipelines/hidream/qwen3_vl_transformers.py b/pipelines/hidream/qwen3_vl_transformers.py index d90d0cf41..f0d1d1074 100644 --- a/pipelines/hidream/qwen3_vl_transformers.py +++ b/pipelines/hidream/qwen3_vl_transformers.py @@ -21,7 +21,7 @@ else: from flash_attn_interface import flash_attn_func as _flash_attn_func except ImportError: try: - from flash_attn import flash_attn_func as _flash_attn_func + from flash_attn import flash_attn_func as _flash_attn_func # pylint: disable=ungrouped-imports except ImportError: _flash_attn_func = None @@ -1655,7 +1655,7 @@ class Qwen3VLModel(Qwen3VLPreTrainedModel): deepstack_visual_embeds = [] image_mask_joint = image_mask[visual_pos_masks] video_mask_joint = video_mask[visual_pos_masks] - for img_embed, vid_embed in zip(deepstack_image_embeds, deepstack_video_embeds): + for img_embed, vid_embed in zip(deepstack_image_embeds, deepstack_video_embeds): # pylint: disable=possibly-used-before-assignment embed_joint = img_embed.new_zeros(visual_pos_masks.sum(), img_embed.shape[-1]).to(img_embed.device) embed_joint[image_mask_joint, :] = img_embed embed_joint[video_mask_joint, :] = vid_embed @@ -1766,7 +1766,7 @@ class Qwen3VLCausalLMOutputWithPast(ModelOutput): class HiDreamO1Qwen3VLTransformer(Qwen3VLPreTrainedModel, GenerationMixin): _checkpoint_conversion_mapping = {} - _tied_weights_keys = ["lm_head.weight"] + _tied_weights_keys = {"lm_head.weight": "model.language_model.embed_tokens.weight"} # Reference: fix gemma3 grad acc #37208 accepts_loss_kwargs = False config: Qwen3VLConfig