Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AUTOMATIC1111
GitHub Repository: AUTOMATIC1111/stable-diffusion-webui
Path: blob/master/extensions-builtin/Lora/network_lora.py
2447 views
1
import torch
2
3
import lyco_helpers
4
import modules.models.sd3.mmdit
5
import network
6
from modules import devices
7
8
9
class ModuleTypeLora(network.ModuleType):
10
def create_module(self, net: network.Network, weights: network.NetworkWeights):
11
if all(x in weights.w for x in ["lora_up.weight", "lora_down.weight"]):
12
return NetworkModuleLora(net, weights)
13
14
if all(x in weights.w for x in ["lora_A.weight", "lora_B.weight"]):
15
w = weights.w.copy()
16
weights.w.clear()
17
weights.w.update({"lora_up.weight": w["lora_B.weight"], "lora_down.weight": w["lora_A.weight"]})
18
19
return NetworkModuleLora(net, weights)
20
21
return None
22
23
24
class NetworkModuleLora(network.NetworkModule):
25
def __init__(self, net: network.Network, weights: network.NetworkWeights):
26
super().__init__(net, weights)
27
28
self.up_model = self.create_module(weights.w, "lora_up.weight")
29
self.down_model = self.create_module(weights.w, "lora_down.weight")
30
self.mid_model = self.create_module(weights.w, "lora_mid.weight", none_ok=True)
31
32
self.dim = weights.w["lora_down.weight"].shape[0]
33
34
def create_module(self, weights, key, none_ok=False):
35
weight = weights.get(key)
36
37
if weight is None and none_ok:
38
return None
39
40
is_linear = type(self.sd_module) in [torch.nn.Linear, torch.nn.modules.linear.NonDynamicallyQuantizableLinear, torch.nn.MultiheadAttention, modules.models.sd3.mmdit.QkvLinear]
41
is_conv = type(self.sd_module) in [torch.nn.Conv2d]
42
43
if is_linear:
44
weight = weight.reshape(weight.shape[0], -1)
45
module = torch.nn.Linear(weight.shape[1], weight.shape[0], bias=False)
46
elif is_conv and key == "lora_down.weight" or key == "dyn_up":
47
if len(weight.shape) == 2:
48
weight = weight.reshape(weight.shape[0], -1, 1, 1)
49
50
if weight.shape[2] != 1 or weight.shape[3] != 1:
51
module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], self.sd_module.kernel_size, self.sd_module.stride, self.sd_module.padding, bias=False)
52
else:
53
module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)
54
elif is_conv and key == "lora_mid.weight":
55
module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], self.sd_module.kernel_size, self.sd_module.stride, self.sd_module.padding, bias=False)
56
elif is_conv and key == "lora_up.weight" or key == "dyn_down":
57
module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)
58
else:
59
raise AssertionError(f'Lora layer {self.network_key} matched a layer with unsupported type: {type(self.sd_module).__name__}')
60
61
with torch.no_grad():
62
if weight.shape != module.weight.shape:
63
weight = weight.reshape(module.weight.shape)
64
module.weight.copy_(weight)
65
66
module.to(device=devices.cpu, dtype=devices.dtype)
67
module.weight.requires_grad_(False)
68
69
return module
70
71
def calc_updown(self, orig_weight):
72
up = self.up_model.weight.to(orig_weight.device)
73
down = self.down_model.weight.to(orig_weight.device)
74
75
output_shape = [up.size(0), down.size(1)]
76
if self.mid_model is not None:
77
# cp-decomposition
78
mid = self.mid_model.weight.to(orig_weight.device)
79
updown = lyco_helpers.rebuild_cp_decomposition(up, down, mid)
80
output_shape += mid.shape[2:]
81
else:
82
if len(down.shape) == 4:
83
output_shape += down.shape[2:]
84
updown = lyco_helpers.rebuild_conventional(up, down, output_shape, self.network.dyn_dim)
85
86
return self.finalize_updown(updown, orig_weight, output_shape)
87
88
def forward(self, x, y):
89
self.up_model.to(device=devices.device)
90
self.down_model.to(device=devices.device)
91
92
return y + self.up_model(self.down_model(x)) * self.multiplier() * self.calc_scale()
93
94
95
96