Instructions to use highscoregames12018/ComfyUI_Files with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use highscoregames12018/ComfyUI_Files with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("TheRaf7/ultra-real-wan2.2", dtype=torch.bfloat16, device_map="cuda") pipe.load_lora_weights("highscoregames12018/ComfyUI_Files") prompt = "-" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Draw Things
- DiffusionBee
| import json | |
| import os | |
| from collections import OrderedDict | |
| from typing import TYPE_CHECKING, Literal, Optional, Union | |
| import torch | |
| from safetensors.torch import load_file, save_file | |
| from toolkit.train_tools import get_torch_dtype | |
| from toolkit.paths import KEYMAPS_ROOT | |
| if TYPE_CHECKING: | |
| from toolkit.stable_diffusion_model import StableDiffusion | |
| def get_slices_from_string(s: str) -> tuple: | |
| slice_strings = s.split(',') | |
| slices = [eval(f"slice({component.strip()})") for component in slice_strings] | |
| return tuple(slices) | |
| def convert_state_dict_to_ldm_with_mapping( | |
| diffusers_state_dict: 'OrderedDict', | |
| mapping_path: str, | |
| base_path: Union[str, None] = None, | |
| device: str = 'cpu', | |
| dtype: torch.dtype = torch.float32 | |
| ) -> 'OrderedDict': | |
| converted_state_dict = OrderedDict() | |
| # load mapping | |
| with open(mapping_path, 'r') as f: | |
| mapping = json.load(f, object_pairs_hook=OrderedDict) | |
| # keep track of keys not matched | |
| ldm_matched_keys = [] | |
| diffusers_matched_keys = [] | |
| ldm_diffusers_keymap = mapping['ldm_diffusers_keymap'] | |
| ldm_diffusers_shape_map = mapping['ldm_diffusers_shape_map'] | |
| ldm_diffusers_operator_map = mapping['ldm_diffusers_operator_map'] | |
| # load base if it exists | |
| # the base just has come keys like timing ids and stuff diffusers doesn't have or they don't match | |
| if base_path is not None: | |
| converted_state_dict = load_file(base_path, device) | |
| # convert to the right dtype | |
| for key in converted_state_dict: | |
| converted_state_dict[key] = converted_state_dict[key].to(device, dtype=dtype) | |
| # process operators first | |
| for ldm_key in ldm_diffusers_operator_map: | |
| # if the key cat is in the ldm key, we need to process it | |
| if 'cat' in ldm_diffusers_operator_map[ldm_key]: | |
| cat_list = [] | |
| for diffusers_key in ldm_diffusers_operator_map[ldm_key]['cat']: | |
| cat_list.append(diffusers_state_dict[diffusers_key].detach()) | |
| converted_state_dict[ldm_key] = torch.cat(cat_list, dim=0).to(device, dtype=dtype) | |
| diffusers_matched_keys.extend(ldm_diffusers_operator_map[ldm_key]['cat']) | |
| ldm_matched_keys.append(ldm_key) | |
| if 'slice' in ldm_diffusers_operator_map[ldm_key]: | |
| tensor_to_slice = diffusers_state_dict[ldm_diffusers_operator_map[ldm_key]['slice'][0]] | |
| slice_text = diffusers_state_dict[ldm_diffusers_operator_map[ldm_key]['slice'][1]] | |
| converted_state_dict[ldm_key] = tensor_to_slice[get_slices_from_string(slice_text)].detach().to(device, | |
| dtype=dtype) | |
| diffusers_matched_keys.extend(ldm_diffusers_operator_map[ldm_key]['slice']) | |
| ldm_matched_keys.append(ldm_key) | |
| # process the rest of the keys | |
| for ldm_key in ldm_diffusers_keymap: | |
| # if the key is in the ldm key, we need to process it | |
| if ldm_diffusers_keymap[ldm_key] in diffusers_state_dict: | |
| tensor = diffusers_state_dict[ldm_diffusers_keymap[ldm_key]].detach().to(device, dtype=dtype) | |
| # see if we need to reshape | |
| if ldm_key in ldm_diffusers_shape_map: | |
| tensor = tensor.view(ldm_diffusers_shape_map[ldm_key][0]) | |
| converted_state_dict[ldm_key] = tensor | |
| diffusers_matched_keys.append(ldm_diffusers_keymap[ldm_key]) | |
| ldm_matched_keys.append(ldm_key) | |
| # see if any are missing from know mapping | |
| mapped_diffusers_keys = list(ldm_diffusers_keymap.values()) | |
| mapped_ldm_keys = list(ldm_diffusers_keymap.keys()) | |
| missing_diffusers_keys = [x for x in mapped_diffusers_keys if x not in diffusers_matched_keys] | |
| missing_ldm_keys = [x for x in mapped_ldm_keys if x not in ldm_matched_keys] | |
| if len(missing_diffusers_keys) > 0: | |
| print(f"WARNING!!!! Missing {len(missing_diffusers_keys)} diffusers keys") | |
| print(missing_diffusers_keys) | |
| if len(missing_ldm_keys) > 0: | |
| print(f"WARNING!!!! Missing {len(missing_ldm_keys)} ldm keys") | |
| print(missing_ldm_keys) | |
| return converted_state_dict | |
| def get_ldm_state_dict_from_diffusers( | |
| state_dict: 'OrderedDict', | |
| sd_version: Literal['1', '2', 'sdxl', 'ssd', 'vega', 'sdxl_refiner'] = '2', | |
| device='cpu', | |
| dtype=get_torch_dtype('fp32'), | |
| ): | |
| if sd_version == '1': | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sd1_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sd1.json') | |
| elif sd_version == '2': | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sd2_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sd2.json') | |
| elif sd_version == 'sdxl': | |
| # load our base | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sdxl_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_sdxl.json') | |
| elif sd_version == 'ssd': | |
| # load our base | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_ssd_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_ssd.json') | |
| elif sd_version == 'vega': | |
| # load our base | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_vega_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_vega.json') | |
| elif sd_version == 'sdxl_refiner': | |
| # load our base | |
| base_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_refiner_ldm_base.safetensors') | |
| mapping_path = os.path.join(KEYMAPS_ROOT, 'stable_diffusion_refiner.json') | |
| else: | |
| raise ValueError(f"Invalid sd_version {sd_version}") | |
| # convert the state dict | |
| return convert_state_dict_to_ldm_with_mapping( | |
| state_dict, | |
| mapping_path, | |
| base_path, | |
| device=device, | |
| dtype=dtype | |
| ) | |
| def save_ldm_model_from_diffusers( | |
| sd: 'StableDiffusion', | |
| output_file: str, | |
| meta: 'OrderedDict', | |
| save_dtype=get_torch_dtype('fp16'), | |
| sd_version: Literal['1', '2', 'sdxl', 'ssd', 'vega'] = '2' | |
| ): | |
| converted_state_dict = get_ldm_state_dict_from_diffusers( | |
| sd.state_dict(), | |
| sd_version, | |
| device='cpu', | |
| dtype=save_dtype | |
| ) | |
| # make sure parent folder exists | |
| os.makedirs(os.path.dirname(output_file), exist_ok=True) | |
| save_file(converted_state_dict, output_file, metadata=meta) | |
| def save_lora_from_diffusers( | |
| lora_state_dict: 'OrderedDict', | |
| output_file: str, | |
| meta: 'OrderedDict', | |
| save_dtype=get_torch_dtype('fp16'), | |
| sd_version: Literal['1', '2', 'sdxl', 'ssd', 'vega'] = '2' | |
| ): | |
| converted_state_dict = OrderedDict() | |
| # only handle sxdxl for now | |
| if sd_version != 'sdxl' and sd_version != 'ssd' and sd_version != 'vega': | |
| raise ValueError(f"Invalid sd_version {sd_version}") | |
| for key, value in lora_state_dict.items(): | |
| # todo verify if this works with ssd | |
| # test encoders share keys for some reason | |
| if key.begins_with('lora_te'): | |
| converted_state_dict[key] = value.detach().to('cpu', dtype=save_dtype) | |
| else: | |
| converted_key = key | |
| # make sure parent folder exists | |
| os.makedirs(os.path.dirname(output_file), exist_ok=True) | |
| save_file(converted_state_dict, output_file, metadata=meta) | |
| def save_t2i_from_diffusers( | |
| t2i_state_dict: 'OrderedDict', | |
| output_file: str, | |
| meta: 'OrderedDict', | |
| dtype=get_torch_dtype('fp16'), | |
| ): | |
| # todo: test compatibility with non diffusers | |
| converted_state_dict = OrderedDict() | |
| for key, value in t2i_state_dict.items(): | |
| converted_state_dict[key] = value.detach().to('cpu', dtype=dtype) | |
| # make sure parent folder exists | |
| os.makedirs(os.path.dirname(output_file), exist_ok=True) | |
| save_file(converted_state_dict, output_file, metadata=meta) | |
| def load_t2i_model( | |
| path_to_file, | |
| device: Union[str] = 'cpu', | |
| dtype: torch.dtype = torch.float32 | |
| ): | |
| raw_state_dict = load_file(path_to_file, device) | |
| converted_state_dict = OrderedDict() | |
| for key, value in raw_state_dict.items(): | |
| # todo see if we need to convert dict | |
| converted_state_dict[key] = value.detach().to(device, dtype=dtype) | |
| return converted_state_dict | |
| def save_ip_adapter_from_diffusers( | |
| combined_state_dict: 'OrderedDict', | |
| output_file: str, | |
| meta: 'OrderedDict', | |
| dtype=get_torch_dtype('fp16'), | |
| direct_save: bool = False | |
| ): | |
| # todo: test compatibility with non diffusers | |
| converted_state_dict = OrderedDict() | |
| for module_name, state_dict in combined_state_dict.items(): | |
| if direct_save: | |
| converted_state_dict[module_name] = state_dict.detach().to('cpu', dtype=dtype) | |
| else: | |
| for key, value in state_dict.items(): | |
| converted_state_dict[f"{module_name}.{key}"] = value.detach().to('cpu', dtype=dtype) | |
| # make sure parent folder exists | |
| os.makedirs(os.path.dirname(output_file), exist_ok=True) | |
| save_file(converted_state_dict, output_file, metadata=meta) | |
| def load_ip_adapter_model( | |
| path_to_file, | |
| device: Union[str] = 'cpu', | |
| dtype: torch.dtype = torch.float32, | |
| direct_load: bool = False | |
| ): | |
| # check if it is safetensors or checkpoint | |
| if path_to_file.endswith('.safetensors'): | |
| raw_state_dict = load_file(path_to_file, device) | |
| combined_state_dict = OrderedDict() | |
| if direct_load: | |
| return raw_state_dict | |
| for combo_key, value in raw_state_dict.items(): | |
| key_split = combo_key.split('.') | |
| module_name = key_split.pop(0) | |
| if module_name not in combined_state_dict: | |
| combined_state_dict[module_name] = OrderedDict() | |
| combined_state_dict[module_name]['.'.join(key_split)] = value.detach().to(device, dtype=dtype) | |
| return combined_state_dict | |
| else: | |
| return torch.load(path_to_file, map_location=device) | |
| def load_custom_adapter_model( | |
| path_to_file, | |
| device: Union[str] = 'cpu', | |
| dtype: torch.dtype = torch.float32 | |
| ): | |
| # check if it is safetensors or checkpoint | |
| if path_to_file.endswith('.safetensors'): | |
| raw_state_dict = load_file(path_to_file, device) | |
| combined_state_dict = OrderedDict() | |
| device = device if isinstance(device, torch.device) else torch.device(device) | |
| dtype = dtype if isinstance(dtype, torch.dtype) else get_torch_dtype(dtype) | |
| for combo_key, value in raw_state_dict.items(): | |
| key_split = combo_key.split('.') | |
| module_name = key_split.pop(0) | |
| if module_name not in combined_state_dict: | |
| combined_state_dict[module_name] = OrderedDict() | |
| combined_state_dict[module_name]['.'.join(key_split)] = value.detach().to(device, dtype=dtype) | |
| return combined_state_dict | |
| else: | |
| return torch.load(path_to_file, map_location=device) | |
| def get_lora_keymap_from_model_keymap(model_keymap: 'OrderedDict') -> 'OrderedDict': | |
| lora_keymap = OrderedDict() | |
| # see if we have dual text encoders " a key that starts with conditioner.embedders.1 | |
| has_dual_text_encoders = False | |
| for key in model_keymap: | |
| if key.startswith('conditioner.embedders.1'): | |
| has_dual_text_encoders = True | |
| break | |
| # map through the keys and values | |
| for key, value in model_keymap.items(): | |
| # ignore bias weights | |
| if key.endswith('bias'): | |
| continue | |
| if key.endswith('.weight'): | |
| # remove the .weight | |
| key = key[:-7] | |
| if value.endswith(".weight"): | |
| # remove the .weight | |
| value = value[:-7] | |
| # unet for all | |
| key = key.replace('model.diffusion_model', 'lora_unet') | |
| if value.startswith('unet'): | |
| value = f"lora_{value}" | |
| # text encoder | |
| if has_dual_text_encoders: | |
| key = key.replace('conditioner.embedders.0', 'lora_te1') | |
| key = key.replace('conditioner.embedders.1', 'lora_te2') | |
| if value.startswith('te0') or value.startswith('te1'): | |
| value = f"lora_{value}" | |
| value.replace('lora_te1', 'lora_te2') | |
| value.replace('lora_te0', 'lora_te1') | |
| key = key.replace('cond_stage_model.transformer', 'lora_te') | |
| if value.startswith('te_'): | |
| value = f"lora_{value}" | |
| # replace periods with underscores | |
| key = key.replace('.', '_') | |
| value = value.replace('.', '_') | |
| # add all the weights | |
| lora_keymap[f"{key}.lora_down.weight"] = f"{value}.lora_down.weight" | |
| lora_keymap[f"{key}.lora_down.bias"] = f"{value}.lora_down.bias" | |
| lora_keymap[f"{key}.lora_up.weight"] = f"{value}.lora_up.weight" | |
| lora_keymap[f"{key}.lora_up.bias"] = f"{value}.lora_up.bias" | |
| lora_keymap[f"{key}.alpha"] = f"{value}.alpha" | |
| return lora_keymap | |