Expand loras to match if they are not the same size in lora merger

This commit is contained in:
Jaret Burkett committed 2026-08-12 10:04:44 -06:00
1 parent 0bacc88e47
commit 0fd3e61c4c
1 file changed
+28 -1
+28 -1
View File
@@ -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]