From 06ba03cf809956ccae8917c3a4fba30b5998a25b Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 23 Jan 2025 15:19:43 -0500 Subject: [PATCH] settings option to disable reference models Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 2 ++ modules/face/photomaker_pipeline.py | 10 +++++----- modules/intel/openvino/__init__.py | 8 ++++---- modules/merging/modules_sdxl.py | 14 +++++++------- modules/model_quant.py | 4 ++-- modules/perflow/pfode_solver.py | 6 +++--- modules/sd_models_compile.py | 5 ++--- modules/shared.py | 18 ++++++++++-------- modules/styles.py | 2 +- modules/ui_extra_networks.py | 4 ++-- modules/ui_extra_networks_checkpoints.py | 2 +- modules/upscaler_simple.py | 14 ++++++++------ 12 files changed, 47 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b1a291a2..f35f7b675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,10 +48,12 @@ - **gallery**: add http fallback for slow/unreliable links - **splash**: add legacy mode indicator on splash screen - **network**: extract thumbnail from model metadata if present + - **network**: setting value to disable use of reference models - **Refactor**: - **upscale**: code refactor to unify latent, resize and model based upscalers - **loader**: ability to run in-memory models - **schedulers**: ability to create model-less schedulers + - **quantiation**: code refactor into dedicated module - **Fixes**: - non-full vae decode - send-to image transfer diff --git a/modules/face/photomaker_pipeline.py b/modules/face/photomaker_pipeline.py index ec5728961..657e96fc7 100644 --- a/modules/face/photomaker_pipeline.py +++ b/modules/face/photomaker_pipeline.py @@ -272,7 +272,7 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline): # textual inversion: process multi-vector tokens if necessary prompt_embeds_list = [] prompts = [prompt, prompt_2] - for prompt, tokenizer, text_encoder in zip(prompts, tokenizers, text_encoders): + for prompt, tokenizer, text_encoder in zip(prompts, tokenizers, text_encoders): # pylint: disable=redefined-argument-from-local if isinstance(self, TextualInversionLoaderMixin): prompt = self.maybe_convert_prompt(prompt, tokenizer) @@ -367,7 +367,7 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline): f"`negative_prompt` should be the same type to `prompt`, but got {type(negative_prompt)} !=" f" {type(prompt)}." ) - elif batch_size != len(negative_prompt): + if batch_size != len(negative_prompt): raise ValueError( f"`negative_prompt`: {negative_prompt} has batch size {len(negative_prompt)}, but `prompt`:" f" {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches" @@ -377,7 +377,7 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline): uncond_tokens = [negative_prompt, negative_prompt_2] negative_prompt_embeds_list = [] - for negative_prompt, tokenizer, text_encoder in zip(uncond_tokens, tokenizers, text_encoders): + for negative_prompt, tokenizer, text_encoder in zip(uncond_tokens, tokenizers, text_encoders): # pylint: disable=redefined-argument-from-local if isinstance(self, TextualInversionLoaderMixin): negative_prompt = self.maybe_convert_prompt(negative_prompt, tokenizer) @@ -735,8 +735,8 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline): ): discrete_timestep_cutoff = int( round( - self.scheduler.config.num_train_timesteps - - (self.denoising_end * self.scheduler.config.num_train_timesteps) + self.scheduler.config.num_train_timesteps # pylint: disable=no-member + - (self.denoising_end * self.scheduler.config.num_train_timesteps) # pylint: disable=no-member ) ) num_inference_steps = len(list(filter(lambda ts: ts >= discrete_timestep_cutoff, timesteps))) diff --git a/modules/intel/openvino/__init__.py b/modules/intel/openvino/__init__.py index a4000c43a..11fa0426f 100644 --- a/modules/intel/openvino/__init__.py +++ b/modules/intel/openvino/__init__.py @@ -221,10 +221,10 @@ def openvino_compile(gm: GraphModule, *example_inputs, model_hash_str: str = Non for idx, _ in enumerate(example_inputs): new_inputs.append(example_inputs[idx].detach().cpu().numpy()) new_inputs = [new_inputs] - if shared.opts.nncf_quant_mode == "INT8": + if shared.opts.nncf_quantize_mode == "INT8": om = nncf.quantize(om, nncf.Dataset(new_inputs)) else: - om = nncf.quantize(om, nncf.Dataset(new_inputs), mode=getattr(nncf.QuantizationMode, shared.opts.nncf_quant_mode), + om = nncf.quantize(om, nncf.Dataset(new_inputs), mode=getattr(nncf.QuantizationMode, shared.opts.nncf_quantize_mode), advanced_parameters=nncf.quantization.advanced_parameters.AdvancedQuantizationParameters( overflow_fix=nncf.quantization.advanced_parameters.OverflowFix.DISABLE, backend_params=None)) @@ -281,10 +281,10 @@ def openvino_compile_cached_model(cached_model_path, *example_inputs): for idx, _ in enumerate(example_inputs): new_inputs.append(example_inputs[idx].detach().cpu().numpy()) new_inputs = [new_inputs] - if shared.opts.nncf_quant_mode == "INT8": + if shared.opts.nncf_quantize_mode == "INT8": om = nncf.quantize(om, nncf.Dataset(new_inputs)) else: - om = nncf.quantize(om, nncf.Dataset(new_inputs), mode=getattr(nncf.QuantizationMode, shared.opts.nncf_quant_mode), + om = nncf.quantize(om, nncf.Dataset(new_inputs), mode=getattr(nncf.QuantizationMode, shared.opts.nncf_quantize_mode), advanced_parameters=nncf.quantization.advanced_parameters.AdvancedQuantizationParameters( overflow_fix=nncf.quantization.advanced_parameters.OverflowFix.DISABLE, backend_params=None)) diff --git a/modules/merging/modules_sdxl.py b/modules/merging/modules_sdxl.py index 61f2cf948..ec994d567 100644 --- a/modules/merging/modules_sdxl.py +++ b/modules/merging/modules_sdxl.py @@ -67,13 +67,13 @@ def load_base(override:str=None): pipeline = diffusers.StableDiffusionXLPipeline.from_pretrained(fn, cache_dir=shared.opts.hfcache_dir, torch_dtype=recipe.dtype, add_watermarker=False) else: yield msg('base: not found') - return None + return pipeline.vae.register_to_config(force_upcast = False) def load_unet(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): if (recipe.unet is None or len(recipe.unet) == 0) and override is None: - return None + return fn = override or recipe.unet if not os.path.isabs(fn): fn = os.path.join(shared.opts.unet_dir, fn) @@ -92,7 +92,7 @@ def load_unet(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): def load_scheduler(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): if recipe.scheduler is None and override is None: - return None + return config = pipe.scheduler.config.__dict__ scheduler = override or recipe.scheduler yield msg(f'scheduler={scheduler}') @@ -107,7 +107,7 @@ def load_scheduler(pipe: diffusers.StableDiffusionXLPipeline, override:str=None) def load_vae(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): if (recipe.vae is None or len(recipe.vae) == 0)and override is None: - return None + return fn = override or recipe.vae if not os.path.isabs(fn): fn = os.path.join(shared.opts.vae_dir, fn) @@ -128,7 +128,7 @@ def load_vae(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): def load_te1(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): if (recipe.te1 is None or len(recipe.te1) == 0) and override is None: - return None + return config = pipe.text_encoder.config.__dict__ pretrained_config = transformers.PretrainedConfig.from_dict(config) fn = override or recipe.te1 @@ -149,7 +149,7 @@ def load_te1(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): def load_te2(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): if (recipe.te2 is None or len(recipe.te2) == 0) and override is None: - return None + return config = pipe.text_encoder_2.config.__dict__ pretrained_config = transformers.PretrainedConfig.from_dict(config) fn = override or recipe.te2 @@ -170,7 +170,7 @@ def load_te2(pipe: diffusers.StableDiffusionXLPipeline, override:str=None): def load_lora(pipe: diffusers.StableDiffusionXLPipeline, override: dict=None, fuse: float=None): if recipe.lora is None and override is None: - return None + return names = [] pipe.unfuse_lora() pipe.unload_lora_weights() diff --git a/modules/model_quant.py b/modules/model_quant.py index 24c517dc3..6798160a8 100644 --- a/modules/model_quant.py +++ b/modules/model_quant.py @@ -223,7 +223,7 @@ def nncf_compress_model(model, op=None, sd_model=None): nncf_send_to_device(model, devices.device) if hasattr(model, "set_input_embeddings") and backup_embeddings is not None: model.set_input_embeddings(backup_embeddings) - if op is not None and shared.opts.quant_shuffle_weights: + if op is not None and shared.opts.nncf_quantize_shuffle_weights: if quant_last_model_name is not None: if "." in quant_last_model_name: last_model_names = quant_last_model_name.split(".") @@ -290,7 +290,7 @@ def optimum_quanto_model(model, op=None, sd_model=None, weights=None, activation quanto.freeze(model) if hasattr(model, "set_input_embeddings") and backup_embeddings is not None: model.set_input_embeddings(backup_embeddings) - if op is not None and shared.opts.quant_shuffle_weights: + if op is not None and shared.opts.optimum_quanto_shuffle_weights: if quant_last_model_name is not None: if "." in quant_last_model_name: last_model_names = quant_last_model_name.split(".") diff --git a/modules/perflow/pfode_solver.py b/modules/perflow/pfode_solver.py index db1b8e903..bffdd1494 100644 --- a/modules/perflow/pfode_solver.py +++ b/modules/perflow/pfode_solver.py @@ -49,7 +49,7 @@ class PFODESolver(): timestep_cond = None if unet.config.time_cond_proj_dim is not None: guidance_scale_tensor = torch.tensor(guidance_scale - 1).repeat(bsz) - timestep_cond = self.get_guidance_scale_embedding( + timestep_cond = self.get_guidance_scale_embedding( # pylint: disable=no-member guidance_scale_tensor, embedding_dim=unet.config.time_cond_proj_dim ).to(device=latents.device, dtype=latents.dtype) @@ -124,7 +124,7 @@ class PFODESolverSDXL(): self.t_terminal = t_terminal self.scheduler = scheduler - train_step_terminal = 0 + train_step_terminal = 0 train_step_initial = train_step_terminal + self.scheduler.config.num_train_timesteps # 0+1000 self.stepsize = (t_terminal-t_initial) / (train_step_terminal - train_step_initial) #1/1000 @@ -186,7 +186,7 @@ class PFODESolverSDXL(): timestep_cond = None if unet.config.time_cond_proj_dim is not None: guidance_scale_tensor = torch.tensor(guidance_scale - 1).repeat(bsz) - timestep_cond = self.get_guidance_scale_embedding( + timestep_cond = self.get_guidance_scale_embedding( # pylint: disable=no-member guidance_scale_tensor, embedding_dim=unet.config.time_cond_proj_dim ).to(device=latents.device, dtype=latents.dtype) diff --git a/modules/sd_models_compile.py b/modules/sd_models_compile.py index 6754984e5..407eeebd8 100644 --- a/modules/sd_models_compile.py +++ b/modules/sd_models_compile.py @@ -1,9 +1,8 @@ -import copy import time import logging import torch -from modules import shared, devices, sd_models, model_quant -from installer import install, setup_logging +from modules import shared, devices, sd_models +from installer import setup_logging #Used by OpenVINO, can be used with TensorRT or Olive diff --git a/modules/shared.py b/modules/shared.py index 7f406d950..da9fa3f6d 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -560,7 +560,7 @@ options_templates.update(options_section(('backends', "Backend Settings"), { })) options_templates.update(options_section(('quantization', "Quantization Settings"), { - "bnb_sep": OptionInfo("

