From beea969fd3429d8e78669ac18dee4b2f79b9571b Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Tue, 10 Dec 2024 12:34:27 -0500 Subject: [PATCH] update lora Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 7 ++++--- modules/lora/extra_networks_lora.py | 6 +++++- modules/lora/networks.py | 19 ++++++++++++------- modules/shared.py | 18 ++++++++++-------- wiki | 2 +- 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5412861a8..8ade15e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,9 +37,8 @@ - LoRA weights are no longer calculated on-the-fly during model execution, but are pre-calculated at the start this results in perceived overhead on generate startup, but results in overall faster execution as LoRA does not need to be processed on each step thanks @AI-Casanova - - *note*: LoRA weights backups are required so LoRA can be unapplied, but can take quite a lot of system memory - if you know you will not need to unapply LoRA, you can disable backups in *settings -> networks -> lora fuse* - in which case, you need to reload model to unapply LoRA + - LoRA weights can be applied/unapplied as on each generate or they can store weights backups for later use + this setting has large performance and resource implications, see [Offload](https://github.com/vladmandic/automatic/wiki/Offload) wiki for details - **Model loader** improvements: - detect model components on model load fail - allow passing absolute path to model loader @@ -98,6 +97,8 @@ - fix prompt caching - fix xyz grid skip final pass - fix sd upscale script +- fix cogvideox-i2v +- lora auto-apply tags remove duplicates ## Update for 2024-11-21 diff --git a/modules/lora/extra_networks_lora.py b/modules/lora/extra_networks_lora.py index 135df1ccb..42c4a92f6 100644 --- a/modules/lora/extra_networks_lora.py +++ b/modules/lora/extra_networks_lora.py @@ -44,6 +44,8 @@ def prompt(p): loaded.tags = loaded.tags[:shared.opts.lora_apply_tags] all_tags.extend(loaded.tags) if len(all_tags) > 0: + all_tags = list(set(all_tags)) + all_tags = [t for t in all_tags if t not in p.prompt] shared.log.debug(f"Load network: type=LoRA tags={all_tags} max={shared.opts.lora_apply_tags} apply") all_tags = ', '.join(all_tags) p.extra_generation_params["LoRA tags"] = all_tags @@ -121,13 +123,15 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): # shared.log.debug(f'Activate network: type=LoRA model="{shared.opts.sd_model_checkpoint}"') self.active = True self.model = shared.opts.sd_model_checkpoint + if 'text_encoder' in include: + networks.timer.clear(complete=True) names, te_multipliers, unet_multipliers, dyn_dims = parse(p, params_list, step) networks.network_load(names, te_multipliers, unet_multipliers, dyn_dims) # load networks.network_activate(include, exclude) if len(networks.loaded_networks) > 0 and len(networks.applied_layers) > 0 and step == 0: infotext(p) prompt(p) - shared.log.info(f'Load network: type=LoRA apply={[n.name for n in networks.loaded_networks]} te={te_multipliers} unet={unet_multipliers} time={networks.timer.summary}') + shared.log.info(f'Load network: type=LoRA apply={[n.name for n in networks.loaded_networks]} mode={"fuse" if shared.opts.lora_fuse_diffusers else "backup"} te={te_multipliers} unet={unet_multipliers} time={networks.timer.summary}') def deactivate(self, p): if shared.native and len(networks.diffuser_loaded) > 0: diff --git a/modules/lora/networks.py b/modules/lora/networks.py index edd82f3e4..ada6f833d 100644 --- a/modules/lora/networks.py +++ b/modules/lora/networks.py @@ -42,6 +42,7 @@ module_types = [ # section: load networks from disk def load_diffusers(name, network_on_disk, lora_scale=shared.opts.extra_networks_default_multiplier) -> Union[network.Network, None]: + t0 = time.time() name = name.replace(".", "_") shared.log.debug(f'Load network: type=LoRA name="{name}" file="{network_on_disk.filename}" detected={network_on_disk.sd_version} method=diffusers scale={lora_scale} fuse={shared.opts.lora_fuse_diffusers}') if not shared.native: @@ -67,6 +68,7 @@ def load_diffusers(name, network_on_disk, lora_scale=shared.opts.extra_networks_ diffuser_scales.append(lora_scale) net = network.Network(name, network_on_disk) net.mtime = os.path.getmtime(network_on_disk.filename) + timer.activate += time.time() - t0 return net @@ -256,10 +258,12 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non if len(diffuser_loaded) > 0: shared.log.debug(f'Load network: type=LoRA loaded={diffuser_loaded} available={shared.sd_model.get_list_adapters()} active={shared.sd_model.get_active_adapters()} scales={diffuser_scales}') try: + t0 = time.time() shared.sd_model.set_adapters(adapter_names=diffuser_loaded, adapter_weights=diffuser_scales) if shared.opts.lora_fuse_diffusers: shared.sd_model.fuse_lora(adapter_names=diffuser_loaded, lora_scale=1.0, fuse_unet=True, fuse_text_encoder=True) # fuse uses fixed scale since later apply does the scaling shared.sd_model.unload_lora_weights() + timer.activate += time.time() - t0 except Exception as e: shared.log.error(f'Load network: type=LoRA {e}') if debug: @@ -301,16 +305,15 @@ def network_backup_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.n bnb = model_quant.load_bnb('Load network: type=LoRA', silent=True) if bnb is not None: with devices.inference_context(): - weights_backup = bnb.functional.dequantize_4bit(weight, quant_state=weight.quant_state, quant_type=weight.quant_type, blocksize=weight.blocksize,) + self.network_weights_backup = bnb.functional.dequantize_4bit(weight, quant_state=weight.quant_state, quant_type=weight.quant_type, blocksize=weight.blocksize,) self.quant_state = weight.quant_state self.quant_type = weight.quant_type self.blocksize = weight.blocksize else: weights_backup = weight.clone() - weights_backup = weights_backup.to(devices.cpu) + self.network_weights_backup = weights_backup.to(devices.cpu) else: - weights_backup = weight.clone() - weights_backup = weights_backup.to(devices.cpu) + self.network_weights_backup = weight.clone().to(devices.cpu) bias_backup = getattr(self, "network_bias_backup", None) if bias_backup is None: @@ -331,7 +334,10 @@ def network_backup_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.n def network_calc_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.GroupNorm, torch.nn.LayerNorm, diffusers.models.lora.LoRACompatibleLinear, diffusers.models.lora.LoRACompatibleConv], network_layer_name: str): if shared.opts.diffusers_offload_mode == "none": - self.to(devices.device) + try: + self.to(devices.device) + except Exception: + pass batch_updown = None batch_ex_bias = None for net in loaded_networks: @@ -501,7 +507,6 @@ def network_deactivate(): def network_activate(include=[], exclude=[]): t0 = time.time() - timer.clear(complete=True) sd_model = getattr(shared.sd_model, "pipe", shared.sd_model) # wrapped model compatiblility if shared.opts.diffusers_offload_mode == "sequential": sd_models.disable_offload(sd_model) @@ -552,7 +557,7 @@ def network_activate(include=[], exclude=[]): if task is not None and len(applied_layers) == 0: pbar.remove_task(task) # hide progress bar for no action weights_devices, weights_dtypes = list(set([x for x in weights_devices if x is not None])), list(set([x for x in weights_dtypes if x is not None])) # noqa: C403 # pylint: disable=R1718 - timer.activate = time.time() - t0 + timer.activate += time.time() - t0 if debug and len(loaded_networks) > 0: shared.log.debug(f'Load network: type=LoRA networks={len(loaded_networks)} components={components} modules={total} apply={len(applied_layers)} device={weights_devices} dtype={weights_dtypes} backup={backup_size} fuse={shared.opts.lora_fuse_diffusers} time={timer.summary}') modules.clear() diff --git a/modules/shared.py b/modules/shared.py index 17db4595f..256850d21 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -914,22 +914,24 @@ options_templates.update(options_section(('extra_networks', "Networks"), { "extra_networks_model_sep": OptionInfo("

Models

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

Embeddings

", "", gr.HTML), - "diffusers_convert_embed": OptionInfo(False, "Auto-convert SD 1.5 embeddings to SDXL ", gr.Checkbox, {"visible": native}), - "extra_networks_styles_sep": OptionInfo("

Styles

", "", gr.HTML), - "extra_networks_styles": OptionInfo(True, "Show built-in styles"), - "extra_networks_wildcard_sep": OptionInfo("

Wildcards

", "", gr.HTML), - "wildcards_enabled": OptionInfo(True, "Enable file wildcards support"), + "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}), "lora_preferred_name": OptionInfo("filename", "LoRA preferred name", gr.Radio, {"choices": ["filename", "alias"], "visible": False}), - "lora_add_hashes_to_infotext": OptionInfo(False, "LoRA add hash info"), + "lora_add_hashes_to_infotext": OptionInfo(False, "LoRA add hash info to metadata"), "lora_fuse_diffusers": OptionInfo(True, "LoRA fuse directly to model"), "lora_force_diffusers": OptionInfo(False if not cmd_opts.use_openvino else True, "LoRA force loading of all models using Diffusers"), "lora_maybe_diffusers": OptionInfo(False, "LoRA force loading of specific models using Diffusers"), "lora_apply_tags": OptionInfo(0, "LoRA auto-apply tags", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}), "lora_in_memory_limit": OptionInfo(0, "LoRA memory cache", gr.Slider, {"minimum": 0, "maximum": 24, "step": 1}), - "lora_quant": OptionInfo("NF4","LoRA precision in quantized models", gr.Radio, {"choices": ["NF4", "FP4"]}), + "lora_quant": OptionInfo("NF4","LoRA precision when quantized", gr.Radio, {"choices": ["NF4", "FP4"]}), + + "extra_networks_styles_sep": OptionInfo("

Styles

", "", gr.HTML), + "extra_networks_styles": OptionInfo(True, "Show built-in styles"), + "extra_networks_embed_sep": OptionInfo("

Embeddings

", "", gr.HTML), + "diffusers_convert_embed": OptionInfo(False, "Auto-convert SD15 embeddings to SDXL ", gr.Checkbox, {"visible": native}), + "extra_networks_wildcard_sep": OptionInfo("

Wildcards

", "", gr.HTML), + "wildcards_enabled": OptionInfo(True, "Enable file wildcards support"), })) options_templates.update(options_section((None, "Internal options"), { diff --git a/wiki b/wiki index 8960da514..95f174900 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 8960da514e9aff4a5d47402925c9498536443379 +Subproject commit 95f1749005d56be490dab95cf92f4ca576d10396