[bugfix]: run the base layer while a LoRA wrapper has no adapter

This commit is contained in:
Aryan Kumar
2026-10-28 14:49:15 -07:00
committed by Junda Su
parent 6743f4b4b7
commit 6bb444eef1
2 changed files with 19 additions and 2 deletions
+5 -2
View File
@@ -163,8 +163,11 @@ class BaseLayerWithLoRA(nn.Module):
lora_B = self.lora_B.to_local()
lora_A = self.lora_A.to_local()
if self.side_branch and (self.lora_A is None or self._strength_is_zero):
# No adapter, or strength 0, is exactly the unadapted layer, down to the output dtype.
if self.lora_A is None or (self.side_branch and self._strength_is_zero):
# No adapter, or strength 0 on a side branch, is exactly the unadapted layer, down to the output dtype.
# A merge-mode wrapper reaches this branch while its first adapter is still loading or after a load
# failed: the pipeline wraps every linear before it reads the weights, so an unadapted request must
# not depend on an adapter that is not there.
return self.base_layer(x)
if not self.merged and not self.disable_lora:
@@ -54,6 +54,20 @@ def _packed_linear(seed: int = 0) -> ReplicatedLinear:
return layer
def test_a_wrapped_layer_without_an_adapter_runs_the_base_layer() -> None:
"""A dense wrapper with no adapter is the base layer.
The pipeline wraps every linear when the first runtime adapter is set. A render that then runs without one, or a
load that failed part-way, must still produce the base model's output instead of failing on the missing factors.
"""
base = _dense_linear()
wrapped = get_lora_layer(base)
assert not wrapped.side_branch and wrapped.lora_A is None
x = torch.randn(2, IN, dtype=torch.bfloat16)
with torch.no_grad():
assert torch.equal(wrapped(x)[0], base(x)[0])
def _factors(seed: int = 1) -> tuple[torch.Tensor, torch.Tensor]:
generator = torch.Generator().manual_seed(seed)
return torch.randn(RANK, IN, generator=generator), torch.randn(OUT, RANK, generator=generator)