Jinl commited on
Commit
a6cec16
1 Parent(s): 2aed4d9

Add application file

Browse files
Files changed (40) hide show
  1. app.py +429 -0
  2. data/content/27032.jpg +0 -0
  3. data/content/29812.jpg +0 -0
  4. data/style/27.jpg +0 -0
  5. data/style/47.jpg +0 -0
  6. requirements.txt +85 -0
  7. utils/__init__.py +0 -0
  8. utils/__pycache__/__init__.cpython-310.pyc +0 -0
  9. utils/__pycache__/__init__.cpython-39.pyc +0 -0
  10. utils/__pycache__/attn_control.cpython-310.pyc +0 -0
  11. utils/__pycache__/attn_control.cpython-39.pyc +0 -0
  12. utils/__pycache__/free_lunch_utils.cpython-310.pyc +0 -0
  13. utils/__pycache__/free_lunch_utils.cpython-39.pyc +0 -0
  14. utils/__pycache__/masactrl_utils.cpython-310.pyc +0 -0
  15. utils/__pycache__/masactrl_utils.cpython-39.pyc +0 -0
  16. utils/__pycache__/merge.cpython-310.pyc +0 -0
  17. utils/__pycache__/merge.cpython-39.pyc +0 -0
  18. utils/__pycache__/patch.cpython-310.pyc +0 -0
  19. utils/__pycache__/patch.cpython-39.pyc +0 -0
  20. utils/__pycache__/pipeline.cpython-310.pyc +0 -0
  21. utils/__pycache__/pipeline.cpython-39.pyc +0 -0
  22. utils/__pycache__/pipeline_ead.cpython-310.pyc +0 -0
  23. utils/__pycache__/pipeline_ead.cpython-39.pyc +0 -0
  24. utils/__pycache__/pipeline_stable_diffusion_xl.cpython-310.pyc +0 -0
  25. utils/__pycache__/pipeline_stable_diffusion_xl.cpython-39.pyc +0 -0
  26. utils/__pycache__/pipeline_xl_edit.cpython-310.pyc +0 -0
  27. utils/__pycache__/pipeline_xl_edit.cpython-39.pyc +0 -0
  28. utils/__pycache__/ptp_utils.cpython-310.pyc +0 -0
  29. utils/__pycache__/ptp_utils.cpython-39.pyc +0 -0
  30. utils/__pycache__/style_attn_control.cpython-310.pyc +0 -0
  31. utils/__pycache__/style_attn_control.cpython-39.pyc +0 -0
  32. utils/__pycache__/superbeastsai.cpython-310.pyc +0 -0
  33. utils/__pycache__/superbeastsai.cpython-39.pyc +0 -0
  34. utils/__pycache__/utils.cpython-310.pyc +0 -0
  35. utils/__pycache__/utils.cpython-39.pyc +0 -0
  36. utils/attn_control.py +129 -0
  37. utils/merge.py +124 -0
  38. utils/pipeline.py +434 -0
  39. utils/ptp_utils.py +225 -0
  40. utils/utils.py +32 -0
