Path: blob/master/extensions-builtin/Lora/network_lora.py
2447 views
import torch12import lyco_helpers3import modules.models.sd3.mmdit4import network5from modules import devices678class ModuleTypeLora(network.ModuleType):9def create_module(self, net: network.Network, weights: network.NetworkWeights):10if all(x in weights.w for x in ["lora_up.weight", "lora_down.weight"]):11return NetworkModuleLora(net, weights)1213if all(x in weights.w for x in ["lora_A.weight", "lora_B.weight"]):14w = weights.w.copy()15weights.w.clear()16weights.w.update({"lora_up.weight": w["lora_B.weight"], "lora_down.weight": w["lora_A.weight"]})1718return NetworkModuleLora(net, weights)1920return None212223class NetworkModuleLora(network.NetworkModule):24def __init__(self, net: network.Network, weights: network.NetworkWeights):25super().__init__(net, weights)2627self.up_model = self.create_module(weights.w, "lora_up.weight")28self.down_model = self.create_module(weights.w, "lora_down.weight")29self.mid_model = self.create_module(weights.w, "lora_mid.weight", none_ok=True)3031self.dim = weights.w["lora_down.weight"].shape[0]3233def create_module(self, weights, key, none_ok=False):34weight = weights.get(key)3536if weight is None and none_ok:37return None3839is_linear = type(self.sd_module) in [torch.nn.Linear, torch.nn.modules.linear.NonDynamicallyQuantizableLinear, torch.nn.MultiheadAttention, modules.models.sd3.mmdit.QkvLinear]40is_conv = type(self.sd_module) in [torch.nn.Conv2d]4142if is_linear:43weight = weight.reshape(weight.shape[0], -1)44module = torch.nn.Linear(weight.shape[1], weight.shape[0], bias=False)45elif is_conv and key == "lora_down.weight" or key == "dyn_up":46if len(weight.shape) == 2:47weight = weight.reshape(weight.shape[0], -1, 1, 1)4849if weight.shape[2] != 1 or weight.shape[3] != 1:50module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], self.sd_module.kernel_size, self.sd_module.stride, self.sd_module.padding, bias=False)51else:52module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)53elif is_conv and key == "lora_mid.weight":54module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], self.sd_module.kernel_size, self.sd_module.stride, self.sd_module.padding, bias=False)55elif is_conv and key == "lora_up.weight" or key == "dyn_down":56module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)57else:58raise AssertionError(f'Lora layer {self.network_key} matched a layer with unsupported type: {type(self.sd_module).__name__}')5960with torch.no_grad():61if weight.shape != module.weight.shape:62weight = weight.reshape(module.weight.shape)63module.weight.copy_(weight)6465module.to(device=devices.cpu, dtype=devices.dtype)66module.weight.requires_grad_(False)6768return module6970def calc_updown(self, orig_weight):71up = self.up_model.weight.to(orig_weight.device)72down = self.down_model.weight.to(orig_weight.device)7374output_shape = [up.size(0), down.size(1)]75if self.mid_model is not None:76# cp-decomposition77mid = self.mid_model.weight.to(orig_weight.device)78updown = lyco_helpers.rebuild_cp_decomposition(up, down, mid)79output_shape += mid.shape[2:]80else:81if len(down.shape) == 4:82output_shape += down.shape[2:]83updown = lyco_helpers.rebuild_conventional(up, down, output_shape, self.network.dyn_dim)8485return self.finalize_updown(updown, orig_weight, output_shape)8687def forward(self, x, y):88self.up_model.to(device=devices.device)89self.down_model.to(device=devices.device)9091return y + self.up_model(self.down_model(x)) * self.multiplier() * self.calc_scale()9293949596