InvokeAI 2.2.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backend/__init__.py +0 -0
- backend/invoke_ai_web_server.py +1724 -0
- backend/modules/__init__.py +0 -0
- backend/modules/create_cmd_parser.py +55 -0
- backend/modules/get_canvas_generation_mode.py +117 -0
- backend/modules/parameters.py +71 -0
- backend/modules/parse_seed_weights.py +47 -0
- configs/INITIAL_MODELS.yaml +80 -0
- configs/models.yaml.example +29 -0
- configs/sd-concepts.txt +803 -0
- configs/stable-diffusion/v1-finetune.yaml +110 -0
- configs/stable-diffusion/v1-finetune_style.yaml +103 -0
- configs/stable-diffusion/v1-inference.yaml +79 -0
- configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
- configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
- docs/assets/invoke-web-server-1.png +0 -0
- docs/assets/invoke_ai_banner.png +0 -0
- invokeai-2.2.4.5.data/data/assets/caution.png +0 -0
- invokeai-2.2.4.5.data/data/configs/INITIAL_MODELS.yaml +80 -0
- invokeai-2.2.4.5.data/data/configs/models.yaml.example +29 -0
- invokeai-2.2.4.5.data/data/configs/sd-concepts.txt +803 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune.yaml +110 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune_style.yaml +103 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inference.yaml +79 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter-Bold.790c108b.ttf +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter.b9a8e5e2.ttf +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/favicon.0d253ced.ico +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index-legacy-b741077f.js +48 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index.0dadf5d0.css +1 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index.21ff81eb.js +625 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/logo.13003d72.png +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills-legacy-dde3a68a.js +4 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills.1ff60148.js +1 -0
- invokeai-2.2.4.5.data/data/frontend/dist/index.html +23 -0
- invokeai-2.2.4.5.data/data/scripts/configure_invokeai.py +797 -0
- invokeai-2.2.4.5.data/data/scripts/create_root.py +43 -0
- invokeai-2.2.4.5.data/data/scripts/dream.py +10 -0
- invokeai-2.2.4.5.data/data/scripts/images2prompt.py +30 -0
- invokeai-2.2.4.5.data/data/scripts/invoke.py +5 -0
- invokeai-2.2.4.5.data/data/scripts/legacy_api.py +681 -0
- invokeai-2.2.4.5.data/data/scripts/load_models.py +12 -0
- invokeai-2.2.4.5.data/data/scripts/merge_embeddings.py +124 -0
- invokeai-2.2.4.5.data/data/scripts/preload_models.py +12 -0
- invokeai-2.2.4.5.data/data/scripts/sd-metadata.py +22 -0
- invokeai-2.2.4.5.dist-info/LICENSE +21 -0
- invokeai-2.2.4.5.dist-info/LICENSE-ModelWeights.txt +294 -0
- invokeai-2.2.4.5.dist-info/METADATA +288 -0
- invokeai-2.2.4.5.dist-info/RECORD +169 -0
- invokeai-2.2.4.5.dist-info/WHEEL +5 -0
- invokeai-2.2.4.5.dist-info/entry_points.txt +4 -0
- invokeai-2.2.4.5.dist-info/top_level.txt +6 -0
- invokeai-2.2.4.5.dist-info/zip-safe +1 -0
- ldm/__init__.py +0 -0
- ldm/data/__init__.py +0 -0
- ldm/data/base.py +31 -0
- ldm/data/imagenet.py +466 -0
- ldm/data/lsun.py +126 -0
- ldm/data/personalized.py +202 -0
- ldm/data/personalized_style.py +169 -0
- ldm/generate.py +1159 -0
- ldm/invoke/CLI.py +960 -0
- ldm/invoke/__init__.py +3 -0
- ldm/invoke/args.py +1257 -0
- ldm/invoke/concepts_lib.py +169 -0
- ldm/invoke/conditioning.py +289 -0
- ldm/invoke/devices.py +27 -0
- ldm/invoke/generator/__init__.py +4 -0
- ldm/invoke/generator/base.py +335 -0
- ldm/invoke/generator/embiggen.py +501 -0
- ldm/invoke/generator/img2img.py +97 -0
- ldm/invoke/generator/inpaint.py +358 -0
- ldm/invoke/generator/omnibus.py +175 -0
- ldm/invoke/generator/txt2img.py +88 -0
- ldm/invoke/generator/txt2img2img.py +182 -0
- ldm/invoke/globals.py +31 -0
- ldm/invoke/image_util.py +70 -0
- ldm/invoke/log.py +66 -0
- ldm/invoke/model_cache.py +449 -0
- ldm/invoke/patchmatch.py +44 -0
- ldm/invoke/pngwriter.py +113 -0
- ldm/invoke/prompt_parser.py +655 -0
- ldm/invoke/readline.py +442 -0
- ldm/invoke/restoration/__init__.py +4 -0
- ldm/invoke/restoration/base.py +38 -0
- ldm/invoke/restoration/codeformer.py +103 -0
- ldm/invoke/restoration/codeformer_arch.py +276 -0
- ldm/invoke/restoration/gfpgan.py +84 -0
- ldm/invoke/restoration/outcrop.py +108 -0
- ldm/invoke/restoration/outpaint.py +92 -0
- ldm/invoke/restoration/realesrgan.py +90 -0
- ldm/invoke/restoration/vqgan_arch.py +435 -0
- ldm/invoke/seamless.py +30 -0
- ldm/invoke/server.py +282 -0
- ldm/invoke/server_legacy.py +246 -0
- ldm/invoke/txt2mask.py +136 -0
- ldm/lr_scheduler.py +143 -0
- ldm/models/__init__.py +0 -0
- ldm/models/autoencoder.py +596 -0
- ldm/models/diffusion/__init__.py +0 -0
- ldm/models/diffusion/classifier.py +355 -0
- ldm/models/diffusion/cross_attention_control.py +443 -0
- ldm/models/diffusion/cross_attention_map_saving.py +95 -0
- ldm/models/diffusion/ddim.py +111 -0
- ldm/models/diffusion/ddpm.py +2263 -0
- ldm/models/diffusion/ksampler.py +312 -0
- ldm/models/diffusion/plms.py +146 -0
- ldm/models/diffusion/sampler.py +450 -0
- ldm/models/diffusion/shared_invokeai_diffusion.py +244 -0
- ldm/modules/__init__.py +0 -0
- ldm/modules/attention.py +274 -0
- ldm/modules/diffusionmodules/__init__.py +0 -0
- ldm/modules/diffusionmodules/model.py +894 -0
- ldm/modules/diffusionmodules/openaimodel.py +1036 -0
- ldm/modules/diffusionmodules/util.py +314 -0
- ldm/modules/distributions/__init__.py +0 -0
- ldm/modules/distributions/distributions.py +104 -0
- ldm/modules/ema.py +88 -0
- ldm/modules/embedding_manager.py +413 -0
- ldm/modules/encoders/__init__.py +0 -0
- ldm/modules/encoders/modules.py +772 -0
- ldm/modules/image_degradation/__init__.py +6 -0
- ldm/modules/image_degradation/bsrgan.py +846 -0
- ldm/modules/image_degradation/bsrgan_light.py +751 -0
- ldm/modules/image_degradation/utils_image.py +1024 -0
- ldm/modules/losses/__init__.py +1 -0
- ldm/modules/losses/contperceptual.py +175 -0
- ldm/modules/losses/vqperceptual.py +240 -0
- ldm/modules/x_transformer.py +752 -0
- ldm/simplet2i.py +13 -0
- ldm/util.py +264 -0
- scripts/configure_invokeai.py +797 -0
- scripts/create_root.py +43 -0
- scripts/dream.py +10 -0
- scripts/images2prompt.py +30 -0
- scripts/invoke.py +5 -0
- scripts/legacy_api.py +681 -0
- scripts/load_models.py +12 -0
- scripts/merge_embeddings.py +124 -0
- scripts/orig_scripts/img2img.py +296 -0
- scripts/orig_scripts/inpaint.py +98 -0
- scripts/orig_scripts/knn2img.py +397 -0
- scripts/orig_scripts/sample_diffusion.py +313 -0
- scripts/orig_scripts/train_searcher.py +147 -0
- scripts/orig_scripts/txt2img.py +324 -0
- scripts/preload_models.py +12 -0
- scripts/sd-metadata.py +22 -0
- vendored/clip/clip/__init__.py +1 -0
- vendored/clip/clip/bpe_simple_vocab_16e6.txt.gz +0 -0
- vendored/clip/clip/clip.py +237 -0
- vendored/clip/clip/model.py +436 -0
- vendored/clip/clip/simple_tokenizer.py +132 -0
- vendored/clip/hubconf.py +42 -0
- vendored/clip/setup.py +21 -0
- vendored/clip/tests/test_consistency.py +25 -0
- vendored/clipseg/datasets/coco_wrapper.py +99 -0
- vendored/clipseg/datasets/pascal_zeroshot.py +60 -0
- vendored/clipseg/datasets/pfe_dataset.py +129 -0
- vendored/clipseg/datasets/phrasecut.py +380 -0
- vendored/clipseg/datasets/utils.py +68 -0
- vendored/clipseg/evaluation_utils.py +292 -0
- vendored/clipseg/general_utils.py +272 -0
- vendored/clipseg/metrics.py +271 -0
- vendored/clipseg/models/clipseg.py +538 -0
- vendored/clipseg/models/vitseg.py +286 -0
- vendored/clipseg/score.py +453 -0
- vendored/clipseg/setup.py +30 -0
- vendored/clipseg/training.py +266 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
from cmath import log
|
|
3
|
+
import torch
|
|
4
|
+
from torch import nn
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from ldm.invoke.concepts_lib import Concepts
|
|
9
|
+
from ldm.data.personalized import per_img_token_list
|
|
10
|
+
from transformers import CLIPTokenizer
|
|
11
|
+
from functools import partial
|
|
12
|
+
from picklescan.scanner import scan_file_path
|
|
13
|
+
|
|
14
|
+
PROGRESSIVE_SCALE = 2000
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_clip_token_for_string(tokenizer, string):
|
|
18
|
+
batch_encoding = tokenizer(
|
|
19
|
+
string,
|
|
20
|
+
truncation=True,
|
|
21
|
+
max_length=77,
|
|
22
|
+
return_length=True,
|
|
23
|
+
return_overflowing_tokens=False,
|
|
24
|
+
padding='max_length',
|
|
25
|
+
return_tensors='pt',
|
|
26
|
+
)
|
|
27
|
+
tokens = batch_encoding['input_ids']
|
|
28
|
+
""" assert (
|
|
29
|
+
torch.count_nonzero(tokens - 49407) == 2
|
|
30
|
+
), f"String '{string}' maps to more than a single token. Please use another string" """
|
|
31
|
+
|
|
32
|
+
return tokens[0, 1]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_bert_token_for_string(tokenizer, string):
|
|
36
|
+
token = tokenizer(string)
|
|
37
|
+
# assert torch.count_nonzero(token) == 3, f"String '{string}' maps to more than a single token. Please use another string"
|
|
38
|
+
|
|
39
|
+
token = token[0, 1]
|
|
40
|
+
|
|
41
|
+
return token
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_embedding_for_clip_token(embedder, token):
|
|
45
|
+
return embedder(token.unsqueeze(0))[0, 0]
|
|
46
|
+
|
|
47
|
+
class EmbeddingManager(nn.Module):
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
embedder,
|
|
51
|
+
placeholder_strings=None,
|
|
52
|
+
initializer_words=None,
|
|
53
|
+
per_image_tokens=False,
|
|
54
|
+
num_vectors_per_token=1,
|
|
55
|
+
progressive_words=False,
|
|
56
|
+
**kwargs,
|
|
57
|
+
):
|
|
58
|
+
super().__init__()
|
|
59
|
+
|
|
60
|
+
self.embedder = embedder
|
|
61
|
+
self.concepts_library=Concepts()
|
|
62
|
+
self.concepts_loaded = dict()
|
|
63
|
+
|
|
64
|
+
self.string_to_token_dict = {}
|
|
65
|
+
self.string_to_param_dict = nn.ParameterDict()
|
|
66
|
+
|
|
67
|
+
self.initial_embeddings = (
|
|
68
|
+
nn.ParameterDict()
|
|
69
|
+
) # These should not be optimized
|
|
70
|
+
|
|
71
|
+
self.progressive_words = progressive_words
|
|
72
|
+
self.progressive_counter = 0
|
|
73
|
+
|
|
74
|
+
self.max_vectors_per_token = num_vectors_per_token
|
|
75
|
+
|
|
76
|
+
if hasattr(
|
|
77
|
+
embedder, 'tokenizer'
|
|
78
|
+
): # using Stable Diffusion's CLIP encoder
|
|
79
|
+
self.is_clip = True
|
|
80
|
+
get_token_for_string = partial(
|
|
81
|
+
get_clip_token_for_string, embedder.tokenizer
|
|
82
|
+
)
|
|
83
|
+
get_embedding_for_tkn = partial(
|
|
84
|
+
get_embedding_for_clip_token,
|
|
85
|
+
embedder.transformer.text_model.embeddings,
|
|
86
|
+
)
|
|
87
|
+
# per bug report #572
|
|
88
|
+
#token_dim = 1280
|
|
89
|
+
token_dim = 768
|
|
90
|
+
else: # using LDM's BERT encoder
|
|
91
|
+
self.is_clip = False
|
|
92
|
+
get_token_for_string = partial(
|
|
93
|
+
get_bert_token_for_string, embedder.tknz_fn
|
|
94
|
+
)
|
|
95
|
+
get_embedding_for_tkn = embedder.transformer.token_emb
|
|
96
|
+
token_dim = 1280
|
|
97
|
+
|
|
98
|
+
if per_image_tokens:
|
|
99
|
+
placeholder_strings.extend(per_img_token_list)
|
|
100
|
+
|
|
101
|
+
for idx, placeholder_string in enumerate(placeholder_strings):
|
|
102
|
+
|
|
103
|
+
token = get_token_for_string(placeholder_string)
|
|
104
|
+
|
|
105
|
+
if initializer_words and idx < len(initializer_words):
|
|
106
|
+
init_word_token = get_token_for_string(initializer_words[idx])
|
|
107
|
+
|
|
108
|
+
with torch.no_grad():
|
|
109
|
+
init_word_embedding = get_embedding_for_tkn(
|
|
110
|
+
init_word_token.cpu()
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
token_params = torch.nn.Parameter(
|
|
114
|
+
init_word_embedding.unsqueeze(0).repeat(
|
|
115
|
+
num_vectors_per_token, 1
|
|
116
|
+
),
|
|
117
|
+
requires_grad=True,
|
|
118
|
+
)
|
|
119
|
+
self.initial_embeddings[
|
|
120
|
+
placeholder_string
|
|
121
|
+
] = torch.nn.Parameter(
|
|
122
|
+
init_word_embedding.unsqueeze(0).repeat(
|
|
123
|
+
num_vectors_per_token, 1
|
|
124
|
+
),
|
|
125
|
+
requires_grad=False,
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
token_params = torch.nn.Parameter(
|
|
129
|
+
torch.rand(
|
|
130
|
+
size=(num_vectors_per_token, token_dim),
|
|
131
|
+
requires_grad=True,
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
self.string_to_token_dict[placeholder_string] = token
|
|
136
|
+
self.string_to_param_dict[placeholder_string] = token_params
|
|
137
|
+
|
|
138
|
+
def forward(
|
|
139
|
+
self,
|
|
140
|
+
tokenized_text,
|
|
141
|
+
embedded_text,
|
|
142
|
+
):
|
|
143
|
+
b, n, device = *tokenized_text.shape, tokenized_text.device
|
|
144
|
+
|
|
145
|
+
for (
|
|
146
|
+
placeholder_string,
|
|
147
|
+
placeholder_token,
|
|
148
|
+
) in self.string_to_token_dict.items():
|
|
149
|
+
|
|
150
|
+
placeholder_embedding = self.string_to_param_dict[
|
|
151
|
+
placeholder_string
|
|
152
|
+
].to(device)
|
|
153
|
+
|
|
154
|
+
if self.progressive_words:
|
|
155
|
+
self.progressive_counter += 1
|
|
156
|
+
max_step_tokens = (
|
|
157
|
+
1 + self.progressive_counter // PROGRESSIVE_SCALE
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
max_step_tokens = self.max_vectors_per_token
|
|
161
|
+
|
|
162
|
+
num_vectors_for_token = min(
|
|
163
|
+
placeholder_embedding.shape[0], max_step_tokens
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
placeholder_rows, placeholder_cols = torch.where(
|
|
167
|
+
tokenized_text == placeholder_token.to(tokenized_text.device)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if placeholder_rows.nelement() == 0:
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
sorted_cols, sort_idx = torch.sort(
|
|
174
|
+
placeholder_cols, descending=True
|
|
175
|
+
)
|
|
176
|
+
sorted_rows = placeholder_rows[sort_idx]
|
|
177
|
+
|
|
178
|
+
for idx in range(sorted_rows.shape[0]):
|
|
179
|
+
row = sorted_rows[idx]
|
|
180
|
+
col = sorted_cols[idx]
|
|
181
|
+
|
|
182
|
+
new_token_row = torch.cat(
|
|
183
|
+
[
|
|
184
|
+
tokenized_text[row][:col],
|
|
185
|
+
placeholder_token.repeat(num_vectors_for_token).to(
|
|
186
|
+
device
|
|
187
|
+
),
|
|
188
|
+
tokenized_text[row][col + 1 :],
|
|
189
|
+
],
|
|
190
|
+
axis=0,
|
|
191
|
+
)[:n]
|
|
192
|
+
new_embed_row = torch.cat(
|
|
193
|
+
[
|
|
194
|
+
embedded_text[row][:col],
|
|
195
|
+
placeholder_embedding[:num_vectors_for_token],
|
|
196
|
+
embedded_text[row][col + 1 :],
|
|
197
|
+
],
|
|
198
|
+
axis=0,
|
|
199
|
+
)[:n]
|
|
200
|
+
|
|
201
|
+
embedded_text[row] = new_embed_row
|
|
202
|
+
tokenized_text[row] = new_token_row
|
|
203
|
+
|
|
204
|
+
return embedded_text
|
|
205
|
+
|
|
206
|
+
def save(self, ckpt_path):
|
|
207
|
+
torch.save(
|
|
208
|
+
{
|
|
209
|
+
'string_to_token': self.string_to_token_dict,
|
|
210
|
+
'string_to_param': self.string_to_param_dict,
|
|
211
|
+
},
|
|
212
|
+
ckpt_path,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def load_concepts(self, concepts:list[str], full=True):
|
|
216
|
+
bin_files = list()
|
|
217
|
+
for concept_name in concepts:
|
|
218
|
+
if concept_name in self.concepts_loaded:
|
|
219
|
+
continue
|
|
220
|
+
else:
|
|
221
|
+
bin_file = self.concepts_library.get_concept_model_path(concept_name)
|
|
222
|
+
if not bin_file:
|
|
223
|
+
continue
|
|
224
|
+
bin_files.append(bin_file)
|
|
225
|
+
self.concepts_loaded[concept_name]=True
|
|
226
|
+
self.load(bin_files, full)
|
|
227
|
+
|
|
228
|
+
def list_terms(self) -> list[str]:
|
|
229
|
+
return self.concepts_loaded.keys()
|
|
230
|
+
|
|
231
|
+
def load(self, ckpt_paths, full=True):
|
|
232
|
+
if len(ckpt_paths) == 0:
|
|
233
|
+
return
|
|
234
|
+
if type(ckpt_paths) != list:
|
|
235
|
+
ckpt_paths = [ckpt_paths]
|
|
236
|
+
ckpt_paths = self._expand_directories(ckpt_paths)
|
|
237
|
+
for c in ckpt_paths:
|
|
238
|
+
self._load(c,full)
|
|
239
|
+
# remember that we know this term and don't try to download it again from the concepts library
|
|
240
|
+
# note that if the concept name is also provided and different from the trigger term, they
|
|
241
|
+
# both will be stored in this dictionary
|
|
242
|
+
for term in self.string_to_param_dict.keys():
|
|
243
|
+
term = term.strip('<').strip('>')
|
|
244
|
+
self.concepts_loaded[term] = True
|
|
245
|
+
print(f'>> Current embedding manager terms: {", ".join(self.string_to_param_dict.keys())}')
|
|
246
|
+
|
|
247
|
+
def _expand_directories(self, paths:list[str]):
|
|
248
|
+
expanded_paths = list()
|
|
249
|
+
for path in paths:
|
|
250
|
+
if os.path.isfile(path):
|
|
251
|
+
expanded_paths.append(path)
|
|
252
|
+
elif os.path.isdir(path):
|
|
253
|
+
for root, _, files in os.walk(path):
|
|
254
|
+
for name in files:
|
|
255
|
+
expanded_paths.append(os.path.join(root,name))
|
|
256
|
+
return [x for x in expanded_paths if os.path.splitext(x)[1] in ('.pt','.bin')]
|
|
257
|
+
|
|
258
|
+
def _load(self, ckpt_path, full=True):
|
|
259
|
+
try:
|
|
260
|
+
scan_result = scan_file_path(ckpt_path)
|
|
261
|
+
if scan_result.infected_files == 1:
|
|
262
|
+
print(f'\n### Security Issues Found in Model: {scan_result.issues_count}')
|
|
263
|
+
print('### For your safety, InvokeAI will not load this embed.')
|
|
264
|
+
return
|
|
265
|
+
except Exception:
|
|
266
|
+
print(f"### WARNING::: Invalid or corrupt embeddings found. Ignoring: {ckpt_path}")
|
|
267
|
+
return
|
|
268
|
+
|
|
269
|
+
embedding_info = self.parse_embedding(ckpt_path)
|
|
270
|
+
if embedding_info:
|
|
271
|
+
self.max_vectors_per_token = embedding_info['num_vectors_per_token']
|
|
272
|
+
self.add_embedding(embedding_info['name'], embedding_info['embedding'], full)
|
|
273
|
+
else:
|
|
274
|
+
print(f'>> Failed to load embedding located at {ckpt_path}. Unsupported file.')
|
|
275
|
+
|
|
276
|
+
def add_embedding(self, token_str, embedding, full):
|
|
277
|
+
if token_str in self.string_to_param_dict:
|
|
278
|
+
print(f">> Embedding manager refusing to overwrite already-loaded term '{token_str}'")
|
|
279
|
+
return
|
|
280
|
+
if not full:
|
|
281
|
+
embedding = embedding.half()
|
|
282
|
+
if len(embedding.shape) == 1:
|
|
283
|
+
embedding = embedding.unsqueeze(0)
|
|
284
|
+
|
|
285
|
+
num_tokens_added = self.embedder.tokenizer.add_tokens(token_str)
|
|
286
|
+
current_embeddings = self.embedder.transformer.resize_token_embeddings(None)
|
|
287
|
+
current_token_count = current_embeddings.num_embeddings
|
|
288
|
+
new_token_count = current_token_count + num_tokens_added
|
|
289
|
+
self.embedder.transformer.resize_token_embeddings(new_token_count)
|
|
290
|
+
|
|
291
|
+
token = get_clip_token_for_string(self.embedder.tokenizer, token_str)
|
|
292
|
+
self.string_to_token_dict[token_str] = token
|
|
293
|
+
self.string_to_param_dict[token_str] = torch.nn.Parameter(embedding)
|
|
294
|
+
|
|
295
|
+
def parse_embedding(self, embedding_file: str):
|
|
296
|
+
file_type = embedding_file.split('.')[-1]
|
|
297
|
+
if file_type == 'pt':
|
|
298
|
+
return self.parse_embedding_pt(embedding_file)
|
|
299
|
+
elif file_type == 'bin':
|
|
300
|
+
return self.parse_embedding_bin(embedding_file)
|
|
301
|
+
else:
|
|
302
|
+
print(f'>> Not a recognized embedding file: {embedding_file}')
|
|
303
|
+
|
|
304
|
+
def parse_embedding_pt(self, embedding_file):
|
|
305
|
+
embedding_ckpt = torch.load(embedding_file, map_location='cpu')
|
|
306
|
+
embedding_info = {}
|
|
307
|
+
|
|
308
|
+
# Check if valid embedding file
|
|
309
|
+
if 'string_to_token' and 'string_to_param' in embedding_ckpt:
|
|
310
|
+
|
|
311
|
+
# Catch variants that do not have the expected keys or values.
|
|
312
|
+
try:
|
|
313
|
+
embedding_info['name'] = embedding_ckpt['name'] or os.path.basename(os.path.splitext(embedding_file)[0])
|
|
314
|
+
|
|
315
|
+
# Check num of embeddings and warn user only the first will be used
|
|
316
|
+
embedding_info['num_of_embeddings'] = len(embedding_ckpt["string_to_token"])
|
|
317
|
+
if embedding_info['num_of_embeddings'] > 1:
|
|
318
|
+
print('>> More than 1 embedding found. Will use the first one')
|
|
319
|
+
|
|
320
|
+
embedding = list(embedding_ckpt['string_to_param'].values())[0]
|
|
321
|
+
except (AttributeError,KeyError):
|
|
322
|
+
return self.handle_broken_pt_variants(embedding_ckpt, embedding_file)
|
|
323
|
+
|
|
324
|
+
embedding_info['embedding'] = embedding
|
|
325
|
+
embedding_info['num_vectors_per_token'] = embedding.size()[0]
|
|
326
|
+
embedding_info['token_dim'] = embedding.size()[1]
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
embedding_info['trained_steps'] = embedding_ckpt['step']
|
|
330
|
+
embedding_info['trained_model_name'] = embedding_ckpt['sd_checkpoint_name']
|
|
331
|
+
embedding_info['trained_model_checksum'] = embedding_ckpt['sd_checkpoint']
|
|
332
|
+
except AttributeError:
|
|
333
|
+
print(">> No Training Details Found. Passing ...")
|
|
334
|
+
|
|
335
|
+
# .pt files found at https://cyberes.github.io/stable-diffusion-textual-inversion-models/
|
|
336
|
+
# They are actually .bin files
|
|
337
|
+
elif len(embedding_ckpt.keys())==1:
|
|
338
|
+
print('>> Detected .bin file masquerading as .pt file')
|
|
339
|
+
embedding_info = self.parse_embedding_bin(embedding_file)
|
|
340
|
+
|
|
341
|
+
else:
|
|
342
|
+
print('>> Invalid embedding format')
|
|
343
|
+
embedding_info = None
|
|
344
|
+
|
|
345
|
+
return embedding_info
|
|
346
|
+
|
|
347
|
+
def parse_embedding_bin(self, embedding_file):
|
|
348
|
+
embedding_ckpt = torch.load(embedding_file, map_location='cpu')
|
|
349
|
+
embedding_info = {}
|
|
350
|
+
|
|
351
|
+
if list(embedding_ckpt.keys()) == 0:
|
|
352
|
+
print(">> Invalid concepts file")
|
|
353
|
+
embedding_info = None
|
|
354
|
+
else:
|
|
355
|
+
for token in list(embedding_ckpt.keys()):
|
|
356
|
+
embedding_info['name'] = token or os.path.basename(os.path.splitext(embedding_file)[0])
|
|
357
|
+
embedding_info['embedding'] = embedding_ckpt[token]
|
|
358
|
+
embedding_info['num_vectors_per_token'] = 1 # All Concepts seem to default to 1
|
|
359
|
+
embedding_info['token_dim'] = embedding_info['embedding'].size()[0]
|
|
360
|
+
|
|
361
|
+
return embedding_info
|
|
362
|
+
|
|
363
|
+
def handle_broken_pt_variants(self, embedding_ckpt:dict, embedding_file:str)->dict:
|
|
364
|
+
'''
|
|
365
|
+
This handles the broken .pt file variants. We only know of one at present.
|
|
366
|
+
'''
|
|
367
|
+
embedding_info = {}
|
|
368
|
+
if isinstance(list(embedding_ckpt['string_to_token'].values())[0],torch.Tensor):
|
|
369
|
+
print(f'>> Variant Embedding Detected. Parsing: {embedding_file}') # example at https://github.com/invoke-ai/InvokeAI/issues/1829
|
|
370
|
+
token = list(embedding_ckpt['string_to_token'].keys())[0]
|
|
371
|
+
embedding_info['name'] = os.path.basename(os.path.splitext(embedding_file)[0])
|
|
372
|
+
embedding_info['embedding'] = embedding_ckpt['string_to_param'].state_dict()[token]
|
|
373
|
+
embedding_info['num_vectors_per_token'] = embedding_info['embedding'].shape[0]
|
|
374
|
+
embedding_info['token_dim'] = embedding_info['embedding'].size()[0]
|
|
375
|
+
else:
|
|
376
|
+
print('>> Invalid embedding format')
|
|
377
|
+
embedding_info = None
|
|
378
|
+
|
|
379
|
+
return embedding_info
|
|
380
|
+
|
|
381
|
+
def has_embedding_for_token(self, token_str):
|
|
382
|
+
return token_str in self.string_to_token_dict
|
|
383
|
+
|
|
384
|
+
def get_embedding_norms_squared(self):
|
|
385
|
+
all_params = torch.cat(
|
|
386
|
+
list(self.string_to_param_dict.values()), axis=0
|
|
387
|
+
) # num_placeholders x embedding_dim
|
|
388
|
+
param_norm_squared = (all_params * all_params).sum(
|
|
389
|
+
axis=-1
|
|
390
|
+
) # num_placeholders
|
|
391
|
+
|
|
392
|
+
return param_norm_squared
|
|
393
|
+
|
|
394
|
+
def embedding_parameters(self):
|
|
395
|
+
return self.string_to_param_dict.parameters()
|
|
396
|
+
|
|
397
|
+
def embedding_to_coarse_loss(self):
|
|
398
|
+
|
|
399
|
+
loss = 0.0
|
|
400
|
+
num_embeddings = len(self.initial_embeddings)
|
|
401
|
+
|
|
402
|
+
for key in self.initial_embeddings:
|
|
403
|
+
optimized = self.string_to_param_dict[key]
|
|
404
|
+
coarse = self.initial_embeddings[key].clone().to(optimized.device)
|
|
405
|
+
|
|
406
|
+
loss = (
|
|
407
|
+
loss
|
|
408
|
+
+ (optimized - coarse)
|
|
409
|
+
@ (optimized - coarse).T
|
|
410
|
+
/ num_embeddings
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
return loss
|
|
File without changes
|