app.py ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import random
4
+ import numpy as np
5
+ import gradio as gr
6
+ from glob import glob
7
+ from datetime import datetime
8
+
9
+ from diffusers import StableDiffusionPipeline,AutoencoderKL
10
+ from diffusers import DDIMScheduler, LCMScheduler, EulerDiscreteScheduler
11
+
12
+ import torch.nn.functional as F
13
+ from PIL import Image,ImageDraw
14
+ from utils.pipeline import ZePoPipeline
15
+ from utils.attn_control import AttentionStyle
16
+ from torchvision.utils import save_image
17
+ import utils.ptp_utils as ptp_utils
18
+
19
+ import torchvision.transforms as transforms
20
+
21
+ try:
22
+ import xformers
23
+ is_xformers = True
24
+ except ImportError:
25
+ is_xformers = False
26
+
27
+ css = """
28
+ .toolbutton {
29
+ margin-buttom: 0em 0em 0em 0em;
30
+ max-width: 2.5em;
31
+ min-width: 2.5em !important;
32
+ height: 2.5em;
33
+ }
34
+ """
35
+ # import sys
36
+ # sys.setrecursionlimit(100000)
37
+
38
+
39
+ class GlobalText:
40
+ def __init__(self):
41
+
42
+ # config dirs
43
+ self.basedir = os.getcwd()
44
+ self.stable_diffusion_dir = os.path.join(self.basedir, "models", "StableDiffusion")
45
+ self.personalized_model_dir = './models/Stable-diffusion'
46
+ self.lora_model_dir = './models/Lora'
47
+ self.savedir = os.path.join(self.basedir, "samples", datetime.now().strftime("Gradio-%Y-%m-%dT%H-%M-%S"))
48
+ self.savedir_sample = os.path.join(self.savedir, "sample")
49
+
50
+ # self.savedir_mask = os.path.join(self.savedir, "mask")
51
+
52
+ self.stable_diffusion_list = ["SimianLuo/LCM_Dreamshaper_v7"
53
+ ]
54
+ self.personalized_model_list = []
55
+ self.lora_model_list = []
56
+
57
+ self.tokenizer = None
58
+ self.text_encoder = None
59
+ self.vae = None
60
+ self.unet = None
61
+ self.pipeline = None
62
+ self.torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
63
+ self.lora_model_state_dict = {}
64
+ self.device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
65
+
66
+ def init_source_image_path(self, source_path):
67
+ self.source_paths = sorted(glob(os.path.join(source_path, '*')))
68
+ self.max_source_index = len(self.source_paths) // 12
69
+ return self.source_paths[0:12]
70
+ def init_style_image_path(self, style_path):
71
+ self.style_paths = sorted(glob(os.path.join(style_path, '*')))
72
+ self.max_style_index = len(self.style_paths) // 12
73
+ return self.style_paths[0:12]
74
+ def init_results_image_path(self):
75
+ results_paths = [os.path.join(self.savedir_sample, file) for file in os.listdir(self.savedir_sample)]
76
+ self.results_paths = sorted(results_paths, key=os.path.getctime, reverse=True)
77
+ self.max_results_index = len(self.results_paths) // 12
78
+ return self.results_paths[0:12]
79
+
80
+ def load_base_pipeline(self, model_path):
81
+
82
+ time_start = datetime.now()
83
+
84
+ self.scheduler = 'LCM'
85
+ scheduler = LCMScheduler.from_pretrained(model_path, subfolder="scheduler")
86
+ self.pipeline = ZePoPipeline.from_pretrained(model_path,scheduler=scheduler,torch_dtype=torch.float16,).to('cuda')
87
+ if is_xformers:
88
+ self.pipeline.enable_xformers_memory_efficient_attention()
89
+ time_end = datetime.now()
90
+ print(f'Load {model_path} successful in {time_end-time_start}')
91
+ return gr.Dropdown()
92
+
93
+ def refresh_stable_diffusion(self,model_path):
94
+
95
+ self.load_base_pipeline(model_path)
96
+
97
+ return self.stable_diffusion_list[0]
98
+
99
+ def update_base_model(self, base_model_dropdown):
100
+ if self.pipeline is None:
101
+ gr.Info(f"Please select a pretrained model path.")
102
+ return None
103
+ else:
104
+ base_model = self.personalized_model_list[base_model_dropdown]
105
+ mid_model = StableDiffusionPipeline.from_single_file(base_model)
106
+ self.pipeline.vae = mid_model.vae
107
+ self.pipeline.unet = mid_model.unet
108
+ self.pipeline.text_encoder = mid_model.text_encoder
109
+ self.pipeline.to(self.device)
110
+ self.personal_model_loaded = base_model_dropdown.split('.')[0]
111
+ print(f'load {base_model_dropdown} model success!')
112
+ return gr.Dropdown()
113
+
114
+
115
+ def generate(self, source, style,
116
+ num_steps, co_feat_step,strength,
117
+ start_ac_layer, end_ac_layer,
118
+ sty_guidance,cfg_scale, mix_q_scale,
119
+ Scheduler, save_intermediate, seed, de_bug,
120
+ target_prompt, negative_prompt_textbox,
121
+ width_slider,height_slider,
122
+ tome_sx, tome_sy, tome_ratio,tome,
123
+ ):
124
+
125
+
126
+ os.makedirs(self.savedir, exist_ok=True)
127
+ os.makedirs(self.savedir_sample, exist_ok=True)
128
+
129
+ if self.pipeline == None:
130
+ self.refresh_stable_diffusion(self.stable_diffusion_list[-1])
131
+ model = self.pipeline
132
+
133
+ if Scheduler == 'DDIM':
134
+ model.scheduler = DDIMScheduler.from_config(model.scheduler.config)
135
+ print(f"Successful adoption of DDIM scheduler")
136
+ if Scheduler == 'LCM':
137
+ model.scheduler = LCMScheduler.from_config(model.scheduler.config)
138
+ print(f"Successful adoption of LCM scheduler")
139
+ if Scheduler == 'EulerDiscrete':
140
+ model.scheduler = EulerDiscreteScheduler.from_config(model.scheduler.config)
141
+
142
+ if seed != '-1' and seed != "": torch.manual_seed(int(seed))
143
+ else: torch.seed()
144
+
145
+ seed = torch.initial_seed()
146
+ print(f"Seed: {seed}")
147
+
148
+ self.sample_count = len(os.listdir(self.savedir_sample))
149
+
150
+
151
+ prompts = [target_prompt] * 3
152
+ source = source.resize((width_slider, height_slider))
153
+ style = style.resize((width_slider, height_slider))
154
+
155
+
156
+ with torch.no_grad():
157
+
158
+ controller = AttentionStyle(num_steps,
159
+ start_ac_layer,
160
+ end_ac_layer,
161
+ style_guidance=sty_guidance,
162
+ mix_q_scale=mix_q_scale,
163
+ de_bug=de_bug,
164
+ )
165
+
166
+ ptp_utils.register_attention_control(model, controller,
167
+ tome,
168
+ sx=tome_sx,
169
+ sy=tome_sy,
170
+ ratio=tome_ratio,
171
+ de_bug=de_bug,)
172
+
173
+ time_begin = datetime.now()
174
+ generate_image = model(prompt=prompts,
175
+ negative_prompt=negative_prompt_textbox,
176
+ image=source,
177
+ style=style,
178
+ num_inference_steps=num_steps,
179
+ eta=0.0,
180
+ guidance_scale=cfg_scale,
181
+ strength=strength,
182
+ save_intermediate=save_intermediate,
183
+ fix_step_index=co_feat_step,
184
+ de_bug = de_bug,
185
+ callback = None
186
+ ).images
187
+ time_end = datetime.now()
188
+ print('generate one image with time {}'.format(time_end-time_begin))
189
+
190
+ save_file_name = f"{self.sample_count}_step{num_steps}_sl{start_ac_layer}_el{end_ac_layer}_ST{strength}_CF{co_feat_step}_STG{sty_guidance}_MQ{mix_q_scale}_CFG{cfg_scale}_seed{seed}.jpg"
191
+
192
+
193
+ save_file_path = os.path.join(self.savedir, save_file_name)
194
+
195
+ save_image(torch.tensor(generate_image).permute(0, 3, 1, 2), save_file_path, nrow=3, padding=0)
196
+ save_image(torch.tensor(generate_image[2:]).permute(0, 3, 1, 2), os.path.join(self.savedir_sample, save_file_name), nrow=3, padding=0)
197
+ self.init_results_image_path()
198
+ return [
199
+ generate_image[0],
200
+ generate_image[1],
201
+ generate_image[2],
202
+ self.init_results_image_path()
203
+ ]
204
+
205
+
206
+ global_text = GlobalText()
207
+
208
+
209
+ def ui():
210
+ with gr.Blocks(css=css) as demo:
211
+ gr.Markdown(
212
+ """
213
+ # [ZePo: Zero-Shot Portrait Stylization with Faster Sampling](https://arxiv.org/abs/2408.05492)
214
+ Jin Liu, Huaibo Huang, Jie Cao, Ran He<br>
215
+ [Arxiv](https://arxiv.org/abs/2408.05492) | [Github](https://github.com/liujin112/ZePo)
216
+ """
217
+ )
218
+ with gr.Column(variant="panel"):
219
+ gr.Markdown(
220
+ """
221
+ ### 1. Select a pretrained model.
222
+ """
223
+ )
224
+ with gr.Row():
225
+ stable_diffusion_dropdown = gr.Dropdown(
226
+ label="Pretrained Model Path",
227
+ choices=global_text.stable_diffusion_list,
228
+ interactive=True,
229
+ allow_custom_value=True
230
+ )
231
+ stable_diffusion_dropdown.change(fn=global_text.load_base_pipeline, inputs=[stable_diffusion_dropdown], outputs=[stable_diffusion_dropdown])
232
+
233
+ stable_diffusion_refresh_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")
234
+ def update_stable_diffusion(stable_diffusion_dropdown):
235
+ global_text.refresh_stable_diffusion(stable_diffusion_dropdown)
236
+
237
+ stable_diffusion_refresh_button.click(fn=update_stable_diffusion, inputs=[stable_diffusion_dropdown], outputs=[stable_diffusion_dropdown])
238
+
239
+
240
+ with gr.Column(variant="panel"):
241
+ gr.Markdown(
242
+ """
243
+ ### 2. Configs for ZePo.
244
+ """
245
+ )
246
+ with gr.Tab("Configs"):
247
+
248
+ with gr.Row():
249
+ with gr.Column():
250
+ with gr.Row():
251
+ source_image = gr.Image(label="Source Image", elem_id="img2maskimg", sources="upload", type="pil",image_mode="RGB", height=256)
252
+ style_image = gr.Image(label="Style Image", elem_id="img2maskimg", sources="upload", type="pil", image_mode="RGB", height=256)
253
+
254
+ generate_image = gr.Image(label="Image with PortraitDiff", type="pil", interactive=True, image_mode="RGB", height=512)
255
+
256
+
257
+ with gr.Row():
258
+ recons_content = gr.Image(label="reconstructed content", type="pil", image_mode="RGB", height=256)
259
+ recons_style = gr.Image(label="reconstructed style", type="pil", image_mode="RGB", height=256)
260
+ prompt_textbox = gr.Textbox(label="Prompt", value='head', lines=1)
261
+ negative_prompt_textbox = gr.Textbox(label="Negative prompt", lines=1)
262
+ with gr.Row(equal_height=False):
263
+ with gr.Column():
264
+ with gr.Tab("Resolution"):
265
+ width_slider = gr.Slider(label="Width", value=512, minimum=256, maximum=1024, step=64)
266
+ height_slider = gr.Slider(label="Height", value=512, minimum=256, maximum=1024, step=64)
267
+ Scheduler = gr.Dropdown(
268
+ ["DDIM", "LCM", "EulerDiscrete"],
269
+ value="LCM",
270
+ label="Scheduler", info="Select a Scheduler")
271
+
272
+
273
+ with gr.Tab("Content Gallery"):
274
+
275
+ with gr.Row():
276
+ source_path = gr.Textbox(value='./data/content', label="Source Path")
277
+ refresh_source_list_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")
278
+ source_gallery_index = gr.Slider(label="Index", value=0, minimum=0, maximum=50, step=1)
279
+ num_gallery_images = 12
280
+ source_image_gallery = gr.Gallery(value=[], columns=4, label="Source Image List")
281
+ refresh_source_list_button.click(fn=global_text.init_source_image_path, inputs=[source_path], outputs=[source_image_gallery])
282
+
283
+ def update_source_list(index):
284
+ if int(index) < 0:
285
+ index = 0
286
+ if int(index) > global_text.max_source_index:
287
+ index = global_text.max_source_index
288
+ return global_text.source_paths[int(index)*num_gallery_images:(int(index)+1)*num_gallery_images]
289
+
290
+ source_gallery_index.change(fn=update_source_list, inputs=[source_gallery_index], outputs=[source_image_gallery])
291
+
292
+ with gr.Tab("Style Gallery"):
293
+
294
+ with gr.Row():
295
+ style_path = gr.Textbox(value='./data/style', label="style Path")
296
+ refresh_style_list_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")
297
+ style_gallery_index = gr.Slider(label="Index", value=0, minimum=0, maximum=50, step=1)
298
+ num_gallery_images = 12
299
+ style_image_gallery = gr.Gallery(value=[], columns=4, label="style Image List")
300
+ refresh_style_list_button.click(fn=global_text.init_style_image_path, inputs=[style_path], outputs=[style_image_gallery])
301
+
302
+
303
+ def update_style_list(index):
304
+ if int(index) < 0:
305
+ index = 0
306
+ if int(index) > global_text.max_style_index:
307
+ index = global_text.max_style_index
308
+ return global_text.style_paths[int(index)*num_gallery_images:(int(index)+1)*num_gallery_images]
309
+
310
+ style_gallery_index.change(fn=update_style_list, inputs=[style_gallery_index], outputs=[style_image_gallery])
311
+
312
+ with gr.Tab("Results Gallery"):
313
+ with gr.Row():
314
+ refresh_results_list_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")
315
+ results_gallery_index = gr.Slider(label="Index", value=0, minimum=0, maximum=50, step=1)
316
+ num_gallery_images = 12
317
+ results_image_gallery = gr.Gallery(value=[], columns=4, label="style Image List")
318
+ refresh_results_list_button.click(fn=global_text.init_results_image_path, inputs=[], outputs=[results_image_gallery])
319
+
320
+
321
+ def update_results_list(index):
322
+ if int(index) < 0:
323
+ index = 0
324
+ if int(index) > global_text.max_results_index:
325
+ index = global_text.max_results_index
326
+ return global_text.results_paths[int(index)*num_gallery_images:(int(index)+1)*num_gallery_images]
327
+
328
+ results_gallery_index.change(fn=update_results_list, inputs=[results_gallery_index], outputs=[style_image_gallery])
329
+
330
+
331
+
332
+ with gr.Row():
333
+ generate_button = gr.Button(value="Generate", variant='primary')
334
+
335
+ with gr.Tab('Base Configs'):
336
+ num_steps = gr.Slider(label="Total Steps", value=4, minimum=0, maximum=25, step=1)
337
+ strength = gr.Slider(label="Noisy Ratio", value=0.5, minimum=0, maximum=1, step=0.01,info="How much noise applied to souce image, 50% for better balance.")
338
+ co_feat_step = gr.Slider(label="Consistency Feature Extract Step", value=99, minimum=0, maximum=999, step=1)
339
+
340
+
341
+ with gr.Row():
342
+ start_ac_layer = gr.Slider(label="Start Layer of AC",
343
+ minimum=0,
344
+ maximum=16,
345
+ value=8,
346
+ step=1)
347
+ end_ac_layer = gr.Slider(label="End Layer of AC",
348
+ minimum=0,
349
+ maximum=16,
350
+ value=16,
351
+ step=1)
352
+
353
+ with gr.Row():
354
+ Style_Guidance = gr.Slider(label="Style Guidance Scale",
355
+ minimum=-1,
356
+ maximum=3,
357
+ value=1.2,
358
+ step=0.01,
359
+ )
360
+ mix_q_scale = gr.Slider(label='Query Mix Ratio',
361
+ minimum=0,
362
+ maximum=2,
363
+ step=0.05,
364
+ value=1.0,
365
+ )
366
+ cfg_scale_slider = gr.Slider(label="CFG Scale", value=2.5, minimum=0, maximum=20, info="Classifier-free guidance scale.")
367
+
368
+ with gr.Row():
369
+ save_intermediate = gr.Checkbox(label="save_intermediate", value=False)
370
+ de_bug = gr.Checkbox(value=False,label='DeBug')
371
+ with gr.Tab('ToMe'):
372
+ with gr.Row():
373
+ tome = gr.Checkbox(label="Token Merge", value=True)
374
+
375
+ tome_ratio = gr.Slider(label='ratio: ',
376
+ minimum=0,
377
+ maximum=1,
378
+ step=0.1,
379
+ value=0.5)
380
+ with gr.Row():
381
+ tome_sx = gr.Slider(label='sx:',
382
+ minimum=0,
383
+ maximum=64,
384
+ step=2,
385
+ value=2)
386
+ tome_sy = gr.Slider(label='sy:',
387
+ minimum=0,
388
+ maximum=64,
389
+ step=2,
390
+ value=2)
391
+
392
+
393
+ with gr.Row():
394
+ seed_textbox = gr.Textbox(label="Seed", value=-1)
395
+ seed_button = gr.Button(value="\U0001F3B2", elem_classes="toolbutton")
396
+ seed_button.click(fn=lambda: random.randint(1, 1e16), inputs=[], outputs=[seed_textbox])
397
+ inputs = [
398
+ source_image, style_image,
399
+ num_steps,co_feat_step,strength,
400
+ start_ac_layer, end_ac_layer,
401
+ Style_Guidance,cfg_scale_slider,mix_q_scale,
402
+ Scheduler, save_intermediate, seed_textbox, de_bug,
403
+ prompt_textbox, negative_prompt_textbox,
404
+ width_slider,height_slider,
405
+ tome_sx, tome_sy, tome_ratio, tome,
406
+ ]
407
+
408
+ generate_button.click(
409
+ fn=global_text.generate,
410
+ inputs=inputs,
411
+ outputs=[recons_style,recons_content,generate_image,results_image_gallery]
412
+ )
413
+
414
+ ex = gr.Examples(
415
+ [
416
+ ["./data/content/27032.jpg","./data/style/27.jpg",4,0.8,0.5,8427921159605868845],
417
+ ["./data/content/29812.jpg","./data/style/47.jpg",4,0.5,0.65,8119359809263726691],
418
+ ],
419
+ [source_image, style_image, num_steps,strength, mix_q_scale, seed_textbox],
420
+ [
421
+ "Example 1",
422
+ ],)
423
+
424
+
425
+ return demo
426
+
427
+ if __name__ == "__main__":
428
+ demo = ui()
429
+ demo.launch(server_name='172.18.32.44',show_error=True)
data/content/27032.jpg ADDED
data/content/29812.jpg ADDED
data/style/27.jpg ADDED
data/style/47.jpg ADDED
requirements.txt ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ accelerate==0.33.0
2
+ aiofiles==23.2.1
3
+ annotated-types==0.7.0
4
+ anyio==4.4.0
5
+ Brotli @ file:///croot/brotli-split_1714483155106/work
6
+ certifi @ file:///croot/certifi_1720453481653/work/certifi
7
+ charset-normalizer @ file:///croot/charset-normalizer_1721748349566/work
8
+ click==8.1.7
9
+ contourpy==1.2.1
10
+ cycler==0.12.1
11
+ diffusers==0.30.0
12
+ exceptiongroup==1.2.2
13
+ fastapi==0.112.0
14
+ ffmpy==0.4.0
15
+ filelock @ file:///croot/filelock_1700591183607/work
16
+ fonttools==4.53.1
17
+ fsspec==2024.6.1
18
+ gmpy2 @ file:///tmp/build/80754af9/gmpy2_1645438755360/work
19
+ gradio==4.41.0
20
+ gradio_client==1.3.0
21
+ h11==0.14.0
22
+ httpcore==1.0.5
23
+ httpx==0.27.0
24
+ huggingface-hub==0.24.5
25
+ idna @ file:///croot/idna_1714398848350/work
26
+ importlib_metadata==8.2.0
27
+ importlib_resources==6.4.0
28
+ Jinja2 @ file:///croot/jinja2_1716993405101/work
29
+ kiwisolver==1.4.5
30
+ markdown-it-py==3.0.0
31
+ MarkupSafe @ file:///croot/markupsafe_1704205993651/work
32
+ matplotlib==3.9.1.post1
33
+ mdurl==0.1.2
34
+ mkl-fft @ file:///croot/mkl_fft_1695058164594/work
35
+ mkl-random @ file:///croot/mkl_random_1695059800811/work
36
+ mkl-service==2.4.0
37
+ mpmath @ file:///croot/mpmath_1690848262763/work
38
+ mypy-extensions==1.0.0
39
+ networkx @ file:///croot/networkx_1717597493534/work
40
+ numpy @ file:///croot/numpy_and_numpy_base_1708638617955/work/dist/numpy-1.26.4-cp39-cp39-linux_x86_64.whl#sha256=6094eeedd869502faa0fd0a8c5ad3a70c5779be06ddd1feb7627e5c212fac420
41
+ orjson==3.10.7
42
+ packaging==24.1
43
+ pandas==2.2.2
44
+ peft==0.12.0
45
+ pillow @ file:///croot/pillow_1721059439630/work
46
+ psutil==6.0.0
47
+ pydantic==2.8.2
48
+ pydantic_core==2.20.1
49
+ pydub==0.25.1
50
+ Pygments==2.18.0
51
+ pyparsing==3.1.2
52
+ pyre-extensions==0.0.29
53
+ PySocks @ file:///tmp/build/80754af9/pysocks_1605305812635/work
54
+ python-dateutil==2.9.0.post0
55
+ python-multipart==0.0.9
56
+ pytz==2024.1
57
+ PyYAML==6.0.2
58
+ regex==2024.7.24
59
+ requests @ file:///croot/requests_1721410876868/work
60
+ rich==13.7.1
61
+ ruff==0.5.7
62
+ safetensors==0.4.4
63
+ semantic-version==2.10.0
64
+ shellingham==1.5.4
65
+ six==1.16.0
66
+ sniffio==1.3.1
67
+ starlette==0.37.2
68
+ sympy @ file:///croot/sympy_1701397643339/work
69
+ tokenizers==0.19.1
70
+ tomlkit==0.12.0
71
+ torch==2.0.1
72
+ torchaudio==2.0.2
73
+ torchvision==0.15.2
74
+ tqdm==4.66.5
75
+ transformers==4.44.0
76
+ triton==2.0.0
77
+ typer==0.12.3
78
+ typing-inspect==0.9.0
79
+ typing_extensions @ file:///croot/typing_extensions_1715268824938/work
80
+ tzdata==2024.1
81
+ urllib3 @ file:///croot/urllib3_1718912636303/work
82
+ uvicorn==0.30.5
83
+ websockets==12.0
84
+ xformers==0.0.20
85
+ zipp==3.19.2
utils/__init__.py ADDED
File without changes
utils/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (139 Bytes). View file
 
