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.
Files changed (169) hide show
  1. backend/__init__.py +0 -0
  2. backend/invoke_ai_web_server.py +1724 -0
  3. backend/modules/__init__.py +0 -0
  4. backend/modules/create_cmd_parser.py +55 -0
  5. backend/modules/get_canvas_generation_mode.py +117 -0
  6. backend/modules/parameters.py +71 -0
  7. backend/modules/parse_seed_weights.py +47 -0
  8. configs/INITIAL_MODELS.yaml +80 -0
  9. configs/models.yaml.example +29 -0
  10. configs/sd-concepts.txt +803 -0
  11. configs/stable-diffusion/v1-finetune.yaml +110 -0
  12. configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  13. configs/stable-diffusion/v1-inference.yaml +79 -0
  14. configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  15. configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  16. docs/assets/invoke-web-server-1.png +0 -0
  17. docs/assets/invoke_ai_banner.png +0 -0
  18. invokeai-2.2.4.5.data/data/assets/caution.png +0 -0
  19. invokeai-2.2.4.5.data/data/configs/INITIAL_MODELS.yaml +80 -0
  20. invokeai-2.2.4.5.data/data/configs/models.yaml.example +29 -0
  21. invokeai-2.2.4.5.data/data/configs/sd-concepts.txt +803 -0
  22. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune.yaml +110 -0
  23. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  24. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inference.yaml +79 -0
  25. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  26. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  27. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter-Bold.790c108b.ttf +0 -0
  28. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter.b9a8e5e2.ttf +0 -0
  29. invokeai-2.2.4.5.data/data/frontend/dist/assets/favicon.0d253ced.ico +0 -0
  30. invokeai-2.2.4.5.data/data/frontend/dist/assets/index-legacy-b741077f.js +48 -0
  31. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.0dadf5d0.css +1 -0
  32. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.21ff81eb.js +625 -0
  33. invokeai-2.2.4.5.data/data/frontend/dist/assets/logo.13003d72.png +0 -0
  34. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills-legacy-dde3a68a.js +4 -0
  35. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills.1ff60148.js +1 -0
  36. invokeai-2.2.4.5.data/data/frontend/dist/index.html +23 -0
  37. invokeai-2.2.4.5.data/data/scripts/configure_invokeai.py +797 -0
  38. invokeai-2.2.4.5.data/data/scripts/create_root.py +43 -0
  39. invokeai-2.2.4.5.data/data/scripts/dream.py +10 -0
  40. invokeai-2.2.4.5.data/data/scripts/images2prompt.py +30 -0
  41. invokeai-2.2.4.5.data/data/scripts/invoke.py +5 -0
  42. invokeai-2.2.4.5.data/data/scripts/legacy_api.py +681 -0
  43. invokeai-2.2.4.5.data/data/scripts/load_models.py +12 -0
  44. invokeai-2.2.4.5.data/data/scripts/merge_embeddings.py +124 -0
  45. invokeai-2.2.4.5.data/data/scripts/preload_models.py +12 -0
  46. invokeai-2.2.4.5.data/data/scripts/sd-metadata.py +22 -0
  47. invokeai-2.2.4.5.dist-info/LICENSE +21 -0
  48. invokeai-2.2.4.5.dist-info/LICENSE-ModelWeights.txt +294 -0
  49. invokeai-2.2.4.5.dist-info/METADATA +288 -0
  50. invokeai-2.2.4.5.dist-info/RECORD +169 -0
  51. invokeai-2.2.4.5.dist-info/WHEEL +5 -0
  52. invokeai-2.2.4.5.dist-info/entry_points.txt +4 -0
  53. invokeai-2.2.4.5.dist-info/top_level.txt +6 -0
  54. invokeai-2.2.4.5.dist-info/zip-safe +1 -0
  55. ldm/__init__.py +0 -0
  56. ldm/data/__init__.py +0 -0
  57. ldm/data/base.py +31 -0
  58. ldm/data/imagenet.py +466 -0
  59. ldm/data/lsun.py +126 -0
  60. ldm/data/personalized.py +202 -0
  61. ldm/data/personalized_style.py +169 -0
  62. ldm/generate.py +1159 -0
  63. ldm/invoke/CLI.py +960 -0
  64. ldm/invoke/__init__.py +3 -0
  65. ldm/invoke/args.py +1257 -0
  66. ldm/invoke/concepts_lib.py +169 -0
  67. ldm/invoke/conditioning.py +289 -0
  68. ldm/invoke/devices.py +27 -0
  69. ldm/invoke/generator/__init__.py +4 -0
  70. ldm/invoke/generator/base.py +335 -0
  71. ldm/invoke/generator/embiggen.py +501 -0
  72. ldm/invoke/generator/img2img.py +97 -0
  73. ldm/invoke/generator/inpaint.py +358 -0
  74. ldm/invoke/generator/omnibus.py +175 -0
  75. ldm/invoke/generator/txt2img.py +88 -0
  76. ldm/invoke/generator/txt2img2img.py +182 -0
  77. ldm/invoke/globals.py +31 -0
  78. ldm/invoke/image_util.py +70 -0
  79. ldm/invoke/log.py +66 -0
  80. ldm/invoke/model_cache.py +449 -0
  81. ldm/invoke/patchmatch.py +44 -0
  82. ldm/invoke/pngwriter.py +113 -0
  83. ldm/invoke/prompt_parser.py +655 -0
  84. ldm/invoke/readline.py +442 -0
  85. ldm/invoke/restoration/__init__.py +4 -0
  86. ldm/invoke/restoration/base.py +38 -0
  87. ldm/invoke/restoration/codeformer.py +103 -0
  88. ldm/invoke/restoration/codeformer_arch.py +276 -0
  89. ldm/invoke/restoration/gfpgan.py +84 -0
  90. ldm/invoke/restoration/outcrop.py +108 -0
  91. ldm/invoke/restoration/outpaint.py +92 -0
  92. ldm/invoke/restoration/realesrgan.py +90 -0
  93. ldm/invoke/restoration/vqgan_arch.py +435 -0
  94. ldm/invoke/seamless.py +30 -0
  95. ldm/invoke/server.py +282 -0
  96. ldm/invoke/server_legacy.py +246 -0
  97. ldm/invoke/txt2mask.py +136 -0
  98. ldm/lr_scheduler.py +143 -0
  99. ldm/models/__init__.py +0 -0
  100. ldm/models/autoencoder.py +596 -0
  101. ldm/models/diffusion/__init__.py +0 -0
  102. ldm/models/diffusion/classifier.py +355 -0
  103. ldm/models/diffusion/cross_attention_control.py +443 -0
  104. ldm/models/diffusion/cross_attention_map_saving.py +95 -0
  105. ldm/models/diffusion/ddim.py +111 -0
  106. ldm/models/diffusion/ddpm.py +2263 -0
  107. ldm/models/diffusion/ksampler.py +312 -0
  108. ldm/models/diffusion/plms.py +146 -0
  109. ldm/models/diffusion/sampler.py +450 -0
  110. ldm/models/diffusion/shared_invokeai_diffusion.py +244 -0
  111. ldm/modules/__init__.py +0 -0
  112. ldm/modules/attention.py +274 -0
  113. ldm/modules/diffusionmodules/__init__.py +0 -0
  114. ldm/modules/diffusionmodules/model.py +894 -0
  115. ldm/modules/diffusionmodules/openaimodel.py +1036 -0
  116. ldm/modules/diffusionmodules/util.py +314 -0
  117. ldm/modules/distributions/__init__.py +0 -0
  118. ldm/modules/distributions/distributions.py +104 -0
  119. ldm/modules/ema.py +88 -0
  120. ldm/modules/embedding_manager.py +413 -0
  121. ldm/modules/encoders/__init__.py +0 -0
  122. ldm/modules/encoders/modules.py +772 -0
  123. ldm/modules/image_degradation/__init__.py +6 -0
  124. ldm/modules/image_degradation/bsrgan.py +846 -0
  125. ldm/modules/image_degradation/bsrgan_light.py +751 -0
  126. ldm/modules/image_degradation/utils_image.py +1024 -0
  127. ldm/modules/losses/__init__.py +1 -0
  128. ldm/modules/losses/contperceptual.py +175 -0
  129. ldm/modules/losses/vqperceptual.py +240 -0
  130. ldm/modules/x_transformer.py +752 -0
  131. ldm/simplet2i.py +13 -0
  132. ldm/util.py +264 -0
  133. scripts/configure_invokeai.py +797 -0
  134. scripts/create_root.py +43 -0
  135. scripts/dream.py +10 -0
  136. scripts/images2prompt.py +30 -0
  137. scripts/invoke.py +5 -0
  138. scripts/legacy_api.py +681 -0
  139. scripts/load_models.py +12 -0
  140. scripts/merge_embeddings.py +124 -0
  141. scripts/orig_scripts/img2img.py +296 -0
  142. scripts/orig_scripts/inpaint.py +98 -0
  143. scripts/orig_scripts/knn2img.py +397 -0
  144. scripts/orig_scripts/sample_diffusion.py +313 -0
  145. scripts/orig_scripts/train_searcher.py +147 -0
  146. scripts/orig_scripts/txt2img.py +324 -0
  147. scripts/preload_models.py +12 -0
  148. scripts/sd-metadata.py +22 -0
  149. vendored/clip/clip/__init__.py +1 -0
  150. vendored/clip/clip/bpe_simple_vocab_16e6.txt.gz +0 -0
  151. vendored/clip/clip/clip.py +237 -0
  152. vendored/clip/clip/model.py +436 -0
  153. vendored/clip/clip/simple_tokenizer.py +132 -0
  154. vendored/clip/hubconf.py +42 -0
  155. vendored/clip/setup.py +21 -0
  156. vendored/clip/tests/test_consistency.py +25 -0
  157. vendored/clipseg/datasets/coco_wrapper.py +99 -0
  158. vendored/clipseg/datasets/pascal_zeroshot.py +60 -0
  159. vendored/clipseg/datasets/pfe_dataset.py +129 -0
  160. vendored/clipseg/datasets/phrasecut.py +380 -0
  161. vendored/clipseg/datasets/utils.py +68 -0
  162. vendored/clipseg/evaluation_utils.py +292 -0
  163. vendored/clipseg/general_utils.py +272 -0
  164. vendored/clipseg/metrics.py +271 -0
  165. vendored/clipseg/models/clipseg.py +538 -0
  166. vendored/clipseg/models/vitseg.py +286 -0
  167. vendored/clipseg/score.py +453 -0
  168. vendored/clipseg/setup.py +30 -0
  169. vendored/clipseg/training.py +266 -0
