Files

48 lines
1.6 KiB
Python

"""The merger node's SVC widget and its factor plumbing."""
import torch
from src.lora_mergekit_merge import LoraMergerMergekit, build_svc_factors
from src.merge.svc import SVC_MODES
def test_widget_offers_the_svc_modes():
spec = LoraMergerMergekit.INPUT_TYPES()["required"]
assert "svc" in spec
choices, opts = spec["svc"]
assert tuple(choices) == SVC_MODES
assert opts["default"] == "off"
def test_build_svc_factors_folds_alpha_and_strength_into_scale():
"""scale must be (alpha/rank) * strength so the factor reproduces the task's
contribution exactly as the merge used it."""
up = torch.randn(8, 4)
down = torch.randn(4, 6)
tuples = {"a": (up, down, torch.tensor(2.0))}
weights = torch.tensor([3.0])
factors = build_svc_factors(tuples, weights)
assert len(factors) == 1
f_up, f_down, scale = factors[0]
assert f_up is up and f_down is down
assert scale == 2.0 / 4 * 3.0
def test_build_svc_factors_defaults_alpha_to_rank():
"""alpha=None means scale 1.0 -- the same convention as the delta builder."""
up = torch.randn(8, 4)
down = torch.randn(4, 6)
factors = build_svc_factors({"a": (up, down, None)}, torch.tensor([1.0]))
assert factors[0][2] == 1.0
def test_build_svc_factors_preserves_order():
ups = [torch.randn(8, 2) for _ in range(3)]
downs = [torch.randn(2, 6) for _ in range(3)]
tuples = {f"l{i}": (ups[i], downs[i], None) for i in range(3)}
factors = build_svc_factors(tuples, torch.tensor([1.0, 2.0, 3.0]))
assert [f[2] for f in factors] == [1.0, 2.0, 3.0]
assert all(factors[i][0] is ups[i] for i in range(3))