utils/__pycache__/__init__.cpython-39.pyc ADDED
Binary file (140 Bytes). View file
 
utils/__pycache__/attn_control.cpython-310.pyc ADDED
Binary file (19.8 kB). View file
 
utils/__pycache__/attn_control.cpython-39.pyc ADDED
Binary file (4.08 kB). View file
 
utils/__pycache__/free_lunch_utils.cpython-310.pyc ADDED
Binary file (12 kB). View file
 
utils/__pycache__/free_lunch_utils.cpython-39.pyc ADDED
Binary file (12.6 kB). View file
 
utils/__pycache__/masactrl_utils.cpython-310.pyc ADDED
Binary file (6.18 kB). View file
 
utils/__pycache__/masactrl_utils.cpython-39.pyc ADDED
Binary file (6.67 kB). View file
 
utils/__pycache__/merge.cpython-310.pyc ADDED
Binary file (4.05 kB). View file
 
utils/__pycache__/merge.cpython-39.pyc ADDED
Binary file (4 kB). View file
 
utils/__pycache__/patch.cpython-310.pyc ADDED
Binary file (7.38 kB). View file
 
utils/__pycache__/patch.cpython-39.pyc ADDED
Binary file (7.36 kB). View file
 
utils/__pycache__/pipeline.cpython-310.pyc ADDED
Binary file (6.76 kB). View file
 
