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,450 @@
1
+ '''
2
+ ldm.models.diffusion.sampler
3
+
4
+ Base class for ldm.models.diffusion.ddim, ldm.models.diffusion.ksampler, etc
5
+ '''
6
+ import torch
7
+ import numpy as np
8
+ from tqdm import tqdm
9
+ from functools import partial
10
+ from ldm.invoke.devices import choose_torch_device
11
+ from ldm.models.diffusion.shared_invokeai_diffusion import InvokeAIDiffuserComponent
12
+
13
+ from ldm.modules.diffusionmodules.util import (
14
+ make_ddim_sampling_parameters,
15
+ make_ddim_timesteps,
16
+ noise_like,
17
+ extract_into_tensor,
18
+ )
19
+
20
+ class Sampler(object):
21
+ def __init__(self, model, schedule='linear', steps=None, device=None, **kwargs):
22
+ self.model = model
23
+ self.ddim_timesteps = None
24
+ self.ddpm_num_timesteps = steps
25
+ self.schedule = schedule
26
+ self.device = device or choose_torch_device()
27
+ self.invokeai_diffuser = InvokeAIDiffuserComponent(self.model,
28
+ model_forward_callback = lambda x, sigma, cond: self.model.apply_model(x, sigma, cond))
29
+
30
+ def register_buffer(self, name, attr):
31
+ if type(attr) == torch.Tensor:
32
+ if attr.device != torch.device(self.device):
33
+ attr = attr.to(torch.float32).to(torch.device(self.device))
34
+ setattr(self, name, attr)
35
+
36
+ # This method was copied over from ddim.py and probably does stuff that is
37
+ # ddim-specific. Disentangle at some point.
38
+ def make_schedule(
39
+ self,
40
+ ddim_num_steps,
41
+ ddim_discretize='uniform',
42
+ ddim_eta=0.0,
43
+ verbose=False,
44
+ ):
45
+ self.total_steps = ddim_num_steps
46
+ self.ddim_timesteps = make_ddim_timesteps(
47
+ ddim_discr_method=ddim_discretize,
48
+ num_ddim_timesteps=ddim_num_steps,
49
+ num_ddpm_timesteps=self.ddpm_num_timesteps,
50
+ verbose=verbose,
51
+ )
52
+ alphas_cumprod = self.model.alphas_cumprod
53
+ assert (
54
+ alphas_cumprod.shape[0] == self.ddpm_num_timesteps
55
+ ), 'alphas have to be defined for each timestep'
56
+ to_torch = (
57
+ lambda x: x.clone()
58
+ .detach()
59
+ .to(torch.float32)
60
+ .to(self.model.device)
61
+ )
62
+
63
+ self.register_buffer('betas', to_torch(self.model.betas))
64
+ self.register_buffer('alphas_cumprod', to_torch(alphas_cumprod))
65
+ self.register_buffer(
66
+ 'alphas_cumprod_prev', to_torch(self.model.alphas_cumprod_prev)
67
+ )
68
+
69
+ # calculations for diffusion q(x_t | x_{t-1}) and others
70
+ self.register_buffer(
71
+ 'sqrt_alphas_cumprod', to_torch(np.sqrt(alphas_cumprod.cpu()))
72
+ )
73
+ self.register_buffer(
74
+ 'sqrt_one_minus_alphas_cumprod',
75
+ to_torch(np.sqrt(1.0 - alphas_cumprod.cpu())),
76
+ )
77
+ self.register_buffer(
78
+ 'log_one_minus_alphas_cumprod',
79
+ to_torch(np.log(1.0 - alphas_cumprod.cpu())),
80
+ )
81
+ self.register_buffer(
82
+ 'sqrt_recip_alphas_cumprod',
83
+ to_torch(np.sqrt(1.0 / alphas_cumprod.cpu())),
84
+ )
85
+ self.register_buffer(
86
+ 'sqrt_recipm1_alphas_cumprod',
87
+ to_torch(np.sqrt(1.0 / alphas_cumprod.cpu() - 1)),
88
+ )
89
+
90
+ # ddim sampling parameters
91
+ (
92
+ ddim_sigmas,
93
+ ddim_alphas,
94
+ ddim_alphas_prev,
95
+ ) = make_ddim_sampling_parameters(
96
+ alphacums=alphas_cumprod.cpu(),
97
+ ddim_timesteps=self.ddim_timesteps,
98
+ eta=ddim_eta,
99
+ verbose=verbose,
100
+ )
101
+ self.register_buffer('ddim_sigmas', ddim_sigmas)
102
+ self.register_buffer('ddim_alphas', ddim_alphas)
103
+ self.register_buffer('ddim_alphas_prev', ddim_alphas_prev)
104
+ self.register_buffer(
105
+ 'ddim_sqrt_one_minus_alphas', np.sqrt(1.0 - ddim_alphas)
106
+ )
107
+ sigmas_for_original_sampling_steps = ddim_eta * torch.sqrt(
108
+ (1 - self.alphas_cumprod_prev)
109
+ / (1 - self.alphas_cumprod)
110
+ * (1 - self.alphas_cumprod / self.alphas_cumprod_prev)
111
+ )
112
+ self.register_buffer(
113
+ 'ddim_sigmas_for_original_num_steps',
114
+ sigmas_for_original_sampling_steps,
115
+ )
116
+
117
+ @torch.no_grad()
118
+ def stochastic_encode(self, x0, t, use_original_steps=False, noise=None):
119
+ # fast, but does not allow for exact reconstruction
120
+ # t serves as an index to gather the correct alphas
121
+ if use_original_steps:
122
+ sqrt_alphas_cumprod = self.sqrt_alphas_cumprod
123
+ sqrt_one_minus_alphas_cumprod = self.sqrt_one_minus_alphas_cumprod
124
+ else:
125
+ sqrt_alphas_cumprod = torch.sqrt(self.ddim_alphas)
126
+ sqrt_one_minus_alphas_cumprod = self.ddim_sqrt_one_minus_alphas
127
+
128
+ if noise is None:
129
+ noise = torch.randn_like(x0)
130
+ return (
131
+ extract_into_tensor(sqrt_alphas_cumprod, t, x0.shape) * x0
132
+ + extract_into_tensor(sqrt_one_minus_alphas_cumprod, t, x0.shape)
133
+ * noise
134
+ )
135
+
136
+ @torch.no_grad()
137
+ def sample(
138
+ self,
139
+ S, # S is steps
140
+ batch_size,
141
+ shape,
142
+ conditioning=None,
143
+ callback=None,
144
+ normals_sequence=None,
145
+ img_callback=None, # TODO: this is very confusing because it is called "step_callback" elsewhere. Change.
146
+ quantize_x0=False,
147
+ eta=0.0,
148
+ mask=None,
149
+ x0=None,
150
+ temperature=1.0,
151
+ noise_dropout=0.0,
152
+ score_corrector=None,
153
+ corrector_kwargs=None,
154
+ verbose=False,
155
+ x_T=None,
156
+ log_every_t=100,
157
+ unconditional_guidance_scale=1.0,
158
+ unconditional_conditioning=None,
159
+ # this has to come in the same format as the conditioning, # e.g. as encoded tokens, ...
160
+ **kwargs,
161
+ ):
162
+
163
+ if conditioning is not None:
164
+ if isinstance(conditioning, dict):
165
+ ctmp = conditioning[list(conditioning.keys())[0]]
166
+ while isinstance(ctmp, list):
167
+ ctmp = ctmp[0]
168
+ cbs = ctmp.shape[0]
169
+ if cbs != batch_size:
170
+ print(f"Warning: Got {cbs} conditionings but batch-size is {batch_size}")
171
+ else:
172
+ if conditioning.shape[0] != batch_size:
173
+ print(f"Warning: Got {conditioning.shape[0]} conditionings but batch-size is {batch_size}")
174
+
175
+ # check to see if make_schedule() has run, and if not, run it
176
+ if self.ddim_timesteps is None:
177
+ self.make_schedule(
178
+ ddim_num_steps=S,
179
+ ddim_eta = eta,
180
+ verbose = False,
181
+ )
182
+
183
+ ts = self.get_timesteps(S)
184
+
185
+ # sampling
186
+ C, H, W = shape
187
+ shape = (batch_size, C, H, W)
188
+ samples, intermediates = self.do_sampling(
189
+ conditioning,
190
+ shape,
191
+ timesteps=ts,
192
+ callback=callback,
193
+ img_callback=img_callback,
194
+ quantize_denoised=quantize_x0,
195
+ mask=mask,
196
+ x0=x0,
197
+ ddim_use_original_steps=False,
198
+ noise_dropout=noise_dropout,
199
+ temperature=temperature,
200
+ score_corrector=score_corrector,
201
+ corrector_kwargs=corrector_kwargs,
202
+ x_T=x_T,
203
+ log_every_t=log_every_t,
204
+ unconditional_guidance_scale=unconditional_guidance_scale,
205
+ unconditional_conditioning=unconditional_conditioning,
206
+ steps=S,
207
+ **kwargs
208
+ )
209
+ return samples, intermediates
210
+
211
+ @torch.no_grad()
212
+ def do_sampling(
213
+ self,
214
+ cond,
215
+ shape,
216
+ timesteps=None,
217
+ x_T=None,
218
+ ddim_use_original_steps=False,
219
+ callback=None,
220
+ quantize_denoised=False,
221
+ mask=None,
222
+ x0=None,
223
+ img_callback=None,
224
+ log_every_t=100,
225
+ temperature=1.0,
226
+ noise_dropout=0.0,
227
+ score_corrector=None,
228
+ corrector_kwargs=None,
229
+ unconditional_guidance_scale=1.0,
230
+ unconditional_conditioning=None,
231
+ steps=None,
232
+ **kwargs
233
+ ):
234
+ b = shape[0]
235
+ time_range = (
236
+ list(reversed(range(0, timesteps)))
237
+ if ddim_use_original_steps
238
+ else np.flip(timesteps)
239
+ )
240
+
241
+ total_steps=steps
242
+
243
+ iterator = tqdm(
244
+ time_range,
245
+ desc=f'{self.__class__.__name__}',
246
+ total=total_steps,
247
+ dynamic_ncols=True,
248
+ )
249
+ old_eps = []
250
+ self.prepare_to_sample(t_enc=total_steps,all_timesteps_count=steps,**kwargs)
251
+ img = self.get_initial_image(x_T,shape,total_steps)
252
+
253
+ # probably don't need this at all
254
+ intermediates = {'x_inter': [img], 'pred_x0': [img]}
255
+
256
+ for i, step in enumerate(iterator):
257
+ index = total_steps - i - 1
258
+ ts = torch.full(
259
+ (b,),
260
+ step,
261
+ device=self.device,
262
+ dtype=torch.long
263
+ )
264
+ ts_next = torch.full(
265
+ (b,),
266
+ time_range[min(i + 1, len(time_range) - 1)],
267
+ device=self.device,
268
+ dtype=torch.long,
269
+ )
270
+
271
+ if mask is not None:
272
+ assert x0 is not None
273
+ img_orig = self.model.q_sample(
274
+ x0, ts
275
+ ) # TODO: deterministic forward pass?
276
+ img = img_orig * mask + (1.0 - mask) * img
277
+
278
+ outs = self.p_sample(
279
+ img,
280
+ cond,
281
+ ts,
282
+ index=index,
283
+ use_original_steps=ddim_use_original_steps,
284
+ quantize_denoised=quantize_denoised,
285
+ temperature=temperature,
286
+ noise_dropout=noise_dropout,
287
+ score_corrector=score_corrector,
288
+ corrector_kwargs=corrector_kwargs,
289
+ unconditional_guidance_scale=unconditional_guidance_scale,
290
+ unconditional_conditioning=unconditional_conditioning,
291
+ old_eps=old_eps,
292
+ t_next=ts_next,
293
+ step_count=steps
294
+ )
295
+ img, pred_x0, e_t = outs
296
+
297
+ old_eps.append(e_t)
298
+ if len(old_eps) >= 4:
299
+ old_eps.pop(0)
300
+ if callback:
301
+ callback(i)
302
+ if img_callback:
303
+ img_callback(img,i)
304
+
305
+ if index % log_every_t == 0 or index == total_steps - 1:
306
+ intermediates['x_inter'].append(img)
307
+ intermediates['pred_x0'].append(pred_x0)
308
+
309
+ return img, intermediates
310
+
311
+ # NOTE that decode() and sample() are almost the same code, and do the same thing.
312
+ # The variable names are changed in order to be confusing.
313
+ @torch.no_grad()
314
+ def decode(
315
+ self,
316
+ x_latent,
317
+ cond,
318
+ t_start,
319
+ img_callback=None,
320
+ unconditional_guidance_scale=1.0,
321
+ unconditional_conditioning=None,
322
+ use_original_steps=False,
323
+ init_latent = None,
324
+ mask = None,
325
+ all_timesteps_count = None,
326
+ **kwargs
327
+ ):
328
+ timesteps = (
329
+ np.arange(self.ddpm_num_timesteps)
330
+ if use_original_steps
331
+ else self.ddim_timesteps
332
+ )
333
+ timesteps = timesteps[:t_start]
334
+
335
+ time_range = np.flip(timesteps)
336
+ total_steps = timesteps.shape[0]
337
+ print(f'>> Running {self.__class__.__name__} sampling starting at step {self.total_steps - t_start} of {self.total_steps} ({total_steps} new sampling steps)')
338
+
339
+ iterator = tqdm(time_range, desc='Decoding image', total=total_steps)
340
+ x_dec = x_latent
341
+ x0 = init_latent
342
+ self.prepare_to_sample(t_enc=total_steps, all_timesteps_count=all_timesteps_count, **kwargs)
343
+
344
+ for i, step in enumerate(iterator):
345
+ index = total_steps - i - 1
346
+ ts = torch.full(
347
+ (x_latent.shape[0],),
348
+ step,
349
+ device=x_latent.device,
350
+ dtype=torch.long,
351
+ )
352
+
353
+ ts_next = torch.full(
354
+ (x_latent.shape[0],),
355
+ time_range[min(i + 1, len(time_range) - 1)],
356
+ device=self.device,
357
+ dtype=torch.long,
358
+ )
359
+
360
+ if mask is not None:
361
+ assert x0 is not None
362
+ xdec_orig = self.q_sample(x0, ts) # TODO: deterministic forward pass?
363
+ x_dec = xdec_orig * mask + (1.0 - mask) * x_dec
364
+
365
+ outs = self.p_sample(
366
+ x_dec,
367
+ cond,
368
+ ts,
369
+ index=index,
370
+ use_original_steps=use_original_steps,
371
+ unconditional_guidance_scale=unconditional_guidance_scale,
372
+ unconditional_conditioning=unconditional_conditioning,
373
+ t_next = ts_next,
374
+ step_count=len(self.ddim_timesteps)
375
+ )
376
+
377
+ x_dec, pred_x0, e_t = outs
378
+ if img_callback:
379
+ img_callback(x_dec,i)
380
+
381
+ return x_dec
382
+
383
+ def get_initial_image(self,x_T,shape,timesteps=None):
384
+ if x_T is None:
385
+ return torch.randn(shape, device=self.device)
386
+ else:
387
+ return x_T
388
+
389
+ def p_sample(
390
+ self,
391
+ img,
392
+ cond,
393
+ ts,
394
+ index,
395
+ repeat_noise=False,
396
+ use_original_steps=False,
397
+ quantize_denoised=False,
398
+ temperature=1.0,
399
+ noise_dropout=0.0,
400
+ score_corrector=None,
401
+ corrector_kwargs=None,
402
+ unconditional_guidance_scale=1.0,
403
+ unconditional_conditioning=None,
404
+ old_eps=None,
405
+ t_next=None,
406
+ steps=None,
407
+ ):
408
+ raise NotImplementedError("p_sample() must be implemented in a descendent class")
409
+
410
+ def prepare_to_sample(self,t_enc,**kwargs):
411
+ '''
412
+ Hook that will be called right before the very first invocation of p_sample()
413
+ to allow subclass to do additional initialization. t_enc corresponds to the actual
414
+ number of steps that will be run, and may be less than total steps if img2img is
415
+ active.
416
+ '''
417
+ pass
418
+
419
+ def get_timesteps(self,ddim_steps):
420
+ '''
421
+ The ddim and plms samplers work on timesteps. This method is called after
422
+ ddim_timesteps are created in make_schedule(), and selects the portion of
423
+ timesteps that will be used for sampling, depending on the t_enc in img2img.
424
+ '''
425
+ return self.ddim_timesteps[:ddim_steps]
426
+
427
+ def q_sample(self,x0,ts):
428
+ '''
429
+ Returns self.model.q_sample(x0,ts). Is overridden in the k* samplers to
430
+ return self.model.inner_model.q_sample(x0,ts)
431
+ '''
432
+ return self.model.q_sample(x0,ts)
433
+
434
+ def conditioning_key(self)->str:
435
+ return self.model.model.conditioning_key
436
+
437
+ def uses_inpainting_model(self)->bool:
438
+ return self.conditioning_key() in ('hybrid','concat')
439
+
440
+ def adjust_settings(self,**kwargs):
441
+ '''
442
+ This is a catch-all method for adjusting any instance variables
443
+ after the sampler is instantiated. No type-checking performed
444
+ here, so use with care!
445
+ '''
446
+ for k in kwargs.keys():
447
+ try:
448
+ setattr(self,k,kwargs[k])
449
+ except AttributeError:
450
+ print(f'** Warning: attempt to set unknown attribute {k} in sampler of type {type(self)}')
@@ -0,0 +1,244 @@
1
+ import traceback
2
+ from math import ceil
3
+ from typing import Callable, Optional, Union
4
+
5
+ import torch
6
+
7
+ from ldm.models.diffusion.cross_attention_control import Arguments, \
8
+ remove_cross_attention_control, setup_cross_attention_control, Context, get_cross_attention_modules, CrossAttentionType
9
+ from ldm.models.diffusion.cross_attention_map_saving import AttentionMapSaver
10
+
11
+
12
+ class InvokeAIDiffuserComponent:
13
+ '''
14
+ The aim of this component is to provide a single place for code that can be applied identically to
15
+ all InvokeAI diffusion procedures.
16
+
17
+ At the moment it includes the following features:
18
+ * Cross attention control ("prompt2prompt")
19
+ * Hybrid conditioning (used for inpainting)
20
+ '''
21
+
22
+
23
+ class ExtraConditioningInfo:
24
+ def __init__(self, tokens_count_including_eos_bos:int, cross_attention_control_args: Optional[Arguments]):
25
+ self.tokens_count_including_eos_bos = tokens_count_including_eos_bos
26
+ self.cross_attention_control_args = cross_attention_control_args
27
+
28
+ @property
29
+ def wants_cross_attention_control(self):
30
+ return self.cross_attention_control_args is not None
31
+
32
+ def __init__(self, model, model_forward_callback:
33
+ Callable[[torch.Tensor, torch.Tensor, torch.Tensor], torch.Tensor]
34
+ ):
35
+ """
36
+ :param model: the unet model to pass through to cross attention control
37
+ :param model_forward_callback: a lambda with arguments (x, sigma, conditioning_to_apply). will be called repeatedly. most likely, this should simply call model.forward(x, sigma, conditioning)
38
+ """
39
+ self.model = model
40
+ self.model_forward_callback = model_forward_callback
41
+ self.cross_attention_control_context = None
42
+
43
+ def setup_cross_attention_control(self, conditioning: ExtraConditioningInfo, step_count: int):
44
+ self.conditioning = conditioning
45
+ self.cross_attention_control_context = Context(
46
+ arguments=self.conditioning.cross_attention_control_args,
47
+ step_count=step_count
48
+ )
49
+ setup_cross_attention_control(self.model, self.cross_attention_control_context)
50
+
51
+ def remove_cross_attention_control(self):
52
+ self.conditioning = None
53
+ self.cross_attention_control_context = None
54
+ remove_cross_attention_control(self.model)
55
+
56
+ def setup_attention_map_saving(self, saver: AttentionMapSaver):
57
+ def callback(slice, dim, offset, slice_size, key):
58
+ if dim is not None:
59
+ # sliced tokens attention map saving is not implemented
60
+ return
61
+ saver.add_attention_maps(slice, key)
62
+
63
+ tokens_cross_attention_modules = get_cross_attention_modules(self.model, CrossAttentionType.TOKENS)
64
+ for identifier, module in tokens_cross_attention_modules:
65
+ key = ('down' if identifier.startswith('down') else
66
+ 'up' if identifier.startswith('up') else
67
+ 'mid')
68
+ module.set_attention_slice_calculated_callback(
69
+ lambda slice, dim, offset, slice_size, key=key: callback(slice, dim, offset, slice_size, key))
70
+
71
+ def remove_attention_map_saving(self):
72
+ tokens_cross_attention_modules = get_cross_attention_modules(self.model, CrossAttentionType.TOKENS)
73
+ for _, module in tokens_cross_attention_modules:
74
+ module.set_attention_slice_calculated_callback(None)
75
+
76
+ def do_diffusion_step(self, x: torch.Tensor, sigma: torch.Tensor,
77
+ unconditioning: Union[torch.Tensor,dict],
78
+ conditioning: Union[torch.Tensor,dict],
79
+ unconditional_guidance_scale: float,
80
+ step_index: Optional[int]=None
81
+ ):
82
+ """
83
+ :param x: current latents
84
+ :param sigma: aka t, passed to the internal model to control how much denoising will occur
85
+ :param unconditioning: embeddings for unconditioned output. for hybrid conditioning this is a dict of tensors [B x 77 x 768], otherwise a single tensor [B x 77 x 768]
86
+ :param conditioning: embeddings for conditioned output. for hybrid conditioning this is a dict of tensors [B x 77 x 768], otherwise a single tensor [B x 77 x 768]
87
+ :param unconditional_guidance_scale: aka CFG scale, controls how much effect the conditioning tensor has
88
+ :param step_index: counts upwards from 0 to (step_count-1) (as passed to setup_cross_attention_control, if using). May be called multiple times for a single step, therefore do not assume that its value will monotically increase. If None, will be estimated by comparing sigma against self.model.sigmas .
89
+ :return: the new latents after applying the model to x using unscaled unconditioning and CFG-scaled conditioning.
90
+ """
91
+
92
+
93
+ cross_attention_control_types_to_do = []
94
+ context: Context = self.cross_attention_control_context
95
+ if self.cross_attention_control_context is not None:
96
+ percent_through = self.estimate_percent_through(step_index, sigma)
97
+ cross_attention_control_types_to_do = context.get_active_cross_attention_control_types_for_step(percent_through)
98
+
99
+ wants_cross_attention_control = (len(cross_attention_control_types_to_do) > 0)
100
+ wants_hybrid_conditioning = isinstance(conditioning, dict)
101
+
102
+ if wants_hybrid_conditioning:
103
+ unconditioned_next_x, conditioned_next_x = self.apply_hybrid_conditioning(x, sigma, unconditioning, conditioning)
104
+ elif wants_cross_attention_control:
105
+ unconditioned_next_x, conditioned_next_x = self.apply_cross_attention_controlled_conditioning(x, sigma, unconditioning, conditioning, cross_attention_control_types_to_do)
106
+ else:
107
+ unconditioned_next_x, conditioned_next_x = self.apply_standard_conditioning(x, sigma, unconditioning, conditioning)
108
+
109
+ # to scale how much effect conditioning has, calculate the changes it does and then scale that
110
+ scaled_delta = (conditioned_next_x - unconditioned_next_x) * unconditional_guidance_scale
111
+ combined_next_x = unconditioned_next_x + scaled_delta
112
+
113
+ return combined_next_x
114
+
115
+
116
+ # methods below are called from do_diffusion_step and should be considered private to this class.
117
+
118
+ def apply_standard_conditioning(self, x, sigma, unconditioning, conditioning):
119
+ # fast batched path
120
+ x_twice = torch.cat([x] * 2)
121
+ sigma_twice = torch.cat([sigma] * 2)
122
+ both_conditionings = torch.cat([unconditioning, conditioning])
123
+ unconditioned_next_x, conditioned_next_x = self.model_forward_callback(x_twice, sigma_twice,
124
+ both_conditionings).chunk(2)
125
+ return unconditioned_next_x, conditioned_next_x
126
+
127
+
128
+ def apply_hybrid_conditioning(self, x, sigma, unconditioning, conditioning):
129
+ assert isinstance(conditioning, dict)
130
+ assert isinstance(unconditioning, dict)
131
+ x_twice = torch.cat([x] * 2)
132
+ sigma_twice = torch.cat([sigma] * 2)
133
+ both_conditionings = dict()
134
+ for k in conditioning:
135
+ if isinstance(conditioning[k], list):
136
+ both_conditionings[k] = [
137
+ torch.cat([unconditioning[k][i], conditioning[k][i]])
138
+ for i in range(len(conditioning[k]))
139
+ ]
140
+ else:
141
+ both_conditionings[k] = torch.cat([unconditioning[k], conditioning[k]])
142
+ unconditioned_next_x, conditioned_next_x = self.model_forward_callback(x_twice, sigma_twice, both_conditionings).chunk(2)
143
+ return unconditioned_next_x, conditioned_next_x
144
+
145
+
146
+ def apply_cross_attention_controlled_conditioning(self, x:torch.Tensor, sigma, unconditioning, conditioning, cross_attention_control_types_to_do):
147
+ # print('pct', percent_through, ': doing cross attention control on', cross_attention_control_types_to_do)
148
+ # slower non-batched path (20% slower on mac MPS)
149
+ # We are only interested in using attention maps for conditioned_next_x, but batching them with generation of
150
+ # unconditioned_next_x causes attention maps to *also* be saved for the unconditioned_next_x.
151
+ # This messes app their application later, due to mismatched shape of dim 0 (seems to be 16 for batched vs. 8)
152
+ # (For the batched invocation the `wrangler` function gets attention tensor with shape[0]=16,
153
+ # representing batched uncond + cond, but then when it comes to applying the saved attention, the
154
+ # wrangler gets an attention tensor which only has shape[0]=8, representing just self.edited_conditionings.)
155
+ # todo: give CrossAttentionControl's `wrangler` function more info so it can work with a batched call as well.
156
+ context:Context = self.cross_attention_control_context
157
+
158
+ try:
159
+ unconditioned_next_x = self.model_forward_callback(x, sigma, unconditioning)
160
+
161
+ # process x using the original prompt, saving the attention maps
162
+ #print("saving attention maps for", cross_attention_control_types_to_do)
163
+ for ca_type in cross_attention_control_types_to_do:
164
+ context.request_save_attention_maps(ca_type)
165
+ _ = self.model_forward_callback(x, sigma, conditioning)
166
+ context.clear_requests(cleanup=False)
167
+
168
+ # process x again, using the saved attention maps to control where self.edited_conditioning will be applied
169
+ #print("applying saved attention maps for", cross_attention_control_types_to_do)
170
+ for ca_type in cross_attention_control_types_to_do:
171
+ context.request_apply_saved_attention_maps(ca_type)
172
+ edited_conditioning = self.conditioning.cross_attention_control_args.edited_conditioning
173
+ conditioned_next_x = self.model_forward_callback(x, sigma, edited_conditioning)
174
+ context.clear_requests(cleanup=True)
175
+
176
+ except:
177
+ context.clear_requests(cleanup=True)
178
+ raise
179
+
180
+ return unconditioned_next_x, conditioned_next_x
181
+
182
+ def estimate_percent_through(self, step_index, sigma):
183
+ if step_index is not None and self.cross_attention_control_context is not None:
184
+ # percent_through will never reach 1.0 (but this is intended)
185
+ return float(step_index) / float(self.cross_attention_control_context.step_count)
186
+ # find the best possible index of the current sigma in the sigma sequence
187
+ smaller_sigmas = torch.nonzero(self.model.sigmas <= sigma)
188
+ sigma_index = smaller_sigmas[-1].item() if smaller_sigmas.shape[0] > 0 else 0
189
+ # flip because sigmas[0] is for the fully denoised image
190
+ # percent_through must be <1
191
+ return 1.0 - float(sigma_index + 1) / float(self.model.sigmas.shape[0])
192
+ # print('estimated percent_through', percent_through, 'from sigma', sigma.item())
193
+
194
+
195
+ # todo: make this work
196
+ @classmethod
197
+ def apply_conjunction(cls, x, t, forward_func, uc, c_or_weighted_c_list, global_guidance_scale):
198
+ x_in = torch.cat([x] * 2)
199
+ t_in = torch.cat([t] * 2) # aka sigmas
200
+
201
+ deltas = None
202
+ uncond_latents = None
203
+ weighted_cond_list = c_or_weighted_c_list if type(c_or_weighted_c_list) is list else [(c_or_weighted_c_list, 1)]
204
+
205
+ # below is fugly omg
206
+ num_actual_conditionings = len(c_or_weighted_c_list)
207
+ conditionings = [uc] + [c for c,weight in weighted_cond_list]
208
+ weights = [1] + [weight for c,weight in weighted_cond_list]
209
+ chunk_count = ceil(len(conditionings)/2)
210
+ deltas = None
211
+ for chunk_index in range(chunk_count):
212
+ offset = chunk_index*2
213
+ chunk_size = min(2, len(conditionings)-offset)
214
+
215
+ if chunk_size == 1:
216
+ c_in = conditionings[offset]
217
+ latents_a = forward_func(x_in[:-1], t_in[:-1], c_in)
218
+ latents_b = None
219
+ else:
220
+ c_in = torch.cat(conditionings[offset:offset+2])
221
+ latents_a, latents_b = forward_func(x_in, t_in, c_in).chunk(2)
222
+
223
+ # first chunk is guaranteed to be 2 entries: uncond_latents + first conditioining
224
+ if chunk_index == 0:
225
+ uncond_latents = latents_a
226
+ deltas = latents_b - uncond_latents
227
+ else:
228
+ deltas = torch.cat((deltas, latents_a - uncond_latents))
229
+ if latents_b is not None:
230
+ deltas = torch.cat((deltas, latents_b - uncond_latents))
231
+
232
+ # merge the weighted deltas together into a single merged delta
233
+ per_delta_weights = torch.tensor(weights[1:], dtype=deltas.dtype, device=deltas.device)
234
+ normalize = False
235
+ if normalize:
236
+ per_delta_weights /= torch.sum(per_delta_weights)
237
+ reshaped_weights = per_delta_weights.reshape(per_delta_weights.shape + (1, 1, 1))
238
+ deltas_merged = torch.sum(deltas * reshaped_weights, dim=0, keepdim=True)
239
+
240
+ # old_return_value = super().forward(x, sigma, uncond, cond, cond_scale)
241
+ # assert(0 == len(torch.nonzero(old_return_value - (uncond_latents + deltas_merged * cond_scale))))
242
+
243
+ return uncond_latents + deltas_merged * global_guidance_scale
244
+
File without changes