BitsAndBytes

", "", gr.HTML), + "bnb_quantization_sep": OptionInfo("

BitsAndBytes

", "", gr.HTML), "bnb_quantization": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "Text Encoder"], "visible": native}), "bnb_quantization_type": OptionInfo("nf4", "Quantization type", gr.Dropdown, {"choices": ['nf4', 'fp8', 'fp4'], "visible": native}), "bnb_quantization_storage": OptionInfo("uint8", "Backend storage", gr.Dropdown, {"choices": ["float16", "float32", "int8", "uint8", "float64", "bfloat16"], "visible": native}), @@ -569,22 +569,23 @@ options_templates.update(options_section(('quantization', "Quantization Settings "optimum_quanto_weights": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "Text Encoder", "ControlNet"], "visible": native}), "optimum_quanto_weights_type": OptionInfo("qint8", "Quantization weights type", gr.Dropdown, {"choices": ['qint8', 'qfloat8_e4m3fn', 'qfloat8_e5m2', 'qint4', 'qint2'], "visible": native}), "optimum_quanto_activations_type": OptionInfo("none", "Quantization activations type ", gr.Dropdown, {"choices": ['none', 'qint8', 'qfloat8_e4m3fn', 'qfloat8_e5m2'], "visible": native}), + "optimum_quanto_shuffle_weights": OptionInfo(False, "Shuffle weights", gr.Checkbox, {"visible": native}), "torchao_sep": OptionInfo("

TorchAO

", "", gr.HTML), "torchao_quantization": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "Text Encoder"], "visible": native}), "torchao_quantization_mode": OptionInfo("pre", "Quantization mode", gr.Dropdown, {"choices": ['pre', 'post'], "visible": native}), "torchao_quantization_type": OptionInfo("int8_weight_only", "Quantization type", gr.Dropdown, {"choices": ['int4_weight_only', 'int8_dynamic_activation_int4_weight', 'int8_weight_only', 'int8_dynamic_activation_int8_weight', 'float8_weight_only', 'float8_dynamic_activation_float8_weight', 'float8_static_activation_float8_weight'], "visible": native}), - "nncf_sep": OptionInfo("

NNCF

", "", gr.HTML), + "nncf_compress_sep": OptionInfo("

NNCF

", "", gr.HTML), "nncf_compress_weights": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "Text Encoder", "ControlNet"], "visible": native}), "nncf_compress_weights_mode": OptionInfo("INT8", "Quantization type", gr.Dropdown, {"choices": ['INT8', 'INT8_SYM', 'INT4_ASYM', 'INT4_SYM', 'NF4'] if cmd_opts.use_openvino else ['INT8']}), "nncf_compress_weights_raito": OptionInfo(0, "Compress ratio", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.01, "visible": cmd_opts.use_openvino}), "nncf_compress_weights_group_size": OptionInfo(0, "Group size", gr.Slider, {"minimum": -1, "maximum": 512, "step": 1, "visible": cmd_opts.use_openvino}), "nncf_quantize": OptionInfo([], "OpenVINO enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "Text Encoder"], "visible": cmd_opts.use_openvino}), - "nncf_quant_mode": OptionInfo("INT8", "OpenVINO mode", gr.Dropdown, {"choices": ['INT8', 'FP8_E4M3', 'FP8_E5M2'], "visible": cmd_opts.use_openvino}), - "quant_shuffle_weights": OptionInfo(False, "Shuffle weights", gr.Checkbox, {"visible": native}), + "nncf_quantize_mode": OptionInfo("INT8", "OpenVINO mode", gr.Dropdown, {"choices": ['INT8', 'FP8_E4M3', 'FP8_E5M2'], "visible": cmd_opts.use_openvino}), + "nncf_quantize_shuffle_weights": OptionInfo(False, "Shuffle weights", gr.Checkbox, {"visible": native}), - "layerwise_sep": OptionInfo("

Layerwise Casting

", "", gr.HTML), + "layerwise_quantization_sep": OptionInfo("

Layerwise Casting

", "", gr.HTML), "layerwise_quantization": OptionInfo([], "Layerwise casting enabled", gr.CheckboxGroup, {"choices": ["Model", "Transformer", "Text Encoder"], "visible": native}), "layerwise_quantization_storage": OptionInfo("float8_e4m3fn", "Layerwise casting storage", gr.Dropdown, {"choices": ["float8_e4m3fn", "float8_e5m2"], "visible": native}), "layerwise_quantization_nonblocking": OptionInfo(False, "Layerwise non-blocking operations", gr.Checkbox, {"visible": native}), @@ -910,8 +911,9 @@ options_templates.update(options_section(('extra_networks', "Networks"), { "extra_networks_fetch": OptionInfo(True, "UI fetch network info on mouse-over"), "extra_network_skip_indexing": OptionInfo(False, "Build info on first access", gr.Checkbox), - "extra_networks_model_sep": OptionInfo("

Models

", "", gr.HTML), - "extra_network_reference": OptionInfo(False, "Use reference values when available", gr.Checkbox), + "extra_networks_model_sep": OptionInfo("

Rerefence models

", "", gr.HTML), + "extra_network_reference_enable": OptionInfo(True, "Enable use of reference models", gr.Checkbox), + "extra_network_reference_values": OptionInfo(False, "Use reference values when available", gr.Checkbox), "extra_networks_lora_sep": OptionInfo("

LoRA

", "", gr.HTML), "extra_networks_default_multiplier": OptionInfo(1.0, "Default strength", gr.Slider, {"minimum": 0.0, "maximum": 2.0, "step": 0.01}), @@ -1189,7 +1191,7 @@ if not native: opts.data['diffusers_offload_mode'] = 'none' prompt_styles = modules.styles.StyleDatabase(opts) -reference_models = readfile(os.path.join('html', 'reference.json')) +reference_models = readfile(os.path.join('html', 'reference.json')) if opts.extra_network_reference_enable else {} cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or (cmd_opts.server_name or False)) and not cmd_opts.insecure devices.args = cmd_opts devices.opts = opts diff --git a/modules/styles.py b/modules/styles.py index 85ae190e2..1517236be 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -135,7 +135,7 @@ def apply_styles_to_extra(p, style: Style): 'size', ] reference_style = get_reference_style() - extra = infotext.parse(reference_style) if shared.opts.extra_network_reference else {} + extra = infotext.parse(reference_style) if shared.opts.extra_network_reference_values else {} style_extra = apply_wildcards_to_prompt(style.extra, [style.wildcards], silent=True) extra.update(infotext.parse(style_extra)) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 769f47581..c9d860ce9 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -227,7 +227,7 @@ class ExtraNetworksPage: for parentdir, dirs in {d: files_cache.walk(d, cached=True, recurse=files_cache.not_hidden) for d in allowed_folders}.items(): for tgt in dirs: tgt = tgt.path - if os.path.join(paths.models_path, 'Reference') in tgt: + if os.path.join(paths.models_path, 'Reference') in tgt and shared.opts.extra_network_reference_enable: subdirs['Reference'] = 1 if shared.native and shared.opts.diffusers_dir in tgt: subdirs[os.path.basename(shared.opts.diffusers_dir)] = 1 @@ -242,7 +242,7 @@ class ExtraNetworksPage: subdirs[subdir] = 1 debug(f"Networks: page='{self.name}' subfolders={list(subdirs)}") subdirs = OrderedDict(sorted(subdirs.items())) - if self.name == 'model': + if self.name == 'model' and shared.opts.extra_network_reference_enable: subdirs['Reference'] = 1 subdirs[os.path.basename(shared.opts.diffusers_dir)] = 1 subdirs.move_to_end(os.path.basename(shared.opts.diffusers_dir)) diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index 66dd21cb0..c08ef357d 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -15,7 +15,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): shared.refresh_checkpoints() def list_reference(self): # pylint: disable=inconsistent-return-statements - if not shared.opts.sd_checkpoint_autodownload: + if not shared.opts.sd_checkpoint_autodownload or not shared.opts.extra_network_reference_enable: return [] for k, v in shared.reference_models.items(): if not shared.native: diff --git a/modules/upscaler_simple.py b/modules/upscaler_simple.py index bd0c6050f..95f2acac2 100644 --- a/modules/upscaler_simple.py +++ b/modules/upscaler_simple.py @@ -31,18 +31,20 @@ class UpscalerResize(Upscaler): def do_upscale(self, img: Image, selected_model=None): if selected_model is None: return img - if selected_model == "Resize Nearest": + elif selected_model == "Resize Nearest": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.NEAREST) - if selected_model == "Resize Lanczos": + elif selected_model == "Resize Lanczos": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.LANCZOS) - if selected_model == "Resize Bicubic": + elif selected_model == "Resize Bicubic": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.BICUBIC) - if selected_model == "Resize Bilinear": + elif selected_model == "Resize Bilinear": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.BILINEAR) - if selected_model == "Resize Hamming": + elif selected_model == "Resize Hamming": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.HAMMING) - if selected_model == "Resize Box": + elif selected_model == "Resize Box": return img.resize((int(img.width * self.scale), int(img.height * self.scale)), resample=Image.Resampling.BOX) + else: + return img def load_model(self, _):