utils/__pycache__/pipeline.cpython-39.pyc ADDED
Binary file (12 kB). View file
 
utils/__pycache__/pipeline_ead.cpython-310.pyc ADDED
Binary file (16 kB). View file
 
utils/__pycache__/pipeline_ead.cpython-39.pyc ADDED
Binary file (12.1 kB). View file
 
utils/__pycache__/pipeline_stable_diffusion_xl.cpython-310.pyc ADDED
Binary file (47.5 kB). View file
 
utils/__pycache__/pipeline_stable_diffusion_xl.cpython-39.pyc ADDED
Binary file (47.5 kB). View file
 
utils/__pycache__/pipeline_xl_edit.cpython-310.pyc ADDED
Binary file (14.3 kB). View file
 
utils/__pycache__/pipeline_xl_edit.cpython-39.pyc ADDED
Binary file (14.1 kB). View file
 
utils/__pycache__/ptp_utils.cpython-310.pyc ADDED
Binary file (5.97 kB). View file
 
utils/__pycache__/ptp_utils.cpython-39.pyc ADDED
Binary file (5.86 kB). View file
 
utils/__pycache__/style_attn_control.cpython-310.pyc ADDED
Binary file (8.98 kB). View file
 
utils/__pycache__/style_attn_control.cpython-39.pyc ADDED
Binary file (8.97 kB). View file
 
utils/__pycache__/superbeastsai.cpython-310.pyc ADDED
Binary file (5.64 kB). View file
 
utils/__pycache__/superbeastsai.cpython-39.pyc ADDED
Binary file (5.64 kB). View file
 
utils/__pycache__/utils.cpython-310.pyc ADDED
Binary file (950 Bytes). View file
 
utils/__pycache__/utils.cpython-39.pyc ADDED
Binary file (946 Bytes). View file
 
