Merge branch 'dev' into Dev/DirectoryCacheing

This commit is contained in:
Steve
2024-01-17 10:35:13 -05:00
committed by GitHub
7 changed files with 13 additions and 32 deletions
+2
View File
@@ -102,6 +102,8 @@ And it also includes fixes for all reported issues so far
- faster json parsing
- faster lora indexing
- lazy load optional imports
- batch embedding load, thanks @midcoastal
10x+ faster embeddings load for large number of embeddings, now works for 1000+ embeddings
- **extra networks**
- 4x faster civitai metadata and previews lookup
- better display and selection of tags & trigger words
-15
View File
@@ -4,54 +4,40 @@ from typing import Optional
def patch(key, obj, field, replacement, add_if_not_exists:bool = False):
"""Replaces a function in a module or a class.
Also stores the original function in this module, possible to be retrieved via original(key, obj, field).
If the function is already replaced by this caller (key), an exception is raised -- use undo() before that.
Arguments:
key: identifying information for who is doing the replacement. You can use __name__.
obj: the module or the class
field: name of the function as a string
replacement: the new function
Returns:
the original function
"""
patch_key = (obj, field)
if patch_key in originals[key]:
raise RuntimeError(f"patch for {field} is already applied")
if not hasattr(obj, field) and not add_if_not_exists:
raise AttributeError(f"type {type(obj)} '{type.__name__}' has no attribute '{field}'")
original_func = getattr(obj, field, None)
originals[key][patch_key] = original_func
setattr(obj, field, replacement)
return original_func
def undo(key, obj, field):
"""Undoes the peplacement by the patch().
If the function is not replaced, raises an exception.
Arguments:
key: identifying information for who is doing the replacement. You can use __name__.
obj: the module or the class
field: name of the function as a string
Returns:
Always None
"""
patch_key = (obj, field)
if patch_key not in originals[key]:
raise RuntimeError(f"there is no patch for {field} to undo")
original_func = originals[key].pop(patch_key)
if original_func is None:
delattr(obj, field)
@@ -62,7 +48,6 @@ def undo(key, obj, field):
def original(key, obj, field):
"""Returns the original function for the patch created by the patch() function"""
patch_key = (obj, field)
return originals[key].get(patch_key, None)
+1 -1
View File
@@ -137,7 +137,7 @@ def prepare_embedding_providers(pipe, clip_skip):
provider = EmbeddingsProvider(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder, truncate=False,
returned_embeddings_type=embedding_type, device=device)
embeddings_providers.append(provider)
if hasattr(pipe, "tokenizer_2") and getattr(pipe, "text_encoder_2"):
if hasattr(pipe, "tokenizer_2") and hasattr(pipe, "text_encoder_2"):
provider = EmbeddingsProvider(tokenizer=pipe.tokenizer_2, text_encoder=pipe.text_encoder_2, truncate=False,
returned_embeddings_type=embedding_type, device=device)
embeddings_providers.append(provider)
+5 -14
View File
@@ -1,24 +1,19 @@
from typing import TYPE_CHECKING, Dict, List, Optional, Union
import torch
from diffusers.loaders.textual_inversion import (
TextualInversionLoaderMixin,
load_textual_inversion_state_dicts,
logger,
nn,
)
from torch import nn
from diffusers.loaders.textual_inversion import TextualInversionLoaderMixin, load_textual_inversion_state_dicts
from modules import shared
from modules.patches import patch_method
if TYPE_CHECKING:
from transformers import PreTrainedModel, PreTrainedTokenizer
try:
from accelerate.hooks import AlignDevicesHook, CpuOffload, remove_hook_from_module
except Exception:
pass
@patch_method(TextualInversionLoaderMixin)
def load_textual_inversion(
self: TextualInversionLoaderMixin,
@@ -28,12 +23,10 @@ def load_textual_inversion(
text_encoder: Optional["PreTrainedModel"] = None,
**kwargs, # pylint: disable=W0613
):
# 1. Set correct tokenizer and text encoder
tokenizer: PreTrainedTokenizer = tokenizer or getattr(self, "tokenizer", None)
text_encoder: PreTrainedModel = text_encoder or getattr(self, "text_encoder", None)
loaded_model_names_or_paths = {}
assert tokenizer and text_encoder, 'Can not resolve `tokenizer` or `text_encoder`'
# 2. Normalize inputs
@@ -99,9 +92,7 @@ def load_textual_inversion(
if hasattr(component, "_hf_hook"):
is_model_cpu_offload = isinstance(getattr(component, "_hf_hook"), CpuOffload) # noqa: B009
is_sequential_cpu_offload = isinstance(getattr(component, "_hf_hook"), AlignDevicesHook) # noqa: B009
logger.info(
"Accelerate hooks detected. Since you have called `load_textual_inversion()`, the previous hooks will be first removed. Then the textual inversion parameters will be loaded and the hooks will be applied again."
)
shared.log.debug("Accelerate hooks detected. Since you have called `load_textual_inversion()`, the previous hooks will be first removed. Then the textual inversion parameters will be loaded and the hooks will be applied again.")
remove_hook_from_module(component, recurse=is_sequential_cpu_offload)
# 7.2 save expected device and dtype
@@ -1,3 +1,4 @@
from typing import List, Optional, Union
import csv
import html
import os
@@ -17,8 +18,8 @@ from modules.textual_inversion.ti_logging import save_settings_to_file
from typing import List, Optional, Union
from modules.files_cache import directory_files, directory_mtime, extension_filter
TokenToAdd = namedtuple("TokenToAdd", ["clip_l", "clip_g"])
TokenToAdd = namedtuple("TokenToAdd", ["clip_l", "clip_g"])
TextualInversionTemplate = namedtuple("TextualInversionTemplate", ["name", "path"])
textual_inversion_templates = {}
+2
View File
@@ -221,12 +221,14 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline):
):
device = device or self._execution_device
"""
if prompt is not None and isinstance(prompt, str):
batch_size = 1
elif prompt is not None and isinstance(prompt, list):
batch_size = len(prompt)
else:
batch_size = prompt_embeds.shape[0]
"""
# Find the token id of the trigger word
image_token_id = self.tokenizer_2.convert_tokens_to_ids(self.trigger_word)