[bugfix]: run the base layer while a LoRA wrapper has no adapter
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user