comdoleger commited on
Commit
3af8e71
·
verified ·
1 Parent(s): 36ccbe3

Upload testing/generate_weight_mappings.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. testing/generate_weight_mappings.py +479 -0
testing/generate_weight_mappings.py ADDED
@@ -0,0 +1,479 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import gc
3
+ import os
4
+ import re
5
+ import os
6
+ # add project root to sys path
7
+ import sys
8
+
9
+ from diffusers import DiffusionPipeline, StableDiffusionXLPipeline
10
+
11
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
12
+
13
+ import torch
14
+ from diffusers.loaders import LoraLoaderMixin
15
+ from safetensors.torch import load_file, save_file
16
+ from collections import OrderedDict
17
+ import json
18
+ from tqdm import tqdm
19
+
20
+ from toolkit.config_modules import ModelConfig
21
+ from toolkit.stable_diffusion_model import StableDiffusion
22
+
23
+ KEYMAPS_FOLDER = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'toolkit', 'keymaps')
24
+
25
+ device = torch.device('cpu')
26
+ dtype = torch.float32
27
+
28
+
29
+ def flush():
30
+ torch.cuda.empty_cache()
31
+ gc.collect()
32
+
33
+
34
+ def get_reduced_shape(shape_tuple):
35
+ # iterate though shape anr remove 1s
36
+ new_shape = []
37
+ for dim in shape_tuple:
38
+ if dim != 1:
39
+ new_shape.append(dim)
40
+ return tuple(new_shape)
41
+
42
+
43
+ parser = argparse.ArgumentParser()
44
+
45
+ # require at lease one config file
46
+ parser.add_argument(
47
+ 'file_1',
48
+ nargs='+',
49
+ type=str,
50
+ help='Path to first safe tensor file'
51
+ )
52
+
53
+ parser.add_argument('--name', type=str, default='stable_diffusion', help='name for mapping to make')
54
+ parser.add_argument('--sdxl', action='store_true', help='is sdxl model')
55
+ parser.add_argument('--refiner', action='store_true', help='is refiner model')
56
+ parser.add_argument('--ssd', action='store_true', help='is ssd model')
57
+ parser.add_argument('--vega', action='store_true', help='is vega model')
58
+ parser.add_argument('--sd2', action='store_true', help='is sd 2 model')
59
+
60
+ args = parser.parse_args()
61
+
62
+ file_path = args.file_1[0]
63
+
64
+ find_matches = False
65
+
66
+ print(f'Loading diffusers model')
67
+
68
+ ignore_ldm_begins_with = []
69
+
70
+ diffusers_file_path = file_path if len(args.file_1) == 1 else args.file_1[1]
71
+ if args.ssd:
72
+ diffusers_file_path = "segmind/SSD-1B"
73
+ if args.vega:
74
+ diffusers_file_path = "segmind/Segmind-Vega"
75
+
76
+ # if args.refiner:
77
+ # diffusers_file_path = "stabilityai/stable-diffusion-xl-refiner-1.0"
78
+
79
+ if not args.refiner:
80
+
81
+ diffusers_model_config = ModelConfig(
82
+ name_or_path=diffusers_file_path,
83
+ is_xl=args.sdxl,
84
+ is_v2=args.sd2,
85
+ is_ssd=args.ssd,
86
+ is_vega=args.vega,
87
+ dtype=dtype,
88
+ )
89
+ diffusers_sd = StableDiffusion(
90
+ model_config=diffusers_model_config,
91
+ device=device,
92
+ dtype=dtype,
93
+ )
94
+ diffusers_sd.load_model()
95
+ # delete things we dont need
96
+ del diffusers_sd.tokenizer
97
+ flush()
98
+
99
+ print(f'Loading ldm model')
100
+ diffusers_state_dict = diffusers_sd.state_dict()
101
+ else:
102
+ # refiner wont work directly with stable diffusion
103
+ # so we need to load the model and then load the state dict
104
+ diffusers_pipeline = StableDiffusionXLPipeline.from_single_file(
105
+ diffusers_file_path,
106
+ torch_dtype=torch.float16,
107
+ use_safetensors=True,
108
+ variant="fp16",
109
+ ).to(device)
110
+ # diffusers_pipeline = StableDiffusionXLPipeline.from_single_file(
111
+ # file_path,
112
+ # torch_dtype=torch.float16,
113
+ # use_safetensors=True,
114
+ # variant="fp16",
115
+ # ).to(device)
116
+
117
+ SD_PREFIX_VAE = "vae"
118
+ SD_PREFIX_UNET = "unet"
119
+ SD_PREFIX_REFINER_UNET = "refiner_unet"
120
+ SD_PREFIX_TEXT_ENCODER = "te"
121
+
122
+ SD_PREFIX_TEXT_ENCODER1 = "te0"
123
+ SD_PREFIX_TEXT_ENCODER2 = "te1"
124
+
125
+ diffusers_state_dict = OrderedDict()
126
+ for k, v in diffusers_pipeline.vae.state_dict().items():
127
+ new_key = k if k.startswith(f"{SD_PREFIX_VAE}") else f"{SD_PREFIX_VAE}_{k}"
128
+ diffusers_state_dict[new_key] = v
129
+ for k, v in diffusers_pipeline.text_encoder_2.state_dict().items():
130
+ new_key = k if k.startswith(f"{SD_PREFIX_TEXT_ENCODER2}_") else f"{SD_PREFIX_TEXT_ENCODER2}_{k}"
131
+ diffusers_state_dict[new_key] = v
132
+ for k, v in diffusers_pipeline.unet.state_dict().items():
133
+ new_key = k if k.startswith(f"{SD_PREFIX_UNET}_") else f"{SD_PREFIX_UNET}_{k}"
134
+ diffusers_state_dict[new_key] = v
135
+
136
+ # add ignore ones as we are only going to focus on unet and copy the rest
137
+ # ignore_ldm_begins_with = ["conditioner.", "first_stage_model."]
138
+
139
+ diffusers_dict_keys = list(diffusers_state_dict.keys())
140
+
141
+ ldm_state_dict = load_file(file_path)
142
+ ldm_dict_keys = list(ldm_state_dict.keys())
143
+
144
+ ldm_diffusers_keymap = OrderedDict()
145
+ ldm_diffusers_shape_map = OrderedDict()
146
+ ldm_operator_map = OrderedDict()
147
+ diffusers_operator_map = OrderedDict()
148
+
149
+ total_keys = len(ldm_dict_keys)
150
+
151
+ matched_ldm_keys = []
152
+ matched_diffusers_keys = []
153
+
154
+ error_margin = 1e-8
155
+
156
+ tmp_merge_key = "TMP___MERGE"
157
+
158
+ te_suffix = ''
159
+ proj_pattern_weight = None
160
+ proj_pattern_bias = None
161
+ text_proj_layer = None
162
+ if args.sdxl or args.ssd or args.vega:
163
+ te_suffix = '1'
164
+ ldm_res_block_prefix = "conditioner.embedders.1.model.transformer.resblocks"
165
+ proj_pattern_weight = r"conditioner\.embedders\.1\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_weight"
166
+ proj_pattern_bias = r"conditioner\.embedders\.1\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_bias"
167
+ text_proj_layer = "conditioner.embedders.1.model.text_projection"
168
+ if args.refiner:
169
+ te_suffix = '1'
170
+ ldm_res_block_prefix = "conditioner.embedders.0.model.transformer.resblocks"
171
+ proj_pattern_weight = r"conditioner\.embedders\.0\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_weight"
172
+ proj_pattern_bias = r"conditioner\.embedders\.0\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_bias"
173
+ text_proj_layer = "conditioner.embedders.0.model.text_projection"
174
+ if args.sd2:
175
+ te_suffix = ''
176
+ ldm_res_block_prefix = "cond_stage_model.model.transformer.resblocks"
177
+ proj_pattern_weight = r"cond_stage_model\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_weight"
178
+ proj_pattern_bias = r"cond_stage_model\.model\.transformer\.resblocks\.(\d+)\.attn\.in_proj_bias"
179
+ text_proj_layer = "cond_stage_model.model.text_projection"
180
+
181
+ if args.sdxl or args.sd2 or args.ssd or args.refiner or args.vega:
182
+ if "conditioner.embedders.1.model.text_projection" in ldm_dict_keys:
183
+ # d_model = int(checkpoint[prefix + "text_projection"].shape[0]))
184
+ d_model = int(ldm_state_dict["conditioner.embedders.1.model.text_projection"].shape[0])
185
+ elif "conditioner.embedders.1.model.text_projection.weight" in ldm_dict_keys:
186
+ # d_model = int(checkpoint[prefix + "text_projection"].shape[0]))
187
+ d_model = int(ldm_state_dict["conditioner.embedders.1.model.text_projection.weight"].shape[0])
188
+ elif "conditioner.embedders.0.model.text_projection" in ldm_dict_keys:
189
+ # d_model = int(checkpoint[prefix + "text_projection"].shape[0]))
190
+ d_model = int(ldm_state_dict["conditioner.embedders.0.model.text_projection"].shape[0])
191
+ else:
192
+ d_model = 1024
193
+
194
+ # do pre known merging
195
+ for ldm_key in ldm_dict_keys:
196
+ try:
197
+ match = re.match(proj_pattern_weight, ldm_key)
198
+ if match:
199
+ if ldm_key == "conditioner.embedders.1.model.transformer.resblocks.0.attn.in_proj_weight":
200
+ print("here")
201
+ number = int(match.group(1))
202
+ new_val = torch.cat([
203
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.weight"],
204
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.weight"],
205
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.weight"],
206
+ ], dim=0)
207
+ # add to matched so we dont check them
208
+ matched_diffusers_keys.append(
209
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.weight")
210
+ matched_diffusers_keys.append(
211
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.weight")
212
+ matched_diffusers_keys.append(
213
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.weight")
214
+ # make diffusers convertable_dict
215
+ diffusers_state_dict[
216
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.{tmp_merge_key}.weight"] = new_val
217
+
218
+ # add operator
219
+ ldm_operator_map[ldm_key] = {
220
+ "cat": [
221
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.weight",
222
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.weight",
223
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.weight",
224
+ ],
225
+ }
226
+
227
+ matched_ldm_keys.append(ldm_key)
228
+
229
+ # text_model_dict[new_key + ".q_proj.weight"] = checkpoint[key][:d_model, :]
230
+ # text_model_dict[new_key + ".k_proj.weight"] = checkpoint[key][d_model: d_model * 2, :]
231
+ # text_model_dict[new_key + ".v_proj.weight"] = checkpoint[key][d_model * 2:, :]
232
+
233
+ # add diffusers operators
234
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.weight"] = {
235
+ "slice": [
236
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_weight",
237
+ f"0:{d_model}, :"
238
+ ]
239
+ }
240
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.weight"] = {
241
+ "slice": [
242
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_weight",
243
+ f"{d_model}:{d_model * 2}, :"
244
+ ]
245
+ }
246
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.weight"] = {
247
+ "slice": [
248
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_weight",
249
+ f"{d_model * 2}:, :"
250
+ ]
251
+ }
252
+
253
+ match = re.match(proj_pattern_bias, ldm_key)
254
+ if match:
255
+ number = int(match.group(1))
256
+ new_val = torch.cat([
257
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.bias"],
258
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.bias"],
259
+ diffusers_state_dict[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.bias"],
260
+ ], dim=0)
261
+ # add to matched so we dont check them
262
+ matched_diffusers_keys.append(f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.bias")
263
+ matched_diffusers_keys.append(f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.bias")
264
+ matched_diffusers_keys.append(f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.bias")
265
+ # make diffusers convertable_dict
266
+ diffusers_state_dict[
267
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.{tmp_merge_key}.bias"] = new_val
268
+
269
+ # add operator
270
+ ldm_operator_map[ldm_key] = {
271
+ "cat": [
272
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.bias",
273
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.bias",
274
+ f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.bias",
275
+ ],
276
+ }
277
+
278
+ matched_ldm_keys.append(ldm_key)
279
+
280
+ # add diffusers operators
281
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.q_proj.bias"] = {
282
+ "slice": [
283
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_bias",
284
+ f"0:{d_model}, :"
285
+ ]
286
+ }
287
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.k_proj.bias"] = {
288
+ "slice": [
289
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_bias",
290
+ f"{d_model}:{d_model * 2}, :"
291
+ ]
292
+ }
293
+ diffusers_operator_map[f"te{te_suffix}_text_model.encoder.layers.{number}.self_attn.v_proj.bias"] = {
294
+ "slice": [
295
+ f"{ldm_res_block_prefix}.{number}.attn.in_proj_bias",
296
+ f"{d_model * 2}:, :"
297
+ ]
298
+ }
299
+ except Exception as e:
300
+ print(f"Error on key {ldm_key}")
301
+ print(e)
302
+
303
+ # update keys
304
+ diffusers_dict_keys = list(diffusers_state_dict.keys())
305
+
306
+ pbar = tqdm(ldm_dict_keys, desc='Matching ldm-diffusers keys', total=total_keys)
307
+ # run through all weights and check mse between them to find matches
308
+ for ldm_key in ldm_dict_keys:
309
+ ldm_shape_tuple = ldm_state_dict[ldm_key].shape
310
+ ldm_reduced_shape_tuple = get_reduced_shape(ldm_shape_tuple)
311
+ for diffusers_key in diffusers_dict_keys:
312
+ if ldm_key == "conditioner.embedders.1.model.transformer.resblocks.0.attn.in_proj_weight" and diffusers_key == "te1_text_model.encoder.layers.0.self_attn.q_proj.weight":
313
+ print("here")
314
+
315
+ diffusers_shape_tuple = diffusers_state_dict[diffusers_key].shape
316
+ diffusers_reduced_shape_tuple = get_reduced_shape(diffusers_shape_tuple)
317
+
318
+ # That was easy. Same key
319
+ # if ldm_key == diffusers_key:
320
+ # ldm_diffusers_keymap[ldm_key] = diffusers_key
321
+ # matched_ldm_keys.append(ldm_key)
322
+ # matched_diffusers_keys.append(diffusers_key)
323
+ # break
324
+
325
+ # if we already have this key mapped, skip it
326
+ if diffusers_key in matched_diffusers_keys:
327
+ continue
328
+
329
+ # if reduced shapes do not match skip it
330
+ if ldm_reduced_shape_tuple != diffusers_reduced_shape_tuple:
331
+ continue
332
+
333
+ ldm_weight = ldm_state_dict[ldm_key]
334
+ did_reduce_ldm = False
335
+ diffusers_weight = diffusers_state_dict[diffusers_key]
336
+ did_reduce_diffusers = False
337
+
338
+ # reduce the shapes to match if they are not the same
339
+ if ldm_shape_tuple != ldm_reduced_shape_tuple:
340
+ ldm_weight = ldm_weight.view(ldm_reduced_shape_tuple)
341
+ did_reduce_ldm = True
342
+
343
+ if diffusers_shape_tuple != diffusers_reduced_shape_tuple:
344
+ diffusers_weight = diffusers_weight.view(diffusers_reduced_shape_tuple)
345
+ did_reduce_diffusers = True
346
+
347
+ # check to see if they match within a margin of error
348
+ mse = torch.nn.functional.mse_loss(ldm_weight.float(), diffusers_weight.float())
349
+ if mse < error_margin:
350
+ ldm_diffusers_keymap[ldm_key] = diffusers_key
351
+ matched_ldm_keys.append(ldm_key)
352
+ matched_diffusers_keys.append(diffusers_key)
353
+
354
+ if did_reduce_ldm or did_reduce_diffusers:
355
+ ldm_diffusers_shape_map[ldm_key] = (ldm_shape_tuple, diffusers_shape_tuple)
356
+ if did_reduce_ldm:
357
+ del ldm_weight
358
+ if did_reduce_diffusers:
359
+ del diffusers_weight
360
+ flush()
361
+
362
+ break
363
+
364
+ pbar.update(1)
365
+
366
+ pbar.close()
367
+
368
+ name = args.name
369
+ if args.sdxl:
370
+ name += '_sdxl'
371
+ elif args.ssd:
372
+ name += '_ssd'
373
+ elif args.vega:
374
+ name += '_vega'
375
+ elif args.refiner:
376
+ name += '_refiner'
377
+ elif args.sd2:
378
+ name += '_sd2'
379
+ else:
380
+ name += '_sd1'
381
+
382
+ # if len(matched_ldm_keys) != len(matched_diffusers_keys):
383
+ unmatched_ldm_keys = [x for x in ldm_dict_keys if x not in matched_ldm_keys]
384
+ unmatched_diffusers_keys = [x for x in diffusers_dict_keys if x not in matched_diffusers_keys]
385
+ # has unmatched keys
386
+
387
+ has_unmatched_keys = len(unmatched_ldm_keys) > 0 or len(unmatched_diffusers_keys) > 0
388
+
389
+
390
+ def get_slices_from_string(s: str) -> tuple:
391
+ slice_strings = s.split(',')
392
+ slices = [eval(f"slice({component.strip()})") for component in slice_strings]
393
+ return tuple(slices)
394
+
395
+
396
+ if has_unmatched_keys:
397
+
398
+ print(
399
+ f"Found {len(unmatched_ldm_keys)} unmatched ldm keys and {len(unmatched_diffusers_keys)} unmatched diffusers keys")
400
+
401
+ unmatched_obj = OrderedDict()
402
+ unmatched_obj['ldm'] = OrderedDict()
403
+ unmatched_obj['diffusers'] = OrderedDict()
404
+
405
+ print(f"Gathering info on unmatched keys")
406
+
407
+ for key in tqdm(unmatched_ldm_keys, desc='Unmatched LDM keys'):
408
+ # get min, max, mean, std
409
+ weight = ldm_state_dict[key]
410
+ weight_min = weight.min().item()
411
+ weight_max = weight.max().item()
412
+ unmatched_obj['ldm'][key] = {
413
+ 'shape': weight.shape,
414
+ "min": weight_min,
415
+ "max": weight_max,
416
+ }
417
+ del weight
418
+ flush()
419
+
420
+ for key in tqdm(unmatched_diffusers_keys, desc='Unmatched Diffusers keys'):
421
+ # get min, max, mean, std
422
+ weight = diffusers_state_dict[key]
423
+ weight_min = weight.min().item()
424
+ weight_max = weight.max().item()
425
+ unmatched_obj['diffusers'][key] = {
426
+ "shape": weight.shape,
427
+ "min": weight_min,
428
+ "max": weight_max,
429
+ }
430
+ del weight
431
+ flush()
432
+
433
+ unmatched_path = os.path.join(KEYMAPS_FOLDER, f'{name}_unmatched.json')
434
+ with open(unmatched_path, 'w') as f:
435
+ f.write(json.dumps(unmatched_obj, indent=4))
436
+
437
+ print(f'Saved unmatched keys to {unmatched_path}')
438
+
439
+ # save ldm remainders
440
+ remaining_ldm_values = OrderedDict()
441
+ for key in unmatched_ldm_keys:
442
+ remaining_ldm_values[key] = ldm_state_dict[key].detach().to('cpu', torch.float16)
443
+
444
+ save_file(remaining_ldm_values, os.path.join(KEYMAPS_FOLDER, f'{name}_ldm_base.safetensors'))
445
+ print(f'Saved remaining ldm values to {os.path.join(KEYMAPS_FOLDER, f"{name}_ldm_base.safetensors")}')
446
+
447
+ # do cleanup of some left overs and bugs
448
+ to_remove = []
449
+ for ldm_key, diffusers_key in ldm_diffusers_keymap.items():
450
+ # get rid of tmp merge keys used to slicing
451
+ if tmp_merge_key in diffusers_key or tmp_merge_key in ldm_key:
452
+ to_remove.append(ldm_key)
453
+
454
+ for key in to_remove:
455
+ del ldm_diffusers_keymap[key]
456
+
457
+ to_remove = []
458
+ # remove identical shape mappings. Not sure why they exist but they do
459
+ for ldm_key, shape_list in ldm_diffusers_shape_map.items():
460
+ # remove identical shape mappings. Not sure why they exist but they do
461
+ # convert to json string to make it easier to compare
462
+ ldm_shape = json.dumps(shape_list[0])
463
+ diffusers_shape = json.dumps(shape_list[1])
464
+ if ldm_shape == diffusers_shape:
465
+ to_remove.append(ldm_key)
466
+
467
+ for key in to_remove:
468
+ del ldm_diffusers_shape_map[key]
469
+
470
+ dest_path = os.path.join(KEYMAPS_FOLDER, f'{name}.json')
471
+ save_obj = OrderedDict()
472
+ save_obj["ldm_diffusers_keymap"] = ldm_diffusers_keymap
473
+ save_obj["ldm_diffusers_shape_map"] = ldm_diffusers_shape_map
474
+ save_obj["ldm_diffusers_operator_map"] = ldm_operator_map
475
+ save_obj["diffusers_ldm_operator_map"] = diffusers_operator_map
476
+ with open(dest_path, 'w') as f:
477
+ f.write(json.dumps(save_obj, indent=4))
478
+
479
+ print(f'Saved keymap to {dest_path}')