Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 7.3k
[core / PEFT / LoRA] Integrate PEFT into Unet#5151
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
cf2c0ba8759f55c90aedc0bfb1363002ea3d6f500c64ca2bbf62e50648842c071d49901fb4aa24c803f611a493a4ea895916b1161b3a02becc135f25c493e5a09530cd3ce0929e500d2edaea1487815060a14573c26c4186996b8268912e410e0e618c42fa199fec57ac925f8ebb16ca81f886e7376debff82de494403c1e8fca9f4f21a7b3568e7f459285f24dad33ec04337b40592a2646f3d0e771f086bd6f502e73a486c7d6994abbc061e316c32dd0d5ba6c180892d1d3c0d9d687e1e252f4a52298dc6b874746de104130491d517e36fe1b2d2825d5b206f0de2265fc2265a928e7a3dc67868b48abb232581db89ffc643eb957108b5d9ce0dbd44f5671c321ec42d974a0598e6a7a6cd69992964525743e7183863e44c17cf435ce97e8cb7a2af9bfd8da2350f497280c0ce80974cfc1c36ec7212c94a8695d2b44e82d83c92aef0bf939e0410f63524b1a07322452b748ae25606db84d0723b55ca039a544ae0a9a01d542d64dc6ff6d6e5d5394d3732043aa599f5566faee801c94452a14779e18f3a25cad5a4b3708ed9323612bec6534264e2d87db0c3dc6172b6474d80a9cb588aeb419b52498dc1702d17b3400c2da1402506e6d80423c4dc79d5e7647a5cd549a02c162ffaf30f4145818836e32e2fa61fc9102399924222e21a279a0fe4203e981af261737cfb2150d93521188d03d1a3fabb521fc55a1a7106b221834f8e21a8d6c44f658d7fd50a7e92c6de4e382ee6ae767fa0f976eb4e1381f708dbaf17206c950d19cFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -17,6 +17,7 @@ | ||
| import torch.nn.functional as F | ||
| from torch import nn | ||
| from ..utils import USE_PEFT_BACKEND | ||
| from ..utils.torch_utils import maybe_allow_in_graph | ||
| from .activations import get_activation | ||
| from .attention_processor import Attention | ||
| @@ -300,6 +301,7 @@ def __init__( | ||
| super().__init__() | ||
| inner_dim = int(dim * mult) | ||
| dim_out = dim_out if dim_out is not None else dim | ||
| linear_cls = LoRACompatibleLinear if not USE_PEFT_BACKEND else nn.Linear | ||
| if activation_fn == "gelu": | ||
| act_fn = GELU(dim, inner_dim) | ||
| @@ -316,14 +318,15 @@ def __init__( | ||
| # project dropout | ||
| self.net.append(nn.Dropout(dropout)) | ||
| # project out | ||
| self.net.append(LoRACompatibleLinear(inner_dim, dim_out)) | ||
| self.net.append(linear_cls(inner_dim, dim_out)) | ||
| # FF as used in Vision Transformer, MLP-Mixer, etc. have a final dropout | ||
| if final_dropout: | ||
| self.net.append(nn.Dropout(dropout)) | ||
| def forward(self, hidden_states: torch.Tensor, scale: float = 1.0) -> torch.Tensor: | ||
| compatible_cls = (GEGLU,) if USE_PEFT_BACKEND else (GEGLU, LoRACompatibleLinear) | ||
| for module in self.net: | ||
| if isinstance(module, (LoRACompatibleLinear, GEGLU)): | ||
| if isinstance(module, compatible_cls): | ||
| hidden_states = module(hidden_states, scale) | ||
| else: | ||
| hidden_states = module(hidden_states) | ||
| @@ -368,7 +371,9 @@ class GEGLU(nn.Module): | ||
| def __init__(self, dim_in: int, dim_out: int): | ||
| super().__init__() | ||
| self.proj = LoRACompatibleLinear(dim_in, dim_out * 2) | ||
| linear_cls = LoRACompatibleLinear if not USE_PEFT_BACKEND else nn.Linear | ||
| self.proj = linear_cls(dim_in, dim_out * 2) | ||
| def gelu(self, gate: torch.Tensor) -> torch.Tensor: | ||
| if gate.device.type != "mps": | ||
| @@ -377,7 +382,8 @@ def gelu(self, gate: torch.Tensor) -> torch.Tensor: | ||
| return F.gelu(gate.to(dtype=torch.float32)).to(dtype=gate.dtype) | ||
| def forward(self, hidden_states, scale: float = 1.0): | ||
| hidden_states, gate = self.proj(hidden_states, scale).chunk(2, dim=-1) | ||
| args = () if USE_PEFT_BACKEND else (scale,) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice. | ||
| hidden_states, gate = self.proj(hidden_states, *args).chunk(2, dim=-1) | ||
| return hidden_states * self.gelu(gate) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -32,10 +32,12 @@ | ||
| DIFFUSERS_CACHE, | ||
| FLAX_WEIGHTS_NAME, | ||
| HF_HUB_OFFLINE, | ||
| MIN_PEFT_VERSION, | ||
| SAFETENSORS_WEIGHTS_NAME, | ||
| WEIGHTS_NAME, | ||
| _add_variant, | ||
| _get_model_file, | ||
| check_peft_version, | ||
| deprecate, | ||
| is_accelerate_available, | ||
| is_torch_version, | ||
| @@ -187,6 +189,7 @@ class ModelMixin(torch.nn.Module, PushToHubMixin): | ||
| _automatically_saved_args = ["_diffusers_version", "_class_name", "_name_or_path"] | ||
| _supports_gradient_checkpointing = False | ||
| _keys_to_ignore_on_load_unexpected = None | ||
| _hf_peft_config_loaded = False | ||
| def __init__(self): | ||
| super().__init__() | ||
| @@ -292,6 +295,153 @@ def disable_xformers_memory_efficient_attention(self): | ||
| """ | ||
| self.set_use_memory_efficient_attention_xformers(False) | ||
| def add_adapter(self, adapter_config, adapter_name: str = "default") -> None: | ||
| r""" | ||
| Adds a new adapter to the current model for training. If no adapter name is passed, a default name is assigned | ||
| to the adapter to follow the convention of the PEFT library. | ||
| If you are not familiar with adapters and PEFT methods, we invite you to read more about them in the PEFT | ||
| [documentation](https://huggingface.co/docs/peft). | ||
| Args: | ||
| adapter_config (`[~peft.PeftConfig]`): | ||
| The configuration of the adapter to add; supported adapters are non-prefix tuning and adaption prompt | ||
| methods. | ||
| adapter_name (`str`, *optional*, defaults to `"default"`): | ||
| The name of the adapter to add. If no name is passed, a default name is assigned to the adapter. | ||
pacman100 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| """ | ||
| check_peft_version(min_version=MIN_PEFT_VERSION) | ||
| from peft import PeftConfig, inject_adapter_in_model | ||
| if not self._hf_peft_config_loaded: | ||
| self._hf_peft_config_loaded = True | ||
| elif adapter_name in self.peft_config: | ||
| raise ValueError(f"Adapter with name {adapter_name} already exists. Please use a different name.") | ||
| if not isinstance(adapter_config, PeftConfig): | ||
| raise ValueError( | ||
| f"adapter_config should be an instance of PeftConfig. Got {type(adapter_config)} instead." | ||
| ) | ||
| # Unlike transformers, here we don't need to retrieve the name_or_path of the unet as the loading logic is | ||
| # handled by the `load_lora_layers` or `LoraLoaderMixin`. Therefore we set it to `None` here. | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite get this. Does it hurt to have ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No it does not, but I think there is no equivalent of it in diffusers per my understanding | ||
| adapter_config.base_model_name_or_path = None | ||
| inject_adapter_in_model(adapter_config, self, adapter_name) | ||
| self.set_adapter(adapter_name) | ||
| def set_adapter(self, adapter_name: Union[str, List[str]]) -> None: | ||
| """ | ||
| Sets a specific adapter by forcing the model to only use that adapter and disables the other adapters. | ||
| If you are not familiar with adapters and PEFT methods, we invite you to read more about them on the PEFT | ||
younesbelkada marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| official documentation: https://huggingface.co/docs/peft | ||
| Args: | ||
| adapter_name (Union[str, List[str]])): | ||
| The list of adapters to set or the adapter name in case of single adapter. | ||
| """ | ||
| check_peft_version(min_version=MIN_PEFT_VERSION) | ||
| if not self._hf_peft_config_loaded: | ||
| raise ValueError("No adapter loaded. Please load an adapter first.") | ||
| if isinstance(adapter_name, str): | ||
| adapter_name = [adapter_name] | ||
| missing = set(adapter_name) - set(self.peft_config) | ||
| if len(missing) > 0: | ||
| raise ValueError( | ||
| f"Following adapter(s) could not be found: {', '.join(missing)}. Make sure you are passing the correct adapter name(s)." | ||
| f" current loaded adapters are: {list(self.peft_config.keys())}" | ||
| ) | ||
| from peft.tuners.tuners_utils import BaseTunerLayer | ||
| _adapters_has_been_set = False | ||
| for _, module in self.named_modules(): | ||
| if isinstance(module, BaseTunerLayer): | ||
| if hasattr(module, "set_adapter"): | ||
| module.set_adapter(adapter_name) | ||
| # Previous versions of PEFT does not support multi-adapter inference | ||
| elif not hasattr(module, "set_adapter") and len(adapter_name) != 1: | ||
| raise ValueError( | ||
| "You are trying to set multiple adapters and you have a PEFT version that does not support multi-adapter inference. Please upgrade to the latest version of PEFT." | ||
| " `pip install -U peft` or `pip install -U git+https://github.com/huggingface/peft.git`" | ||
| ) | ||
| else: | ||
| module.active_adapter = adapter_name | ||
| _adapters_has_been_set = True | ||
| if not _adapters_has_been_set: | ||
| raise ValueError( | ||
| "Did not succeeded in setting the adapter. Please make sure you are using a model that supports adapters." | ||
| ) | ||
| def disable_adapters(self) -> None: | ||
| r""" | ||
| Disable all adapters attached to the model and fallback to inference with the base model only. | ||
| If you are not familiar with adapters and PEFT methods, we invite you to read more about them on the PEFT | ||
| official documentation: https://huggingface.co/docs/peft | ||
| """ | ||
| check_peft_version(min_version=MIN_PEFT_VERSION) | ||
| if not self._hf_peft_config_loaded: | ||
| raise ValueError("No adapter loaded. Please load an adapter first.") | ||
| from peft.tuners.tuners_utils import BaseTunerLayer | ||
| for _, module in self.named_modules(): | ||
| if isinstance(module, BaseTunerLayer): | ||
| if hasattr(module, "enable_adapters"): | ||
| module.enable_adapters(enabled=False) | ||
| else: | ||
| # support for older PEFT versions | ||
| module.disable_adapters = True | ||
| def enable_adapters(self) -> None: | ||
| """ | ||
| Enable adapters that are attached to the model. The model will use `self.active_adapters()` to retrieve the | ||
| list of adapters to enable. | ||
| If you are not familiar with adapters and PEFT methods, we invite you to read more about them on the PEFT | ||
| official documentation: https://huggingface.co/docs/peft | ||
| """ | ||
| check_peft_version(min_version=MIN_PEFT_VERSION) | ||
| if not self._hf_peft_config_loaded: | ||
| raise ValueError("No adapter loaded. Please load an adapter first.") | ||
| from peft.tuners.tuners_utils import BaseTunerLayer | ||
| for _, module in self.named_modules(): | ||
| if isinstance(module, BaseTunerLayer): | ||
| if hasattr(module, "enable_adapters"): | ||
| module.enable_adapters(enabled=True) | ||
| else: | ||
| # support for older PEFT versions | ||
| module.disable_adapters = False | ||
| def active_adapters(self) -> List[str]: | ||
| """ | ||
| Gets the current list of active adapters of the model. | ||
| If you are not familiar with adapters and PEFT methods, we invite you to read more about them on the PEFT | ||
| official documentation: https://huggingface.co/docs/peft | ||
| """ | ||
| check_peft_version(min_version=MIN_PEFT_VERSION) | ||
| if not self._hf_peft_config_loaded: | ||
| raise ValueError("No adapter loaded. Please load an adapter first.") | ||
| from peft.tuners.tuners_utils import BaseTunerLayer | ||
| for _, module in self.named_modules(): | ||
| if isinstance(module, BaseTunerLayer): | ||
| return module.active_adapter | ||
BenjaminBossan marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| def save_pretrained( | ||
| self, | ||
| save_directory: Union[str, os.PathLike], | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.