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,312 @@
|
|
|
1
|
+
"""wrapper around part of Katherine Crowson's k-diffusion library, making it call compatible with other Samplers"""
|
|
2
|
+
|
|
3
|
+
import k_diffusion as K
|
|
4
|
+
import torch
|
|
5
|
+
from torch import nn
|
|
6
|
+
|
|
7
|
+
from .cross_attention_map_saving import AttentionMapSaver
|
|
8
|
+
from .sampler import Sampler
|
|
9
|
+
from .shared_invokeai_diffusion import InvokeAIDiffuserComponent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# at this threshold, the scheduler will stop using the Karras
|
|
13
|
+
# noise schedule and start using the model's schedule
|
|
14
|
+
STEP_THRESHOLD = 30
|
|
15
|
+
|
|
16
|
+
def cfg_apply_threshold(result, threshold = 0.0, scale = 0.7):
|
|
17
|
+
if threshold <= 0.0:
|
|
18
|
+
return result
|
|
19
|
+
maxval = 0.0 + torch.max(result).cpu().numpy()
|
|
20
|
+
minval = 0.0 + torch.min(result).cpu().numpy()
|
|
21
|
+
if maxval < threshold and minval > -threshold:
|
|
22
|
+
return result
|
|
23
|
+
if maxval > threshold:
|
|
24
|
+
maxval = min(max(1, scale*maxval), threshold)
|
|
25
|
+
if minval < -threshold:
|
|
26
|
+
minval = max(min(-1, scale*minval), -threshold)
|
|
27
|
+
return torch.clamp(result, min=minval, max=maxval)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CFGDenoiser(nn.Module):
|
|
31
|
+
def __init__(self, model, threshold = 0, warmup = 0):
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.inner_model = model
|
|
34
|
+
self.threshold = threshold
|
|
35
|
+
self.warmup_max = warmup
|
|
36
|
+
self.warmup = max(warmup / 10, 1)
|
|
37
|
+
self.invokeai_diffuser = InvokeAIDiffuserComponent(model,
|
|
38
|
+
model_forward_callback=lambda x, sigma, cond: self.inner_model(x, sigma, cond=cond))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def prepare_to_sample(self, t_enc, **kwargs):
|
|
42
|
+
|
|
43
|
+
extra_conditioning_info = kwargs.get('extra_conditioning_info', None)
|
|
44
|
+
|
|
45
|
+
if extra_conditioning_info is not None and extra_conditioning_info.wants_cross_attention_control:
|
|
46
|
+
self.invokeai_diffuser.setup_cross_attention_control(extra_conditioning_info, step_count = t_enc)
|
|
47
|
+
else:
|
|
48
|
+
self.invokeai_diffuser.remove_cross_attention_control()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def forward(self, x, sigma, uncond, cond, cond_scale):
|
|
52
|
+
next_x = self.invokeai_diffuser.do_diffusion_step(x, sigma, uncond, cond, cond_scale)
|
|
53
|
+
if self.warmup < self.warmup_max:
|
|
54
|
+
thresh = max(1, 1 + (self.threshold - 1) * (self.warmup / self.warmup_max))
|
|
55
|
+
self.warmup += 1
|
|
56
|
+
else:
|
|
57
|
+
thresh = self.threshold
|
|
58
|
+
if thresh > self.threshold:
|
|
59
|
+
thresh = self.threshold
|
|
60
|
+
return cfg_apply_threshold(next_x, thresh)
|
|
61
|
+
|
|
62
|
+
class KSampler(Sampler):
|
|
63
|
+
def __init__(self, model, schedule='lms', device=None, **kwargs):
|
|
64
|
+
denoiser = K.external.CompVisDenoiser(model)
|
|
65
|
+
super().__init__(
|
|
66
|
+
denoiser,
|
|
67
|
+
schedule,
|
|
68
|
+
steps=model.num_timesteps,
|
|
69
|
+
)
|
|
70
|
+
self.sigmas = None
|
|
71
|
+
self.ds = None
|
|
72
|
+
self.s_in = None
|
|
73
|
+
self.karras_max = kwargs.get('karras_max',STEP_THRESHOLD)
|
|
74
|
+
if self.karras_max is None:
|
|
75
|
+
self.karras_max = STEP_THRESHOLD
|
|
76
|
+
|
|
77
|
+
def make_schedule(
|
|
78
|
+
self,
|
|
79
|
+
ddim_num_steps,
|
|
80
|
+
ddim_discretize='uniform',
|
|
81
|
+
ddim_eta=0.0,
|
|
82
|
+
verbose=False,
|
|
83
|
+
):
|
|
84
|
+
outer_model = self.model
|
|
85
|
+
self.model = outer_model.inner_model
|
|
86
|
+
super().make_schedule(
|
|
87
|
+
ddim_num_steps,
|
|
88
|
+
ddim_discretize='uniform',
|
|
89
|
+
ddim_eta=0.0,
|
|
90
|
+
verbose=False,
|
|
91
|
+
)
|
|
92
|
+
self.model = outer_model
|
|
93
|
+
self.ddim_num_steps = ddim_num_steps
|
|
94
|
+
# we don't need both of these sigmas, but storing them here to make
|
|
95
|
+
# comparison easier later on
|
|
96
|
+
self.model_sigmas = self.model.get_sigmas(ddim_num_steps)
|
|
97
|
+
self.karras_sigmas = K.sampling.get_sigmas_karras(
|
|
98
|
+
n=ddim_num_steps,
|
|
99
|
+
sigma_min=self.model.sigmas[0].item(),
|
|
100
|
+
sigma_max=self.model.sigmas[-1].item(),
|
|
101
|
+
rho=7.,
|
|
102
|
+
device=self.device,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if ddim_num_steps >= self.karras_max:
|
|
106
|
+
print(f'>> Ksampler using model noise schedule (steps >= {self.karras_max})')
|
|
107
|
+
self.sigmas = self.model_sigmas
|
|
108
|
+
else:
|
|
109
|
+
print(f'>> Ksampler using karras noise schedule (steps < {self.karras_max})')
|
|
110
|
+
self.sigmas = self.karras_sigmas
|
|
111
|
+
|
|
112
|
+
# ALERT: We are completely overriding the sample() method in the base class, which
|
|
113
|
+
# means that inpainting will not work. To get this to work we need to be able to
|
|
114
|
+
# modify the inner loop of k_heun, k_lms, etc, as is done in an ugly way
|
|
115
|
+
# in the lstein/k-diffusion branch.
|
|
116
|
+
|
|
117
|
+
@torch.no_grad()
|
|
118
|
+
def decode(
|
|
119
|
+
self,
|
|
120
|
+
z_enc,
|
|
121
|
+
cond,
|
|
122
|
+
t_enc,
|
|
123
|
+
img_callback=None,
|
|
124
|
+
unconditional_guidance_scale=1.0,
|
|
125
|
+
unconditional_conditioning=None,
|
|
126
|
+
use_original_steps=False,
|
|
127
|
+
init_latent = None,
|
|
128
|
+
mask = None,
|
|
129
|
+
**kwargs
|
|
130
|
+
):
|
|
131
|
+
samples,_ = self.sample(
|
|
132
|
+
batch_size = 1,
|
|
133
|
+
S = t_enc,
|
|
134
|
+
x_T = z_enc,
|
|
135
|
+
shape = z_enc.shape[1:],
|
|
136
|
+
conditioning = cond,
|
|
137
|
+
unconditional_guidance_scale=unconditional_guidance_scale,
|
|
138
|
+
unconditional_conditioning = unconditional_conditioning,
|
|
139
|
+
img_callback = img_callback,
|
|
140
|
+
x0 = init_latent,
|
|
141
|
+
mask = mask,
|
|
142
|
+
**kwargs
|
|
143
|
+
)
|
|
144
|
+
return samples
|
|
145
|
+
|
|
146
|
+
# this is a no-op, provided here for compatibility with ddim and plms samplers
|
|
147
|
+
@torch.no_grad()
|
|
148
|
+
def stochastic_encode(self, x0, t, use_original_steps=False, noise=None):
|
|
149
|
+
return x0
|
|
150
|
+
|
|
151
|
+
# Most of these arguments are ignored and are only present for compatibility with
|
|
152
|
+
# other samples
|
|
153
|
+
@torch.no_grad()
|
|
154
|
+
def sample(
|
|
155
|
+
self,
|
|
156
|
+
S,
|
|
157
|
+
batch_size,
|
|
158
|
+
shape,
|
|
159
|
+
conditioning=None,
|
|
160
|
+
callback=None,
|
|
161
|
+
normals_sequence=None,
|
|
162
|
+
img_callback=None,
|
|
163
|
+
attention_maps_callback=None,
|
|
164
|
+
quantize_x0=False,
|
|
165
|
+
eta=0.0,
|
|
166
|
+
mask=None,
|
|
167
|
+
x0=None,
|
|
168
|
+
temperature=1.0,
|
|
169
|
+
noise_dropout=0.0,
|
|
170
|
+
score_corrector=None,
|
|
171
|
+
corrector_kwargs=None,
|
|
172
|
+
verbose=True,
|
|
173
|
+
x_T=None,
|
|
174
|
+
log_every_t=100,
|
|
175
|
+
unconditional_guidance_scale=1.0,
|
|
176
|
+
unconditional_conditioning=None,
|
|
177
|
+
extra_conditioning_info: InvokeAIDiffuserComponent.ExtraConditioningInfo=None,
|
|
178
|
+
threshold = 0,
|
|
179
|
+
perlin = 0,
|
|
180
|
+
# this has to come in the same format as the conditioning, # e.g. as encoded tokens, ...
|
|
181
|
+
**kwargs,
|
|
182
|
+
):
|
|
183
|
+
def route_callback(k_callback_values):
|
|
184
|
+
if img_callback is not None:
|
|
185
|
+
img_callback(k_callback_values['x'],k_callback_values['i'])
|
|
186
|
+
|
|
187
|
+
# if make_schedule() hasn't been called, we do it now
|
|
188
|
+
if self.sigmas is None:
|
|
189
|
+
self.make_schedule(
|
|
190
|
+
ddim_num_steps=S,
|
|
191
|
+
ddim_eta = eta,
|
|
192
|
+
verbose = False,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# sigmas are set up in make_schedule - we take the last steps items
|
|
196
|
+
sigmas = self.sigmas[-S-1:]
|
|
197
|
+
|
|
198
|
+
# x_T is variation noise. When an init image is provided (in x0) we need to add
|
|
199
|
+
# more randomness to the starting image.
|
|
200
|
+
if x_T is not None:
|
|
201
|
+
if x0 is not None:
|
|
202
|
+
x = x_T + torch.randn_like(x0, device=self.device) * sigmas[0]
|
|
203
|
+
else:
|
|
204
|
+
x = x_T * sigmas[0]
|
|
205
|
+
else:
|
|
206
|
+
x = torch.randn([batch_size, *shape], device=self.device) * sigmas[0]
|
|
207
|
+
|
|
208
|
+
model_wrap_cfg = CFGDenoiser(self.model, threshold=threshold, warmup=max(0.8*S,S-10))
|
|
209
|
+
model_wrap_cfg.prepare_to_sample(S, extra_conditioning_info=extra_conditioning_info)
|
|
210
|
+
|
|
211
|
+
# setup attention maps saving. checks for None are because there are multiple code paths to get here.
|
|
212
|
+
attention_maps_saver = None
|
|
213
|
+
if attention_maps_callback is not None and extra_conditioning_info is not None:
|
|
214
|
+
eos_token_index = extra_conditioning_info.tokens_count_including_eos_bos - 1
|
|
215
|
+
attention_map_token_ids = range(1, eos_token_index)
|
|
216
|
+
attention_maps_saver = AttentionMapSaver(token_ids = attention_map_token_ids, latents_shape=x.shape[-2:])
|
|
217
|
+
model_wrap_cfg.invokeai_diffuser.setup_attention_map_saving(attention_maps_saver)
|
|
218
|
+
|
|
219
|
+
extra_args = {
|
|
220
|
+
'cond': conditioning,
|
|
221
|
+
'uncond': unconditional_conditioning,
|
|
222
|
+
'cond_scale': unconditional_guidance_scale,
|
|
223
|
+
}
|
|
224
|
+
print(f'>> Sampling with k_{self.schedule} starting at step {len(self.sigmas)-S-1} of {len(self.sigmas)-1} ({S} new sampling steps)')
|
|
225
|
+
sampling_result = (
|
|
226
|
+
K.sampling.__dict__[f'sample_{self.schedule}'](
|
|
227
|
+
model_wrap_cfg, x, sigmas, extra_args=extra_args,
|
|
228
|
+
callback=route_callback
|
|
229
|
+
),
|
|
230
|
+
None,
|
|
231
|
+
)
|
|
232
|
+
if attention_maps_saver is not None:
|
|
233
|
+
attention_maps_callback(attention_maps_saver)
|
|
234
|
+
return sampling_result
|
|
235
|
+
|
|
236
|
+
# this code will support inpainting if and when ksampler API modified or
|
|
237
|
+
# a workaround is found.
|
|
238
|
+
@torch.no_grad()
|
|
239
|
+
def p_sample(
|
|
240
|
+
self,
|
|
241
|
+
img,
|
|
242
|
+
cond,
|
|
243
|
+
ts,
|
|
244
|
+
index,
|
|
245
|
+
unconditional_guidance_scale=1.0,
|
|
246
|
+
unconditional_conditioning=None,
|
|
247
|
+
extra_conditioning_info=None,
|
|
248
|
+
**kwargs,
|
|
249
|
+
):
|
|
250
|
+
if self.model_wrap is None:
|
|
251
|
+
self.model_wrap = CFGDenoiser(self.model)
|
|
252
|
+
extra_args = {
|
|
253
|
+
'cond': cond,
|
|
254
|
+
'uncond': unconditional_conditioning,
|
|
255
|
+
'cond_scale': unconditional_guidance_scale,
|
|
256
|
+
}
|
|
257
|
+
if self.s_in is None:
|
|
258
|
+
self.s_in = img.new_ones([img.shape[0]])
|
|
259
|
+
if self.ds is None:
|
|
260
|
+
self.ds = []
|
|
261
|
+
|
|
262
|
+
# terrible, confusing names here
|
|
263
|
+
steps = self.ddim_num_steps
|
|
264
|
+
t_enc = self.t_enc
|
|
265
|
+
|
|
266
|
+
# sigmas is a full steps in length, but t_enc might
|
|
267
|
+
# be less. We start in the middle of the sigma array
|
|
268
|
+
# and work our way to the end after t_enc steps.
|
|
269
|
+
# index starts at t_enc and works its way to zero,
|
|
270
|
+
# so the actual formula for indexing into sigmas:
|
|
271
|
+
# sigma_index = (steps-index)
|
|
272
|
+
s_index = t_enc - index - 1
|
|
273
|
+
self.model_wrap.prepare_to_sample(s_index, extra_conditioning_info=extra_conditioning_info)
|
|
274
|
+
img = K.sampling.__dict__[f'_{self.schedule}'](
|
|
275
|
+
self.model_wrap,
|
|
276
|
+
img,
|
|
277
|
+
self.sigmas,
|
|
278
|
+
s_index,
|
|
279
|
+
s_in = self.s_in,
|
|
280
|
+
ds = self.ds,
|
|
281
|
+
extra_args=extra_args,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return img, None, None
|
|
285
|
+
|
|
286
|
+
# REVIEW THIS METHOD: it has never been tested. In particular,
|
|
287
|
+
# we should not be multiplying by self.sigmas[0] if we
|
|
288
|
+
# are at an intermediate step in img2img. See similar in
|
|
289
|
+
# sample() which does work.
|
|
290
|
+
def get_initial_image(self,x_T,shape,steps):
|
|
291
|
+
print(f'WARNING: ksampler.get_initial_image(): get_initial_image needs testing')
|
|
292
|
+
x = (torch.randn(shape, device=self.device) * self.sigmas[0])
|
|
293
|
+
if x_T is not None:
|
|
294
|
+
return x_T + x
|
|
295
|
+
else:
|
|
296
|
+
return x
|
|
297
|
+
|
|
298
|
+
def prepare_to_sample(self,t_enc,**kwargs):
|
|
299
|
+
self.t_enc = t_enc
|
|
300
|
+
self.model_wrap = None
|
|
301
|
+
self.ds = None
|
|
302
|
+
self.s_in = None
|
|
303
|
+
|
|
304
|
+
def q_sample(self,x0,ts):
|
|
305
|
+
'''
|
|
306
|
+
Overrides parent method to return the q_sample of the inner model.
|
|
307
|
+
'''
|
|
308
|
+
return self.model.inner_model.q_sample(x0,ts)
|
|
309
|
+
|
|
310
|
+
def conditioning_key(self)->str:
|
|
311
|
+
return self.model.inner_model.model.conditioning_key
|
|
312
|
+
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""SAMPLING ONLY."""
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
import numpy as np
|
|
5
|
+
from tqdm import tqdm
|
|
6
|
+
from functools import partial
|
|
7
|
+
from ldm.invoke.devices import choose_torch_device
|
|
8
|
+
from ldm.models.diffusion.shared_invokeai_diffusion import InvokeAIDiffuserComponent
|
|
9
|
+
from ldm.models.diffusion.sampler import Sampler
|
|
10
|
+
from ldm.modules.diffusionmodules.util import noise_like
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PLMSSampler(Sampler):
|
|
14
|
+
def __init__(self, model, schedule='linear', device=None, **kwargs):
|
|
15
|
+
super().__init__(model,schedule,model.num_timesteps, device)
|
|
16
|
+
|
|
17
|
+
def prepare_to_sample(self, t_enc, **kwargs):
|
|
18
|
+
super().prepare_to_sample(t_enc, **kwargs)
|
|
19
|
+
|
|
20
|
+
extra_conditioning_info = kwargs.get('extra_conditioning_info', None)
|
|
21
|
+
all_timesteps_count = kwargs.get('all_timesteps_count', t_enc)
|
|
22
|
+
|
|
23
|
+
if extra_conditioning_info is not None and extra_conditioning_info.wants_cross_attention_control:
|
|
24
|
+
self.invokeai_diffuser.setup_cross_attention_control(extra_conditioning_info, step_count = all_timesteps_count)
|
|
25
|
+
else:
|
|
26
|
+
self.invokeai_diffuser.remove_cross_attention_control()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# this is the essential routine
|
|
30
|
+
@torch.no_grad()
|
|
31
|
+
def p_sample(
|
|
32
|
+
self,
|
|
33
|
+
x, # image, called 'img' elsewhere
|
|
34
|
+
c, # conditioning, called 'cond' elsewhere
|
|
35
|
+
t, # timesteps, called 'ts' elsewhere
|
|
36
|
+
index,
|
|
37
|
+
repeat_noise=False,
|
|
38
|
+
use_original_steps=False,
|
|
39
|
+
quantize_denoised=False,
|
|
40
|
+
temperature=1.0,
|
|
41
|
+
noise_dropout=0.0,
|
|
42
|
+
score_corrector=None,
|
|
43
|
+
corrector_kwargs=None,
|
|
44
|
+
unconditional_guidance_scale=1.0,
|
|
45
|
+
unconditional_conditioning=None,
|
|
46
|
+
old_eps=[],
|
|
47
|
+
t_next=None,
|
|
48
|
+
step_count:int=1000, # total number of steps
|
|
49
|
+
**kwargs,
|
|
50
|
+
):
|
|
51
|
+
b, *_, device = *x.shape, x.device
|
|
52
|
+
|
|
53
|
+
def get_model_output(x, t):
|
|
54
|
+
if (
|
|
55
|
+
unconditional_conditioning is None
|
|
56
|
+
or unconditional_guidance_scale == 1.0
|
|
57
|
+
):
|
|
58
|
+
# damian0815 would like to know when/if this code path is used
|
|
59
|
+
e_t = self.model.apply_model(x, t, c)
|
|
60
|
+
else:
|
|
61
|
+
# step_index counts in the opposite direction to index
|
|
62
|
+
step_index = step_count-(index+1)
|
|
63
|
+
e_t = self.invokeai_diffuser.do_diffusion_step(x, t,
|
|
64
|
+
unconditional_conditioning, c,
|
|
65
|
+
unconditional_guidance_scale,
|
|
66
|
+
step_index=step_index)
|
|
67
|
+
if score_corrector is not None:
|
|
68
|
+
assert self.model.parameterization == 'eps'
|
|
69
|
+
e_t = score_corrector.modify_score(
|
|
70
|
+
self.model, e_t, x, t, c, **corrector_kwargs
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return e_t
|
|
74
|
+
|
|
75
|
+
alphas = (
|
|
76
|
+
self.model.alphas_cumprod
|
|
77
|
+
if use_original_steps
|
|
78
|
+
else self.ddim_alphas
|
|
79
|
+
)
|
|
80
|
+
alphas_prev = (
|
|
81
|
+
self.model.alphas_cumprod_prev
|
|
82
|
+
if use_original_steps
|
|
83
|
+
else self.ddim_alphas_prev
|
|
84
|
+
)
|
|
85
|
+
sqrt_one_minus_alphas = (
|
|
86
|
+
self.model.sqrt_one_minus_alphas_cumprod
|
|
87
|
+
if use_original_steps
|
|
88
|
+
else self.ddim_sqrt_one_minus_alphas
|
|
89
|
+
)
|
|
90
|
+
sigmas = (
|
|
91
|
+
self.model.ddim_sigmas_for_original_num_steps
|
|
92
|
+
if use_original_steps
|
|
93
|
+
else self.ddim_sigmas
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def get_x_prev_and_pred_x0(e_t, index):
|
|
97
|
+
# select parameters corresponding to the currently considered timestep
|
|
98
|
+
a_t = torch.full((b, 1, 1, 1), alphas[index], device=device)
|
|
99
|
+
a_prev = torch.full(
|
|
100
|
+
(b, 1, 1, 1), alphas_prev[index], device=device
|
|
101
|
+
)
|
|
102
|
+
sigma_t = torch.full((b, 1, 1, 1), sigmas[index], device=device)
|
|
103
|
+
sqrt_one_minus_at = torch.full(
|
|
104
|
+
(b, 1, 1, 1), sqrt_one_minus_alphas[index], device=device
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# current prediction for x_0
|
|
108
|
+
pred_x0 = (x - sqrt_one_minus_at * e_t) / a_t.sqrt()
|
|
109
|
+
if quantize_denoised:
|
|
110
|
+
pred_x0, _, *_ = self.model.first_stage_model.quantize(pred_x0)
|
|
111
|
+
# direction pointing to x_t
|
|
112
|
+
dir_xt = (1.0 - a_prev - sigma_t**2).sqrt() * e_t
|
|
113
|
+
noise = (
|
|
114
|
+
sigma_t
|
|
115
|
+
* noise_like(x.shape, device, repeat_noise)
|
|
116
|
+
* temperature
|
|
117
|
+
)
|
|
118
|
+
if noise_dropout > 0.0:
|
|
119
|
+
noise = torch.nn.functional.dropout(noise, p=noise_dropout)
|
|
120
|
+
x_prev = a_prev.sqrt() * pred_x0 + dir_xt + noise
|
|
121
|
+
return x_prev, pred_x0
|
|
122
|
+
|
|
123
|
+
e_t = get_model_output(x, t)
|
|
124
|
+
if len(old_eps) == 0:
|
|
125
|
+
# Pseudo Improved Euler (2nd order)
|
|
126
|
+
x_prev, pred_x0 = get_x_prev_and_pred_x0(e_t, index)
|
|
127
|
+
e_t_next = get_model_output(x_prev, t_next)
|
|
128
|
+
e_t_prime = (e_t + e_t_next) / 2
|
|
129
|
+
elif len(old_eps) == 1:
|
|
130
|
+
# 2nd order Pseudo Linear Multistep (Adams-Bashforth)
|
|
131
|
+
e_t_prime = (3 * e_t - old_eps[-1]) / 2
|
|
132
|
+
elif len(old_eps) == 2:
|
|
133
|
+
# 3nd order Pseudo Linear Multistep (Adams-Bashforth)
|
|
134
|
+
e_t_prime = (23 * e_t - 16 * old_eps[-1] + 5 * old_eps[-2]) / 12
|
|
135
|
+
elif len(old_eps) >= 3:
|
|
136
|
+
# 4nd order Pseudo Linear Multistep (Adams-Bashforth)
|
|
137
|
+
e_t_prime = (
|
|
138
|
+
55 * e_t
|
|
139
|
+
- 59 * old_eps[-1]
|
|
140
|
+
+ 37 * old_eps[-2]
|
|
141
|
+
- 9 * old_eps[-3]
|
|
142
|
+
) / 24
|
|
143
|
+
|
|
144
|
+
x_prev, pred_x0 = get_x_prev_and_pred_x0(e_t_prime, index)
|
|
145
|
+
|
|
146
|
+
return x_prev, pred_x0, e_t
|