@@ -0,0 +1,772 @@
1
+ import math
2
+ import os.path
3
+ import torch
4
+ import torch.nn as nn
5
+ from functools import partial
6
+ import vendored.clip.clip.clip as clip
7
+ from einops import rearrange, repeat
8
+ from transformers import CLIPTokenizer, CLIPTextModel
9
+ import kornia
10
+ from ldm.invoke.devices import choose_torch_device
11
+ from ldm.invoke.globals import Globals
12
+
13
+ from ldm.modules.x_transformer import (
14
+ Encoder,
15
+ TransformerWrapper,
16
+ ) # TODO: can we directly rely on lucidrains code and simply add this as a reuirement? --> test
17
+
18
+
19
+ def _expand_mask(mask, dtype, tgt_len=None):
20
+ """
21
+ Expands attention_mask from `[bsz, seq_len]` to `[bsz, 1, tgt_seq_len, src_seq_len]`.
22
+ """
23
+ bsz, src_len = mask.size()
24
+ tgt_len = tgt_len if tgt_len is not None else src_len
25
+
26
+ expanded_mask = (
27
+ mask[:, None, None, :].expand(bsz, 1, tgt_len, src_len).to(dtype)
28
+ )
29
+
30
+ inverted_mask = 1.0 - expanded_mask
31
+
32
+ return inverted_mask.masked_fill(
33
+ inverted_mask.to(torch.bool), torch.finfo(dtype).min
34
+ )
35
+
36
+
37
+ def _build_causal_attention_mask(bsz, seq_len, dtype):
38
+ # lazily create causal attention mask, with full attention between the vision tokens
39
+ # pytorch uses additive attention mask; fill with -inf
40
+ mask = torch.empty(bsz, seq_len, seq_len, dtype=dtype)
41
+ mask.fill_(torch.tensor(torch.finfo(dtype).min))
42
+ mask.triu_(1) # zero out the lower diagonal
43
+ mask = mask.unsqueeze(1) # expand mask
44
+ return mask
45
+
46
+
47
+ class AbstractEncoder(nn.Module):
48
+ def __init__(self):
49
+ super().__init__()
50
+
51
+ def encode(self, *args, **kwargs):
52
+ raise NotImplementedError
53
+
54
+
55
+ class ClassEmbedder(nn.Module):
56
+ def __init__(self, embed_dim, n_classes=1000, key='class'):
57
+ super().__init__()
58
+ self.key = key
59
+ self.embedding = nn.Embedding(n_classes, embed_dim)
60
+
61
+ def forward(self, batch, key=None):
62
+ if key is None:
63
+ key = self.key
64
+ # this is for use in crossattn
65
+ c = batch[key][:, None]
66
+ c = self.embedding(c)
67
+ return c
68
+
69
+
70
+ class TransformerEmbedder(AbstractEncoder):
71
+ """Some transformer encoder layers"""
72
+
73
+ def __init__(
74
+ self,
75
+ n_embed,
76
+ n_layer,
77
+ vocab_size,
78
+ max_seq_len=77,
79
+ device=choose_torch_device(),
80
+ ):
81
+ super().__init__()
82
+ self.device = device
83
+ self.transformer = TransformerWrapper(
84
+ num_tokens=vocab_size,
85
+ max_seq_len=max_seq_len,
86
+ attn_layers=Encoder(dim=n_embed, depth=n_layer),
87
+ )
88
+
89
+ def forward(self, tokens):
90
+ tokens = tokens.to(self.device) # meh
91
+ z = self.transformer(tokens, return_embeddings=True)
92
+ return z
93
+
94
+ def encode(self, x):
95
+ return self(x)
96
+
97
+
98
+ class BERTTokenizer(AbstractEncoder):
99
+ """Uses a pretrained BERT tokenizer by huggingface. Vocab size: 30522 (?)"""
100
+
101
+ def __init__(
102
+ self, device=choose_torch_device(), vq_interface=True, max_length=77
103
+ ):
104
+ super().__init__()
105
+ from transformers import (
106
+ BertTokenizerFast,
107
+ )
108
+
109
+ cache = os.path.join(Globals.root,'models/bert-base-uncased')
110
+ try:
111
+ self.tokenizer = BertTokenizerFast.from_pretrained(
112
+ 'bert-base-uncased',
113
+ cache_dir=cache,
114
+ local_files_only=True
115
+ )
116
+ except OSError:
117
+ raise SystemExit(
118
+ "* Couldn't load Bert tokenizer files. Try running scripts/preload_models.py from an internet-conected machine."
119
+ )
120
+ self.device = device
121
+ self.vq_interface = vq_interface
122
+ self.max_length = max_length
123
+
124
+ def forward(self, text):
125
+ batch_encoding = self.tokenizer(
126
+ text,
127
+ truncation=True,
128
+ max_length=self.max_length,
129
+ return_length=True,
130
+ return_overflowing_tokens=False,
131
+ padding='max_length',
132
+ return_tensors='pt',
133
+ )
134
+ tokens = batch_encoding['input_ids'].to(self.device)
135
+ return tokens
136
+
137
+ @torch.no_grad()
138
+ def encode(self, text):
139
+ tokens = self(text)
140
+ if not self.vq_interface:
141
+ return tokens
142
+ return None, None, [None, None, tokens]
143
+
144
+ def decode(self, text):
145
+ return text
146
+
147
+
148
+ class BERTEmbedder(AbstractEncoder):
149
+ """Uses the BERT tokenizr model and add some transformer encoder layers"""
150
+
151
+ def __init__(
152
+ self,
153
+ n_embed,
154
+ n_layer,
155
+ vocab_size=30522,
156
+ max_seq_len=77,
157
+ device=choose_torch_device(),
158
+ use_tokenizer=True,
159
+ embedding_dropout=0.0,
160
+ ):
161
+ super().__init__()
162
+ self.use_tknz_fn = use_tokenizer
163
+ if self.use_tknz_fn:
164
+ self.tknz_fn = BERTTokenizer(
165
+ vq_interface=False, max_length=max_seq_len
166
+ )
167
+ self.device = device
168
+ self.transformer = TransformerWrapper(
169
+ num_tokens=vocab_size,
170
+ max_seq_len=max_seq_len,
171
+ attn_layers=Encoder(dim=n_embed, depth=n_layer),
172
+ emb_dropout=embedding_dropout,
173
+ )
174
+
175
+ def forward(self, text, embedding_manager=None):
176
+ if self.use_tknz_fn:
177
+ tokens = self.tknz_fn(text) # .to(self.device)
178
+ else:
179
+ tokens = text
180
+ z = self.transformer(
181
+ tokens, return_embeddings=True, embedding_manager=embedding_manager
182
+ )
183
+ return z
184
+
185
+ def encode(self, text, **kwargs):
186
+ # output of length 77
187
+ return self(text, **kwargs)
188
+
189
+
190
+ class SpatialRescaler(nn.Module):
191
+ def __init__(
192
+ self,
193
+ n_stages=1,
194
+ method='bilinear',
195
+ multiplier=0.5,
196
+ in_channels=3,
197
+ out_channels=None,
198
+ bias=False,
199
+ ):
200
+ super().__init__()
201
+ self.n_stages = n_stages
202
+ assert self.n_stages >= 0
203
+ assert method in [
204
+ 'nearest',
205
+ 'linear',
206
+ 'bilinear',
207
+ 'trilinear',
208
+ 'bicubic',
209
+ 'area',
210
+ ]
211
+ self.multiplier = multiplier
212
+ self.interpolator = partial(
213
+ torch.nn.functional.interpolate, mode=method
214
+ )
215
+ self.remap_output = out_channels is not None
216
+ if self.remap_output:
217
+ print(
218
+ f'Spatial Rescaler mapping from {in_channels} to {out_channels} channels after resizing.'
219
+ )
220
+ self.channel_mapper = nn.Conv2d(
221
+ in_channels, out_channels, 1, bias=bias
222
+ )
223
+
224
+ def forward(self, x):
225
+ for stage in range(self.n_stages):
226
+ x = self.interpolator(x, scale_factor=self.multiplier)
227
+
228
+ if self.remap_output:
229
+ x = self.channel_mapper(x)
230
+ return x
231
+
232
+ def encode(self, x):
233
+ return self(x)
234
+
235
+
236
+ class FrozenCLIPEmbedder(AbstractEncoder):
237
+ """Uses the CLIP transformer encoder for text (from Hugging Face)"""
238
+
239
+ def __init__(
240
+ self,
241
+ version='openai/clip-vit-large-patch14',
242
+ device=choose_torch_device(),
243
+ max_length=77,
244
+ ):
245
+ super().__init__()
246
+ cache = os.path.join(Globals.root,'models',version)
247
+ self.tokenizer = CLIPTokenizer.from_pretrained(
248
+ version,
249
+ cache_dir=cache,
250
+ local_files_only=True
251
+ )
252
+ self.transformer = CLIPTextModel.from_pretrained(
253
+ version,
254
+ cache_dir=cache,
255
+ local_files_only=True
256
+ )
257
+ self.device = device
258
+ self.max_length = max_length
259
+ self.freeze()
260
+
261
+ def embedding_forward(
262
+ self,
263
+ input_ids=None,
264
+ position_ids=None,
265
+ inputs_embeds=None,
266
+ embedding_manager=None,
267
+ ) -> torch.Tensor:
268
+
269
+ seq_length = (
270
+ input_ids.shape[-1]
271
+ if input_ids is not None
272
+ else inputs_embeds.shape[-2]
273
+ )
274
+
275
+ if position_ids is None:
276
+ position_ids = self.position_ids[:, :seq_length]
277
+
278
+ if inputs_embeds is None:
279
+ inputs_embeds = self.token_embedding(input_ids)
280
+
281
+ if embedding_manager is not None:
282
+ inputs_embeds = embedding_manager(input_ids, inputs_embeds)
283
+
284
+ position_embeddings = self.position_embedding(position_ids)
285
+ embeddings = inputs_embeds + position_embeddings
286
+
287
+ return embeddings
288
+
289
+ self.transformer.text_model.embeddings.forward = (
290
+ embedding_forward.__get__(self.transformer.text_model.embeddings)
291
+ )
292
+
293
+ def encoder_forward(
294
+ self,
295
+ inputs_embeds,
296
+ attention_mask=None,
297
+ causal_attention_mask=None,
298
+ output_attentions=None,
299
+ output_hidden_states=None,
300
+ return_dict=None,
301
+ ):
302
+ output_attentions = (
303
+ output_attentions
304
+ if output_attentions is not None
305
+ else self.config.output_attentions
306
+ )
307
+ output_hidden_states = (
308
+ output_hidden_states
309
+ if output_hidden_states is not None
310
+ else self.config.output_hidden_states
311
+ )
312
+ return_dict = (
313
+ return_dict
314
+ if return_dict is not None
315
+ else self.config.use_return_dict
316
+ )
317
+
318
+ encoder_states = () if output_hidden_states else None
319
+ all_attentions = () if output_attentions else None
320
+
321
+ hidden_states = inputs_embeds
322
+ for idx, encoder_layer in enumerate(self.layers):
323
+ if output_hidden_states:
324
+ encoder_states = encoder_states + (hidden_states,)
325
+
326
+ layer_outputs = encoder_layer(
327
+ hidden_states,
328
+ attention_mask,
329
+ causal_attention_mask,
330
+ output_attentions=output_attentions,
331
+ )
332
+
333
+ hidden_states = layer_outputs[0]
334
+
335
+ if output_attentions:
336
+ all_attentions = all_attentions + (layer_outputs[1],)
337
+
338
+ if output_hidden_states:
339
+ encoder_states = encoder_states + (hidden_states,)
340
+
341
+ return hidden_states
342
+
343
+ self.transformer.text_model.encoder.forward = encoder_forward.__get__(
344
+ self.transformer.text_model.encoder
345
+ )
346
+
347
+ def text_encoder_forward(
348
+ self,
349
+ input_ids=None,
350
+ attention_mask=None,
351
+ position_ids=None,
352
+ output_attentions=None,
353
+ output_hidden_states=None,
354
+ return_dict=None,
355
+ embedding_manager=None,
356
+ ):
357
+ output_attentions = (
358
+ output_attentions
359
+ if output_attentions is not None
360
+ else self.config.output_attentions
361
+ )
362
+ output_hidden_states = (
363
+ output_hidden_states
364
+ if output_hidden_states is not None
365
+ else self.config.output_hidden_states
366
+ )
367
+ return_dict = (
368
+ return_dict
369
+ if return_dict is not None
370
+ else self.config.use_return_dict
371
+ )
372
+
373
+ if input_ids is None:
374
+ raise ValueError('You have to specify either input_ids')
375
+
376
+ input_shape = input_ids.size()
377
+ input_ids = input_ids.view(-1, input_shape[-1])
378
+
379
+ hidden_states = self.embeddings(
380
+ input_ids=input_ids,
381
+ position_ids=position_ids,
382
+ embedding_manager=embedding_manager,
383
+ )
384
+
385
+ bsz, seq_len = input_shape
386
+ # CLIP's text model uses causal mask, prepare it here.
387
+ # https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L324
388
+ causal_attention_mask = _build_causal_attention_mask(
389
+ bsz, seq_len, hidden_states.dtype
390
+ ).to(hidden_states.device)
391
+
392
+ # expand attention_mask
393
+ if attention_mask is not None:
394
+ # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
395
+ attention_mask = _expand_mask(
396
+ attention_mask, hidden_states.dtype
397
+ )
398
+
399
+ last_hidden_state = self.encoder(
400
+ inputs_embeds=hidden_states,
401
+ attention_mask=attention_mask,
402
+ causal_attention_mask=causal_attention_mask,
403
+ output_attentions=output_attentions,
404
+ output_hidden_states=output_hidden_states,
405
+ return_dict=return_dict,
406
+ )
407
+
408
+ last_hidden_state = self.final_layer_norm(last_hidden_state)
409
+
410
+ return last_hidden_state
411
+
412
+ self.transformer.text_model.forward = text_encoder_forward.__get__(
413
+ self.transformer.text_model
414
+ )
415
+
416
+ def transformer_forward(
417
+ self,
418
+ input_ids=None,
419
+ attention_mask=None,
420
+ position_ids=None,
421
+ output_attentions=None,
422
+ output_hidden_states=None,
423
+ return_dict=None,
424
+ embedding_manager=None,
425
+ ):
426
+ return self.text_model(
427
+ input_ids=input_ids,
428
+ attention_mask=attention_mask,
429
+ position_ids=position_ids,
430
+ output_attentions=output_attentions,
431
+ output_hidden_states=output_hidden_states,
432
+ return_dict=return_dict,
433
+ embedding_manager=embedding_manager,
434
+ )
435
+
436
+ self.transformer.forward = transformer_forward.__get__(
437
+ self.transformer
438
+ )
439
+
440
+ def freeze(self):
441
+ self.transformer = self.transformer.eval()
442
+ for param in self.parameters():
443
+ param.requires_grad = False
444
+
445
+ def forward(self, text, **kwargs):
446
+ batch_encoding = self.tokenizer(
447
+ text,
448
+ truncation=True,
449
+ max_length=self.max_length,
450
+ return_length=True,
451
+ return_overflowing_tokens=False,
452
+ padding='max_length',
453
+ return_tensors='pt',
454
+ )
455
+ tokens = batch_encoding['input_ids'].to(self.device)
456
+ z = self.transformer(input_ids=tokens, **kwargs)
457
+
458
+ return z
459
+
460
+ def encode(self, text, **kwargs):
461
+ return self(text, **kwargs)
462
+
463
+ class WeightedFrozenCLIPEmbedder(FrozenCLIPEmbedder):
464
+
465
+ fragment_weights_key = "fragment_weights"
466
+ return_tokens_key = "return_tokens"
467
+
468
+ def forward(self, text: list, **kwargs):
469
+ '''
470
+
471
+ :param text: A batch of prompt strings, or, a batch of lists of fragments of prompt strings to which different
472
+ weights shall be applied.
473
+ :param kwargs: If the keyword arg "fragment_weights" is passed, it shall contain a batch of lists of weights
474
+ for the prompt fragments. In this case text must contain batches of lists of prompt fragments.
475
+ :return: A tensor of shape (B, 77, 768) containing weighted embeddings
476
+ '''
477
+ if self.fragment_weights_key not in kwargs:
478
+ # fallback to base class implementation
479
+ return super().forward(text, **kwargs)
480
+
481
+ fragment_weights = kwargs[self.fragment_weights_key]
482
+ # self.transformer doesn't like receiving "fragment_weights" as an argument
483
+ kwargs.pop(self.fragment_weights_key)
484
+
485
+ should_return_tokens = False
486
+ if self.return_tokens_key in kwargs:
487
+ should_return_tokens = kwargs.get(self.return_tokens_key, False)
488
+ # self.transformer doesn't like having extra kwargs
489
+ kwargs.pop(self.return_tokens_key)
490
+
491
+ batch_z = None
492
+ batch_tokens = None
493
+ for fragments, weights in zip(text, fragment_weights):
494
+
495
+ # First, weight tokens in individual fragments by scaling the feature vectors as requested (effectively
496
+ # applying a multiplier to the CFG scale on a per-token basis).
497
+ # For tokens weighted<1, intuitively we want SD to become not merely *less* interested in the concept
498
+ # captured by the fragment but actually *dis*interested in it (a 0.01 interest in "red" is still an active
499
+ # interest, however small, in redness; what the user probably intends when they attach the number 0.01 to
500
+ # "red" is to tell SD that it should almost completely *ignore* redness).
501
+ # To do this, the embedding is lerped away from base_embedding in the direction of an embedding for a prompt
502
+ # string from which the low-weighted fragment has been simply removed. The closer the weight is to zero, the
503
+ # closer the resulting embedding is to an embedding for a prompt that simply lacks this fragment.
504
+
505
+ # handle weights >=1
506
+ tokens, per_token_weights = self.get_tokens_and_weights(fragments, weights)
507
+ base_embedding = self.build_weighted_embedding_tensor(tokens, per_token_weights, **kwargs)
508
+
509
+ # this is our starting point
510
+ embeddings = base_embedding.unsqueeze(0)
511
+ per_embedding_weights = [1.0]
512
+
513
+ # now handle weights <1
514
+ # Do this by building extra embeddings tensors that lack the words being <1 weighted. These will be lerped
515
+ # with the embeddings tensors that have the words, such that if the weight of a word is 0.5, the resulting
516
+ # embedding will be exactly half-way between the unweighted prompt and the prompt with the <1 weighted words
517
+ # removed.
518
+ # eg for "mountain:1 man:0.5", intuitively the "man" should be "half-gone". therefore, append an embedding
519
+ # for "mountain" (i.e. without "man") to the already-produced embedding for "mountain man", and weight it
520
+ # such that the resulting lerped embedding is exactly half-way between "mountain man" and "mountain".
521
+ for index, fragment_weight in enumerate(weights):
522
+ if fragment_weight < 1:
523
+ fragments_without_this = fragments[:index] + fragments[index+1:]
524
+ weights_without_this = weights[:index] + weights[index+1:]
525
+ tokens, per_token_weights = self.get_tokens_and_weights(fragments_without_this, weights_without_this)
526
+ embedding_without_this = self.build_weighted_embedding_tensor(tokens, per_token_weights, **kwargs)
527
+
528
+ embeddings = torch.cat((embeddings, embedding_without_this.unsqueeze(0)), dim=1)
529
+ # weight of the embedding *without* this fragment gets *stronger* as its weight approaches 0
530
+ # if fragment_weight = 0, basically we want embedding_without_this to completely overwhelm base_embedding
531
+ # therefore:
532
+ # fragment_weight = 1: we are at base_z => lerp weight 0
533
+ # fragment_weight = 0.5: we are halfway between base_z and here => lerp weight 1
534
+ # fragment_weight = 0: we're now entirely overriding base_z ==> lerp weight inf
535
+ # so let's use tan(), because:
536
+ # tan is 0.0 at 0,
537
+ # 1.0 at PI/4, and
538
+ # inf at PI/2
539
+ # -> tan((1-weight)*PI/2) should give us ideal lerp weights
540
+ epsilon = 1e-9
541
+ fragment_weight = max(epsilon, fragment_weight) # inf is bad
542
+ embedding_lerp_weight = math.tan((1.0 - fragment_weight) * math.pi / 2)
543
+ # todo handle negative weight?
544
+
545
+ per_embedding_weights.append(embedding_lerp_weight)
546
+
547
+ lerped_embeddings = self.apply_embedding_weights(embeddings, per_embedding_weights, normalize=True).squeeze(0)
548
+
549
+ #print(f"assembled tokens for '{fragments}' into tensor of shape {lerped_embeddings.shape}")
550
+
551
+ # append to batch
552
+ batch_z = lerped_embeddings.unsqueeze(0) if batch_z is None else torch.cat([batch_z, lerped_embeddings.unsqueeze(0)], dim=1)
553
+ batch_tokens = tokens.unsqueeze(0) if batch_tokens is None else torch.cat([batch_tokens, tokens.unsqueeze(0)], dim=1)
554
+
555
+ # should have shape (B, 77, 768)
556
+ #print(f"assembled all tokens into tensor of shape {batch_z.shape}")
557
+
558
+ if should_return_tokens:
559
+ return batch_z, batch_tokens
560
+ else:
561
+ return batch_z
562
+
563
+ def get_tokens(self, fragments: list[str], include_start_and_end_markers: bool = True) -> list[list[int]]:
564
+ tokens = self.tokenizer(
565
+ fragments,
566
+ truncation=True,
567
+ max_length=self.max_length,
568
+ return_overflowing_tokens=False,
569
+ padding='do_not_pad',
570
+ return_tensors=None, # just give me a list of ints
571
+ )['input_ids']
572
+ if include_start_and_end_markers:
573
+ return tokens
574
+ else:
575
+ return [x[1:-1] for x in tokens]
576
+
577
+
578
+ @classmethod
579
+ def apply_embedding_weights(self, embeddings: torch.Tensor, per_embedding_weights: list[float], normalize:bool) -> torch.Tensor:
580
+ per_embedding_weights = torch.tensor(per_embedding_weights, dtype=embeddings.dtype, device=embeddings.device)
581
+ if normalize:
582
+ per_embedding_weights = per_embedding_weights / torch.sum(per_embedding_weights)
583
+ reshaped_weights = per_embedding_weights.reshape(per_embedding_weights.shape + (1, 1,))
584
+ #reshaped_weights = per_embedding_weights.reshape(per_embedding_weights.shape + (1,1,)).expand(embeddings.shape)
585
+ return torch.sum(embeddings * reshaped_weights, dim=1)
586
+ # lerped embeddings has shape (77, 768)
587
+
588
+
589
+ def get_tokens_and_weights(self, fragments: list[str], weights: list[float]) -> (torch.Tensor, torch.Tensor):
590
+ '''
591
+
592
+ :param fragments:
593
+ :param weights: Per-fragment weights (CFG scaling). No need for these to be normalized. They will not be normalized here and that's fine.
594
+ :return:
595
+ '''
596
+ # empty is meaningful
597
+ if len(fragments) == 0 and len(weights) == 0:
598
+ fragments = ['']
599
+ weights = [1]
600
+ item_encodings = self.tokenizer(
601
+ fragments,
602
+ truncation=True,
603
+ max_length=self.max_length,
604
+ return_overflowing_tokens=True,
605
+ padding='do_not_pad',
606
+ return_tensors=None, # just give me a list of ints
607
+ )['input_ids']
608
+ all_tokens = []
609
+ per_token_weights = []
610
+ #print("all fragments:", fragments, weights)
611
+ for index, fragment in enumerate(item_encodings):
612
+ weight = weights[index]
613
+ #print("processing fragment", fragment, weight)
614
+ fragment_tokens = item_encodings[index]
615
+ #print("fragment", fragment, "processed to", fragment_tokens)
616
+ # trim bos and eos markers before appending
617
+ all_tokens.extend(fragment_tokens[1:-1])
618
+ per_token_weights.extend([weight] * (len(fragment_tokens) - 2))
619
+
620
+ if (len(all_tokens) + 2) > self.max_length:
621
+ excess_token_count = (len(all_tokens) + 2) - self.max_length
622
+ print(f">> Prompt is {excess_token_count} token(s) too long and has been truncated")
623
+ all_tokens = all_tokens[:self.max_length - 2]
624
+ per_token_weights = per_token_weights[:self.max_length - 2]
625
+
626
+ # pad out to a 77-entry array: [eos_token, <prompt tokens>, eos_token, ..., eos_token]
627
+ # (77 = self.max_length)
628
+ pad_length = self.max_length - 1 - len(all_tokens)
629
+ all_tokens.insert(0, self.tokenizer.bos_token_id)
630
+ all_tokens.extend([self.tokenizer.eos_token_id] * pad_length)
631
+ per_token_weights.insert(0, 1)
632
+ per_token_weights.extend([1] * pad_length)
633
+
634
+ all_tokens_tensor = torch.tensor(all_tokens, dtype=torch.long).to(self.device)
635
+ per_token_weights_tensor = torch.tensor(per_token_weights, dtype=torch.float32).to(self.device)
636
+ #print(f"assembled all_tokens_tensor with shape {all_tokens_tensor.shape}")
637
+ return all_tokens_tensor, per_token_weights_tensor
638
+
639
+ def build_weighted_embedding_tensor(self, tokens: torch.Tensor, per_token_weights: torch.Tensor, weight_delta_from_empty=True, **kwargs) -> torch.Tensor:
640
+ '''
641
+ Build a tensor representing the passed-in tokens, each of which has a weight.
642
+ :param tokens: A tensor of shape (77) containing token ids (integers)
643
+ :param per_token_weights: A tensor of shape (77) containing weights (floats)
644
+ :param method: Whether to multiply the whole feature vector for each token or just its distance from an "empty" feature vector
645
+ :param kwargs: passed on to self.transformer()
646
+ :return: A tensor of shape (1, 77, 768) representing the requested weighted embeddings.
647
+ '''
648
+ #print(f"building weighted embedding tensor for {tokens} with weights {per_token_weights}")
649
+ z = self.transformer(input_ids=tokens.unsqueeze(0), **kwargs)
650
+ batch_weights_expanded = per_token_weights.reshape(per_token_weights.shape + (1,)).expand(z.shape)
651
+
652
+ if weight_delta_from_empty:
653
+ empty_tokens = self.tokenizer([''] * z.shape[0],
654
+ truncation=True,
655
+ max_length=self.max_length,
656
+ padding='max_length',
657
+ return_tensors='pt'
658
+ )['input_ids'].to(self.device)
659
+ empty_z = self.transformer(input_ids=empty_tokens, **kwargs)
660
+ z_delta_from_empty = z - empty_z
661
+ weighted_z = empty_z + (z_delta_from_empty * batch_weights_expanded)
662
+
663
+ weighted_z_delta_from_empty = (weighted_z-empty_z)
664
+ #print("weighted z has delta from empty with sum", weighted_z_delta_from_empty.sum().item(), "mean", weighted_z_delta_from_empty.mean().item() )
665
+
666
+ #print("using empty-delta method, first 5 rows:")
667
+ #print(weighted_z[:5])
668
+
669
+ return weighted_z
670
+
671
+ else:
672
+ original_mean = z.mean()
673
+ z *= batch_weights_expanded
674
+ after_weighting_mean = z.mean()
675
+ # correct the mean. not sure if this is right but it's what the automatic1111 fork of SD does
676
+ mean_correction_factor = original_mean/after_weighting_mean
677
+ z *= mean_correction_factor
678
+ return z
679
+
680
+
681
+ class FrozenCLIPTextEmbedder(nn.Module):
682
+ """
683
+ Uses the CLIP transformer encoder for text.
684
+ """
685
+
686
+ def __init__(
687
+ self,
688
+ version='ViT-L/14',
689
+ device=choose_torch_device(),
690
+ max_length=77,
691
+ n_repeat=1,
692
+ normalize=True,
693
+ ):
694
+ super().__init__()
695
+ self.model, _ = clip.load(version, jit=False, device=device)
696
+ self.device = device
697
+ self.max_length = max_length
698
+ self.n_repeat = n_repeat
699
+ self.normalize = normalize
700
+
701
+ def freeze(self):
702
+ self.model = self.model.eval()
703
+ for param in self.parameters():
704
+ param.requires_grad = False
705
+
706
+ def forward(self, text):
707
+ tokens = clip.tokenize(text).to(self.device)
708
+ z = self.model.encode_text(tokens)
709
+ if self.normalize:
710
+ z = z / torch.linalg.norm(z, dim=1, keepdim=True)
711
+ return z
712
+
713
+ def encode(self, text):
714
+ z = self(text)
715
+ if z.ndim == 2:
716
+ z = z[:, None, :]
717
+ z = repeat(z, 'b 1 d -> b k d', k=self.n_repeat)
718
+ return z
719
+
720
+
721
+ class FrozenClipImageEmbedder(nn.Module):
722
+ """
723
+ Uses the CLIP image encoder.
724
+ """
725
+
726
+ def __init__(
727
+ self,
728
+ model,
729
+ jit=False,
730
+ device=choose_torch_device(),
731
+ antialias=False,
732
+ ):
733
+ super().__init__()
734
+ self.model, _ = clip.load(name=model, device=device, jit=jit)
735
+
736
+ self.antialias = antialias
737
+
738
+ self.register_buffer(
739
+ 'mean',
740
+ torch.Tensor([0.48145466, 0.4578275, 0.40821073]),
741
+ persistent=False,
742
+ )
743
+ self.register_buffer(
744
+ 'std',
745
+ torch.Tensor([0.26862954, 0.26130258, 0.27577711]),
746
+ persistent=False,
747
+ )
748
+
749
+ def preprocess(self, x):
750
+ # normalize to [0,1]
751
+ x = kornia.geometry.resize(
752
+ x,
753
+ (224, 224),
754
+ interpolation='bicubic',
755
+ align_corners=True,
756
+ antialias=self.antialias,
757
+ )
758
+ x = (x + 1.0) / 2.0
759
+ # renormalize according to clip
760
+ x = kornia.enhance.normalize(x, self.mean, self.std)
761
+ return x
762
+
763
+ def forward(self, x):
764
+ # x is assumed to be in range [-1,1]
765
+ return self.model.encode_image(self.preprocess(x))
766
+
767
+
768
+ if __name__ == '__main__':
769
+ from ldm.util import count_params
770
+
771
+ model = FrozenCLIPEmbedder()
772
+ count_params(model, verbose=True)