Expand loras to match if they are not the same size in lora merger
This commit is contained in:
1 parent
0bacc88e47
commit
0fd3e61c4c
1 file changed
+28
-1
@@ -24,6 +24,15 @@ def log(message: str) -> None:
|
|||||||
print(message, flush=True)
|
print(message, flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
def pad_to_shape(tensor: torch.Tensor, shape: tuple) -> torch.Tensor:
|
||||||
|
"""Zero-pad a tensor up to the given shape (e.g. to match a larger LoRA rank)."""
|
||||||
|
if tuple(tensor.shape) == tuple(shape):
|
||||||
|
return tensor
|
||||||
|
out = torch.zeros(shape, dtype=tensor.dtype, device=tensor.device)
|
||||||
|
out[tuple(slice(0, s) for s in tensor.shape)] = tensor
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Merge a list of LoRAs into a single checkpoint."
|
description="Merge a list of LoRAs into a single checkpoint."
|
||||||
@@ -88,6 +97,24 @@ def main() -> int:
|
|||||||
for key, tensor in state_dict.items():
|
for key, tensor in state_dict.items():
|
||||||
scaled = tensor.to(torch.float32) * strength
|
scaled = tensor.to(torch.float32) * strength
|
||||||
if key in merged:
|
if key in merged:
|
||||||
|
existing = merged[key]
|
||||||
|
if existing.shape != scaled.shape:
|
||||||
|
if existing.ndim != scaled.ndim:
|
||||||
|
print(
|
||||||
|
f"Cannot merge key '{key}': incompatible shapes "
|
||||||
|
f"{tuple(existing.shape)} vs {tuple(scaled.shape)}",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
return 2
|
||||||
|
# Different LoRA ranks: zero-pad both to the max size on
|
||||||
|
# each mismatched dim so they can merge as equal sizes.
|
||||||
|
target = tuple(
|
||||||
|
max(a, b) for a, b in zip(existing.shape, scaled.shape)
|
||||||
|
)
|
||||||
|
existing = pad_to_shape(existing, target)
|
||||||
|
scaled = pad_to_shape(scaled, target)
|
||||||
|
merged[key] = existing
|
||||||
merged[key].add_(scaled)
|
merged[key].add_(scaled)
|
||||||
else:
|
else:
|
||||||
merged[key] = scaled
|
merged[key] = scaled
|
||||||
@@ -102,7 +129,7 @@ def main() -> int:
|
|||||||
"ss_base_model_version",
|
"ss_base_model_version",
|
||||||
"software",
|
"software",
|
||||||
]
|
]
|
||||||
orig_metadata = f.metadata()
|
orig_metadata = f.metadata() or {}
|
||||||
for meta_key in metadata_to_keep:
|
for meta_key in metadata_to_keep:
|
||||||
if meta_key in orig_metadata:
|
if meta_key in orig_metadata:
|
||||||
metadata[meta_key] = orig_metadata[meta_key]
|
metadata[meta_key] = orig_metadata[meta_key]
|
||||||
|
|||||||
Reference in new issue
Block a user