Skip to content

Commit 8a41940

Browse files
PiSSA, OLoRA: Delete initial adapter after conversion instead of the active adapter (huggingface#1933)
Resolves huggingface#1860 As discussed in that issue, it's not user friendly to delete the default adapter of a PiSSA/OLoRA model after calling save_pretrained with weight conversion. Instead, it is much more intuitive to delete the initial adapter instead, since it is loaded inside the method and not by the user, so it's really an implementation detail. Apart from this, I made the following related changes: - Put everything in a try ... finally to ensure that the initial adapter does not hang around if there is an error (thus not hogging memory). - Renamed initial_adapter to initial_adapter_name, to make it clear that this is the name and not the adapter itself.
1 parent bc3df1d commit 8a41940

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

src/peft/peft_model.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -271,24 +271,29 @@ def save_mutated_as_lora(peft_config, path_initial_model_for_weight_conversion,
271271
str(peft_config.init_lora_weights).lower().startswith(prefix) for prefix in ["pissa", "olora", "true"]
272272
):
273273
warnings.warn(
274-
"`path_initial_model_for_weight_conversion` only works for converting a PiSSA or OLoRA adapter to a LoRA adapter"
274+
"`path_initial_model_for_weight_conversion` only works for converting a PiSSA or OLoRA adapter to "
275+
"a LoRA adapter"
275276
)
276-
initial_adapter = os.path.basename(path_initial_model_for_weight_conversion)
277-
self.load_adapter(
278-
os.path.dirname(path_initial_model_for_weight_conversion),
279-
subfolder=initial_adapter,
280-
adapter_name=initial_adapter,
281-
)
282-
if any(
283-
str(self.peft_config[initial_adapter].init_lora_weights).lower().startswith(prefix)
284-
for prefix in ["pissa", "olora"]
285-
):
286-
raise ValueError(
287-
"The `init_lora_weights` parameter of the initial adapter should be set to `True`. "
288-
"Otherwise, `self.load_adapter` will subtract the decomposed values again based on the residual model."
277+
initial_adapter_name = os.path.basename(path_initial_model_for_weight_conversion)
278+
try:
279+
self.load_adapter(
280+
os.path.dirname(path_initial_model_for_weight_conversion),
281+
subfolder=initial_adapter_name,
282+
adapter_name=initial_adapter_name,
283+
)
284+
is_pissa = str(self.peft_config[initial_adapter_name].init_lora_weights).lower().startswith("pissa")
285+
is_olora = str(self.peft_config[initial_adapter_name].init_lora_weights).lower() == "olora"
286+
if is_pissa or is_olora:
287+
raise ValueError(
288+
"The `init_lora_weights` parameter of the initial adapter should be set to `True`. "
289+
"Otherwise, `self.load_adapter` will subtract the decomposed values again based on the "
290+
"residual model."
291+
)
292+
output_state_dict = self.base_model.subtract_mutated_init(
293+
output_state_dict, initial_adapter_name, kwargs
289294
)
290-
output_state_dict = self.base_model.subtract_mutated_init(output_state_dict, initial_adapter, kwargs)
291-
self.delete_adapter(adapter_name)
295+
finally:
296+
self.delete_adapter(initial_adapter_name)
292297
return output_state_dict
293298

294299
if is_main_process:

tests/test_initialization.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,13 @@ def test_lora_pissa_conversion_same_output_after_loading(self, data, tmp_path):
323323
)
324324

325325
# save the model with conversion
326+
peft_config_keys_before = list(peft_model.peft_config.keys())
326327
peft_model.save_pretrained(
327328
tmp_path / "pissa-model-converted", path_initial_model_for_weight_conversion=tmp_path / "init-model"
328329
)
330+
peft_config_keys_after = list(peft_model.peft_config.keys())
331+
assert peft_config_keys_before == peft_config_keys_after
332+
329333
model_converted = PeftModel.from_pretrained(deepcopy(model), tmp_path / "pissa-model-converted")
330334
output_converted = model_converted(data)[0]
331335

@@ -597,9 +601,13 @@ def test_olora_conversion_same_output_after_loading(self, data, tmp_path):
597601
)
598602

599603
# save the model with conversion
604+
peft_config_keys_before = list(peft_model.peft_config.keys())
600605
peft_model.save_pretrained(
601606
tmp_path / "olora-model-converted", path_initial_model_for_weight_conversion=tmp_path / "init-model"
602607
)
608+
peft_config_keys_after = list(peft_model.peft_config.keys())
609+
assert peft_config_keys_before == peft_config_keys_after
610+
603611
model_converted = PeftModel.from_pretrained(deepcopy(model), tmp_path / "olora-model-converted")
604612
output_converted = model_converted(data)[0]
605613

0 commit comments

Comments
 (0)