Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new feature of SafeLoRA #2201

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Conversation

chiayi-hsu
Copy link

The pull request was closed due to syncing with the latest version of PEFT, so I have requested the pull request again.
I have made all the necessary changes based on our previous conversations in this version.

If there are any issues, please let me know.

Thank you.

Copy link
Member

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update to the SafeLoRA PR. I did another review and found a few areas to improve. Please take a look. Also, please run make style once you're finished with your changed.

examples/safelora/README.md Outdated Show resolved Hide resolved
examples/safelora/README.md Outdated Show resolved Hide resolved
save_weights=True)

final_lora_weight = apply_safelora(config)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a bit more to the example. For instance, how to save and load these weights?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added more descriptions to the example.
If you feel there are still any missing parts, please let me know.

Comment on lines 15 to 16
config = SafeLoraConfig(base_model_path='../LLM_Models/llama-2-7b-hf/',\
aligned_model_path='../LLM_Models/llama-2-7b-chat-fp16/',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the HF model ids for these two.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been modified.

Comment on lines 215 to 217
peft_weights = {name: f.get_tensor(name).to(safelora_config.dtype) for name in f.keys()}
else:
peft_weights = {name: f.get_tensor(name).to(safelora_config.dtype) for name in f.keys()}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 lines are identical

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been modified.

- if (safelora_config.devices).lower() == "cpu":
-        peft_weights = {name: f.get_tensor(name).to(safelora_config.dtype) for name in f.keys()}
- else:
-        peft_weights = {name: f.get_tensor(name).to(safelora_config.dtype) for name in f.keys()}
+ peft_weights = {name: f.get_tensor(name).to(safelora_config.dtype) for name in f.keys()}

]
align_model_parameters = [
name for name in sl_align.weight_map.keys() if any(v in name for v in list(peft_config.target_modules))
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check that base_model_parameters and align_model_parameters are the same?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a check to verify if the model weights are the same.

+ if (sl_base.get_tensor(name_base) == sl_align.get_tensor(name_align)).all():
+        raise ValueError("The weights of the base Model and the aligned Model should be different.")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant something else. Would we expect that base_model_parameters == align_model_parameters? If not, under what circumstances would they differ?

return safety_vector


def project_weights(configs, peft_weights, v):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename configs to config or safelora_config.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been modified.

metadata={"help": "The path of the LoRA wieghts and configs."},
)

select_layers_type: str = field(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of str, we can annotate this as Literal["threshold", "number"].

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been modified.

src/peft/utils/safelora.py Outdated Show resolved Hide resolved
select_layers_type='threshold',
save_weights=True)

final_lora_weight = apply_safelora(config)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example should show inference, here we only create the weights. What are the next steps?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added more explanations in the README.md and also included code on how to use the SafeLoRA model.

@BenjaminBossan
Copy link
Member

@chiayi-hsu Once you're finished with your changes and want me to give another review, please ping me.

@chiayi-hsu
Copy link
Author

@BenjaminBossan I have completed the modifications. Please help review them. Thanks!

Copy link
Member

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the updates. I did another review. Most of what I found are just smaller things like docs, please take a look.

Now as a next step, it is important that we also add some unit tests. This not going to be very straightforward, because we cannot easily test model alignment and we also don't want to use any big models during unit testing.

One proposal for this would be to use a small model like hf-internal-testing/tiny-random-OPTForCausalLM as the base model. Then let's modify some weights (setting them to 0?) and save this as the "aligned" model. Then call apply_safelora with these 2 models and various options to see if those tests pass. This would not really check the alignment though.

In addition, we could think about adding a true alignment test for the nightly run with GPU. For this test, it would be okay to use a bigger model (but ideally still not too big).

LMK what you think about this testing strategy and if you have further questions.

Apart from this, please call make style on your PR, as this is a prerequisite for the CI to pass.

This is the configuration class to store the configuration of a safeLora.


Args:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please format the docstring to be in line with the other docstrings used in PEFT. As an example, check here:

Comment on lines +62 to +72
default="meta-llama/Llama-2-7b-hf",
metadata={"help": "The path of the base model for obtaining the aligned matrix."},
)

aligned_model_path: str = field(
default="TheBloke/Llama-2-7B-Chat-fp16",
metadata={"help": "The path of the aligned model for obtaining the aligned matrix."},
)

peft_model_path: str = field(
default="LisaSchunke/llama-2-7b-peft-finetuned-20000-dataset",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it doesn't make sense to set default values here, I would remove them. WDYT?


peft_model_path: str = field(
default="LisaSchunke/llama-2-7b-peft-finetuned-20000-dataset",
metadata={"help": "The path of the LoRA wieghts and configs."},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
metadata={"help": "The path of the LoRA wieghts and configs."},
metadata={"help": "The path of the LoRA weights and config."},


device: str = field(
default="cuda",
metadata={"help": "Device is used in SafeLoRA. (cuda or cpu)"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
metadata={"help": "Device is used in SafeLoRA. (cuda or cpu)"},
metadata={"help": "Device that is used for SafeLoRA (cuda or cpu)."},

src/peft/utils/safelora.py Outdated Show resolved Hide resolved
After fine-tuning large language models (LLMs) using LoRA, the alignment of the resulting models may decrease.
Therefore, applying `apply_safelora()` is intended to help preserve the alignment of the final models.

It is important to note that the model weights of the aligned model and the base model must be of the same size.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also mention that right now, only safetensors format is supported.

)

with safe_open(
f"{os.path.join(safelora_config.peft_model_path, 'adapter_model.safetensors')}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not hard-code adapter_model.safetensors, let's use peft.utils.constants.SAFETENSORS_WEIGHTS_NAME.

final_weights, _ = project_weights(safelora_config, peft_weights, projected_matrix)

if safelora_config.save_weights:
save_file(final_weights, f"{os.path.join(safelora_config.peft_model_path, 'adapter_model.safetensors')}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not hard-code adapter_model.safetensors, let's use peft.utils.constants.SAFETENSORS_WEIGHTS_NAME.

examples/safelora/README.md Outdated Show resolved Hide resolved
examples/safelora/README.md Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants