Spaces:
Running
on
Zero
Running
on
Zero
| import copy | |
| import logging | |
| import uuid | |
| import torch | |
| from modules.NeuralNetwork import unet | |
| from modules.Utilities import util | |
| from modules.Device import Device | |
| def wipe_lowvram_weight(m): | |
| if hasattr(m, "prev_comfy_cast_weights"): | |
| m.comfy_cast_weights = m.prev_comfy_cast_weights | |
| del m.prev_comfy_cast_weights | |
| m.weight_function = None | |
| m.bias_function = None | |
| class ModelPatcher: | |
| def __init__( | |
| self, | |
| model: torch.nn.Module, | |
| load_device: torch.device, | |
| offload_device: torch.device, | |
| size: int = 0, | |
| current_device: torch.device = None, | |
| weight_inplace_update: bool = False, | |
| ): | |
| """#### Initialize the ModelPatcher class. | |
| #### Args: | |
| - `model` (torch.nn.Module): The model. | |
| - `load_device` (torch.device): The device to load the model on. | |
| - `offload_device` (torch.device): The device to offload the model to. | |
| - `size` (int, optional): The size of the model. Defaults to 0. | |
| - `current_device` (torch.device, optional): The current device. Defaults to None. | |
| - `weight_inplace_update` (bool, optional): Whether to update weights in place. Defaults to False. | |
| """ | |
| self.size = size | |
| self.model = model | |
| self.patches = {} | |
| self.backup = {} | |
| self.object_patches = {} | |
| self.object_patches_backup = {} | |
| self.model_options = {"transformer_options": {}} | |
| self.model_size() | |
| self.load_device = load_device | |
| self.offload_device = offload_device | |
| if current_device is None: | |
| self.current_device = self.offload_device | |
| else: | |
| self.current_device = current_device | |
| self.weight_inplace_update = weight_inplace_update | |
| self.model_lowvram = False | |
| self.lowvram_patch_counter = 0 | |
| self.patches_uuid = uuid.uuid4() | |
| if not hasattr(self.model, "model_loaded_weight_memory"): | |
| self.model.model_loaded_weight_memory = 0 | |
| if not hasattr(self.model, "model_lowvram"): | |
| self.model.model_lowvram = False | |
| if not hasattr(self.model, "lowvram_patch_counter"): | |
| self.model.lowvram_patch_counter = 0 | |
| def loaded_size(self) -> int: | |
| """#### Get the loaded size | |
| #### Returns: | |
| - `int`: The loaded size | |
| """ | |
| return self.model.model_loaded_weight_memory | |
| def model_size(self) -> int: | |
| """#### Get the size of the model. | |
| #### Returns: | |
| - `int`: The size of the model. | |
| """ | |
| if self.size > 0: | |
| return self.size | |
| model_sd = self.model.state_dict() | |
| self.size = Device.module_size(self.model) | |
| self.model_keys = set(model_sd.keys()) | |
| return self.size | |
| def clone(self) -> "ModelPatcher": | |
| """#### Clone the ModelPatcher object. | |
| #### Returns: | |
| - `ModelPatcher`: The cloned ModelPatcher object. | |
| """ | |
| n = ModelPatcher( | |
| self.model, | |
| self.load_device, | |
| self.offload_device, | |
| self.size, | |
| self.current_device, | |
| weight_inplace_update=self.weight_inplace_update, | |
| ) | |
| n.patches = {} | |
| for k in self.patches: | |
| n.patches[k] = self.patches[k][:] | |
| n.patches_uuid = self.patches_uuid | |
| n.object_patches = self.object_patches.copy() | |
| n.model_options = copy.deepcopy(self.model_options) | |
| n.model_keys = self.model_keys | |
| n.backup = self.backup | |
| n.object_patches_backup = self.object_patches_backup | |
| return n | |
| def is_clone(self, other: object) -> bool: | |
| """#### Check if the object is a clone. | |
| #### Args: | |
| - `other` (object): The other object. | |
| #### Returns: | |
| - `bool`: Whether the object is a clone. | |
| """ | |
| if hasattr(other, "model") and self.model is other.model: | |
| return True | |
| return False | |
| def memory_required(self, input_shape: tuple) -> float: | |
| """#### Calculate the memory required for the model. | |
| #### Args: | |
| - `input_shape` (tuple): The input shape. | |
| #### Returns: | |
| - `float`: The memory required. | |
| """ | |
| return self.model.memory_required(input_shape=input_shape) | |
| def set_model_unet_function_wrapper(self, unet_wrapper_function: callable) -> None: | |
| """#### Set the UNet function wrapper for the model. | |
| #### Args: | |
| - `unet_wrapper_function` (callable): The UNet function wrapper. | |
| """ | |
| self.model_options["model_function_wrapper"] = unet_wrapper_function | |
| def set_model_denoise_mask_function(self, denoise_mask_function: callable) -> None: | |
| """#### Set the denoise mask function for the model. | |
| #### Args: | |
| - `denoise_mask_function` (callable): The denoise mask function. | |
| """ | |
| self.model_options["denoise_mask_function"] = denoise_mask_function | |
| def get_model_object(self, name: str) -> object: | |
| """#### Get an object from the model. | |
| #### Args: | |
| - `name` (str): The name of the object. | |
| #### Returns: | |
| - `object`: The object. | |
| """ | |
| return util.get_attr(self.model, name) | |
| def model_patches_to(self, device: torch.device) -> None: | |
| """#### Move model patches to a device. | |
| #### Args: | |
| - `device` (torch.device): The device. | |
| """ | |
| self.model_options["transformer_options"] | |
| if "model_function_wrapper" in self.model_options: | |
| wrap_func = self.model_options["model_function_wrapper"] | |
| if hasattr(wrap_func, "to"): | |
| self.model_options["model_function_wrapper"] = wrap_func.to(device) | |
| def model_dtype(self) -> torch.dtype: | |
| """#### Get the data type of the model. | |
| #### Returns: | |
| - `torch.dtype`: The data type. | |
| """ | |
| if hasattr(self.model, "get_dtype"): | |
| return self.model.get_dtype() | |
| def add_patches( | |
| self, patches: dict, strength_patch: float = 1.0, strength_model: float = 1.0 | |
| ) -> list: | |
| """#### Add patches to the model. | |
| #### Args: | |
| - `patches` (dict): The patches to add. | |
| - `strength_patch` (float, optional): The strength of the patches. Defaults to 1.0. | |
| - `strength_model` (float, optional): The strength of the model. Defaults to 1.0. | |
| #### Returns: | |
| - `list`: The list of patched keys. | |
| """ | |
| p = set() | |
| for k in patches: | |
| if k in self.model_keys: | |
| p.add(k) | |
| current_patches = self.patches.get(k, []) | |
| current_patches.append((strength_patch, patches[k], strength_model)) | |
| self.patches[k] = current_patches | |
| self.patches_uuid = uuid.uuid4() | |
| return list(p) | |
| def set_model_patch(self, patch: list, name: str): | |
| """#### Set a patch for the model. | |
| #### Args: | |
| - `patch` (list): The patch. | |
| - `name` (str): The name of the patch. | |
| """ | |
| to = self.model_options["transformer_options"] | |
| if "patches" not in to: | |
| to["patches"] = {} | |
| to["patches"][name] = to["patches"].get(name, []) + [patch] | |
| def set_model_attn1_patch(self, patch: list): | |
| """#### Set the attention 1 patch for the model. | |
| #### Args: | |
| - `patch` (list): The patch. | |
| """ | |
| self.set_model_patch(patch, "attn1_patch") | |
| def set_model_attn2_patch(self, patch: list): | |
| """#### Set the attention 2 patch for the model. | |
| #### Args: | |
| - `patch` (list): The patch. | |
| """ | |
| self.set_model_patch(patch, "attn2_patch") | |
| def set_model_attn1_output_patch(self, patch: list): | |
| """#### Set the attention 1 output patch for the model. | |
| #### Args: | |
| - `patch` (list): The patch. | |
| """ | |
| self.set_model_patch(patch, "attn1_output_patch") | |
| def set_model_attn2_output_patch(self, patch: list): | |
| """#### Set the attention 2 output patch for the model. | |
| #### Args: | |
| - `patch` (list): The patch. | |
| """ | |
| self.set_model_patch(patch, "attn2_output_patch") | |
| def model_state_dict(self, filter_prefix: str = None) -> dict: | |
| """#### Get the state dictionary of the model. | |
| #### Args: | |
| - `filter_prefix` (str, optional): The prefix to filter. Defaults to None. | |
| #### Returns: | |
| - `dict`: The state dictionary. | |
| """ | |
| sd = self.model.state_dict() | |
| list(sd.keys()) | |
| return sd | |
| def patch_weight_to_device(self, key: str, device_to: torch.device = None) -> None: | |
| """#### Patch the weight of a key to a device. | |
| #### Args: | |
| - `key` (str): The key. | |
| - `device_to` (torch.device, optional): The device to patch to. Defaults to None. | |
| """ | |
| if key not in self.patches: | |
| return | |
| weight = util.get_attr(self.model, key) | |
| inplace_update = self.weight_inplace_update | |
| if key not in self.backup: | |
| self.backup[key] = weight.to( | |
| device=self.offload_device, copy=inplace_update | |
| ) | |
| if device_to is not None: | |
| temp_weight = Device.cast_to_device( | |
| weight, device_to, torch.float32, copy=True | |
| ) | |
| else: | |
| temp_weight = weight.to(torch.float32, copy=True) | |
| out_weight = self.calculate_weight(self.patches[key], temp_weight, key).to( | |
| weight.dtype | |
| ) | |
| if inplace_update: | |
| util.copy_to_param(self.model, key, out_weight) | |
| else: | |
| util.set_attr_param(self.model, key, out_weight) | |
| def load( | |
| self, | |
| device_to: torch.device = None, | |
| lowvram_model_memory: int = 0, | |
| force_patch_weights: bool = False, | |
| full_load: bool = False, | |
| ): | |
| """#### Load the model. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to load to. Defaults to None. | |
| - `lowvram_model_memory` (int, optional): The low VRAM model memory. Defaults to 0. | |
| - `force_patch_weights` (bool, optional): Whether to force patch weights. Defaults to False. | |
| - `full_load` (bool, optional): Whether to fully load the model. Defaults to False. | |
| """ | |
| mem_counter = 0 | |
| patch_counter = 0 | |
| lowvram_counter = 0 | |
| loading = [] | |
| for n, m in self.model.named_modules(): | |
| if hasattr(m, "comfy_cast_weights") or hasattr(m, "weight"): | |
| loading.append((Device.module_size(m), n, m)) | |
| load_completely = [] | |
| loading.sort(reverse=True) | |
| for x in loading: | |
| n = x[1] | |
| m = x[2] | |
| module_mem = x[0] | |
| lowvram_weight = False | |
| if not full_load and hasattr(m, "comfy_cast_weights"): | |
| if mem_counter + module_mem >= lowvram_model_memory: | |
| lowvram_weight = True | |
| lowvram_counter += 1 | |
| if hasattr(m, "prev_comfy_cast_weights"): # Already lowvramed | |
| continue | |
| weight_key = "{}.weight".format(n) | |
| bias_key = "{}.bias".format(n) | |
| if lowvram_weight: | |
| if weight_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(weight_key) | |
| if bias_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(bias_key) | |
| m.prev_comfy_cast_weights = m.comfy_cast_weights | |
| m.comfy_cast_weights = True | |
| else: | |
| if hasattr(m, "comfy_cast_weights"): | |
| if m.comfy_cast_weights: | |
| wipe_lowvram_weight(m) | |
| if hasattr(m, "weight"): | |
| mem_counter += module_mem | |
| load_completely.append((module_mem, n, m)) | |
| load_completely.sort(reverse=True) | |
| for x in load_completely: | |
| n = x[1] | |
| m = x[2] | |
| weight_key = "{}.weight".format(n) | |
| bias_key = "{}.bias".format(n) | |
| if hasattr(m, "comfy_patched_weights"): | |
| if m.comfy_patched_weights is True: | |
| continue | |
| self.patch_weight_to_device(weight_key, device_to=device_to) | |
| self.patch_weight_to_device(bias_key, device_to=device_to) | |
| logging.debug("lowvram: loaded module regularly {} {}".format(n, m)) | |
| m.comfy_patched_weights = True | |
| for x in load_completely: | |
| x[2].to(device_to) | |
| if lowvram_counter > 0: | |
| logging.info( | |
| "loaded partially {} {} {}".format( | |
| lowvram_model_memory / (1024 * 1024), | |
| mem_counter / (1024 * 1024), | |
| patch_counter, | |
| ) | |
| ) | |
| self.model.model_lowvram = True | |
| else: | |
| logging.info( | |
| "loaded completely {} {} {}".format( | |
| lowvram_model_memory / (1024 * 1024), | |
| mem_counter / (1024 * 1024), | |
| full_load, | |
| ) | |
| ) | |
| self.model.model_lowvram = False | |
| if full_load: | |
| self.model.to(device_to) | |
| mem_counter = self.model_size() | |
| self.model.lowvram_patch_counter += patch_counter | |
| self.model.device = device_to | |
| self.model.model_loaded_weight_memory = mem_counter | |
| def patch_model_flux( | |
| self, | |
| device_to: torch.device = None, | |
| lowvram_model_memory: int =0, | |
| load_weights: bool = True, | |
| force_patch_weights: bool = False, | |
| ): | |
| """#### Patch the model. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to patch to. Defaults to None. | |
| - `lowvram_model_memory` (int, optional): The low VRAM model memory. Defaults to 0. | |
| - `load_weights` (bool, optional): Whether to load weights. Defaults to True. | |
| - `force_patch_weights` (bool, optional): Whether to force patch weights. Defaults to False. | |
| #### Returns: | |
| - `torch.nn.Module`: The patched model. | |
| """ | |
| for k in self.object_patches: | |
| old = util.set_attr(self.model, k, self.object_patches[k]) | |
| if k not in self.object_patches_backup: | |
| self.object_patches_backup[k] = old | |
| if lowvram_model_memory == 0: | |
| full_load = True | |
| else: | |
| full_load = False | |
| if load_weights: | |
| self.load( | |
| device_to, | |
| lowvram_model_memory=lowvram_model_memory, | |
| force_patch_weights=force_patch_weights, | |
| full_load=full_load, | |
| ) | |
| return self.model | |
| def patch_model_lowvram_flux( | |
| self, | |
| device_to: torch.device = None, | |
| lowvram_model_memory: int = 0, | |
| force_patch_weights: bool = False, | |
| ) -> torch.nn.Module: | |
| """#### Patch the model for low VRAM. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to patch to. Defaults to None. | |
| - `lowvram_model_memory` (int, optional): The low VRAM model memory. Defaults to 0. | |
| - `force_patch_weights` (bool, optional): Whether to force patch weights. Defaults to False. | |
| #### Returns: | |
| - `torch.nn.Module`: The patched model. | |
| """ | |
| self.patch_model(device_to) | |
| logging.info( | |
| "loading in lowvram mode {}".format(lowvram_model_memory / (1024 * 1024)) | |
| ) | |
| class LowVramPatch: | |
| def __init__(self, key: str, model_patcher: "ModelPatcher"): | |
| self.key = key | |
| self.model_patcher = model_patcher | |
| def __call__(self, weight: torch.Tensor) -> torch.Tensor: | |
| return self.model_patcher.calculate_weight( | |
| self.model_patcher.patches[self.key], weight, self.key | |
| ) | |
| mem_counter = 0 | |
| patch_counter = 0 | |
| for n, m in self.model.named_modules(): | |
| lowvram_weight = False | |
| if hasattr(m, "comfy_cast_weights"): | |
| module_mem = Device.module_size(m) | |
| if mem_counter + module_mem >= lowvram_model_memory: | |
| lowvram_weight = True | |
| weight_key = "{}.weight".format(n) | |
| bias_key = "{}.bias".format(n) | |
| if lowvram_weight: | |
| if weight_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(weight_key) | |
| else: | |
| m.weight_function = LowVramPatch(weight_key, self) | |
| patch_counter += 1 | |
| if bias_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(bias_key) | |
| else: | |
| m.bias_function = LowVramPatch(bias_key, self) | |
| patch_counter += 1 | |
| m.prev_comfy_cast_weights = m.comfy_cast_weights | |
| m.comfy_cast_weights = True | |
| else: | |
| if hasattr(m, "weight"): | |
| self.patch_weight_to_device(weight_key, device_to) | |
| self.patch_weight_to_device(bias_key, device_to) | |
| m.to(device_to) | |
| mem_counter += Device.module_size(m) | |
| logging.debug("lowvram: loaded module regularly {}".format(m)) | |
| self.model_lowvram = True | |
| self.lowvram_patch_counter = patch_counter | |
| return self.model | |
| def patch_model( | |
| self, device_to: torch.device = None, patch_weights: bool = True | |
| ) -> torch.nn.Module: | |
| """#### Patch the model. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to patch to. Defaults to None. | |
| - `patch_weights` (bool, optional): Whether to patch weights. Defaults to True. | |
| #### Returns: | |
| - `torch.nn.Module`: The patched model. | |
| """ | |
| for k in self.object_patches: | |
| old = util.set_attr(self.model, k, self.object_patches[k]) | |
| if k not in self.object_patches_backup: | |
| self.object_patches_backup[k] = old | |
| if patch_weights: | |
| model_sd = self.model_state_dict() | |
| for key in self.patches: | |
| if key not in model_sd: | |
| logging.warning( | |
| "could not patch. key doesn't exist in model: {}".format(key) | |
| ) | |
| continue | |
| self.patch_weight_to_device(key, device_to) | |
| if device_to is not None: | |
| self.model.to(device_to) | |
| self.current_device = device_to | |
| return self.model | |
| def patch_model_lowvram( | |
| self, | |
| device_to: torch.device = None, | |
| lowvram_model_memory: int = 0, | |
| force_patch_weights: bool = False, | |
| ) -> torch.nn.Module: | |
| """#### Patch the model for low VRAM. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to patch to. Defaults to None. | |
| - `lowvram_model_memory` (int, optional): The low VRAM model memory. Defaults to 0. | |
| - `force_patch_weights` (bool, optional): Whether to force patch weights. Defaults to False. | |
| #### Returns: | |
| - `torch.nn.Module`: The patched model. | |
| """ | |
| self.patch_model(device_to, patch_weights=False) | |
| logging.info( | |
| "loading in lowvram mode {}".format(lowvram_model_memory / (1024 * 1024)) | |
| ) | |
| class LowVramPatch: | |
| def __init__(self, key: str, model_patcher: "ModelPatcher"): | |
| self.key = key | |
| self.model_patcher = model_patcher | |
| def __call__(self, weight: torch.Tensor) -> torch.Tensor: | |
| return self.model_patcher.calculate_weight( | |
| self.model_patcher.patches[self.key], weight, self.key | |
| ) | |
| mem_counter = 0 | |
| patch_counter = 0 | |
| for n, m in self.model.named_modules(): | |
| lowvram_weight = False | |
| if hasattr(m, "comfy_cast_weights"): | |
| module_mem = Device.module_size(m) | |
| if mem_counter + module_mem >= lowvram_model_memory: | |
| lowvram_weight = True | |
| weight_key = "{}.weight".format(n) | |
| bias_key = "{}.bias".format(n) | |
| if lowvram_weight: | |
| if weight_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(weight_key) | |
| else: | |
| m.weight_function = LowVramPatch(weight_key, self) | |
| patch_counter += 1 | |
| if bias_key in self.patches: | |
| if force_patch_weights: | |
| self.patch_weight_to_device(bias_key) | |
| else: | |
| m.bias_function = LowVramPatch(bias_key, self) | |
| patch_counter += 1 | |
| m.prev_comfy_cast_weights = m.comfy_cast_weights | |
| m.comfy_cast_weights = True | |
| else: | |
| if hasattr(m, "weight"): | |
| self.patch_weight_to_device(weight_key, device_to) | |
| self.patch_weight_to_device(bias_key, device_to) | |
| m.to(device_to) | |
| mem_counter += Device.module_size(m) | |
| logging.debug("lowvram: loaded module regularly {}".format(m)) | |
| self.model_lowvram = True | |
| self.lowvram_patch_counter = patch_counter | |
| return self.model | |
| def calculate_weight( | |
| self, patches: list, weight: torch.Tensor, key: str | |
| ) -> torch.Tensor: | |
| """#### Calculate the weight of a key. | |
| #### Args: | |
| - `patches` (list): The list of patches. | |
| - `weight` (torch.Tensor): The weight tensor. | |
| - `key` (str): The key. | |
| #### Returns: | |
| - `torch.Tensor`: The calculated weight. | |
| """ | |
| for p in patches: | |
| alpha = p[0] | |
| v = p[1] | |
| p[2] | |
| v[0] | |
| v = v[1] | |
| mat1 = Device.cast_to_device(v[0], weight.device, torch.float32) | |
| mat2 = Device.cast_to_device(v[1], weight.device, torch.float32) | |
| v[4] | |
| if v[2] is not None: | |
| alpha *= v[2] / mat2.shape[0] | |
| weight += ( | |
| (alpha * torch.mm(mat1.flatten(start_dim=1), mat2.flatten(start_dim=1))) | |
| .reshape(weight.shape) | |
| .type(weight.dtype) | |
| ) | |
| return weight | |
| def unpatch_model( | |
| self, device_to: torch.device = None, unpatch_weights: bool = True | |
| ) -> None: | |
| """#### Unpatch the model. | |
| #### Args: | |
| - `device_to` (torch.device, optional): The device to unpatch to. Defaults to None. | |
| - `unpatch_weights` (bool, optional): Whether to unpatch weights. Defaults to True. | |
| """ | |
| if unpatch_weights: | |
| keys = list(self.backup.keys()) | |
| for k in keys: | |
| util.set_attr_param(self.model, k, self.backup[k]) | |
| self.backup.clear() | |
| if device_to is not None: | |
| self.model.to(device_to) | |
| self.current_device = device_to | |
| keys = list(self.object_patches_backup.keys()) | |
| self.object_patches_backup.clear() | |
| def partially_load(self, device_to: torch.device, extra_memory: int = 0) -> int: | |
| """#### Partially load the model. | |
| #### Args: | |
| - `device_to` (torch.device): The device to load to. | |
| - `extra_memory` (int, optional): The extra memory. Defaults to 0. | |
| #### Returns: | |
| - `int`: The memory loaded. | |
| """ | |
| self.unpatch_model(unpatch_weights=False) | |
| self.patch_model(patch_weights=False) | |
| full_load = False | |
| if self.model.model_lowvram is False: | |
| return 0 | |
| if self.model.model_loaded_weight_memory + extra_memory > self.model_size(): | |
| full_load = True | |
| current_used = self.model.model_loaded_weight_memory | |
| self.load( | |
| device_to, | |
| lowvram_model_memory=current_used + extra_memory, | |
| full_load=full_load, | |
| ) | |
| return self.model.model_loaded_weight_memory - current_used | |
| def add_object_patch(self, name, obj): | |
| self.object_patches[name] = obj | |
| def unet_prefix_from_state_dict(state_dict: dict) -> str: | |
| """#### Get the UNet prefix from the state dictionary. | |
| #### Args: | |
| - `state_dict` (dict): The state dictionary. | |
| #### Returns: | |
| - `str`: The UNet prefix. | |
| """ | |
| candidates = [ | |
| "model.diffusion_model.", # ldm/sgm models | |
| "model.model.", # audio models | |
| ] | |
| counts = {k: 0 for k in candidates} | |
| for k in state_dict: | |
| for c in candidates: | |
| if k.startswith(c): | |
| counts[c] += 1 | |
| break | |
| top = max(counts, key=counts.get) | |
| if counts[top] > 5: | |
| return top | |
| else: | |
| return "model." # aura flow and others | |
| def load_diffusion_model_state_dict( | |
| sd, model_options={} | |
| ) -> ModelPatcher: | |
| """#### Load the diffusion model state dictionary. | |
| #### Args: | |
| - `sd`: The state dictionary. | |
| - `model_options` (dict, optional): The model options. Defaults to {}. | |
| #### Returns: | |
| - `ModelPatcher`: The model patcher. | |
| """ | |
| # load unet in diffusers or regular format | |
| dtype = model_options.get("dtype", None) | |
| # Allow loading unets from checkpoint files | |
| diffusion_model_prefix = unet_prefix_from_state_dict(sd) | |
| temp_sd = util.state_dict_prefix_replace( | |
| sd, {diffusion_model_prefix: ""}, filter_keys=True | |
| ) | |
| if len(temp_sd) > 0: | |
| sd = temp_sd | |
| parameters = util.calculate_parameters(sd) | |
| load_device = Device.get_torch_device() | |
| model_config = unet.model_config_from_unet(sd, "") | |
| if model_config is not None: | |
| new_sd = sd | |
| offload_device = Device.unet_offload_device() | |
| if dtype is None: | |
| unet_dtype2 = Device.unet_dtype( | |
| model_params=parameters, | |
| supported_dtypes=model_config.supported_inference_dtypes, | |
| ) | |
| else: | |
| unet_dtype2 = dtype | |
| manual_cast_dtype = Device.unet_manual_cast( | |
| unet_dtype2, load_device, model_config.supported_inference_dtypes | |
| ) | |
| model_config.set_inference_dtype(unet_dtype2, manual_cast_dtype) | |
| model_config.custom_operations = model_options.get( | |
| "custom_operations", model_config.custom_operations | |
| ) | |
| model = model_config.get_model(new_sd, "") | |
| model = model.to(offload_device) | |
| model.load_model_weights(new_sd, "") | |
| left_over = sd.keys() | |
| if len(left_over) > 0: | |
| logging.info("left over keys in unet: {}".format(left_over)) | |
| return ModelPatcher(model, load_device=load_device, offload_device=offload_device) | |