Description
The documented low-level adapter API does not round-trip shared tuner state when adapters are injected directly.
The low-level API supports inject_adapter_in_model(model, config) followed by get_peft_model_state_dict and set_peft_model_state_dict. Direct injection returns the original model with PEFT layers inserted, while shared tensors remain registered on the temporary BaseTuner. Several tuner-specific state-dict hooks still assume the base_model.* keys from the PeftModel wrapper.
This affects:
- TinyLoRA:
tinylora_v is silently omitted from the saved state dict.
- UniLoRA: saving raises a
KeyError for base_model.unilora_theta_d.
- VeRA and PVeRA: saving with the default
save_projection=True raises a projection-missing ValueError.
- VBLoRA: saving raises a
KeyError for base_model.vblora_vector_bank.
- FRoD: projection buffers are silently omitted and loading then raises a projection-missing
ValueError.
Reproduction
With a small torch.nn.Linear model on the current main branch:
model = inject_adapter_in_model(config, model)
state_dict = get_peft_model_state_dict(model)
set_peft_model_state_dict(model, state_dict)
For TinyLoRA on cuda:0, setting the source shared vector to 0.7 produced:
saved keys = ['lin0.tinylora_A', 'lin0.tinylora_B', 'lin0.tinylora_P']
missing adapter key = 'lin0.tinylora_v.default.0'
source v mean = 0.7
loaded v mean = 0.0
max output diff = 0.8507426
The corresponding get_peft_model wrapper path saves the shared tensors correctly for all six tuners.
Expected behavior
Directly injected shared tuners should save all adapter-owned shared tensors, load them without adapter-related missing keys, and preserve the model output. The existing get_peft_model save/load behavior should remain unchanged.
This is separate from #3495, which concerns UniLoRA trainability during injection rather than state-dict serialization.
Description
The documented low-level adapter API does not round-trip shared tuner state when adapters are injected directly.
The low-level API supports
inject_adapter_in_model(model, config)followed byget_peft_model_state_dictandset_peft_model_state_dict. Direct injection returns the original model with PEFT layers inserted, while shared tensors remain registered on the temporaryBaseTuner. Several tuner-specific state-dict hooks still assume thebase_model.*keys from thePeftModelwrapper.This affects:
tinylora_vis silently omitted from the saved state dict.KeyErrorforbase_model.unilora_theta_d.save_projection=Trueraises a projection-missingValueError.KeyErrorforbase_model.vblora_vector_bank.ValueError.Reproduction
With a small
torch.nn.Linearmodel on the currentmainbranch:For TinyLoRA on
cuda:0, setting the source shared vector to0.7produced:The corresponding
get_peft_modelwrapper path saves the shared tensors correctly for all six tuners.Expected behavior
Directly injected shared tuners should save all adapter-owned shared tensors, load them without adapter-related missing keys, and preserve the model output. The existing
get_peft_modelsave/load behavior should remain unchanged.This is separate from #3495, which concerns UniLoRA trainability during injection rather than state-dict serialization.