utils/attn_control.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn.functional as nnf
3
+ import abc
4
+ import math
5
+ from torchvision.utils import save_image
6
+
7
+
8
+ LOW_RESOURCE = False
9
+ MAX_NUM_WORDS = 77
10
+ device = "cuda" if torch.cuda.is_available() else "cpu"
11
+ torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
12
+
13
+
14
+
15
+ class AttentionControl(abc.ABC):
16
+
17
+ def step_callback(self, x_t):
18
+ return x_t
19
+
20
+ def between_steps(self):
21
+ return
22
+
23
+ @property
24
+ def start_att_layers(self):
25
+ return self.start_ac_layer #if LOW_RESOURCE else 0
26
+ @property
27
+ def end_att_layers(self):
28
+ return self.end_ac_layer
29
+
30
+
31
+
32
+
33
+ @abc.abstractmethod
34
+ def forward(self, q, k, v, num_heads,attn):
35
+ raise NotImplementedError
36
+
37
+ def attn_forward(self, q, k, v, num_heads,attention_probs,attn):
38
+ if q.shape[0]//num_heads == 3:
39
+ h_s_re = self.forward(q, k, v, num_heads,attention_probs, attn)
40
+
41
+ else:
42
+ uq,cq = q.chunk(2)
43
+ uk,ck = k.chunk(2)
44
+ uv,cv = v.chunk(2)
45
+ u_attn, c_attn = attention_probs.chunk(2)
46
+
47
+ u_h_s_re = self.forward(uq, uk, uv, num_heads,u_attn, attn)
48
+
49
+ c_h_s_re = self.forward(cq, ck, cv, num_heads,c_attn, attn)
50
+ h_s_re = (u_h_s_re, c_h_s_re)
51
+ return h_s_re
52
+
53
+ def __call__(self, q, k, v, num_heads,attention_probs,attn):
54
+
55
+
56
+ if self.cur_att_layer >= self.start_att_layers and self.cur_att_layer < self.end_att_layers:
57
+ h_s_re = self.attn_forward(q, k, v, num_heads,attention_probs,attn)
58
+ else:
59
+ h_s_re=None
60
+
61
+
62
+ self.cur_att_layer += 1
63
+
64
+ if self.cur_att_layer == self.num_att_layers // 2: #+ self.num_uncond_att_layers:
65
+ self.cur_att_layer = 0 #self.num_uncond_att_layers
66
+ self.cur_step += 1
67
+ self.between_steps()
68
+ return h_s_re
69
+
70
+ def reset(self):
71
+ self.cur_step = 0
72
+ self.cur_att_layer = 0
73
+
74
+ def __init__(self):
75
+ self.cur_step = 0
76
+ self.num_att_layers = -1
77
+ self.cur_att_layer = 0
78
+
79
+ def enhance_tensor(tensor: torch.Tensor, contrast_factor: float = 1.67) -> torch.Tensor:
80
+ """ Compute the attention map contrasting. """
81
+ mean_feat = tensor.mean(dim=-1, keepdims=True)
82
+ adjusted_tensor = (tensor - mean_feat) * contrast_factor + mean_feat
83
+ return adjusted_tensor
84
+
85
+ class AttentionStyle(AttentionControl):
86
+
87
+ def __init__(self,
88
+ num_steps,
89
+ start_ac_layer, end_ac_layer,
90
+ style_guidance=0.3,
91
+ mix_q_scale=1.0,
92
+ de_bug=False,
93
+ ):
94
+ super(AttentionStyle, self).__init__()
95
+
96
+
97
+ self.start_ac_layer = start_ac_layer
98
+ self.end_ac_layer = end_ac_layer
99
+ self.num_steps=num_steps
100
+ self.de_bug = de_bug
101
+ self.style_guidance = style_guidance
102
+ self.coef = None
103
+ self.mix_q_scale = mix_q_scale
104
+
105
+ def forward(self, q, k, v, num_heads, attention_probs, attn):
106
+
107
+
108
+ if self.de_bug:
109
+ import pdb; pdb.set_trace()
110
+
111
+ if self.mix_q_scale < 1.0:
112
+ q[num_heads*2:] = q[num_heads*2:] * self.mix_q_scale + (1 - self.mix_q_scale) * q[num_heads*1:num_heads*2]
113
+ b,n,d = k.shape
114
+ re_q = q[num_heads*2:] # b,n,d,
115
+ re_k = torch.cat([k[num_heads*1:num_heads*2],k[num_heads*0:num_heads*1]],dim=1) #b,2n,d
116
+ v_re = torch.cat([v[num_heads*1:num_heads*2],v[num_heads*0:num_heads*1]],dim=1) #b,2n,d
117
+ re_sim = torch.bmm(re_q, re_k.transpose(-1, -2)) * attn.scale
118
+ re_sim[:,:,n:] = re_sim[:,:,n:] * self.style_guidance
119
+ re_attention_map = re_sim.softmax(-1)
120
+ h_s_re = torch.bmm(re_attention_map, v_re)
121
+
122
+
123
+
124
+ return h_s_re
125
+
126
+
127
+
128
+
129
+
utils/merge.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from typing import Tuple, Callable
3
+
4
+
5
+ def do_nothing(x: torch.Tensor, mode:str=None):
6
+ return x
7
+
8
+
9
+ def mps_gather_workaround(input, dim, index):
10
+ if input.shape[-1] == 1:
11
+ return torch.gather(
12
+ input.unsqueeze(-1),
13
+ dim - 1 if dim < 0 else dim,
14
+ index.unsqueeze(-1)
15
+ ).squeeze(-1)
16
+ else:
17
+ return torch.gather(input, dim, index)
18
+
19
+
20
+ def bipartite_soft_matching_random2d(metric: torch.Tensor,
21
+ w: int, h: int, sx: int, sy: int, r: int,
22
+ no_rand: bool = False,
23
+ generator: torch.Generator = None) -> Tuple[Callable, Callable]:
24
+ """
25
+ Partitions the tokens into src and dst and merges r tokens from src to dst.
26
+ Dst tokens are partitioned by choosing one randomy in each (sx, sy) region.
27
+
28
+ Args:
29
+ - metric [B, N, C]: metric to use for similarity
30
+ - w: image width in tokens
31
+ - h: image height in tokens
32
+ - sx: stride in the x dimension for dst, must divide w
33
+ - sy: stride in the y dimension for dst, must divide h
34
+ - r: number of tokens to remove (by merging)
35
+ - no_rand: if true, disable randomness (use top left corner only)
36
+ - rand_seed: if no_rand is false, and if not None, sets random seed.
37
+ """
38
+ B, N, _ = metric.shape
39
+
40
+ if r <= 0:
41
+ return do_nothing, do_nothing
42
+
43
+ gather = mps_gather_workaround if metric.device.type == "mps" else torch.gather
44
+
45
+ with torch.no_grad():
46
+ hsy, wsx = h // sy, w // sx
47
+
48
+ # For each sy by sx kernel, randomly assign one token to be dst and the rest src
49
+ if no_rand:
50
+ rand_idx = torch.zeros(hsy, wsx, 1, device=metric.device, dtype=torch.int64)
51
+ else:
52
+ rand_idx = torch.randint(sy*sx, size=(hsy, wsx, 1), device=generator.device, generator=generator).to(metric.device)
53
+
54
+ # The image might not divide sx and sy, so we need to work on a view of the top left if the idx buffer instead
55
+ idx_buffer_view = torch.zeros(hsy, wsx, sy*sx, device=metric.device, dtype=torch.int64)
56
+ idx_buffer_view.scatter_(dim=2, index=rand_idx, src=-torch.ones_like(rand_idx, dtype=rand_idx.dtype))
57
+ idx_buffer_view = idx_buffer_view.view(hsy, wsx, sy, sx).transpose(1, 2).reshape(hsy * sy, wsx * sx)
58
+
59
+ # Image is not divisible by sx or sy so we need to move it into a new buffer
60
+ if (hsy * sy) < h or (wsx * sx) < w:
61
+ idx_buffer = torch.zeros(h, w, device=metric.device, dtype=torch.int64)
62
+ idx_buffer[:(hsy * sy), :(wsx * sx)] = idx_buffer_view
63
+ else:
64
+ idx_buffer = idx_buffer_view
65
+
66
+ # We set dst tokens to be -1 and src to be 0, so an argsort gives us dst|src indices
67
+ rand_idx = idx_buffer.reshape(1, -1, 1).argsort(dim=1)
68
+
69
+ # We're finished with these
70
+ del idx_buffer, idx_buffer_view
71
+
72
+ # rand_idx is currently dst|src, so split them
73
+ num_dst = hsy * wsx
74
+ a_idx = rand_idx[:, num_dst:, :] # src
75
+ b_idx = rand_idx[:, :num_dst, :] # dst
76
+
77
+ def split(x):
78
+ C = x.shape[-1]
79
+ src = gather(x, dim=1, index=a_idx.expand(B, N - num_dst, C))
80
+ dst = gather(x, dim=1, index=b_idx.expand(B, num_dst, C))
81
+ return src, dst
82
+
83
+ # Cosine similarity between A and B
84
+ metric = metric / metric.norm(dim=-1, keepdim=True)
85
+ a, b = split(metric)
86
+ scores = a @ b.transpose(-1, -2)
87
+
88
+ # Can't reduce more than the # tokens in src
89
+ r = min(a.shape[1], r)
90
+
91
+ # Find the most similar greedily
92
+ node_max, node_idx = scores.max(dim=-1)
93
+ edge_idx = node_max.argsort(dim=-1, descending=True)[..., None]
94
+
95
+ unm_idx = edge_idx[..., r:, :] # Unmerged Tokens
96
+ src_idx = edge_idx[..., :r, :] # Merged Tokens
97
+ dst_idx = gather(node_idx[..., None], dim=-2, index=src_idx)
98
+
99
+ def merge(x: torch.Tensor, mode="mean") -> torch.Tensor:
100
+ src, dst = split(x)
101
+ n, t1, c = src.shape
102
+
103
+ unm = gather(src, dim=-2, index=unm_idx.expand(n, t1 - r, c))
104
+ src = gather(src, dim=-2, index=src_idx.expand(n, r, c))
105
+ dst = dst.scatter_reduce(-2, dst_idx.expand(n, r, c), src, reduce=mode)
106
+
107
+ return torch.cat([unm, dst], dim=1)
108
+
109
+ def unmerge(x: torch.Tensor) -> torch.Tensor:
110
+ unm_len = unm_idx.shape[1]
111
+ unm, dst = x[..., :unm_len, :], x[..., unm_len:, :]
112
+ _, _, c = unm.shape
113
+
114
+ src = gather(dst, dim=-2, index=dst_idx.expand(B, r, c))
115
+
116
+ # Combine back to the original shape
117
+ out = torch.zeros(B, N, c, device=x.device, dtype=x.dtype)
118
+ out.scatter_(dim=-2, index=b_idx.expand(B, num_dst, c), src=dst)
119
+ out.scatter_(dim=-2, index=gather(a_idx.expand(B, a_idx.shape[1], 1), dim=1, index=unm_idx).expand(B, unm_len, c), src=unm)
120
+ out.scatter_(dim=-2, index=gather(a_idx.expand(B, a_idx.shape[1], 1), dim=1, index=src_idx).expand(B, r, c), src=src)
121
+
122
+ return out
123
+
124
+ return merge, unmerge
utils/pipeline.py ADDED
@@ -0,0 +1,434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import inspect
2
+ from typing import Any, Callable, Dict, List, Optional, Union
3
+ import os
4
+ import numpy as np
5
+ import PIL
6
+ import torch
7
+ from packaging import version
8
+ from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
9
+
10
+ from diffusers.configuration_utils import FrozenDict
11
+ from diffusers.image_processor import PipelineImageInput, VaeImageProcessor
12
+ from diffusers.loaders import LoraLoaderMixin, TextualInversionLoaderMixin
13
+ from diffusers.models import AutoencoderKL, UNet2DConditionModel
14
+ from diffusers.schedulers import LCMScheduler
15
+ from diffusers.utils import PIL_INTERPOLATION, deprecate, logging
16
+ from diffusers.utils.torch_utils import randn_tensor
17
+ from diffusers.pipelines.pipeline_utils import DiffusionPipeline
18
+ from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput
19
+ from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker
20
+
21
+ logger = logging.get_logger(__name__)
22
+
23
+
24
+
25
+ class ZePoPipeline(DiffusionPipeline, TextualInversionLoaderMixin, LoraLoaderMixin):
26
+ model_cpu_offload_seq = "text_encoder->unet->vae"
27
+ _optional_components = ["safety_checker", "feature_extractor"]
28
+
29
+ def __init__(
30
+ self,
31
+ vae: AutoencoderKL,
32
+ text_encoder: CLIPTextModel,
33
+ tokenizer: CLIPTokenizer,
34
+ unet: UNet2DConditionModel,
35
+ scheduler: LCMScheduler,
36
+ safety_checker: StableDiffusionSafetyChecker,
37
+ feature_extractor: CLIPImageProcessor,
38
+ requires_safety_checker: bool = True,
39
+ ):
40
+ super().__init__()
41
+
42
+ if hasattr(scheduler.config, "steps_offset") and scheduler.config.steps_offset != 1:
43
+ deprecation_message = (
44
+ f"The configuration file of this scheduler: {scheduler} is outdated. `steps_offset`"
45
+ f" should be set to 1 instead of {scheduler.config.steps_offset}. Please make sure "
46
+ "to update the config accordingly as leaving `steps_offset` might led to incorrect results"
47
+ " in future versions. If you have downloaded this checkpoint from the Hugging Face Hub,"
48
+ " it would be very nice if you could open a Pull request for the `scheduler/scheduler_config.json`"
49
+ " file"
50
+ )
51
+ deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False)
52
+ new_config = dict(scheduler.config)
53
+ new_config["steps_offset"] = 1
54
+ scheduler._internal_dict = FrozenDict(new_config)
55
+
56
+ if safety_checker is None and requires_safety_checker:
57
+ logger.warning(
58
+ f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`. Ensure"
59
+ " that you abide to the conditions of the Stable Diffusion license and do not expose unfiltered"
60
+ " results in services or applications open to the public. Both the diffusers team and Hugging Face"
61
+ " strongly recommend to keep the safety filter enabled in all public facing circumstances, disabling"
62
+ " it only for use-cases that involve analyzing network behavior or auditing its results. For more"
63
+ " information, please have a look at https://github.com/huggingface/diffusers/pull/254 ."
64
+ )
65
+
66
+ if safety_checker is not None and feature_extractor is None:
67
+ raise ValueError(
68
+ "Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety"
69
+ " checker. If you do not want to use the safety checker, you can pass `'safety_checker=None'` instead."
70
+ )
71
+ is_unet_version_less_0_9_0 = hasattr(unet.config, "_diffusers_version") and version.parse(
72
+ version.parse(unet.config._diffusers_version).base_version
73
+ ) < version.parse("0.9.0.dev0")
74
+ is_unet_sample_size_less_64 = hasattr(unet.config, "sample_size") and unet.config.sample_size < 64
75
+ if is_unet_version_less_0_9_0 and is_unet_sample_size_less_64:
76
+ deprecation_message = (
77
+ "The configuration file of the unet has set the default `sample_size` to smaller than"
78
+ " 64 which seems highly unlikely .If you're checkpoint is a fine-tuned version of any of the"
79
+ " following: \n- CompVis/stable-diffusion-v1-4 \n- CompVis/stable-diffusion-v1-3 \n-"
80
+ " CompVis/stable-diffusion-v1-2 \n- CompVis/stable-diffusion-v1-1 \n- runwayml/stable-diffusion-v1-5"
81
+ " \n- runwayml/stable-diffusion-inpainting \n you should change 'sample_size' to 64 in the"
82
+ " configuration file. Please make sure to update the config accordingly as leaving `sample_size=32`"
83
+ " in the config might lead to incorrect results in future versions. If you have downloaded this"
84
+ " checkpoint from the Hugging Face Hub, it would be very nice if you could open a Pull request for"
85
+ " the `unet/config.json` file"
86
+ )
87
+ deprecate("sample_size<64", "1.0.0", deprecation_message, standard_warn=False)
88
+ new_config = dict(unet.config)
89
+ new_config["sample_size"] = 64
90
+ unet._internal_dict = FrozenDict(new_config)
91
+
92
+ self.register_modules(
93
+ vae=vae,
94
+ text_encoder=text_encoder,
95
+ tokenizer=tokenizer,
96
+ unet=unet,
97
+ scheduler=scheduler,
98
+ safety_checker=safety_checker,
99
+ feature_extractor=feature_extractor,
100
+ )
101
+ self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1)
102
+ self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor)
103
+ self.register_to_config(requires_safety_checker=requires_safety_checker)
104
+
105
+ # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.StableDiffusionImg2ImgPipeline.check_inputs
106
+ def check_inputs(
107
+ self, prompt, strength, callback_steps, negative_prompt=None, prompt_embeds=None, negative_prompt_embeds=None
108
+ ):
109
+ if strength < 0 or strength > 1:
110
+ raise ValueError(f"The value of strength should in [0.0, 1.0] but is {strength}")
111
+
112
+ if (callback_steps is None) or (
113
+ callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0)
114
+ ):
115
+ raise ValueError(
116
+ f"`callback_steps` has to be a positive integer but is {callback_steps} of type"
117
+ f" {type(callback_steps)}."
118
+ )
119
+
120
+ if prompt is not None and prompt_embeds is not None:
121
+ raise ValueError(
122
+ f"Cannot forward both `prompt`: {prompt} and `prompt_embeds`: {prompt_embeds}. Please make sure to"
123
+ " only forward one of the two."
124
+ )
125
+ elif prompt is None and prompt_embeds is None:
126
+ raise ValueError(
127
+ "Provide either `prompt` or `prompt_embeds`. Cannot leave both `prompt` and `prompt_embeds` undefined."
128
+ )
129
+ elif prompt is not None and (not isinstance(prompt, str) and not isinstance(prompt, list)):
130
+ raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")
131
+
132
+ if negative_prompt is not None and negative_prompt_embeds is not None:
133
+ raise ValueError(
134
+ f"Cannot forward both `negative_prompt`: {negative_prompt} and `negative_prompt_embeds`:"
135
+ f" {negative_prompt_embeds}. Please make sure to only forward one of the two."
136
+ )
137
+
138
+ if prompt_embeds is not None and negative_prompt_embeds is not None:
139
+ if prompt_embeds.shape != negative_prompt_embeds.shape:
140
+ raise ValueError(
141
+ "`prompt_embeds` and `negative_prompt_embeds` must have the same shape when passed directly, but"
142
+ f" got: `prompt_embeds` {prompt_embeds.shape} != `negative_prompt_embeds`"
143
+ f" {negative_prompt_embeds.shape}."
144
+ )
145
+
146
+ def prepare_extra_step_kwargs(self, generator, eta):
147
+
148
+
149
+ accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())
150
+ extra_step_kwargs = {}
151
+ if accepts_eta:
152
+ extra_step_kwargs["eta"] = eta
153
+
154
+ # check if the scheduler accepts generator
155
+ accepts_generator = "generator" in set(inspect.signature(self.scheduler.step).parameters.keys())
156
+ if accepts_generator:
157
+ extra_step_kwargs["generator"] = generator
158
+ return extra_step_kwargs
159
+
160
+
161
+ # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.decode_latents
162
+ def decode_latents(self, latents):
163
+ deprecation_message = "The decode_latents method is deprecated and will be removed in 1.0.0. Please use VaeImageProcessor.postprocess(...) instead"
164
+ deprecate("decode_latents", "1.0.0", deprecation_message, standard_warn=False)
165
+
166
+ latents = 1 / self.vae.config.scaling_factor * latents
167
+ image = self.vae.decode(latents, return_dict=False)[0]
168
+ image = (image / 2 + 0.5).clamp(0, 1)
169
+ # we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16
170
+ image = image.cpu().permute(0, 2, 3, 1).float().numpy()
171
+ return image
172
+
173
+ # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.StableDiffusionImg2ImgPipeline.get_timesteps
174
+ def get_timesteps(self, num_inference_steps, strength, device):
175
+ # get the original timestep using init_timestep
176
+ init_timestep = min( int(num_inference_steps * strength), num_inference_steps)
177
+ init_timestep = max(init_timestep, 1)
178
+ t_start = max(num_inference_steps - init_timestep, 0)
179
+
180
+ timesteps = self.scheduler.timesteps[t_start * self.scheduler.order :]
181
+
182
+ return timesteps, num_inference_steps - t_start
183
+
184
+ def prepare_latents(self, image, timestep, device,dtype, denoise_model, generator=None):
185
+ image = image.to(device=device,dtype=dtype)
186
+
187
+ batch_size = image.shape[0]
188
+
189
+ if image.shape[1] == 4:
190
+ init_latents = image
191
+
192
+ else:
193
+ if isinstance(generator, list) and len(generator) != batch_size:
194
+ raise ValueError(
195
+ f"You have passed a list of generators of length {len(generator)}, but requested an effective batch"
196
+ f" size of {batch_size}. Make sure the batch size matches the length of the generators."
197
+ )
198
+
199
+ if isinstance(generator, list):
200
+ init_latents = [
201
+ self.vae.encode(image[i : i + 1]).latent_dist.sample(generator[i]) for i in range(batch_size)
202
+ ]
203
+ init_latents = torch.cat(init_latents, dim=0)
204
+ else:
205
+ init_latents = self.vae.encode(image).latent_dist.sample(generator)
206
+
207
+ init_latents = self.vae.config.scaling_factor * init_latents
208
+
209
+
210
+
211
+ # add noise to latents using the timestep
212
+ shape = init_latents.shape
213
+ noise = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
214
+
215
+ # get latents
216
+ clean_latents = init_latents
217
+ if denoise_model:
218
+ init_latents = self.scheduler.add_noise(init_latents, noise, timestep)
219
+ latents = init_latents
220
+ else:
221
+ latents = noise
222
+
223
+ return latents, clean_latents
224
+
225
+ @torch.no_grad()
226
+ def __call__(
227
+ self,
228
+ prompt: Union[str, List[str]],
229
+ negative_prompt: Union[str, List[str]]=None,
230
+ image: PipelineImageInput = None,
231
+ style: PipelineImageInput = None,
232
+ strength: float = 0.5,
233
+ num_inference_steps: Optional[int] = 50,
234
+ original_inference_steps: Optional[int] = 50,
235
+ guidance_scale: Optional[float] = 7.5,
236
+ eta: Optional[float] = 1.0,
237
+ generator: Optional[Union[torch.Generator, List[torch.Generator]]] = None,
238
+ prompt_embeds: Optional[torch.FloatTensor] = None,
239
+ output_type: Optional[str] = "pil",
240
+ return_dict: bool = True,
241
+ callback: Optional[Callable[[int, int, torch.FloatTensor], None]] = None,
242
+ callback_steps: int = 1,
243
+ cross_attention_kwargs: Optional[Dict[str, Any]] = None,
244
+ denoise_model: Optional[bool] = True,
245
+ fix_step_index = 0,
246
+ target_start_step = -1,
247
+ save_intermediate = False,
248
+ de_bug=False,
249
+
250
+ ):
251
+ # 1. Check inputs
252
+ self.check_inputs(prompt, strength, callback_steps)
253
+ num_inference_steps = int(num_inference_steps * (1/strength))
254
+ print(f'num_inference_steps {num_inference_steps} is multiple by {int(1/strength)}.')
255
+ # 2. Define call parameters
256
+ batch_size = len(prompt)
257
+ device = self._execution_device
258
+ # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
259
+ # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
260
+ # corresponds to doing no classifier free guidance.
261
+ do_classifier_free_guidance = guidance_scale > 1.0
262
+
263
+
264
+ # text embeddings
265
+ text_input = self.tokenizer(
266
+ prompt,
267
+ padding="max_length",
268
+ max_length=77,
269
+ return_tensors="pt"
270
+ )
271
+ dtype=self.unet.dtype
272
+ prompt_embeds = self.text_encoder(text_input.input_ids.to(device))[0]
273
+ prompt_embeds=prompt_embeds.to(dtype=dtype, device=device)
274
+ #print("input text embeddings :", prompt_embeds.shape)
275
+
276
+ if guidance_scale > 1.:
277
+ max_length = text_input.input_ids.shape[-1]
278
+ if negative_prompt:
279
+ uc_text = negative_prompt
280
+ else:
281
+ uc_text = ""
282
+ # uc_text = "ugly, tiling, poorly drawn hands, poorly drawn feet, body out of frame, cut off, low contrast, underexposed, distorted face"
283
+ unconditional_input = self.tokenizer(
284
+ [uc_text] * batch_size,
285
+ padding="max_length",
286
+ max_length=77,
287
+ return_tensors="pt"
288
+ )
289
+ # unconditional_input.input_ids = unconditional_input.input_ids[:, 1:]
290
+ unconditional_embeddings = self.text_encoder(unconditional_input.input_ids.to(device))[0]
291
+ unconditional_embeddings=unconditional_embeddings.to(dtype=dtype, device=device)
292
+ prompt_embeds = torch.cat([unconditional_embeddings, prompt_embeds], dim=0)
293
+
294
+ #print("prompt embeds shape: ", prompt_embeds.shape)
295
+
296
+
297
+ # 4. Preprocess image
298
+ image = self.image_processor.preprocess(image)
299
+ style = self.image_processor.preprocess(style)
300
+
301
+ # 5. Prepare timesteps
302
+ if isinstance(self.scheduler, LCMScheduler):
303
+ self.scheduler.set_timesteps(
304
+ num_inference_steps=num_inference_steps,
305
+ device=device,
306
+ original_inference_steps=original_inference_steps)
307
+ else:
308
+ self.scheduler.set_timesteps(
309
+ num_inference_steps=num_inference_steps,
310
+ device=device,)
311
+ print(f"num_inference_steps is {self.scheduler.timesteps}")
312
+ timesteps, num_inference_steps = self.get_timesteps(num_inference_steps, strength, device)
313
+
314
+ #print(f"All timesteps is : {timesteps}")
315
+ latent_timestep = torch.tensor([fix_step_index], device=device)
316
+
317
+ assert timesteps != []
318
+
319
+ print("The time-steps are: ", timesteps)
320
+
321
+ # 6. Prepare latent variables
322
+ src_latents, src_clean_latents = self.prepare_latents(
323
+ image, latent_timestep, device,dtype, denoise_model, generator
324
+ )
325
+
326
+
327
+ sty_latents, sty_clean_latents = self.prepare_latents(
328
+ style, latent_timestep, device,dtype, denoise_model, generator
329
+ )
330
+
331
+
332
+ mutual_latents, _ = self.prepare_latents(
333
+ image, timesteps[:1], device, dtype, denoise_model, generator
334
+ )
335
+
336
+ # mutual_latents = src_latents
337
+ #latents = torch.cat([sty_t_latents, src_t_latents], dim=0)
338
+ # 7. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
339
+ extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
340
+ generator = extra_step_kwargs.pop("generator", None)
341
+
342
+ # 8. Denoising loop
343
+ num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order
344
+ with self.progress_bar(total=num_inference_steps) as progress_bar:
345
+ for i, t in enumerate(timesteps):
346
+ if de_bug:
347
+
348
+ import pdb; pdb.set_trace()
349
+
350
+ model_input = torch.cat(
351
+ [
352
+ sty_latents,
353
+ src_latents,
354
+ mutual_latents
355
+
356
+ ],
357
+ dim=0,
358
+ )
359
+ # predict the noise residual
360
+ if do_classifier_free_guidance:
361
+ concat_latent_model_input = torch.cat([model_input] * 2)
362
+ concat_prompt_embeds = prompt_embeds
363
+ #raise NotImplementedError("Classifier free guidance is not yet supported")
364
+ else:
365
+ concat_latent_model_input = model_input
366
+ concat_prompt_embeds = prompt_embeds
367
+ assert len(concat_prompt_embeds) == len(concat_latent_model_input)
368
+
369
+ timestep = torch.cat([latent_timestep] * (batch_size-1)+[t[None]], dim=0)
370
+
371
+ if do_classifier_free_guidance:
372
+ timestep = torch.cat([timestep] * 2)
373
+
374
+
375
+ concat_noise_pred = self.unet(
376
+ concat_latent_model_input,
377
+ timestep,
378
+ cross_attention_kwargs=cross_attention_kwargs,
379
+ encoder_hidden_states=concat_prompt_embeds,
380
+ ).sample
381
+ # perform guidance
382
+ if do_classifier_free_guidance:
383
+
384
+ (
385
+ noise_pred,
386
+ noise_pred_uncond,
387
+ ) = concat_noise_pred.chunk(2, dim=0)
388
+
389
+
390
+ noise_pred = noise_pred_uncond + guidance_scale * (noise_pred - noise_pred_uncond)
391
+
392
+ else:
393
+ noise_pred = concat_noise_pred
394
+
395
+ (style_noise_pred, source_noise_pred, mutual_noise_pred) = noise_pred.chunk(3, dim=0)
396
+
397
+ noise = torch.randn_like(
398
+ source_noise_pred
399
+ )
400
+
401
+
402
+ if isinstance(self.scheduler, LCMScheduler):
403
+ mutual_latents, pred_x0_mutual = self.scheduler.step(mutual_noise_pred, t, mutual_latents, return_dict=False)
404
+ else:
405
+ ddim_out = self.scheduler.step(mutual_noise_pred, t, mutual_latents)
406
+ mutual_latents, pred_x0_mutual = ddim_out.prev_sample, ddim_out.pred_original_sample
407
+
408
+
409
+ pred_x0 = torch.cat([sty_clean_latents,src_clean_latents,pred_x0_mutual ], dim=0)
410
+
411
+ if i == len(timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):
412
+ progress_bar.update()
413
+
414
+ model_input = torch.cat([sty_latents,src_latents,mutual_latents],dim=0,)
415
+
416
+ # 9. Post-processing
417
+ if not output_type == "latent":
418
+ image = self.vae.decode(pred_x0 / self.vae.config.scaling_factor, return_dict=False)[0]
419
+ has_nsfw_concept = None
420
+ else:
421
+ image = pred_x0
422
+ has_nsfw_concept = None
423
+
424
+ if has_nsfw_concept is None:
425
+ do_denormalize = [True] * image.shape[0]
426
+ else:
427
+ do_denormalize = [not has_nsfw for has_nsfw in has_nsfw_concept]
428
+
429
+ image = self.image_processor.postprocess(image, output_type='np', do_denormalize=do_denormalize)
430
+
431
+ if not return_dict:
432
+ return (image, has_nsfw_concept)
433
+
434
+ return StableDiffusionPipelineOutput(images=image, nsfw_content_detected=has_nsfw_concept)
utils/ptp_utils.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import numpy as np
16
+ import torch
17
+ from typing import Optional, Union, Tuple, Dict
18
+ from PIL import Image
19
+ from . import merge
20
+ from .utils import isinstance_str, init_generator
21
+
22
+ def save_images(images,dest, num_rows=1, offset_ratio=0.02):
23
+ if type(images) is list:
24
+ num_empty = len(images) % num_rows
25
+ elif images.ndim == 4:
26
+ num_empty = images.shape[0] % num_rows
27
+ else:
28
+ images = [images]
29
+ num_empty = 0
30
+
31
+ pil_img = Image.fromarray(images[-1])
32
+ pil_img.save(dest)
33
+ # display(pil_img)
34
+
35
+
36
+ def save_image(images,dest, num_rows=1, offset_ratio=0.02):
37
+ print(images.shape)
38
+ pil_img = Image.fromarray(images[0])
39
+ pil_img.save(dest)
40
+
41
+ def register_attention_control(model, controller, tome, ratio, sx, sy, de_bug):
42
+ class AttnProcessor():
43
+ def __init__(self,place_in_unet,de_bug):
44
+ self.place_in_unet = place_in_unet
45
+ self.de_bug = de_bug
46
+ def __call__(self,
47
+ attn,
48
+ hidden_states,
49
+ encoder_hidden_states=None,
50
+ attention_mask=None,
51
+ temb=None,
52
+ scale=1.0,):
53
+ # The `Attention` class can call different attention processors / attention functions
54
+
55
+ residual = hidden_states
56
+
57
+ if attn.spatial_norm is not None:
58
+ hidden_states = attn.spatial_norm(hidden_states, temb)
59
+
60
+ input_ndim = hidden_states.ndim
61
+
62
+ if input_ndim == 4:
63
+ batch_size, channel, height, width = hidden_states.shape
64
+ hidden_states = hidden_states.view(batch_size, channel, height * width).transpose(1, 2)
65
+
66
+ h = attn.heads
67
+ is_cross = encoder_hidden_states is not None
68
+ if encoder_hidden_states is None:
69
+ encoder_hidden_states = hidden_states
70
+ elif attn.norm_cross:
71
+ encoder_hidden_states = attn.norm_encoder_hidden_states(encoder_hidden_states)
72
+
73
+ batch_size, sequence_length, _ = (
74
+ hidden_states.shape if encoder_hidden_states is None else encoder_hidden_states.shape
75
+ )
76
+ attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size)
77
+
78
+
79
+
80
+
81
+ q = attn.to_q(hidden_states)
82
+ k = attn.to_k(encoder_hidden_states)
83
+ v = attn.to_v(encoder_hidden_states)
84
+ q = attn.head_to_batch_dim(q)
85
+ k = attn.head_to_batch_dim(k)
86
+ v = attn.head_to_batch_dim(v)
87
+
88
+
89
+ # print('unmerge:', q.shape)
90
+ #pass
91
+ attention_probs = attn.get_attention_scores(q, k, attention_mask) # bh,n,n
92
+
93
+ #
94
+
95
+ if is_cross:
96
+ pass
97
+ #attention_probs = controller(attention_probs , is_cross, self.place_in_unet)
98
+ x = hidden_states
99
+
100
+ hidden_states = torch.bmm(attention_probs, v)
101
+
102
+ if not is_cross:
103
+
104
+ if tome:
105
+
106
+ r = int(x.shape[1] * ratio)
107
+ H = W = int(np.sqrt(x.shape[1]))
108
+ generator = init_generator(x.device)
109
+ m, u = merge.bipartite_soft_matching_random2d(x, W, H, sx, sy, r,
110
+ no_rand=False, generator=generator)
111
+ x = m(x)
112
+ m_k = attn.to_k(x)
113
+ m_v = attn.to_v(x)
114
+ m_k = attn.head_to_batch_dim(m_k)
115
+ m_v = attn.head_to_batch_dim(m_v)
116
+ # print('merged:', m_q.shape)
117
+ # m_k = k
118
+ # m_v = v
119
+ #m_k, m_v = map(lambda t: rearrange(t, 'b n (h d) -> (b h) n d', h=h), (m_k, m_v))
120
+ else:
121
+ m_k = k
122
+ m_v = v
123
+ # if self.de_bug:
124
+ # import pdb;pdb.set_trace()
125
+ h_s_re = controller(q, m_k, m_v, attn.heads, attention_probs, attn)
126
+
127
+ if h_s_re != None and hidden_states.shape[0]//attn.heads == 3:
128
+
129
+ hidden_states[2*attn.heads:]=h_s_re
130
+
131
+ if hidden_states.shape[0]//attn.heads != 3 and h_s_re != None:
132
+ (u_h_s_re, c_h_s_re) = h_s_re
133
+ if u_h_s_re != None:
134
+
135
+ hidden_states[2*attn.heads:3*attn.heads] = u_h_s_re
136
+ hidden_states[5*attn.heads:] = c_h_s_re
137
+ hidden_states = attn.batch_to_head_dim(hidden_states)
138
+
139
+ # linear proj
140
+ hidden_states = attn.to_out[0](hidden_states)
141
+ # dropout
142
+ hidden_states = attn.to_out[1](hidden_states)
143
+
144
+ if input_ndim == 4:
145
+ hidden_states = hidden_states.transpose(-1, -2).reshape(batch_size, channel, height, width)
146
+
147
+ if attn.residual_connection:
148
+ hidden_states = hidden_states + residual
149
+
150
+ hidden_states = hidden_states / attn.rescale_output_factor
151
+
152
+ return hidden_states
153
+
154
+
155
+ def register_recr(net_, count, place_in_unet):
156
+ for idx, m in enumerate(net_.modules()):
157
+ # print(m.__class__.__name__)
158
+ if m.__class__.__name__ == "Attention":
159
+ count+=1
160
+ m.processor = AttnProcessor( place_in_unet, de_bug)
161
+ return count
162
+
163
+ cross_att_count = 0
164
+ sub_nets = model.unet.named_children()
165
+ for net in sub_nets:
166
+ if "down" in net[0]:
167
+ cross_att_count += register_recr(net[1], 0, "down")
168
+ elif "up" in net[0]:
169
+ cross_att_count += register_recr(net[1], 0, "up")
170
+ elif "mid" in net[0]:
171
+ cross_att_count += register_recr(net[1], 0, "mid")
172
+ controller.num_att_layers = cross_att_count
173
+ #print(f'this model have {cross_att_count} attn layer')
174
+
175
+ def get_word_inds(text: str, word_place: int, tokenizer):
176
+ split_text = text.split(" ")
177
+ if type(word_place) is str:
178
+ word_place = [i for i, word in enumerate(split_text) if word_place == word]
179
+ elif type(word_place) is int:
180
+ word_place = [word_place]
181
+ out = []
182
+ if len(word_place) > 0:
183
+ words_encode = [tokenizer.decode([item]).strip("#") for item in tokenizer.encode(text)][1:-1]
184
+ cur_len, ptr = 0, 0
185
+
186
+ for i in range(len(words_encode)):
187
+ cur_len += len(words_encode[i])
188
+ if ptr in word_place:
189
+ out.append(i + 1)
190
+ if cur_len >= len(split_text[ptr]):
191
+ ptr += 1
192
+ cur_len = 0
193
+ return np.array(out)
194
+
195
+
196
+ def update_alpha_time_word(alpha, bounds: Union[float, Tuple[float, float]], prompt_ind: int, word_inds: Optional[torch.Tensor]=None):
197
+ if type(bounds) is float:
198
+ bounds = 0, bounds
199
+ start, end = int(bounds[0] * alpha.shape[0]), int(bounds[1] * alpha.shape[0])
200
+ if word_inds is None:
201
+ word_inds = torch.arange(alpha.shape[2])
202
+ alpha[: start, prompt_ind, word_inds] = 0
203
+ alpha[start: end, prompt_ind, word_inds] = 1
204
+ alpha[end:, prompt_ind, word_inds] = 0
205
+ return alpha
206
+
207
+
208
+ def get_time_words_attention_alpha(prompts, num_steps, cross_replace_steps: Union[float, Tuple[float, float], Dict[str, Tuple[float, float]]],
209
+ tokenizer, max_num_words=77):
210
+ if type(cross_replace_steps) is not dict:
211
+ cross_replace_steps = {"default_": cross_replace_steps}
212
+ if "default_" not in cross_replace_steps:
213
+ cross_replace_steps["default_"] = (0., 1.)
214
+ alpha_time_words = torch.zeros(num_steps + 1, len(prompts) - 1, max_num_words)
215
+ for i in range(len(prompts) - 1):
216
+ alpha_time_words = update_alpha_time_word(alpha_time_words, cross_replace_steps["default_"],
217
+ i)
218
+ for key, item in cross_replace_steps.items():
219
+ if key != "default_":
220
+ inds = [get_word_inds(prompts[i], key, tokenizer) for i in range(1, len(prompts))]
221
+ for i, ind in enumerate(inds):
222
+ if len(ind) > 0:
223
+ alpha_time_words = update_alpha_time_word(alpha_time_words, item, i, ind)
224
+ alpha_time_words = alpha_time_words.reshape(num_steps + 1, len(prompts) - 1, 1, 1, max_num_words) # time, batch, heads, pixels, words
225
+ return alpha_time_words
utils/utils.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+
4
+ def isinstance_str(x: object, cls_name: str):
5
+ """
6
+ Checks whether x has any class *named* cls_name in its ancestry.
7
+ Doesn't require access to the class's implementation.
8
+
9
+ Useful for patching!
10
+ """
11
+
12
+ for _cls in x.__class__.__mro__:
13
+ if _cls.__name__ == cls_name:
14
+ return True
15
+
16
+ return False
17
+
18
+
19
+ def init_generator(device: torch.device, fallback: torch.Generator=None):
20
+ """
21
+ Forks the current default random generator given device.
22
+ """
23
+ if device.type == "cpu":
24
+ return torch.Generator(device="cpu").set_state(torch.get_rng_state())
25
+ elif device.type == "cuda":
26
+ return torch.Generator(device=device).set_state(torch.cuda.get_rng_state())
27
+ else:
28
+ if fallback is None:
29
+ return init_generator(torch.device("cpu"))
30
+ else:
31
+ return fallback
32
+