15
15
# For sdxl - OpenAIWrapper will be called, which will call the underlying diffusion_model
16
16
# When controlnet is enabled, the underlying model is not available to use, therefore we skip
17
17
18
- def find_noise_for_image (p , cond , uncond , cfg_scale , steps ):
18
+ @torch .no_grad ()
19
+ def find_noise_for_image (p , cond , uncond , cfg_scale , steps , skip_sdxl_vector ):
19
20
x = p .init_latent .clone ()
20
21
21
22
s_in = x .new_ones ([x .shape [0 ]])
@@ -36,53 +37,27 @@ def find_noise_for_image(p, cond, uncond, cfg_scale, steps):
36
37
sigma_in = torch .cat ([sigmas [i ] * s_in ] * 2 )
37
38
38
39
if shared .sd_model .is_sdxl :
39
- cond_tensor = cond ['crossattn' ]
40
- uncond_tensor = uncond ['crossattn' ]
41
- cond_in = torch .cat ([uncond_tensor , cond_tensor ])
40
+ cond_in = {"crossattn" : [torch .cat ([uncond ['crossattn' ], cond ['crossattn' ]])], "vector" : [torch .cat ([uncond ['vector' ], cond ['vector' ]])]}
42
41
else :
43
- cond_in = torch .cat ([uncond , cond ])
42
+ cond_in = { "c_concat" : [ torch .cat ([p . image_conditioning ] * 2 )], "c_crossattn" : [ torch . cat ([ uncond , cond ])]}
44
43
45
- image_conditioning = torch .cat ([p .image_conditioning ] * 2 )
46
- cond_in = {"c_concat" : [image_conditioning ], "c_crossattn" : [cond_in ]}
47
-
48
- c_out , c_in = [K .utils .append_dims (k , x_in .ndim ) for k in dnw .get_scalings (sigma_in )[skip :]]
49
44
t = dnw .sigma_to_t (sigma_in )
50
-
51
- if shared .sd_model .is_sdxl :
52
- num_classes_hack = shared .sd_model .model .diffusion_model .num_classes
53
- shared .sd_model .model .diffusion_model .num_classes = None
54
- try :
55
- eps = shared .sd_model .model (x_in * c_in , t , {"crossattn" : cond_in ["c_crossattn" ][0 ]} )
56
- finally :
57
- shared .sd_model .model .diffusion_model .num_classes = num_classes_hack
58
- else :
59
- eps = shared .sd_model .apply_model (x_in * c_in , t , cond = cond_in )
60
-
61
- denoised_uncond , denoised_cond = (x_in + eps * c_out ).chunk (2 )
62
-
63
- denoised = denoised_uncond + (denoised_cond - denoised_uncond ) * cfg_scale
64
-
65
- d = (x - denoised ) / sigmas [i ]
66
45
dt = sigmas [i ] - sigmas [i - 1 ]
67
-
68
- x = x + d * dt
46
+ x += noise_from_model (x , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip , skip_sdxl_vector )
69
47
70
48
sd_samplers_common .store_latent (x )
71
49
72
50
# This shouldn't be necessary, but solved some VRAM issues
73
- del x_in , sigma_in , cond_in , c_out , c_in , t ,
74
- del eps , denoised_uncond , denoised_cond , denoised , d , dt
51
+ del x_in , sigma_in , cond_in , t , dt
75
52
76
53
shared .state .nextjob ()
77
54
78
- return x / x .std ()
79
-
80
-
81
- Cached = namedtuple ("Cached" , ["noise" , "cfg_scale" , "steps" , "latent" , "original_prompt" , "original_negative_prompt" , "sigma_adjustment" , "second_order_correction" , "noise_sigma_intensity" ])
55
+ return x , sigmas [- 1 ]
82
56
83
57
84
58
# Based on changes suggested by briansemrau in https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/736
85
- def find_noise_for_image_sigma_adjustment (p , cond , uncond , cfg_scale , steps , correction_factor , sigma_intensity ):
59
+ @torch .no_grad ()
60
+ def find_noise_for_image_sigma_adjustment (p , cond , uncond , cfg_scale , steps , correction_factor , skip_sdxl_vector ):
86
61
x = p .init_latent .clone ()
87
62
88
63
s_in = x .new_ones ([x .shape [0 ]])
@@ -100,14 +75,9 @@ def find_noise_for_image_sigma_adjustment(p, cond, uncond, cfg_scale, steps, cor
100
75
shared .state .sampling_step += 1
101
76
sigma_in = torch .cat ([sigmas [i - 1 ] * s_in ] * 2 )
102
77
if shared .sd_model .is_sdxl :
103
- cond_tensor = cond ['crossattn' ]
104
- uncond_tensor = uncond ['crossattn' ]
105
- cond_in = torch .cat ([uncond_tensor , cond_tensor ])
78
+ cond_in = {"crossattn" : [torch .cat ([uncond ['crossattn' ], cond ['crossattn' ]])], "vector" : [torch .cat ([uncond ['vector' ], cond ['vector' ]])]}
106
79
else :
107
- cond_in = torch .cat ([uncond , cond ])
108
-
109
- image_conditioning = torch .cat ([p .image_conditioning ] * 2 )
110
- cond_in = {"c_concat" : [image_conditioning ], "c_crossattn" : [cond_in ]}
80
+ cond_in = {"c_concat" : [torch .cat ([p .image_conditioning ] * 2 )], "c_crossattn" : [torch .cat ([uncond , cond ])]}
111
81
112
82
if i == 1 :
113
83
t = dnw .sigma_to_t (torch .cat ([sigmas [i ] * s_in ] * 2 ))
@@ -116,37 +86,35 @@ def find_noise_for_image_sigma_adjustment(p, cond, uncond, cfg_scale, steps, cor
116
86
t = dnw .sigma_to_t (sigma_in )
117
87
dt = (sigmas [i ] - sigmas [i - 1 ]) / sigmas [i - 1 ]
118
88
119
- noise = noise_from_model (x , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip )
89
+ noise = noise_from_model (x , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip , skip_sdxl_vector )
120
90
121
91
if correction_factor > 0 : # runs model with previously calculated noise
122
- recalculated_noise = noise_from_model (x + noise , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip )
92
+ recalculated_noise = noise_from_model (x + noise , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip , skip_sdxl_vector )
123
93
noise = recalculated_noise * correction_factor + noise * (1 - correction_factor )
124
94
125
95
x += noise
126
96
127
97
sd_samplers_common .store_latent (x )
128
98
129
- # This shouldn't be necessary, but solved some VRAM issues
130
- #del x_in, sigma_in, cond_in, c_out, c_in, t
131
- #del eps, denoised_uncond, denoised_cond, denoised, dt
132
-
133
99
shared .state .nextjob ()
134
100
135
- # Chooses between std and sigmas[-1]
136
- return x / (x .std ()* (1 - sigma_intensity ) + sigmas [- 1 ]* sigma_intensity )
101
+ return x , sigmas [- 1 ]
137
102
138
- def noise_from_model (x , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip ):
103
+ @torch .no_grad ()
104
+ def noise_from_model (x , t , dt , sigma_in , cond_in , cfg_scale , dnw , skip , skip_sdxl_vector ):
139
105
140
106
if cfg_scale == 1 : # Case where denoised_uncond should not be calculated - 50% speedup, also good for sdxl in experiments
141
107
x_in = x
142
108
sigma_in = sigma_in [1 :2 ]
143
109
c_out , c_in = [K .utils .append_dims (k , x_in .ndim ) for k in dnw .get_scalings (sigma_in )[skip :]]
144
- cond_in = {"c_concat" :[ cond_in [ "c_concat" ][ 0 ][1 :2 ]], "c_crossattn" : [ cond_in [ "c_crossattn" ][ 0 ][ 1 : 2 ]] }
110
+ cond_in = {k :[ v [ 0 ][1 :2 ]] for k , v in cond_in . items () }
145
111
if shared .sd_model .is_sdxl :
146
112
num_classes_hack = shared .sd_model .model .diffusion_model .num_classes
147
- shared .sd_model .model .diffusion_model .num_classes = None
113
+ if skip_sdxl_vector :
114
+ shared .sd_model .model .diffusion_model .num_classes = None
115
+ cond_in ["vector" ][0 ] = None
148
116
try :
149
- eps = shared .sd_model .model (x_in * c_in , t [1 :2 ], {"crossattn" : cond_in ["c_crossattn " ][0 ]})
117
+ eps = shared .sd_model .model (x_in * c_in , t [1 :2 ], {"crossattn" : cond_in ["crossattn" ][ 0 ], "vector" : cond_in [ "vector " ][0 ]})
150
118
finally :
151
119
shared .sd_model .model .diffusion_model .num_classes = num_classes_hack
152
120
else :
@@ -160,9 +128,11 @@ def noise_from_model(x, t, dt, sigma_in, cond_in, cfg_scale, dnw, skip):
160
128
161
129
if shared .sd_model .is_sdxl :
162
130
num_classes_hack = shared .sd_model .model .diffusion_model .num_classes
163
- shared .sd_model .model .diffusion_model .num_classes = None
131
+ if skip_sdxl_vector :
132
+ shared .sd_model .model .diffusion_model .num_classes = None
133
+ cond_in ["vector" ][0 ] = None
164
134
try :
165
- eps = shared .sd_model .model (x_in * c_in , t , {"crossattn" : cond_in ["c_crossattn " ][0 ]} )
135
+ eps = shared .sd_model .model (x_in * c_in , t , {"crossattn" : cond_in ["crossattn" ][ 0 ], "vector" : cond_in [ "vector " ][0 ]} )
166
136
finally :
167
137
shared .sd_model .model .diffusion_model .num_classes = num_classes_hack
168
138
else :
@@ -174,6 +144,9 @@ def noise_from_model(x, t, dt, sigma_in, cond_in, cfg_scale, dnw, skip):
174
144
175
145
return - denoised * dt
176
146
147
+ Cached = namedtuple ("Cached" , ["noise" , "cfg_scale" , "steps" , "latent" , "original_prompt" , "original_negative_prompt" , "sigma_adjustment" , "second_order_correction" , "skip_sdxl_vector" ])
148
+
149
+
177
150
class Script (scripts .Script ):
178
151
def __init__ (self ):
179
152
self .cache = None
@@ -189,35 +162,38 @@ def ui(self, is_img2img):
189
162
* `CFG Scale` should be 2 or lower.
190
163
''' )
191
164
192
- override_sampler = gr .Checkbox (label = "Override `Sampling method` to Euler?(this method is built for it)" , value = True , elem_id = self .elem_id ("override_sampler" ))
165
+ override_sampler = gr .Checkbox (label = "Override `Sampling method` to Euler?(this method is built for it)" , value = False , elem_id = self .elem_id ("override_sampler" ))
193
166
194
- override_prompt = gr .Checkbox (label = "Override `prompt` to the same value as `original prompt`?(and `negative prompt`)" , value = True , elem_id = self .elem_id ("override_prompt" ))
167
+ override_prompt = gr .Checkbox (label = "Override `prompt` to the same value as `original prompt`?(and `negative prompt`)" , value = False , elem_id = self .elem_id ("override_prompt" ))
195
168
original_prompt = gr .Textbox (label = "Original prompt" , lines = 1 , elem_id = self .elem_id ("original_prompt" ))
196
169
original_negative_prompt = gr .Textbox (label = "Original negative prompt" , lines = 1 , elem_id = self .elem_id ("original_negative_prompt" ))
197
170
198
171
override_steps = gr .Checkbox (label = "Override `Sampling Steps` to the same value as `Decode steps`?" , value = True , elem_id = self .elem_id ("override_steps" ))
199
- st = gr .Slider (label = "Decode steps" , minimum = 1 , maximum = 150 , step = 1 , value = 50 , elem_id = self .elem_id ("st" ))
172
+ st = gr .Slider (label = "Decode steps" , minimum = 1 , maximum = 150 , step = 1 , value = 20 , elem_id = self .elem_id ("st" ))
200
173
201
174
override_strength = gr .Checkbox (label = "Override `Denoising strength` to 1?" , value = True , elem_id = self .elem_id ("override_strength" ))
202
175
203
176
cfg = gr .Slider (label = "Decode CFG scale" , minimum = 0.0 , maximum = 15.0 , step = 0.1 , value = 1.0 , elem_id = self .elem_id ("cfg" ))
204
177
randomness = gr .Slider (label = "Randomness" , minimum = 0.0 , maximum = 1.0 , step = 0.01 , value = 0.0 , elem_id = self .elem_id ("randomness" ))
205
- sigma_adjustment = gr .Checkbox (label = "Sigma adjustment for finding noise for image" , value = False , elem_id = self .elem_id ("sigma_adjustment" ))
178
+ sigma_adjustment = gr .Checkbox (label = "Sigma adjustment for finding noise for image" , value = True , elem_id = self .elem_id ("sigma_adjustment" ))
206
179
second_order_correction = gr .Slider (label = "Correct noise by running model again" , minimum = 0.0 , maximum = 1.0 , step = 0.01 , value = 0.5 , elem_id = self .elem_id ("second_order_correction" ),
207
180
info = "use 0 (disabled) for original script behaviour, 0.5 reccomended value. Runs the model again to recalculate noise and correct it by given factor. Higher adheres to original image more." )
208
181
noise_sigma_intensity = gr .Slider (label = "Weight scaling std vs sigma based" , minimum = - 1.0 , maximum = 2.0 , step = 0.01 , value = 0.5 , elem_id = self .elem_id ("noise_sigma_intensity" ),
209
182
info = "use 1 for original script behaviour, 0.5 reccomended value. Decides whether to use fixed sigma value or dynamic standard deviation to scale noise. Lower gives softer images." )
183
+ skip_sdxl_vector = gr .Checkbox (label = "Skip sdxl vectors" , info = "may cause distortion if false" , value = True , elem_id = self .elem_id ("skip_sdxl_vector" ))
184
+
210
185
return [
211
186
info ,
212
187
override_sampler ,
213
188
override_prompt , original_prompt , original_negative_prompt ,
214
189
override_steps , st ,
215
190
override_strength ,
216
191
cfg , randomness , sigma_adjustment , second_order_correction ,
217
- noise_sigma_intensity
192
+ noise_sigma_intensity , skip_sdxl_vector
218
193
]
219
194
220
- def run (self , p , _ , override_sampler , override_prompt , original_prompt , original_negative_prompt , override_steps , st , override_strength , cfg , randomness , sigma_adjustment , second_order_correction , noise_sigma_intensity ):
195
+ @torch .no_grad ()
196
+ def run (self , p , _ , override_sampler , override_prompt , original_prompt , original_negative_prompt , override_steps , st , override_strength , cfg , randomness , sigma_adjustment , second_order_correction , noise_sigma_intensity , skip_sdxl_vector ):
221
197
# Override
222
198
if override_sampler :
223
199
p .sampler_name = "Euler"
@@ -237,15 +213,16 @@ def sample_extra(conditioning, unconditional_conditioning, seeds, subseeds, subs
237
213
and self .cache .original_negative_prompt == original_negative_prompt \
238
214
and self .cache .sigma_adjustment == sigma_adjustment \
239
215
and self .cache .second_order_correction == second_order_correction \
240
- and self .cache .noise_sigma_intensity == noise_sigma_intensity
216
+ and self .cache .skip_sdxl_vector == skip_sdxl_vector
217
+
241
218
same_everything = same_params and self .cache .latent .shape == lat .shape and np .abs (self .cache .latent - lat ).sum () < 100
242
219
243
220
rand_noise = processing .create_random_tensors (p .init_latent .shape [1 :], seeds = seeds , subseeds = subseeds , subseed_strength = p .subseed_strength , seed_resize_from_h = p .seed_resize_from_h , seed_resize_from_w = p .seed_resize_from_w , p = p )
244
221
245
222
if same_everything :
246
- rec_noise = self .cache .noise
223
+ rec_noise , sigma_val = self .cache .noise
247
224
else :
248
- # This prevents a crash, because I don't know how to access the underlying .diffusion_model yet when controlnet is enabled. WIP
225
+ # This prevents a crash, because I don't know how to access the underlying .diffusion_model yet when controlnet is enabled.
249
226
# modules.sd_unet -> we're good
250
227
# scripts.hook -> we're cooked
251
228
if "scripts.hook" in str (shared .sd_model .model .diffusion_model .forward .__module__ ):
@@ -257,21 +234,23 @@ def sample_extra(conditioning, unconditional_conditioning, seeds, subseeds, subs
257
234
cond = p .sd_model .get_learned_conditioning (p .batch_size * [original_prompt ])
258
235
uncond = p .sd_model .get_learned_conditioning (p .batch_size * [original_negative_prompt ])
259
236
if sigma_adjustment :
260
- rec_noise = find_noise_for_image_sigma_adjustment (p , cond , uncond , cfg , st , second_order_correction , noise_sigma_intensity )
237
+ rec_noise , sigma_val = find_noise_for_image_sigma_adjustment (p , cond , uncond , cfg , st , second_order_correction , skip_sdxl_vector )
261
238
else :
262
- rec_noise = find_noise_for_image (p , cond , uncond , cfg , st )
263
- self .cache = Cached (rec_noise , cfg , st , lat , original_prompt , original_negative_prompt , sigma_adjustment , second_order_correction , noise_sigma_intensity )
239
+ rec_noise , sigma_val = find_noise_for_image (p , cond , uncond , cfg , st , skip_sdxl_vector )
240
+ self .cache = Cached ((rec_noise , sigma_val ), cfg , st , lat , original_prompt , original_negative_prompt , sigma_adjustment , second_order_correction , skip_sdxl_vector )
241
+
242
+ rec_noise = rec_noise / (rec_noise .std ()* (1 - noise_sigma_intensity ) + sigma_val * noise_sigma_intensity )
264
243
265
244
combined_noise = ((1 - randomness ) * rec_noise + randomness * rand_noise ) / ((randomness ** 2 + (1 - randomness )** 2 ) ** 0.5 )
266
245
267
246
sampler = sd_samplers .create_sampler (p .sampler_name , p .sd_model )
268
247
248
+ p .seed = p .seed + 1
249
+
269
250
sigmas = sampler .model_wrap .get_sigmas (p .steps )
270
251
271
252
noise_dt = combined_noise - (p .init_latent / sigmas [0 ])
272
253
273
- p .seed = p .seed + 1
274
-
275
254
return sampler .sample_img2img (p , p .init_latent , noise_dt , conditioning , unconditional_conditioning , image_conditioning = p .image_conditioning )
276
255
277
256
p .sample = sample_extra
0 commit comments