Skip to content

Conversation

@younesbelkada
Copy link
Contributor

@younesbelkada younesbelkada commented Jun 6, 2023

What does this PR do?

This PR integrates safetensors into peft

The logic now is as follows:

  • When saving locally a model, by default save the pickle file.
  • If a user wants to go for a safer serialization (recommended), users should pass safe_serialization=True to save_pretrained method
  • Same logic applies for push_to_hub method, by default we push on the Hub pickle file, except if a user calls safe_serialization=True to that method.
  • Inside from_pretrained, first look if the safetensors weights are present locally, then check for the pickle file. If none of them are present locally, try to fetch the safetensors weights from remote Hub, if not try to fetch the pickle file for remote.

What do you think?

An example of safetensors adapter weights on the Hub: https://huggingface.co/ybelkada/test-st-lora/tree/main

Fixes #546

cc @Narsil @pacman100

@HuggingFaceDocBuilderDev
Copy link

HuggingFaceDocBuilderDev commented Jun 6, 2023

The documentation is not available anymore as the PR was closed or merged.

Copy link

@Narsil Narsil left a comment

Choose a reason for hiding this comment

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

Shouldnt' you make the safetensors loading optional ? Just because there are already some PEFT pickled files out there already ? (Maybe it's handled elsewhere)

Comment on lines 407 to 419
filename = hf_hub_download(
model_id, SAFETENSORS_WEIGHTS_NAME, subfolder=kwargs.get("subfolder", None), **kwargs
)
except: # noqa
try:
filename = hf_hub_download(
model_id, WEIGHTS_NAME, subfolder=kwargs.get("subfolder", None), **kwargs
)
except: # noqa
raise ValueError(
f"Can't find weights for {model_id} in {model_id} or in the Hugging Face Hub. "
f"Please check that the file {WEIGHTS_NAME} or {SAFETENSORS_WEIGHTS_NAME} is present at {model_id}."
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like the double try / except will find a better workaround

Copy link
Contributor Author

Choose a reason for hiding this comment

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

using EntryNotFoundError for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@younesbelkada younesbelkada requested a review from pacman100 June 6, 2023 15:52
@classmethod
def from_pretrained(cls, model, model_id, adapter_name="default", is_trainable=False, **kwargs):
def from_pretrained(
cls, model, model_id, adapter_name="default", is_trainable=False, load_safetensors=False, **kwargs
Copy link

Choose a reason for hiding this comment

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

Suggested change
cls, model, model_id, adapter_name="default", is_trainable=False, load_safetensors=False, **kwargs
cls, model, model_id, adapter_name="default", is_trainable=False, use_safetensors=False, **kwargs

For consistency with transformers and diffusers. And it should probably be None instead of False if we want to make it the default.


if os.path.exists(os.path.join(path, WEIGHTS_NAME)):
# load_safetensors is only used for remote weights
remote_weights_name = SAFETENSORS_WEIGHTS_NAME if load_safetensors else WEIGHTS_NAME
Copy link

Choose a reason for hiding this comment

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

Since the default is False this will always use the pickled file iiuc unless user specifically asks for it.

Copy link
Contributor

@pacman100 pacman100 left a comment

Choose a reason for hiding this comment

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

Thank you @younesbelkada for adding support to safetensors and related nice tests 🔐🤗, left a couple comments

@younesbelkada
Copy link
Contributor Author

This is PR is ready for a final review! I have also updated the PR description a bit
Would love to get a final round of review
@pacman100 @Narsil

@younesbelkada
Copy link
Contributor Author

younesbelkada commented Jun 7, 2023

I think this is still to be done?

I don't know if we should add a ternary logic here as safetensors becomes a core dependency on this PR. With these changes from_pretrained first looks for safetensors weights either locally or on the Hub, then looks for pickle weights. So from my understanding there is no need to apply a ternary logic

Copy link
Contributor

@pacman100 pacman100 left a comment

Choose a reason for hiding this comment

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

Thank you @younesbelkada for iterating, LGTM, super cool feature addition!

isinstance(whisper_8bit.base_model.model.model.decoder.layers[0].self_attn.v_proj, Linear8bitLt)
)

@require_bitsandbytes
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice test!

def active_peft_config(self):
return self.peft_config[self.active_adapter]

def push_to_hub(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As huggingface/transformers#24074 will be merged maybe we should remove this method? @pacman100

Copy link
Contributor Author

@younesbelkada younesbelkada Jun 7, 2023

Choose a reason for hiding this comment

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

EDT: let's leave it as it is and remove it on the next transformers release

Copy link
Contributor

Choose a reason for hiding this comment

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

let's remove it as it is taken care in transformers and the next release is in couple of days

@younesbelkada
Copy link
Contributor Author

Thanks a lot @pacman100 ! I just left one open question: #553 (comment)

Copy link
Contributor

@pacman100 pacman100 left a comment

Choose a reason for hiding this comment

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

Thank you!

def active_peft_config(self):
return self.peft_config[self.active_adapter]

def push_to_hub(
Copy link
Contributor

Choose a reason for hiding this comment

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

let's remove it as it is taken care in transformers and the next release is in couple of days

@younesbelkada younesbelkada merged commit 189a6b8 into huggingface:main Jun 9, 2023
@younesbelkada younesbelkada deleted the add-st branch June 9, 2023 10:33
Guy-Bilitski pushed a commit to Guy-Bilitski/peft that referenced this pull request May 13, 2025
* add v1

* clean up

* more improvements

* add device

* final adjustements

* use `EntryNotFoundError`

* better checks

* add tests and final fixes

* make style && make quality

* remove `push_to_hub` because of the release
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.

Support safetensors for PEFT adapters or raise an exception when safe_serialization=True is specified

4 participants