5252
5353
5454if is_peft_available ():
55- from peft import LoraConfig , inject_adapter_in_model , set_peft_model_state_dict
55+ from peft import LoraConfig
5656 from peft .tuners .tuners_utils import BaseTunerLayer
5757 from peft .utils import get_peft_model_state_dict
5858
@@ -253,31 +253,41 @@ def _model_output(self, model, inputs_dict):
253253
254254 @require_peft_version_greater ("0.13.1" )
255255 @torch .no_grad ()
256- def test_lora_low_cpu_mem_usage_with_injection (self ):
257- """Tests that the LoRA state dict can be injected with low_cpu_mem_usage."""
256+ def test_lora_low_cpu_mem_usage_with_loading (self , tmp_path , atol = 1e-4 , rtol = 1e-4 ):
257+ """Tests that a LoRA adapter can be loaded with ` low_cpu_mem_usage=True` ."""
258258
259- model = self .model_class (** self .get_init_dict ()).to (torch_device )
259+ model = self .model_class (** self .get_init_dict ()).eval ().to (torch_device )
260+ inputs_dict = self .get_dummy_inputs ()
260261 lora_config = LoraConfig (
261262 r = 4 ,
262263 lora_alpha = 4 ,
263264 target_modules = ["to_q" , "to_k" , "to_v" , "to_out.0" ],
264265 init_lora_weights = False ,
265266 use_dora = False ,
266267 )
267- inject_adapter_in_model (lora_config , model , low_cpu_mem_usage = True )
268+ model . add_adapter (lora_config )
268269 assert check_if_lora_correctly_set (model ), "LoRA layers not set correctly"
269- assert "meta" in {p .device .type for p in model .parameters ()}, "The LoRA params should be on 'meta' device."
270270
271- peft_state_dict = get_peft_model_state_dict (model )
272- assert all (v .device .type == "meta" for v in peft_state_dict .values ()), "The LoRA state dict should be on meta."
273- dummy_state_dict = {
274- k : torch .randn (v .shape , device = torch_device , dtype = v .dtype ) for k , v in peft_state_dict .items ()
275- }
276- set_peft_model_state_dict (model , dummy_state_dict , low_cpu_mem_usage = True )
271+ torch .manual_seed (0 )
272+ output_lora = self ._model_output (model , inputs_dict )
273+
274+ model .save_lora_adapter (tmp_path )
275+ model .unload_lora ()
276+ assert not check_if_lora_correctly_set (model ), "LoRA should be unloaded"
277+
278+ model .load_lora_adapter (tmp_path , prefix = None , use_safetensors = True , low_cpu_mem_usage = True )
279+ assert check_if_lora_correctly_set (model ), "LoRA layers not set correctly"
277280 assert "meta" not in {p .device .type for p in model .parameters ()}, "No param should be on 'meta' device."
278281
279- output = self ._model_output (model , self .get_dummy_inputs ())
280- assert not torch .isnan (output ).any (), "Forward pass should work after low_cpu_mem_usage injection."
282+ torch .manual_seed (0 )
283+ output_low_cpu_mem = self ._model_output (model , inputs_dict )
284+ assert_tensors_close (
285+ output_lora ,
286+ output_low_cpu_mem ,
287+ atol = atol ,
288+ rtol = rtol ,
289+ msg = "Loading with `low_cpu_mem_usage` should give the same results." ,
290+ )
281291
282292 @skip_mps
283293 @pytest .mark .xfail (
@@ -314,7 +324,7 @@ def test_lora_fuse_nan(self):
314324
315325 @require_peft_version_greater ("0.13.2" )
316326 @torch .no_grad ()
317- def test_lora_B_bias (self , base_model_output , atol = 1e-3 , rtol = 1e-3 ):
327+ def test_lora_B_bias (self , base_model_output , tmp_path , atol = 1e-3 , rtol = 1e-3 ):
318328 # Seeded like the `base_model_output` fixture, so that fixture is this model's no-LoRA output.
319329 torch .manual_seed (0 )
320330 model = self .model_class (** self .get_init_dict ()).eval ().to (torch_device )
@@ -327,19 +337,7 @@ def test_lora_B_bias(self, base_model_output, atol=1e-3, rtol=1e-3):
327337 "target_modules" : ["to_q" , "to_k" , "to_v" , "to_out.0" ],
328338 "init_lora_weights" : False ,
329339 }
330- model .add_adapter (LoraConfig (** lora_config_kwargs , lora_bias = False ), adapter_name = "adapter-1" )
331- # `init_lora_weights=False` initializes `lora_A`/`lora_B` randomly, so keep a copy of them and reuse them for
332- # the `lora_bias=True` adapter below. Otherwise the two adapters would differ by their random init and not by
333- # the presence of the LoRA bias.
334- lora_weights = {k : v .clone () for k , v in get_peft_model_state_dict (model , adapter_name = "adapter-1" ).items ()}
335- torch .manual_seed (0 )
336- lora_bias_false_output = self ._model_output (model , inputs_dict )
337- model .delete_adapters ("adapter-1" )
338-
339340 model .add_adapter (LoraConfig (** lora_config_kwargs , lora_bias = True ), adapter_name = "adapter-1" )
340- # `lora_weights` has no bias entries, so the (randomly initialized, non-zero as `init_lora_weights=False`)
341- # `lora_B` biases are left untouched and are the only difference w.r.t. the `lora_bias=False` adapter.
342- set_peft_model_state_dict (model , lora_weights , adapter_name = "adapter-1" )
343341 lora_biases = [
344342 module .lora_B ["adapter-1" ].bias
345343 for module in model .modules ()
@@ -351,6 +349,22 @@ def test_lora_B_bias(self, base_model_output, atol=1e-3, rtol=1e-3):
351349 torch .manual_seed (0 )
352350 lora_bias_true_output = self ._model_output (model , inputs_dict )
353351
352+ # `init_lora_weights=False` initializes `lora_A`/`lora_B` randomly, so reload the very same weights (minus the
353+ # bias entries) as a `lora_bias=False` adapter. Otherwise the two adapters would differ by their random init
354+ # and not by the presence of the LoRA bias.
355+ model .save_lora_adapter (tmp_path , adapter_name = "adapter-1" )
356+ model .delete_adapters ("adapter-1" )
357+ state_dict = safetensors .torch .load_file (os .path .join (tmp_path , "pytorch_lora_weights.safetensors" ))
358+ state_dict = {k : v for k , v in state_dict .items () if not k .endswith ("lora_B.bias" )}
359+ model .load_lora_adapter (
360+ state_dict ,
361+ prefix = None ,
362+ adapter_name = "adapter-1" ,
363+ metadata = {** lora_config_kwargs , "lora_bias" : False },
364+ )
365+ torch .manual_seed (0 )
366+ lora_bias_false_output = self ._model_output (model , inputs_dict )
367+
354368 assert not torch .allclose (original_output , lora_bias_false_output , atol = atol , rtol = rtol )
355369 assert not torch .allclose (original_output , lora_bias_true_output , atol = atol , rtol = rtol )
356370 assert not torch .allclose (lora_bias_false_output , lora_bias_true_output , atol = atol , rtol = rtol )
0 commit comments