jumbo update, see changelog

This commit is contained in:
Vladimir Mandic
2024-09-18 13:48:30 -04:00
parent 67aeaac1ce
commit 2acb883dda
33 changed files with 247 additions and 141 deletions
+14 -2
View File
@@ -1,11 +1,12 @@
# Change Log for SD.Next
## Update for 2024-09-17
## Update for 2024-09-18
- **flux**
- avoid unet load if unchanged
- mark specific unet as unavailable if load failed
- fix diffusers local model name parsing
- full prompt parser will auto-select `xhinker` for flux models
- **xyz grid** full refactor
- multi-mode: *selectable-script* and *alwayson-script*
- allow usage combined with other scripts
@@ -29,9 +30,20 @@
- if prompt contains `_tags_` it will be used as placeholder for replacement, otherwise tags will be appended
- used tags are also logged and registered in image metadata
- correct using of `extra_networks_default_multiplier` if not scale is specified
- **hf** force logout/login on token change
- **text encoder**:
- allow loading different custom text encoders: *clip-vit-l, clip-vit-g, t5*
will automatically find appropriate encoder in the loaded model and replace it with loaded text encoder
download text encoders into folder set in settings -> system paths -> text encoders
default `models/Text-encoder` folder is used if no custom path is set
example *clip-vit-l* models: [Detailed & Smooth](https://huggingface.co/zer0int/CLIP-GmP-ViT-L-14), [LongCLIP](https://huggingface.co/zer0int/LongCLIP-GmP-ViT-L-14)
- xyz grid support for text encoder
- full prompt parser now correctly works with different prompts in batch
- **huggingface**:
- force logout/login on token change
- unified handling of cache folder: set via `HF_HUB` or `HF_HUB_CACHE` or via settings -> system paths
- **backend=original** is now marked as in maintenance-only mode
- **python 3.12** improved compatibility, automatically handle `setuptools`
- massive log cleanup
- minor ui optimizations
## Update for 2024-09-13
@@ -61,7 +61,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork):
loaded.tags = loaded.tags[:shared.opts.lora_apply_tags]
all_tags.extend(loaded.tags)
if len(all_tags) > 0:
shared.log.debug(f"LoRA apply: max={shared.opts.lora_apply_tags} tags{all_tags}")
shared.log.debug(f"Load network: type=LoRA max={shared.opts.lora_apply_tags} tags={all_tags} apply")
all_tags = ', '.join(all_tags)
p.extra_generation_params["LoRA tags"] = all_tags
if p.all_prompts is not None:
@@ -129,7 +129,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork):
if len(names) > 0 and step == 0:
self.infotext(p)
self.prompt(p)
shared.log.info(f'LoRA apply: {names} patch={t1-t0:.2f} te={te_multipliers} unet={unet_multipliers} dims={dyn_dims} load={t2-t1:.2f}')
shared.log.info(f'Load network: type=LoRA apply={names} patch={t1-t0:.2f} te={te_multipliers} unet={unet_multipliers} dims={dyn_dims} load={t2-t1:.2f}')
elif self.active:
self.active = False
+12 -15
View File
@@ -86,25 +86,24 @@ def load_diffusers(name, network_on_disk, lora_scale=shared.opts.extra_networks_
t0 = time.time()
name = name.replace(".", "_")
#cached = lora_cache.get(name, None)
shared.log.debug(f'LoRA load: name="{name}" file="{network_on_disk.filename}" type=diffusers scale={lora_scale} fuse={shared.opts.lora_fuse_diffusers}')
shared.log.debug(f'Load network: type=LoRA name="{name}" file="{network_on_disk.filename}" type=diffusers scale={lora_scale} fuse={shared.opts.lora_fuse_diffusers}')
# if cached is not None:
# return cached
if not shared.native:
return None
if not hasattr(shared.sd_model, 'load_lora_weights'):
shared.log.error(f'LoRA load failed: class={shared.sd_model.__class__} does not implement load lora')
shared.log.error(f'Load network: type=LoRA class={shared.sd_model.__class__} does not implement load lora')
return None
try:
shared.sd_model.load_lora_weights(network_on_disk.filename, adapter_name=name)
except Exception as e:
if 'already in use' in str(e):
# shared.log.warning(f'LoRA load failed: file={network_on_disk.filename} {e}')
pass
else:
if 'The following keys have not been correctly renamed' in str(e):
shared.log.error(f'LoRA load failed: file="{network_on_disk.filename}" diffusers unsupported format')
shared.log.error(f'Load network: type=LoRA file="{network_on_disk.filename}" diffusers unsupported format')
else:
shared.log.error(f'LoRA load failed: file="{network_on_disk.filename}" {e}')
shared.log.error(f'Load network: type=LoRA file="{network_on_disk.filename}" {e}')
if debug:
errors.display(e, "LoRA")
return None
@@ -123,7 +122,7 @@ def load_network(name, network_on_disk) -> network.Network:
t0 = time.time()
cached = lora_cache.get(name, None)
if debug:
shared.log.debug(f'LoRA load: name="{name}" file="{network_on_disk.filename}" type=lora {"cached" if cached else ""}')
shared.log.debug(f'Load network: type=LoRA name="{name}" file="{network_on_disk.filename}" type=lora {"cached" if cached else ""}')
if cached is not None:
return cached
net = network.Network(name, network_on_disk)
@@ -148,8 +147,6 @@ def load_network(name, network_on_disk) -> network.Network:
network_part = '.'.join(parts[-2:]).replace('lora_A', 'lora_down').replace('lora_B', 'lora_up')
else:
key_network_without_network_parts, network_part = key_network.split(".", 1)
# if debug:
# shared.log.debug(f'LoRA load: name="{name}" full={key_network} network={network_part} key={key_network_without_network_parts}')
key, sd_module = convert(key_network_without_network_parts) # Now returns lists
if sd_module[0] is None:
if "bundle_emb" not in key_network:
@@ -222,7 +219,7 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No
if network_on_disk is not None:
shorthash = getattr(network_on_disk, 'shorthash', '').lower()
if debug:
shared.log.debug(f'LoRA load: name="{name}" file="{network_on_disk.filename}" hash="{shorthash}"')
shared.log.debug(f'Load network: type=LoRA name="{name}" file="{network_on_disk.filename}" hash="{shorthash}"')
try:
if recompile_model:
shared.compiled_model_state.lora_model.append(f"{name}:{te_multipliers[i] if te_multipliers else shared.opts.extra_networks_default_multiplier}")
@@ -234,13 +231,13 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No
net.mentioned_name = name
network_on_disk.read_hash()
except Exception as e:
shared.log.error(f'LoRA load failed: file="{network_on_disk.filename}" {e}')
shared.log.error(f'Load network: type=LoRA file="{network_on_disk.filename}" {e}')
if debug:
errors.display(e, 'LoRA')
continue
if net is None:
failed_to_load_networks.append(name)
shared.log.error(f'LoRA unknown type: network="{name}"')
shared.log.error(f'Load network: type=LoRA network="{name}" unknown type')
continue
if shared.native:
shared.sd_model.embedding_db.load_diffusers_embedding(None, net.bundle_embeddings)
@@ -253,17 +250,17 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No
name = next(iter(lora_cache))
lora_cache.pop(name, None)
if len(diffuser_loaded) > 0:
shared.log.debug(f'LoRA loaded={diffuser_loaded} scales={diffuser_scales}')
shared.log.debug(f'Load network: type=LoRA loaded={diffuser_loaded} scales={diffuser_scales}')
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()
if len(loaded_networks) > 0 and debug:
shared.log.debug(f'LoRA loaded={len(loaded_networks)} cache={list(lora_cache)}')
shared.log.debug(f'Load network: type=LoRA loaded={len(loaded_networks)} cache={list(lora_cache)}')
devices.torch_gc()
if recompile_model:
shared.log.info("LoRA recompiling model")
shared.log.info("Load network: type=LoRA recompiling model")
backup_lora_model = shared.compiled_model_state.lora_model
if 'Model' in shared.opts.cuda_compile:
shared.sd_model = sd_models_compile.compile_diffusers(shared.sd_model)
@@ -532,7 +529,7 @@ def list_available_networks():
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
for fn in candidates:
executor.submit(add_network, fn)
shared.log.info(f'LoRA networks: available={len(available_networks)} folders={len(forbidden_network_aliases)}')
shared.log.info(f'Available LoRAs: items={len(available_networks)} folders={len(forbidden_network_aliases)}')
def infotext_pasted(infotext, params): # pylint: disable=W0613
@@ -110,7 +110,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
return item
except Exception as e:
shared.log.error(f"Networks: type=lora file={name} {e}")
shared.log.error(f'Networks: type=lora file="{name}" {e}')
if debug:
from modules import errors
errors.display('e', 'Lora')
+3 -2
View File
@@ -88,6 +88,7 @@ def setup_logging():
from rich.theme import Theme
from rich.logging import RichHandler
from rich.console import Console
from rich import print as rprint
from rich.pretty import install as pretty_install
from rich.traceback import install as traceback_install
@@ -102,6 +103,7 @@ def setup_logging():
level = logging.DEBUG if args.debug else logging.INFO
log.setLevel(logging.DEBUG) # log to file is always at level debug for facility `sd`
log.print = rprint
global console # pylint: disable=global-statement
console = Console(log_time=True, log_time_format='%H:%M:%S-%f', theme=Theme({
"traceback.border": "black",
@@ -789,7 +791,7 @@ def run_extension_installer(folder):
env['PYTHONPATH'] = os.path.abspath(".")
result = subprocess.run(f'"{sys.executable}" "{path_installer}"', shell=True, env=env, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=folder)
txt = result.stdout.decode(encoding="utf8", errors="ignore")
debug(f'Extension installer: file={path_installer} {txt}')
debug(f'Extension installer: file="{path_installer}" {txt}')
if result.returncode != 0:
global errors # pylint: disable=global-statement
errors += 1
@@ -975,7 +977,6 @@ def set_environment():
os.environ.setdefault('KINETO_LOG_LEVEL', '3')
os.environ.setdefault('DO_NOT_TRACK', '1')
os.environ.setdefault('HF_HUB_CACHE', opts.get('hfcache_dir', os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub')))
log.debug(f'Huggingface folders: home="{os.environ.get("HF_HUB")}" cache="{os.environ.get("HF_HUB_CACHE")}"')
allocator = f'garbage_collection_threshold:{opts.get("torch_gc_threshold", 80)/100:0.2f},max_split_size_mb:512'
if opts.get("torch_malloc", "native") == 'cudaMallocAsync':
allocator += ',backend:cudaMallocAsync'
+1 -1
View File
@@ -16,7 +16,7 @@ class DeepDanbooru:
if self.model is not None:
return
model_path = os.path.join(paths.models_path, "DeepDanbooru")
shared.log.debug(f'Loading interrogate model: type=DeepDanbooru folder={model_path}')
shared.log.debug(f'Loading interrogate model: type=DeepDanbooru folder="{model_path}"')
files = modelloader.load_models(
model_path=model_path,
model_url='https://github.com/AUTOMATIC1111/TorchDeepDanbooru/releases/download/v1/model-resnet_custom_v3.pt',
+3 -3
View File
@@ -80,13 +80,13 @@ def face_id(
basename, _ext = os.path.splitext(filename)
model_path = hf.hf_hub_download(repo_id=folder, filename=filename, cache_dir=shared.opts.diffusers_dir)
if model_path is None:
shared.log.error(f"FaceID download failed: model={model} file={ip_ckpt}")
shared.log.error(f'FaceID download failed: model={model} file="{ip_ckpt}"')
return None
if faceid_model_weights is None or faceid_model_name != model or not cache:
shared.log.debug(f"FaceID load: model={model} file={ip_ckpt}")
shared.log.debug(f'FaceID load: model={model} file="{ip_ckpt}"')
faceid_model_weights = torch.load(model_path, map_location="cpu")
else:
shared.log.debug(f"FaceID cached: model={model} file={ip_ckpt}")
shared.log.debug(f'FaceID cached: model={model} file="{ip_ckpt}"')
if "XL Plus" in model and shared.sd_model_type == 'sd':
image_encoder_path = "laion/CLIP-ViT-H-14-laion2B-s32B-b79K"
+1 -1
View File
@@ -240,5 +240,5 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapt
t1 = time.time()
shared.log.info(f'IP adapter: {ip_str} image={adapter_images} mask={adapter_masks is not None} time={t1-t0:.2f}')
except Exception as e:
shared.log.error(f'IP adapter failed to load: repo={base_repo} folder={ip_subfolder} weights={adapters} names={adapter_names} {e}')
shared.log.error(f'IP adapter failed to load: repo="{base_repo}" folder="{ip_subfolder}" weights={adapters} names={adapter_names} {e}')
return True
+1 -1
View File
@@ -72,7 +72,7 @@ def download_model():
filename = os.path.basename(parts.path)
cached_file = os.path.join(model_dir, filename)
if not os.path.exists(cached_file):
log.info(f'LaMa download: url={LAMA_MODEL_URL} file={cached_file}')
log.info(f'LaMa download: url="{LAMA_MODEL_URL}" file="{cached_file}"')
hash_prefix = None
download_url_to_file(LAMA_MODEL_URL, cached_file, hash_prefix, progress=True)
return cached_file
+2 -2
View File
@@ -139,7 +139,7 @@ def load_transformer(file_path): # triggered by opts.sd_unet change
"torch_dtype": devices.dtype,
"cache_dir": shared.opts.hfcache_dir,
}
shared.log.info(f'Loading UNet: type=FLUX file="{file_path}" offload={shared.opts.diffusers_offload_mode} quant={quant} dtype={devices.dtype}')
shared.log.info(f'Load module: type=UNet/Transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} quant={quant} dtype={devices.dtype}')
if quant == 'qint8' or quant == 'qint4':
_transformer, _text_encoder_2 = load_flux_quanto(file_path)
if _transformer is not None:
@@ -191,7 +191,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch
if shared.opts.sd_text_encoder != 'None':
try:
debug(f'Loading FLUX: t5="{shared.opts.sd_text_encoder}"')
from modules.model_t5 import load_t5
from modules.model_te import load_t5
_text_encoder_2 = load_t5(t5=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir)
if _text_encoder_2 is not None:
text_encoder_2 = _text_encoder_2
+2 -2
View File
@@ -2,13 +2,13 @@ import diffusers
def load_pixart(checkpoint_info, diffusers_load_config={}):
from modules import shared, devices, modelloader, model_t5
from modules import shared, devices, modelloader, model_te
modelloader.hf_login()
# shared.opts.data['cuda_dtype'] = 'FP32' # override
# shared.opts.data['diffusers_offload_mode}'] = "model" # override
# devices.set_cuda_params()
fn = checkpoint_info.path.replace('huggingface/', '')
t5 = model_t5.load_t5(shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir)
t5 = model_te.load_t5(shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir)
transformer = diffusers.PixArtTransformer2DModel.from_pretrained(
fn,
subfolder = 'transformer',
+68 -11
View File
@@ -3,19 +3,21 @@ import json
import torch
import transformers
from safetensors.torch import load_file
from modules import shared, devices, files_cache
from modules import shared, devices, files_cache, errors
from installer import install
t5_dict = {}
te_dict = {}
debug = os.environ.get('SD_LOAD_DEBUG', None) is not None
loaded_te = None
def load_t5(t5=None, cache_dir=None):
from modules import modelloader
modelloader.hf_login()
repo_id = 'stabilityai/stable-diffusion-3-medium-diffusers'
fn = t5_dict.get(t5) if t5 in t5_dict else None
if fn is not None:
fn = te_dict.get(t5) if t5 in te_dict else None
if fn is not None and 'fp8' in t5.lower():
from accelerate.utils import set_module_tensor_to_device
with open(os.path.join('configs', 'flux', 'text_encoder_2', 'config.json'), encoding='utf8') as f:
t5_config = transformers.T5Config(**json.load(f))
@@ -35,6 +37,11 @@ def load_t5(t5=None, cache_dir=None):
except Exception:
shared.log.error(f"FLUX: Failed to cast text encoder to {devices.dtype}, set dtype to {t5.dtype}")
raise
elif fn is not None:
with open(os.path.join('configs', 'flux', 'text_encoder_2', 'config.json'), encoding='utf8') as f:
t5_config = transformers.T5Config(**json.load(f))
state_dict = load_file(fn)
t5 = transformers.T5EncoderModel.from_pretrained(None, state_dict=state_dict, config=t5_config)
elif 'fp16' in t5.lower():
t5 = transformers.T5EncoderModel.from_pretrained(repo_id, subfolder='text_encoder_3', cache_dir=cache_dir, torch_dtype=devices.dtype)
elif 'fp4' in t5.lower():
@@ -67,11 +74,22 @@ def load_t5(t5=None, cache_dir=None):
def set_t5(pipe, module, t5=None, cache_dir=None):
global loaded_te # pylint: disable=global-statement
if loaded_te == shared.opts.sd_text_encoder:
return
if pipe is None or not hasattr(pipe, module):
return pipe
t5 = load_t5(t5=t5, cache_dir=cache_dir)
if module == "text_encoder_2" and t5 is None: # do not unload te2
t5 = None
try:
t5 = load_t5(t5=t5, cache_dir=cache_dir)
except Exception as e:
shared.log.error(f'Load module: type={module} class="T5" file="{shared.opts.sd_text_encoder}" {e}')
if debug:
errors.display(e, 'TE:')
t5 = None
if t5 is None:
return None
loaded_te = shared.opts.sd_text_encoder
setattr(pipe, module, t5)
if shared.opts.diffusers_offload_mode == "sequential":
from accelerate import cpu_offload
@@ -86,9 +104,48 @@ def set_t5(pipe, module, t5=None, cache_dir=None):
return pipe
def refresh_t5_list():
t5_dict.clear()
for file in files_cache.list_files(shared.opts.t5_dir, ext_filter=[".safetensors"]):
def set_te(pipe):
global loaded_te # pylint: disable=global-statement
if loaded_te == shared.opts.sd_text_encoder:
return
from modules.sd_models import move_model
if 'vit-l' in shared.opts.sd_text_encoder.lower() and hasattr(shared.sd_model, 'text_encoder') and shared.sd_model.text_encoder.__class__.__name__ == 'CLIPTextModel':
try:
config = transformers.PretrainedConfig.from_json_file('configs/sdxl/text_encoder/config.json')
state_dict = load_file(os.path.join(shared.opts.te_dir, f'{shared.opts.sd_text_encoder}.safetensors'))
te = transformers.CLIPTextModel.from_pretrained(pretrained_model_name_or_path=None, state_dict=state_dict, config=config)
except Exception as e:
shared.log.error(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}" {e}')
if debug:
errors.display(e, 'TE:')
state_dict = None
te = None
if te is not None:
loaded_te = shared.opts.sd_text_encoder
pipe.text_encoder = te.to(dtype=devices.dtype)
shared.log.info(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}"')
move_model(pipe.text_encoder, devices.device)
if 'vit-g' in shared.opts.sd_text_encoder.lower() and hasattr(shared.sd_model, 'text_encoder_2') and shared.sd_model.text_encoder_2.__class__.__name__ == 'CLIPTextModelWithProjection':
try:
config = transformers.PretrainedConfig.from_json_file('configs/sdxl/text_encoder_2/config.json')
state_dict = load_file(os.path.join(shared.opts.te_dir, f'{shared.opts.sd_text_encoder}.safetensors'))
te = transformers.CLIPTextModelWithProjection.from_pretrained(pretrained_model_name_or_path=None, state_dict=state_dict, config=config)
except Exception as e:
shared.log.error(f'Load module: type module="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}" {e}')
if debug:
errors.display(e, 'TE:')
state_dict = None
te = None
if te is not None:
loaded_te = shared.opts.sd_text_encoder
pipe.text_encoder_2 = te.to(dtype=devices.dtype)
shared.log.info(f'Load module: type="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}"')
move_model(pipe.text_encoder_2, devices.device)
def refresh_te_list():
te_dict.clear()
for file in files_cache.list_files(shared.opts.te_dir, ext_filter=[".safetensors"]):
name = os.path.splitext(os.path.basename(file))[0]
t5_dict[name] = file
shared.log.debug(f'Available T5s: path="{shared.opts.t5_dir}" items={len(t5_dict)}')
te_dict[name] = file
shared.log.info(f'Available TEs: path="{shared.opts.te_dir}" items={len(te_dict)}')
+9 -9
View File
@@ -50,11 +50,11 @@ def download_civit_meta(model_path: str, model_id):
if r.status_code == 200:
try:
shared.writefile(r.json(), filename=fn, mode='w', silent=True)
msg = f'CivitAI download: id={model_id} url={url} file={fn}'
msg = f'CivitAI download: id={model_id} url={url} file="{fn}"'
shared.log.info(msg)
return msg
except Exception as e:
msg = f'CivitAI download error: id={model_id} url={url} file={fn} {e}'
msg = f'CivitAI download error: id={model_id} url={url} file="{fn}" {e}'
errors.display(e, 'CivitAI download error')
shared.log.error(msg)
return msg
@@ -66,7 +66,7 @@ def download_civit_preview(model_path: str, preview_url: str):
preview_file = os.path.splitext(model_path)[0] + ext
if os.path.exists(preview_file):
return ''
res = f'CivitAI download: url={preview_url} file={preview_file}'
res = f'CivitAI download: url={preview_url} file="{preview_file}"'
r = shared.req(preview_url, stream=True)
total_size = int(r.headers.get('content-length', 0))
block_size = 16384 # 16KB blocks
@@ -88,7 +88,7 @@ def download_civit_preview(model_path: str, preview_url: str):
except Exception as e:
os.remove(preview_file)
res += f' error={e}'
shared.log.error(f'CivitAI download error: url={preview_url} file={preview_file} written={written} {e}')
shared.log.error(f'CivitAI download error: url={preview_url} file="{preview_file}" written={written} {e}')
shared.state.end()
if img is None:
return res
@@ -281,7 +281,7 @@ def load_diffusers_models(clear=True):
friendly = os.path.join(place, name)
snapshots = os.listdir(os.path.join(folder, "snapshots"))
if len(snapshots) == 0:
shared.log.warning(f"Diffusers folder has no snapshots: location={place} folder={folder} name={name}")
shared.log.warning(f'Diffusers folder has no snapshots: location="{place}" folder="{folder}" name="{name}"')
continue
for snapshot in snapshots:
commit = os.path.join(folder, 'snapshots', snapshot)
@@ -296,10 +296,10 @@ def load_diffusers_models(clear=True):
if os.path.exists(os.path.join(folder, 'hidden')):
continue
except Exception as e:
debug(f"Error analyzing diffusers model: {folder} {e}")
debug(f'Error analyzing diffusers model: "{folder}" {e}')
except Exception as e:
shared.log.error(f"Error listing diffusers: {place} {e}")
shared.log.debug(f'Scanning diffusers cache: folder={place} items={len(list(diffuser_repos))} time={time.time()-t0:.2f}')
shared.log.debug(f'Scanning diffusers cache: folder="{place}" items={len(list(diffuser_repos))} time={time.time()-t0:.2f}')
return diffuser_repos
@@ -444,7 +444,7 @@ def load_file_from_url(url: str, *, model_dir: str, progress: bool = True, file_
file_name = os.path.basename(parts.path)
cached_file = os.path.abspath(os.path.join(model_dir, file_name))
if not os.path.exists(cached_file):
shared.log.info(f'Downloading: url="{url}" file={cached_file}')
shared.log.info(f'Downloading: url="{url}" file="{cached_file}"')
download_url_to_file(url, cached_file)
if os.path.exists(cached_file):
return cached_file
@@ -577,5 +577,5 @@ def load_upscalers():
names.append(name[8:])
shared.sd_upscalers = sorted(datas, key=lambda x: x.name.lower() if not isinstance(x.scaler, (UpscalerNone, UpscalerLanczos, UpscalerNearest)) else "") # Special case for UpscalerNone keeps it at the beginning of the list.
t1 = time.time()
shared.log.debug(f"Load upscalers: total={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} time={t1-t0:.2f} {names}")
shared.log.info(f"Available Upscalers: items={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} time={t1-t0:.2f} types={names}")
return [x.name for x in shared.sd_upscalers]
+1 -1
View File
@@ -101,7 +101,7 @@ def create_paths(opts):
create_path(fix_path('diffusers_dir'))
create_path(fix_path('vae_dir'))
create_path(fix_path('unet_dir'))
create_path(fix_path('t5_dir'))
create_path(fix_path('te_dir'))
create_path(fix_path('lora_dir'))
create_path(fix_path('embeddings_dir'))
create_path(fix_path('hypernetwork_dir'))
+45 -25
View File
@@ -165,38 +165,58 @@ def encode_prompts(pipe, p, prompts: list, negative_prompts: list, steps: int, c
return
else:
t0 = time.time()
positive_schedule, scheduled = get_prompt_schedule(prompts[0], steps)
negative_schedule, neg_scheduled = get_prompt_schedule(negative_prompts[0], steps)
p.scheduled_prompt = scheduled or neg_scheduled
p.prompt_embeds = []
p.positive_pooleds = []
p.negative_embeds = []
p.negative_pooleds = []
if shared.opts.diffusers_offload_mode == "balanced":
pipe = sd_models.apply_balanced_offload(pipe)
elif hasattr(pipe, "maybe_free_model_hooks"):
# if the last job is interrupted, model will stay in the vram and cause oom, send everything back to cpu before continuing
pipe.maybe_free_model_hooks()
devices.torch_gc()
for i in range(max(len(positive_schedule), len(negative_schedule))):
positive_prompt = positive_schedule[i % len(positive_schedule)]
negative_prompt = negative_schedule[i % len(negative_schedule)]
if shared.opts.prompt_attention == "xhinker parser":
prompt_embed, positive_pooled, negative_embed, negative_pooled = get_xhinker_text_embeddings(pipe, positive_prompt, negative_prompt, clip_skip)
else:
prompt_embed, positive_pooled, negative_embed, negative_pooled = get_weighted_text_embeddings(pipe, positive_prompt, negative_prompt, clip_skip)
if prompt_embed is not None:
p.prompt_embeds.append(torch.cat([prompt_embed] * len(prompts), dim=0))
if negative_embed is not None:
p.negative_embeds.append(torch.cat([negative_embed] * len(negative_prompts), dim=0))
if positive_pooled is not None:
p.positive_pooleds.append(torch.cat([positive_pooled] * len(prompts), dim=0))
if negative_pooled is not None:
p.negative_pooleds.append(torch.cat([negative_pooled] * len(negative_prompts), dim=0))
prompt_embeds, positive_pooleds, negative_embeds, negative_pooleds = [], [], [], []
last_prompt, last_negative = None, None
for prompt, negative in zip(prompts, negative_prompts):
prompt_embed, positive_pooled, negative_embed, negative_pooled = None, None, None, None
if last_prompt == prompt and last_negative == negative or False:
prompt_embeds.append(prompt_embed)
positive_pooleds.append(positive_pooled)
negative_embeds.append(negative_embed)
negative_pooleds.append(negative_pooled)
continue
positive_schedule, scheduled = get_prompt_schedule(prompt, steps)
negative_schedule, neg_scheduled = get_prompt_schedule(negative, steps)
p.scheduled_prompt = scheduled or neg_scheduled
p.prompt_embeds = []
p.positive_pooleds = []
p.negative_embeds = []
p.negative_pooleds = []
if shared.opts.sd_textencoder_cache:
for i in range(max(len(positive_schedule), len(negative_schedule))):
positive_prompt = positive_schedule[i % len(positive_schedule)]
negative_prompt = negative_schedule[i % len(negative_schedule)]
if shared.opts.prompt_attention == "xhinker parser" or 'Flux' in pipe.__class__.__name__:
prompt_embed, positive_pooled, negative_embed, negative_pooled = get_xhinker_text_embeddings(pipe, positive_prompt, negative_prompt, clip_skip)
else:
prompt_embed, positive_pooled, negative_embed, negative_pooled = get_weighted_text_embeddings(pipe, positive_prompt, negative_prompt, clip_skip)
prompt_embeds.append(prompt_embed)
positive_pooleds.append(positive_pooled)
negative_embeds.append(negative_embed)
negative_pooleds.append(negative_pooled)
last_prompt, last_negative = prompt, negative
def fix_length(embeds):
max_len = max([p.shape[1] for p in embeds])
for i, p in enumerate(embeds):
if p.shape[1] < max_len:
expanded = torch.zeros((p.shape[0], max_len, p.shape[2]), device=p.device, dtype=p.dtype)
expanded[:, :p.shape[1], :] = p
embeds[i] = expanded
return torch.cat(embeds, dim=0)
p.prompt_embeds.append(fix_length(prompt_embeds))
p.negative_embeds.append(fix_length(negative_embeds))
p.positive_pooleds.append(fix_length(positive_pooleds))
p.negative_pooleds.append(fix_length(negative_pooleds))
if shared.opts.sd_textencoder_cache and p.batch_size == 1:
cache.update({
'prompt_embeds': p.prompt_embeds,
'negative_embeds': p.negative_embeds,
+38 -26
View File
@@ -161,15 +161,15 @@ def list_models():
if shared.cmd_opts.ckpt is not None:
if not os.path.exists(shared.cmd_opts.ckpt) and not shared.native:
if shared.cmd_opts.ckpt.lower() != "none":
shared.log.warning(f"Requested checkpoint not found: {shared.cmd_opts.ckpt}")
shared.log.warning(f"Requested model not found: {shared.cmd_opts.ckpt}")
else:
checkpoint_info = CheckpointInfo(shared.cmd_opts.ckpt)
if checkpoint_info.name is not None:
checkpoint_info.register()
shared.opts.data['sd_model_checkpoint'] = checkpoint_info.title
elif shared.cmd_opts.ckpt != shared.default_sd_model_file and shared.cmd_opts.ckpt is not None:
shared.log.warning(f"Checkpoint not found: {shared.cmd_opts.ckpt}")
shared.log.info(f'Available models: path="{shared.opts.ckpt_dir}" items={len(checkpoints_list)} time={time.time()-t0:.2f}')
shared.log.warning(f"Model not found: {shared.cmd_opts.ckpt}")
shared.log.info(f'Available Models: path="{shared.opts.ckpt_dir}" items={len(checkpoints_list)} time={time.time()-t0:.2f}')
checkpoints_list = dict(sorted(checkpoints_list.items(), key=lambda cp: cp[1].filename))
@@ -342,7 +342,7 @@ def read_metadata_from_safetensors(filename):
metadata_len = int.from_bytes(metadata_len, "little")
json_start = file.read(2)
if metadata_len <= 2 or json_start not in (b'{"', b"{'"):
shared.log.error(f"Model metadata invalid: fn={filename}")
shared.log.error(f'Model metadata invalid: file="{filename}"')
json_data = json_start + file.read(metadata_len-2)
json_obj = json.loads(json_data)
for k, v in json_obj.get("__metadata__", {}).items():
@@ -370,7 +370,7 @@ def read_metadata_from_safetensors(filename):
pass
res[k] = v
except Exception as e:
shared.log.error(f"Model metadata: fn={filename} {e}")
shared.log.error(f'Model metadata: file="{filename}" {e}')
sd_metadata[filename] = res
global sd_metadata_pending # pylint: disable=global-statement
sd_metadata_pending += 1
@@ -682,28 +682,28 @@ def set_diffuser_options(sd_model, vae = None, op: str = 'model', offload=True):
if hasattr(sd_model, "vae"):
if vae is not None:
sd_model.vae = vae
shared.log.debug(f'Setting {op} VAE: name="{sd_vae.loaded_vae_file}"')
shared.log.debug(f'Setting {op}: component=VAE name="{sd_vae.loaded_vae_file}"')
if shared.opts.diffusers_vae_upcast != 'default':
sd_model.vae.config.force_upcast = True if shared.opts.diffusers_vae_upcast == 'true' else False
shared.log.debug(f'Setting {op} VAE: upcast={sd_model.vae.config.force_upcast}')
shared.log.debug(f'Setting {op}: component=VAE upcast={sd_model.vae.config.force_upcast}')
if shared.opts.no_half_vae:
devices.dtype_vae = torch.float32
sd_model.vae.to(devices.dtype_vae)
shared.log.debug(f'Setting {op} VAE: no-half=True')
shared.log.debug(f'Setting {op}: component=VAE no-half=True')
if hasattr(sd_model, "enable_vae_slicing"):
if shared.opts.diffusers_vae_slicing:
shared.log.debug(f'Setting {op}: slicing=True')
shared.log.debug(f'Setting {op}: component=VAE slicing=True')
sd_model.enable_vae_slicing()
else:
sd_model.disable_vae_slicing()
if hasattr(sd_model, "enable_vae_tiling"):
if shared.opts.diffusers_vae_tiling:
shared.log.debug(f'Setting {op}: tiling=True')
shared.log.debug(f'Setting {op}: component=VAE tiling=True')
sd_model.enable_vae_tiling()
else:
sd_model.disable_vae_tiling()
if hasattr(sd_model, "vqvae"):
shared.log.debug(f'Setting {op} VQVAE: upcast=True')
shared.log.debug(f'Setting {op}: component=VQVAE upcast=True')
sd_model.vqvae.to(torch.float32) # vqvae is producing nans in fp16
set_diffusers_attention(sd_model)
@@ -1262,8 +1262,8 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
return
if shared.opts.diffusers_vae_upcast != 'default' and model_type in ['Stable Diffusion', 'Stable Diffusion XL']:
diffusers_load_config['force_upcast'] = True if shared.opts.diffusers_vae_upcast == 'true' else False
if debug_load:
shared.log.debug(f'Model args: {diffusers_load_config}')
# if debug_load:
# shared.log.debug(f'Model args: {diffusers_load_config}')
if sd_model is not None:
diffusers_load_config.pop('vae', None)
diffusers_load_config.pop('safety_checker', None)
@@ -1311,6 +1311,12 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
else:
model_data.sd_model = sd_model
reload_text_encoder(initial=True) # must be before embeddings
timer.record("te")
if debug_load:
shared.log.trace(f'Model components: {list(get_signature(sd_model).values())}')
from modules.textual_inversion import textual_inversion
sd_model.embedding_db = textual_inversion.EmbeddingDatabase()
sd_model.embedding_db.add_embedding_dir(shared.opts.embeddings_dir)
@@ -1337,8 +1343,6 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
move_model(sd_model, devices.device)
timer.record("move")
reload_text_encoder(initial=True)
if shared.opts.ipex_optimize:
sd_model = sd_models_compile.ipex_optimize(sd_model)
@@ -1347,14 +1351,14 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
timer.record("compile")
except Exception as e:
shared.log.error("Failed to load diffusers model")
errors.display(e, "loading Diffusers model")
shared.log.error("Failed to load model")
errors.display(e, "Model")
devices.torch_gc(force=True)
if shared.cmd_opts.profile:
errors.profile(pr, 'Load')
script_callbacks.model_loaded_callback(sd_model)
shared.log.info(f"Load {op}: time={timer.summary()} native={get_native(sd_model)} {memory_stats()}")
shared.log.info(f"Load {op}: time={timer.summary()} native={get_native(sd_model)} memory={memory_stats()}")
class DiffusersTaskType(Enum):
@@ -1377,6 +1381,11 @@ def get_diffusers_task(pipe: diffusers.DiffusionPipeline) -> DiffusersTaskType:
return DiffusersTaskType.TEXT_2_IMAGE
def get_signature(cls):
signature = inspect.signature(cls.__init__, follow_wrapped=True, eval_str=True)
return signature.parameters
def switch_pipe(cls: diffusers.DiffusionPipeline, pipeline: diffusers.DiffusionPipeline = None, args = {}):
"""
args:
@@ -1393,8 +1402,8 @@ def switch_pipe(cls: diffusers.DiffusionPipeline, pipeline: diffusers.DiffusionP
if pipeline is None:
pipeline = shared.sd_model
new_pipe = None
signature = inspect.signature(cls.__init__, follow_wrapped=True, eval_str=True)
possible = signature.parameters.keys()
signature = get_signature(cls)
possible = signature.keys()
if isinstance(pipeline, cls) and args == {}:
return pipeline
pipe_dict = {}
@@ -1412,10 +1421,10 @@ def switch_pipe(cls: diffusers.DiffusionPipeline, pipeline: diffusers.DiffusionP
for item in possible:
if item in ['self', 'args', 'kwargs']: # skip
continue
if signature.parameters[item].default != inspect._empty: # has default value so we dont have to worry about it # pylint: disable=protected-access
if signature[item].default != inspect._empty: # has default value so we dont have to worry about it # pylint: disable=protected-access
continue
if item not in components_used:
shared.log.warning(f'Pipeling switch: missing component={item} type={signature.parameters[item].annotation}')
shared.log.warning(f'Pipeling switch: missing component={item} type={signature[item].annotation}')
pipe_dict[item] = None # try but not likely to work
components_missing.append(item)
new_pipe = cls(**pipe_dict)
@@ -1576,7 +1585,7 @@ def set_diffusers_attention(pipe):
if 'ControlNet' in pipe.__class__.__name__: # do not replace attention in ControlNet pipelines
return
shared.log.debug(f"Setting model: attention={shared.opts.cross_attention_optimization}")
shared.log.debug(f'Setting model: attention="{shared.opts.cross_attention_optimization}"')
if shared.opts.cross_attention_optimization == "Disabled":
pass # do nothing
elif shared.opts.cross_attention_optimization == "Scaled-Dot-Product": # The default set by Diffusers
@@ -1716,16 +1725,19 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, timer=None,
def reload_text_encoder(initial=False):
if initial and (shared.opts.sd_text_encoder is None or shared.opts.sd_text_encoder == 'None'):
return # dont unload
signature = inspect.signature(shared.sd_model.__class__.__init__, follow_wrapped=True, eval_str=True).parameters
signature = get_signature(shared.sd_model)
t5 = [k for k, v in signature.items() if 'T5EncoderModel' in str(v)]
if len(t5) > 0:
from modules.model_t5 import set_t5
from modules.model_te import set_t5
shared.log.debug(f'Load: t5={shared.opts.sd_text_encoder} module="{t5[0]}"')
set_t5(pipe=shared.sd_model, module=t5[0], t5=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir)
elif hasattr(shared.sd_model, 'text_encoder_3'):
from modules.model_t5 import set_t5
from modules.model_te import set_t5
shared.log.debug(f'Load: t5={shared.opts.sd_text_encoder} module="text_encoder_3"')
set_t5(pipe=shared.sd_model, module='text_encoder_3', t5=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir)
elif hasattr(shared.sd_model, 'text_encoder') and 'vit' in shared.opts.sd_text_encoder.lower():
from modules.model_te import set_te
set_te(pipe=shared.sd_model)
def reload_model_weights(sd_model=None, info=None, reuse_dict=False, op='model', force=False):
+2 -2
View File
@@ -52,7 +52,7 @@ def load_unet(model):
if not hasattr(model, 'unet') or model.unet is None:
shared.log.error('UNet not found in current model')
return
shared.log.info(f'Loading UNet: name="{shared.opts.sd_unet}" file="{unet_dict[shared.opts.sd_unet]}" config="{config_file}"')
shared.log.info(f'Load module: type=UNet name="{shared.opts.sd_unet}" file="{unet_dict[shared.opts.sd_unet]}" config="{config_file}"')
from diffusers import UNet2DConditionModel
from safetensors.torch import load_file
unet = UNet2DConditionModel.from_config(model.unet.config if config is None else config).to(devices.device, devices.dtype)
@@ -73,4 +73,4 @@ def refresh_unet_list():
for file in files_cache.list_files(shared.opts.unet_dir, ext_filter=[".safetensors"]):
name = os.path.splitext(os.path.basename(file))[0]
unet_dict[name] = file
shared.log.debug(f'Available UNets: path="{shared.opts.unet_dir}" items={len(unet_dict)}')
shared.log.info(f'Available UNets: path="{shared.opts.unet_dir}" items={len(unet_dict)}')
+1 -1
View File
@@ -210,7 +210,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"):
vae_config = sd_models.get_load_config(model_file, model_type, config_type='json')
if vae_config is not None:
diffusers_load_config['config'] = os.path.join(vae_config, 'vae')
shared.log.info(f'Load VAE: model="{vae_file}" source={vae_source} config={diffusers_load_config}')
shared.log.info(f'Load module: type=VAE model="{vae_file}" source={vae_source} config={diffusers_load_config}')
try:
import diffusers
if os.path.isfile(vae_file):
+11 -4
View File
@@ -81,6 +81,14 @@ compatibility_opts = ['clip_skip', 'uni_pc_lower_order_final', 'uni_pc_order']
console = Console(log_time=True, log_time_format='%H:%M:%S-%f')
dir_timestamps = {}
dir_cache = {}
if os.environ.get("HF_HUB_CACHE", None) is not None:
hfcache_dir = os.environ.get("HF_HUB_CACHE")
elif os.environ.get("HF_HUB", None) is not None:
hfcache_dir = os.path.join(os.environ.get("HF_HUB"), '.cache')
else:
hfcache_dir = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub')
os.environ["HF_HUB_CACHE"] = hfcache_dir
log.debug(f'Huggingface cache: folder="{hfcache_dir}"')
class Backend(Enum):
@@ -406,8 +414,7 @@ options_templates.update(options_section(('sd', "Execution & Models"), {
"sd_model_refiner": OptionInfo('None', "Refiner model", gr.Dropdown, lambda: {"choices": ['None'] + list_checkpoint_tiles()}, refresh=refresh_checkpoints),
"sd_vae": OptionInfo("Automatic", "VAE model", gr.Dropdown, lambda: {"choices": shared_items.sd_vae_items()}, refresh=shared_items.refresh_vae_list),
"sd_unet": OptionInfo("None", "UNET model", gr.Dropdown, lambda: {"choices": shared_items.sd_unet_items()}, refresh=shared_items.refresh_unet_list),
# "sd_text_encoder": OptionInfo('None', "Text encoder model", gr.Dropdown, lambda: {"choices": ['None', 'T5 FP4', 'T5 FP8', 'T5 INT8', 'T5 QINT8', 'T5 FP16']}),
"sd_text_encoder": OptionInfo('None', "Text encoder model", gr.Dropdown, lambda: {"choices": shared_items.sd_t5_items()}, refresh=shared_items.refresh_t5_list),
"sd_text_encoder": OptionInfo('None', "Text encoder model", gr.Dropdown, lambda: {"choices": shared_items.sd_te_items()}, refresh=shared_items.refresh_te_list),
"sd_model_dict": OptionInfo('None', "Use separate base dict", gr.Dropdown, lambda: {"choices": ['None'] + list_checkpoint_tiles()}, refresh=refresh_checkpoints),
"sd_checkpoint_autoload": OptionInfo(True, "Model autoload on start"),
"sd_textencoder_cache": OptionInfo(True, "Cache text encoder results"),
@@ -574,10 +581,10 @@ options_templates.update(options_section(('system-paths', "System Paths"), {
"models_dir": OptionInfo('models', "Base path where all models are stored", folder=True),
"ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Folder with stable diffusion models", folder=True),
"diffusers_dir": OptionInfo(os.path.join(paths.models_path, 'Diffusers'), "Folder with Huggingface models", folder=True),
"hfcache_dir": OptionInfo(os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub'), "Folder for Huggingface cache", folder=True),
"hfcache_dir": OptionInfo(hfcache_dir, "Folder for Huggingface cache", folder=True),
"vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Folder with VAE files", folder=True),
"unet_dir": OptionInfo(os.path.join(paths.models_path, 'UNET'), "Folder with UNET files", folder=True),
"t5_dir": OptionInfo(os.path.join(paths.models_path, 'T5'), "Folder with T5 files", folder=True),
"te_dir": OptionInfo(os.path.join(paths.models_path, 'Text-encoder'), "Folder with Text encoder files", folder=True),
"sd_lora": OptionInfo("", "Add LoRA to prompt", gr.Textbox, {"visible": False}),
"lora_dir": OptionInfo(os.path.join(paths.models_path, 'Lora'), "Folder with LoRA network(s)", folder=True),
"lyco_dir": OptionInfo(os.path.join(paths.models_path, 'LyCORIS'), "Folder with LyCORIS network(s)", gr.Text, {"visible": False}),
+6 -6
View File
@@ -23,15 +23,15 @@ def refresh_unet_list():
modules.sd_unet.refresh_unet_list()
def sd_t5_items():
import modules.model_t5
def sd_te_items():
import modules.model_te
predefined = ['None', 'T5 FP4', 'T5 FP8', 'T5 INT8', 'T5 QINT8', 'T5 FP16']
return predefined + list(modules.model_t5.t5_dict)
return predefined + list(modules.model_te.te_dict)
def refresh_t5_list():
import modules.model_t5
modules.model_t5.refresh_t5_list()
def refresh_te_list():
import modules.model_te
modules.model_te.refresh_te_list()
def list_crossattention(diffusers=False):
+6 -6
View File
@@ -175,10 +175,10 @@ class StyleDatabase:
try:
os.makedirs(opts.styles_dir, exist_ok=True)
self.save_styles(opts.styles_dir, verbose=True)
shared.log.debug(f'Migrated styles: file={legacy_file} folder={opts.styles_dir}')
shared.log.debug(f'Migrated styles: file="{legacy_file}" folder="{opts.styles_dir}"')
self.reload()
except Exception as e:
shared.log.error(f'styles failed to migrate: file={legacy_file} error={e}')
shared.log.error(f'styles failed to migrate: file="{legacy_file}" error={e}')
if not os.path.isdir(opts.styles_dir):
opts.styles_dir = os.path.join(paths.models_path, "styles")
self.path = opts.styles_dir
@@ -216,7 +216,7 @@ class StyleDatabase:
)
self.styles[style["name"]] = new_style
except Exception as e:
shared.log.error(f'Failed to load style: file={fn} error={e}')
shared.log.error(f'Failed to load style: file="{fn}" error={e}')
return new_style
@@ -244,7 +244,7 @@ class StyleDatabase:
list_folder(self.path)
t1 = time.time()
shared.log.debug(f'Load styles: folder="{self.path}" items={len(self.styles.keys())} time={t1-t0:.2f}')
shared.log.info(f'Available Styles: folder="{self.path}" items={len(self.styles.keys())} time={t1-t0:.2f}')
def find_style(self, name):
found = [style for style in self.styles.values() if style.name == name]
@@ -334,9 +334,9 @@ class StyleDatabase:
with open(fn, 'w', encoding='utf-8') as f:
json.dump(style, f, indent=2)
if verbose:
shared.log.debug(f'Saved style: name={name} file={fn}')
shared.log.debug(f'Saved style: name={name} file="{fn}"')
except Exception as e:
shared.log.error(f'Failed to save style: name={name} file={path} error={e}')
shared.log.error(f'Failed to save style: name={name} file="{path}" error={e}')
count = len(list(self.styles))
if count > 0:
shared.log.debug(f'Saved styles: folder="{path}" items={count}')
@@ -287,9 +287,7 @@ class EmbeddingDatabase:
try:
embedding.vector_sizes = [v.shape[-1] for v in embedding.vec]
if shared.opts.diffusers_convert_embed and 768 in hiddensizes and 1280 in hiddensizes and 1280 not in embedding.vector_sizes and 768 in embedding.vector_sizes:
embedding.vec.append(
convert_embedding(embedding.vec[embedding.vector_sizes.index(768)], text_encoders[hiddensizes.index(768)],
text_encoders[hiddensizes.index(1280)]))
embedding.vec.append(convert_embedding(embedding.vec[embedding.vector_sizes.index(768)], text_encoders[hiddensizes.index(768)], text_encoders[hiddensizes.index(1280)]))
embedding.vector_sizes.append(1280)
if (not all(vs in hiddensizes for vs in embedding.vector_sizes) or # Skip SD2.1 in SD1.5/SDXL/SD3 vis versa
len(embedding.vector_sizes) > len(hiddensizes) or # Skip SDXL/SD3 in SD1.5
@@ -311,7 +309,7 @@ class EmbeddingDatabase:
insert_vectors(embedding, tokenizers, text_encoders, hiddensizes)
self.register_embedding(embedding, shared.sd_model)
except Exception as e:
shared.log.error(f'Embedding load: name={embedding.name} fn={embedding.filename} {e}')
shared.log.error(f'Embedding load: name="{embedding.name}" file="{embedding.filename}" {e}')
return
def load_from_file(self, path, filename):
@@ -418,7 +416,7 @@ class EmbeddingDatabase:
if self.previously_displayed_embeddings != displayed_embeddings:
self.previously_displayed_embeddings = displayed_embeddings
t1 = time.time()
shared.log.info(f"Load embeddings: loaded={len(self.word_embeddings)} skipped={len(self.skipped_embeddings)} time={t1-t0:.2f}")
shared.log.info(f"Load network: type=embeddings loaded={len(self.word_embeddings)} skipped={len(self.skipped_embeddings)} time={t1-t0:.2f}")
def find_embedding_at_position(self, tokens, offset):
+2 -2
View File
@@ -203,10 +203,10 @@ def open_folder(result_gallery, gallery_index = 0):
except Exception:
folder = shared.opts.outdir_samples
if not os.path.exists(folder):
shared.log.warning(f'Folder open: folder={folder} does not exist')
shared.log.warning(f'Folder open: folder="{folder}" does not exist')
return
elif not os.path.isdir(folder):
shared.log.warning(f"Folder open: folder={folder} not a folder")
shared.log.warning(f'Folder open: folder="{folder}" not a folder')
return
if not shared.cmd_opts.hide_ui_dir_config:
+1 -1
View File
@@ -37,7 +37,7 @@ def list_extensions():
fn = os.path.join(paths.script_path, "html", "extensions.json")
extensions_list = shared.readfile(fn, silent=True) or []
if type(extensions_list) != list:
shared.log.warning(f'Invalid extensions list: file={fn}')
shared.log.warning(f'Invalid extensions list: file="{fn}"')
extensions_list = []
if len(extensions_list) == 0:
shared.log.info('Extension list is empty: refresh required')
+1 -1
View File
@@ -64,7 +64,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
record["info"] = self.find_info(checkpoint.filename)
record["description"] = self.find_description(checkpoint.filename, record["info"])
except Exception as e:
shared.log.debug(f"Networks error: type=model file={name} {e}")
shared.log.debug(f'Networks error: type=model file="{name}" {e}')
return record
def list_items(self):
+1 -1
View File
@@ -27,7 +27,7 @@ class ExtraNetworksPageHypernetworks(ui_extra_networks.ExtraNetworksPage):
"size": os.path.getsize(path),
}
except Exception as e:
shared.log.debug(f"Networks error: type=hypernetwork file={path} {e}")
shared.log.debug(f'Networks error: type=hypernetwork file="{path}" {e}')
def allowed_directories_for_previews(self):
return [shared.opts.hypernetwork_dir]
+1 -1
View File
@@ -93,7 +93,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage):
"size": os.path.getsize(style.filename),
}
except Exception as e:
shared.log.debug(f"Networks error: type=style file={k} {e}")
shared.log.debug(f'Networks error: type=style file="{k}" {e}')
return item
def list_items(self):
@@ -37,7 +37,7 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
record["info"] = self.find_info(embedding.filename)
record["description"] = self.find_description(embedding.filename, record["info"])
except Exception as e:
shared.log.debug(f"Networks error: type=embedding file={embedding.filename} {e}")
shared.log.debug(f'Networks error: type=embedding file="{embedding.filename}" {e}')
return record
def list_items(self):
+1 -1
View File
@@ -31,7 +31,7 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage):
record["description"] = self.find_description(filename, record["info"])
yield record
except Exception as e:
shared.log.debug(f"Networks error: type=vae file={filename} {e}")
shared.log.debug(f'Networks error: type=vae file="{filename}" {e}')
def allowed_directories_for_previews(self):
return [v for v in [shared.opts.vae_dir] if v is not None]
+2
View File
@@ -25,6 +25,8 @@ voluptuous
yapf
fasteners
orjson
ruff
pylint
invisible-watermark
pi-heif
safetensors==0.4.5
+1 -1
View File
@@ -51,7 +51,7 @@ class Script(scripts.Script):
shared.sd_model.unet.load_state_dict(load_file(hf_hub_download(repo_id=repo, subfolder=models[model], filename="diffusion_pytorch_model.safetensors")), strict=False)
sd_models.move_model(shared.sd_model, devices.device) # move pipeline to device
sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model')
shared.log.debug(f'ResAdapter: pipeline={shared.sd_model.__class__.__name__} model="{model}" weight={weight} fn={models[model]}')
shared.log.debug(f'ResAdapter: pipeline={shared.sd_model.__class__.__name__} model="{model}" weight={weight} file="{models[model]}"')
processed = processing.process_images(p)
shared.sd_model = old_pipe
return processed
+2 -2
View File
@@ -1,5 +1,5 @@
from scripts.xyz_grid_shared import apply_field, apply_task_args, apply_setting, apply_prompt, apply_order, apply_sampler, apply_hr_sampler_name, confirm_samplers, apply_checkpoint, apply_refiner, apply_unet, apply_dict, apply_clip_skip, apply_vae, list_lora, apply_lora, apply_te, apply_styles, apply_upscaler, apply_context, apply_face_restore, apply_override, apply_processing, format_value_add_label, format_value, format_value_join_list, do_nothing, format_nothing, str_permutations # pylint: disable=no-name-in-module
from modules import shared, sd_samplers, ipadapter, sd_models, sd_vae, sd_unet
from modules import shared, shared_items, sd_samplers, ipadapter, sd_models, sd_vae, sd_unet
class AxisOption:
@@ -86,7 +86,7 @@ axis_options = [
AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: ['None'] + list(sd_vae.vae_dict)),
AxisOption("LoRA", str, apply_lora, cost=0.5, choices=list_lora),
AxisOption("LoRA strength", float, apply_setting('extra_networks_default_multiplier')),
AxisOption("Text encoder", str, apply_te, cost=0.7, choices=lambda: ['None', 'T5 FP4', 'T5 FP8', 'T5 FP16']),
AxisOption("Text encoder", str, apply_te, cost=0.7, choices=shared_items.sd_te_items),
AxisOption("Styles", str, apply_styles, choices=lambda: [s.name for s in shared.prompt_styles.styles.values()]),
AxisOption("Seed", int, apply_field("seed")),
AxisOption("Steps", int, apply_field("steps")),
+2 -2
View File
@@ -24,7 +24,7 @@ import modules.scripts
import modules.sd_models
import modules.sd_vae
import modules.sd_unet
import modules.model_t5
import modules.model_te
import modules.progress
import modules.ui
import modules.txt2img
@@ -91,7 +91,7 @@ def initialize():
modules.sd_unet.refresh_unet_list()
timer.startup.record("unet")
modules.model_t5.refresh_t5_list()
modules.model_te.refresh_te_list()
timer.startup.record("unet")
extensions.list_extensions()