Commit Graph

114 Commits

Author SHA1 Message Date
Ihor Vitenko 1598ecb8fc DOC Expand installation guide (#3406)
Expand contributing installation guide with fork and setup steps

Quote editable install and link contributing guide from install.md

Fix relative path of contributing link in install.md
2026-07-08 16:43:59 +02:00
Daoyuan Li 5d3916b304 DOC Fix typos (#3328) 2026-06-18 18:16:52 +02:00
githubnemo daf335f503 Documentation re-structure (#3300)
The current state of the PEFT docs is not one of structure and I was constantly annoyed that whenever I wanted to change something there were several places that needed touching and they all felt disconnected. So this is my attempt at structuring the docs. Some of these ideas are quite old (discussed in 01/2025) but are still valid.

I've removed most of the code guides without replacement. That's not ideal, I think we should have code examples but I'm think they should be method-focused. Maybe one general example of a training workflow is sufficient because most methods follow the same scheme.

All details from the method guides (prompting, lora, oft/boft, etc.) are now integrated into the respective method pages instead. I would have hesitated to do this if these guides would have integrated information about the adapters but they didn't. I think it makes a lot more sense to have one place for each method to gather examples/tips/recommendations and that is now the `package_refernce/<method>` page. This page now also hosts a small space that shows the MetaMathQA (and potentially other) benchmark results highlighted for that method.

I've moved the LoRA initializations to `package_reference/lora#Initialization` and converted the init methods to `<hfoption>`-tags. This collapses them to a list but may reduce searchability through the document - at least firefox is not able to search 'through' the option tabs. This also doesn't make them appear in the ToC and people specifically searching for, say, PiSSA won't find it directly. I think that's OK though, since the search is able to locate it.

The quicktour is a bit more detailed about what happens under the hood (quick doesn't have to mean simplistic) and includes some new visualizations. I hope that we can integrate more visualizations in the future where it makes sense.

* Remove PEFT method space + front page buttons

The space was not that useful anymore since most methods are compatible
with most models.

The front page buttons are, at least temporarily, with the exception
of the quicktour and method overview buttons. I like the visuals
but there should only be elements that are useful.

---------

Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com>
Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2026-06-15 16:01:06 +02:00
Benjamin Bossan 64a9867ff5 Generic quantization support for BOFT, MiSS, VeRA (#3117)
Problem description

Right now, if a new PEFT method wants to add support for quantized
layers, it requires a significant amount of work. Notably, the method
needs to implement dedicated layer classes for each quantization method
(e.g. one class for bnb 4bit, one for bnb 8bit, one for AWQ, ...). These
classes typically are >90% boilerplate and the actual difference between
implementations of these classes is minimal.

The result of that is that, at the moment, most PEFT methods don't
support any, or only very few, quantization methods, even though the
amount of actual logic required to support these methods is relatively
small.

Suggested solution

This PR is a suggestion of how to solve the issue. With a few extra
lines, we should be able to support all quantization methods in all PEFT
methods. The general approach is to add an attribute to each PEFT layer,
self.quantization_backend, which supports these methods:

- get_base_weight - set_base_weight

When the PEFT layers use these methods to access and write to the base
layer weight, and if the weight is quantized, the new classes will deal
with that correctly. This means that we no longer need a dedicated layer
class to deal with quantized layers, the normal layer class will do.
E.g. for MiSS, the normal miss.Linear class can deal with bnb layers,
there is no need to add a miss/bnb.py module with dedicated layers.

A few rewrites in the existing PEFT methods are required to support this
new quantization backend class, but the amount of total code needed for
that is considerably smaller than adding new classes for each
quantization method.

Furthermore, these quantization backend classes are agnostic with regard
to the PEFT method. Therefore, with M PEFT methods and N quantization
methods, we no longer need MxN implementations to support quantization
but only M+N.

Migration

For LoRA, we have already implemented the layer classes for each
supported quantization method. For the sake of consistency, it could
still make sense to migrate LoRA to the new approach if it's accepted.
This needs to be accompanied by detailed regression testing to ensure
that everything keeps working. I would only suggest to deprecate and
remove abandoned quantization methods (perhaps for a v1.0 release).

Scope

Updating all PEFT methods is too much for a single PR. This PR focuses
on only three PEFT methods for now:

- MiSS: A pretty normal PEFT method, representative of many other PEFT
methods. - BOFT: Also pretty normal, but requires slight rewrite of the
forward step. Similar changes may be required for other methods too. -
VeRA: Already supports bnb but with this PR, specific BNB layers are no
longer needed.
2026-06-04 17:42:52 +02:00
victor7246 baa6a04316 FEAT Add MonteCLoRA (#2943)
Implements MonteCLoRA: "Robust and Efficient Fine-tuning of LLMs with
Bayesian Reparameterization of Low-Rank Adaptation"

https://huggingface.co/papers/2411.04358

This LoRA variant augments the LoRA A matrix by including Monte Carlo
estimations of the LoRA parameters. This promises to make the model
more robust to hyper-parameter choice and to lead to better
regularization, at the cost of a small increase in the count of
learnable parameters. There is no extra cost at inference time compared
to normal LoRA.
2026-05-21 02:11:12 +02:00
roymiles 77628eeb38 FEAT Add VeLoRA (#3159)
Implements "VeLoRA: Memory Efficient Training using Rank-1 Sub-Token
Projections"

(https://huggingface.co/papers/2405.17991)

VeLoRA is a LoRA variant that reduces memory required for training by
compressing the activations saved for the LoRA in the forward pass and
then reconstructing them in the backwards pass. Compared to gradient
checkpointing, VeLoRA is faster but requires more memory. The LoRA
adapter itself is unaffected and can be used like any normal LoRA
adapter.
2026-05-08 19:11:54 +02:00
Oswaldo Ludwig 14e0a59a41 FEAT Add KappaTune (#3106)
Implements KappaTune based on:

"The Condition Number as a Scale-Invariant Proxy for Information Encoding in
Neural Units"

https://arxiv.org/abs/2506.16289

This is a helper function that can be run on the base model to identify the
layers that are most suited for fine-tuning. It works for Linear and MoE
layers. By targeting these layers with LoRA or other PEFT methods, the model
should train well without forgetting useful information from pre-training.
2026-05-08 14:54:22 +02:00
Qubitium-ModelCloud 8c6943cca3 ENH Update GPT-QModel, fully remove AutoGPTQ (#3190) 2026-04-29 13:52:07 +02:00
Benjamin Bossan 9e86c043f3 DOC: Section on weight tying with LoRA (#3066)
Now that the PRs in relation to #2864 have been merged, we should also
properly document weight tying behavior in PEFT. I added a section to
the docs based on said issue.
2026-04-09 16:24:12 +02:00
Benjamin Bossan a1bd324515 DOC: Info about runtime performance of LoRA on MoE (#3138)
At inference, PEFT can result in a substantial runtime overhead when
targeting MoE parameters. This is now documented, as well as how to
avoid the overhead.
2026-04-09 12:02:16 +02:00
Benjamin Bossan 9bd6f7f277 DOC Update contribution guidelines (#3119)
Especially the section on adding new PEFT methods was incomplete and
should be more actionable now.

With the arrival of coding agents, there is even the small chance that
someone might read it.
2026-04-08 11:15:54 +02:00
Benjamin Bossan 2d488820ab FIX Broken tests with torchao >= 0.16 (#3101)
Torchao made some API changes, which have to be reflected in the tests.
Moreover, for this to pass, we also need transformers to make the
corresponding adjustments:

https://github.com/huggingface/transformers/pull/44604

While working on this, I migrated the tests from unittest to pytest
style.
2026-03-31 14:27:38 +02:00
Michael Benayoun 3fb7842e8f FEAT LoRA support for Transformers TP (#3079)
Adds support for Tensor Parallel (TP) to LoRA.

Embedding layers not included yet.
2026-03-18 17:04:13 +01:00
githubnemo e8fa88871e Update contributing guidelines regarding typos (#3094)
There's no official rule how we regard typo PRs. To give contributors
a clear vision of how we want typo PRs to be handled I suggest this
update to the guidelines.
2026-03-12 15:48:16 +01:00
Bruno Alvisio 10f3ea8eed FEAT Adds support for Transformer Engine with LoRA (#3048) 2026-03-03 12:01:10 +01:00
Benjamin Bossan 2e49b6f687 CHORE: Remove deprecated Bone method (#3051)
Bone was deprecated in favor of MiSS. Removal is scheduled for PEFT
v0.19.0. Old checkpoints can be converted using
scripts/convert-bone-to-miss.py.

Unrelated change: I found the skip for GPT2 for the unloading decoder
test to be unnecessary (it was probably redundant with the skip for
Conv1D layers), so that function was removed completely.
2026-02-23 18:07:13 +01:00
githubnemo 8f73327fb9 Improve LoftQ documentation (#3041)
To me the LoftQ application process was not immediately obvious.
I'm sure it can't hurt to add a bit of context what the two main
ways are to apply LoftQ.

In my quest to search for enlightenment I was often directed to the
quantization guide in the PEFT docs which featured a lot less details
than the developer guide for LoRA. Since LoftQ is mainly used in quantization
I think it makes sense to move it there and link there from the developer guide.
2026-02-13 11:32:05 +01:00
Kashif Rasul 4d970440a3 [LoRA] Document support for effective rank for LoRA on MOE experts (#3007)
Add docs on how to set the rank of LoRA adaptors to the experts in MOEs to be the rank / total experts


---------

Co-authored-by: githubnemo <githubnemo@users.noreply.github.com>
2026-01-27 17:30:17 +01:00
githubnemo 7bb40eaf43 Intruder dimension reduction for LoRA (#2999)
Implementation for https://github.com/huggingface/peft/issues/2907.

After some experimentation I think this is an implementation of the 
forgetting through intruder dimensions mitigation presented by the paper
[LoRA vs Full Fine-tuning: An Illusion of Equivalence](https://huggingface.co/papers/2410.21228).

The implementation takes a model with a loaded LoRA adapter and applies the
mitigation to form a new adapter on the same model. This makes it possible
to compare the results directly.

You can find a script to evaluate the changes here: https://gist.github.com/githubnemo/5932e99125d498c4f353017916ffc3ea

Support for `torch.compile` was considered during review but first experiments
didn't  yield clear results which is why support was postponed.


## Alternative approaches

I can think of two possible modes how the conversion could be done differently.
The first one is already proposed in the original issue, namely applying the
mitigation on the merged weights. In this case we will lose the ability to
unmerge and modify the adapter directly which loses all the flexibility of
an adapter.

The second way is to modify A/B directly. Since we have the intruder dimensions
and compute the SVD of (W+dW) to build the mitigation vectors it is conceivable
that it also possible to apply the mitigation directly to the adapter's A/B
matrices. Initial testing wasn't successful so I chose the easier (but 
computationally more intensive) route of first merging the weights, applying
the mitigation and then re-computing the delta weight (and subsequently the
A/B matrices using SVD of the adapter's rank).

---------

Co-authored-by: nemo <git@ningu.net>
2026-01-26 18:16:27 +01:00
githubnemo 1d08144b85 Bugfix turned into restructuring (#3003)
* Bugfix turned into restructuring

Initially I wanted to fix a docs builder bug where the `loraga` autodoc path
was broken since the contents of that module were partially removed.

Then I noticed that LoRA-GA (an initialization method) had its own
`package_resource/lora_ga.md` documentation which is unusual for this kind of
method since as of now all init methods are documented in the LoRA developer guide.
Therefore, I decided to fix the bugs by a) removing the erronous paths and
b) move the package resource page of LoRA-GA to the LoRA developer guide.

Once I arrived there I noticed that aLoRA and DoRA are categorized as initialization
methods which is not true. Also QLoRA and parameter targeting were also in the
same section. These now reside in the new "Training" section. For inference
methods such as aLoRA and Arrow there is now an "Inference" section.

* Small fixes

* Apply suggestions from code review

Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>

* Visualize result via table

---------

Co-authored-by: nemo <git@ningu.net>
Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2026-01-22 19:10:55 +01:00
Benjamin Bossan a33b17893b ENH Caching option for DoRA inferrence (#2661)
Resolves #2651

This PR adds caching of the LoRA weight and the weight norm from DoRA
for faster inference. Since, during inference, the weights don't change,
there is no need to recalculate those weights for a DoRA module each
time.

During training, recalculation is needed, thus there is no caching when
the module has training=True.

The cache does not prevent each and every possible duplicate
calculation. For instance, the weight norm is calculated during module
initialization and then again during the first forward pass when
performing inference. Only starting from the second forward pass on will
the weight norms be cached.

The PR includes a script to measure the effect of caching. On my
machine, I get:

avg time LoRA:                     0.0717 sec
avg time DoRA no caching:          0.1718 sec
avg time DoRA with caching:        0.0840 sec

memory LoRA:                       15612.00 MB
memory DoRA no caching:            16212.00 MB
memory DoRA with caching:          22118.00 MB

DoRA time overhead no caching:     139.52%
DoRA time overhead with caching:   17.08%

DoRA memory overhead no caching:   3.84%
DoRA memory overhead with caching: 41.67%


Thus, caching can significantly reduce inference time but at a
noticeable cost in memory.
2026-01-14 16:49:46 +01:00
David Figueroa 6bf24ac0fc DOC Update LoRA dev guides wrt to unloading (#2871) 2025-10-27 14:44:51 +01:00
Shantanu Gupta 1a1f97263d CHORE Replace deprecated torch_dtype with dtype (#2837)
Note: Diffusers is left as is for now, might need an update later.
2025-10-16 14:59:09 +02:00
Benjamin Bossan 190f9873b1 CHORE DOC Migrate tips syntax (#2801)
Discussed internally
2025-09-29 10:33:57 +02:00
Benjamin Bossan 7b2a5b1f02 DOC: Explain how to use multiple adapters at the same time (#2763)
Explain how to use multiple adapters (e.g. 2 LoRA adapters) at the same
time, as the API is not quite intuitive and there are some footguns
around trainable parameters.

This question has come up multiple times in the past (for recent
examples, check #2749 and #2756). Thus it's a good idea to properly
document this.

---------

Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2025-09-25 17:58:57 +02:00
Mohammadtaha Bagherifard 42db980676 Add Arrow + GenKnowSub to LoRA (#2644)
This PR adds support for Arrow, a modular routing mechanism for LoRA experts introduced here, as well as the refinement method GenKnowSub, proposed in our ACL 2025 Main Conference paper. GenKnowSub enhances Arrow by subtracting a general-domain LoRA from task-specific ones prior to routing, leading to improved generalisation and modularity.
2025-09-08 14:21:37 +02:00
githubnemo de60e88b6b Fix missing code start in docs (#2768)
There was a minor typo which a suggestion of PR #2609 which broke code formatting for one code sample.

This is a simple fix for that.
2025-09-03 18:37:52 +02:00
Greenewald 293aea5df6 Support for Activated LoRA (#2609)
This PR migrates Activated LoRA (aLoRA) support from a standalone Github (see above) to PEFT itself.

Note there is also an active PR for vLLM inference support for Activated LoRA: vllm-project/vllm#19710 . There are also collections of aLoRA models on huggingface (in the ibm-granite org), note that these preexisting models run off of the standalone github repo and will be updated to work with this new PEFT feature if merged.

Description of changes: Activated LoRA is a modification of the LoRA architecture to "activate" the adapter weights only on tokens coming after a specified invocation_string. This fact makes it so that KV values for the string coming before the activation matches KV values for the base model. This allows KV cache for the input to be interchangeable between the base model and adapter model, and allows for major speedups in inference pipelines (e.g. agentic pipelines) that want to use both base models and adapter models. See the paper for detailed exploration of use cases and further elaboration.

Other notes:

The crux of the changes are really in layer.py. Everything else is simply managing the alora_offsets quantity which defines where the weights start to be activated. This is determined by scanning input strings for the invocation_string defined in the aLoraConfig.
    
I believe that aLoRA really only makes sense for CausalLMs, hence I've only implemented this for that model type.

Merging doesn't make sense for aLoRA adapters since the weights are not universally applied to all tokens.
    
I used the LoRA code as a starting point, but did not implement various seemingly extra features in that code.

As of now, invocation_string should probably start and end with special tokens, to avoid tokenizer issues at the boundary. Open to suggestions on how to make this more general if needed.

---------

Co-authored-by: githubnemo <githubnemo@users.noreply.github.com>
2025-09-03 18:26:50 +02:00
Benjamin Bossan a2c6612b12 FIX Multiple issues with target_parameters (#2710)
There are a few issues with target_parameters that are fixed in this PR.

Existing parametrizations

When using target_parameters with LoRA, after the forward call finishes,
the LoRA parametrization is removed. However, this also used to remove
all other parametrizations on the same parameter, which is bad. With
this PR, only the LoRA parametrization is removed.

Module repr

This PR also extends the __repr__ of lora.ParamWrapper to contain the
parameter name, which makes it more useful.

Extend testing

Added a tiny gpt-oss model to the target_parameters test suite.

Multiple LoRA adapters with target_parameters

There is an issue when adding a second LoRA adapter with
target_paramters, where this second adapter would not actually be
applied correctly. The corresponding unit test was too lax to notice the
bug. This is not easy to fix, so for now we forbid adding a second
adapter with target_parameters. This is very strict but it's better than
having silent errors.

Although it was possible to fix that specific issue, the solution
resulted in ever deeply nested adapters (i.e. with multiple
.base_layer). This in turn results in those infixes to be part of the
state_dict. But then we cannot load the individual adapters correctly,
except if the model is restored in the exact same order as it was
previously created. This is not normally a requirement in PEFT (e.g. I
can create a model with two adapters and later decide to load only one
of them).

In the long run, we need to think about solutions that would allow this.
It may require some form of normalization of the layers to prevent ever
deeper nesting. Also, what is ugly right now is that, given that the
LoRA lives on a module but actually targets one of possibly multiple
parameter, the LoRA weights don't actually reference said parameter in
any name. That means, purely from the state_dict, it is unclear which
parameter a LoRA weight belongs to. Ideally, this should be encoded in
the LoRA weight key.
2025-08-12 13:59:29 +02:00
Yao Matrix e98a59ec2d DOC Make docs more device agnostic (e.g. XPU) (#2728)
Also adjusted some more examples.

Signed-off-by: Yao, Matrix <matrix.yao@intel.com>
2025-08-08 12:06:22 +02:00
Benjamin Bossan 337be05f03 ENH: Adapter injection based on state_dict (#2637)
Make it possible to inject the PEFT adapters based on a state_dict
instead of the PEFT config.

See https://github.com/huggingface/diffusers/issues/11874 for context.

Description

Right now, when creating a PEFT adapter like LoRA, the adapter layers
are injected based on the PEFT config, most notably the entries in
`target_modules`, but other arguments also play into this. Generally,
this is a good approach, but it breaks down in some situations. For
instance, in diffusers, we often have the situation that the checkpoint
was created without PEFT/diffusers, thus there is no PEFT config, only
the `state_dict`. To load these checkpoints in diffusers, the current
approach is to reverse-engineer a valid PEFT config based on the keys in
the `state_dict`.

Unfortunately, this is error prone. Moreover, not every combination of
`state_dict` keys can be easily expressed in a PEFT config through a
combination of `target_modules`, `exclude_modules`, etc. Yes, in theory
everything can be expressed by passing `target_module=<regex_pattern>`,
but reverse-engineering such a regex correctly and efficiently is very
hard (and thus currently not done).

This PR implements a completely different approach to inject adapters.
Instead of relying on the PEFT config to determine which layers to
target, it takes the `state_dict` directly as the source of truth. This
should allow to exactly match what is desired.

Implementation details

I took care to implement this change in a way that if no `state_dict` is
passed, the exact same code path as previously is taken. The risk of
breaking anything should thus be minimized.

Technically, it is not necessary to pass the `state_dict`, we are only
interested in the keys. I still called the argument `state_dict`, since
that is typically what we have at this point, but this can be easily
changed.

I thought it might be a good idea, if the `state_dict` is used, to still
check what modules would have been targeted if we had used the PEFT
config. Then, the results are compared and a warning is given if they
differ. This allows the user to see if the PEFT config is not correctly
specified. While running some diffusers tests, I never encountered this
warning, which is good. However, if we plan, for instance, to get rid of
all the reverse engineering of the PEFT config in diffusers, it would
make more sense to not give this warning.

Caveats

When the original LoRA model was using `target_parameters`, injecting
from `state_dict` will not work correctly. The problem is that the
`state_dict` looks the same, whether the module or a parameter was
targeted. Therefore, we cannot correctly determine the user's intent.

For now, what I decided to do is:

1. Always assume that `target_modules` is meant, as it's the far more
   common occurrence.
2. When we detect `target_parameters` while using `state_dict` for
   injection, we raise an error.
3. If we don't detect this, injection might just slip through, resulting
   in modules being targeted (if they are valid modules) instead of
   parameters.
4. Document that these two features don't work together.

I think overall, this is not too concerning, as both features are rather
niche and thus unlikely to be used in conjunction.

Related changes

While working on this PR, I made a couple of related, though not
strictly necessary, changes:

- Refactor tests in `test_low_level_api.py` to use pytest instead of
  unittest
- Add default target modules for LoHa and LoKr (just copying LoRA)
- Most PEFT method's model classes like `LoraModel` had an `__init__`
  that effectively just called `super()` with the same arguments. I
  removed these `__init__` methods.
2025-08-01 18:39:53 +02:00
githubnemo 92d65cafa5 Update extending vocab docs (#2669)
- Recommends trainable tokens as first measure
- Clarifies a few things about saving embeddings
- Adds full-finetuning as an option of last resort

---------

Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com>
2025-07-25 13:09:00 +02:00
Quentin Gallouédec 04a5ed7b2f DOC Fix error in code example (#2666) 2025-07-24 12:13:41 +02:00
Benjamin Bossan f3b97c3704 FEAT Allow LoRA to target nn.Parameter (#2638)
Normally, nn.Parameter cannot be targeted with LoRA adapters. This can
be problematic, e.g. when there are MoE layers that use nn.Parameter
directly, or when there is nn.Linear but the weight is passed directly
instead of calling forward (e.g. MHA).

It would be possible to craft a solution involving a special LoRA layer
for each of the modules that use nn.Parameter directly (e.g. lora.MHA)
but that doesn't scale. This PR is implements a direct way to target
nn.Parameter making use of torch.nn.utils.parametrize.

Using the feature requires passing target_parameters to the LoraConfig.
During the forward pass, when the parameter is acceessed, the LoRA
weights are added to the weights while still ensuring that gradients
flow correctly to the LoRA weights.

Right now, only LoRA supports this feature. Moreover, it is not possible
to target multiple parameters of the same module with the same adapter.
A workaround is to use multiple adapters (i.e. with different names).

---------

Co-authored-by: githubnemo <githubnemo@users.noreply.github.com>
2025-07-15 16:18:46 +02:00
Benjamin Bossan 1f4143a7ca DOC Update README, contributing.md, GH templates (#2588)
- Use a more up to date example code in the README
- A section on transformers integration
- Update devs to tag
- Simplify issue template (did not seem useful in practice)
- Update contribution guideline

---------

Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2025-06-18 18:11:59 +02:00
Quentin Gallouédec b3130c9edb Use HF Papers (#2542)
Replaced all arxiv.org/pdf links with HF papers.
2025-05-27 13:48:53 +02:00
omahs d5776f605d fix typos (#2544) 2025-05-26 17:35:55 +02:00
Daniel Socek 003cf20bcd FEAT Add LoRA INC support (#2499)
Add LoRA Adds Intel Neural Compressor.

---------

Signed-off-by: Daniel Socek <daniel.socek@intel.com>
2025-04-28 18:39:37 +02:00
Aaron Chung 0c2bdbb11a FEAT Add LoRA-FA to PEFT (#2468)
Adds LoRA with frozen A (LoRA-FA) to PEFT.

Paper: https://arxiv.org/abs/2308.03303
2025-04-10 10:53:19 +02:00
Benjamin Bossan dfd82f73f0 Fix: Multiple PEFT methods have issues with models loaded in float16 or bfloat16 (#2433)
As a user, it should be possible to manually cast the base model to a
lower precision dtype, float16 or bfloat16, and still have the different
PEFT methods work correctly. Currently, this is not the case for many
PEFT methods, as can be replicated by the added tests.

To understand the problem, it helps to take a step back. By default,
PEFT will treat the adapter weights with high precision, i.e. with
float32. When the base model is lower precision, the user needs to pass
inputs in lower precision too, as otherwise self.base_layer(x) would
fail. However, this low precision input clashes with the high precision
adapter weights.

The solution implemented in this PR is to cast the input to a higher
dtype [1]. That way, the whole adapter operation is conducted in high
precision. Only once that has finished will the final result be cast to
the original dtype. This should lead to better results, but it may
require more memory. Note that this is how LoRA is implemented, so the
changes in this PR bring the other methods more in line with what LoRA
does.

If the user does not want the adapter to be in float32, they can always
pass autocast_adapter_dtype=False when calling get_peft_model or
PeftModel.from_pretrained. This is also tested.

Besides adjusting the forward method to account for these changes, the
merge and unmerge methods also often had to be adjusted, as they did not
correctly account for the base model dtype. Now, those methods should
always conserve the original dtype of the base model.

Note that if, for whatever reason, the input casting in [1] is not
desired, users can use the disable_input_dtype_casting context manager
to disable it (more context information on this feature can be found in
PR #2353). I updated the corresponding code to be agnostic to the
specific PEFT method (beforehand, it was only for LoRA).

Note that model.merge_adapter(safe_merge=True) did not work so far, even
though the argument was documented it was not actually there. This is
now fixed.
2025-04-04 12:06:17 +02:00
Benjamin Bossan 2f063e6342 ENH: Extend the regex for rank/alpha pattern (#2419)
Supersedes #2382

Right now, the regex used to match the keys passed for rank_pattern and
alpha_pattern requires that either:

1. The module name is identical to the key
2. The module name having a prefix and then ending on the key

This is restrictive, since it doesn't allow to disambiguate between all
cases. E.g. if we have a model with these attributes:

- model.foo
- model.bar.foo

We cannot currently target just model.foo. (We can already target only
model.bar.foo by passing "bar.foo" as a key to the rank_pattern /
alpha_pattern dict).

This PR makes it possible to pass "^foo" as a key. This way,
model.bar.foo is not targeted, as the key does not start with "foo".

As a general rule for users, if they intend to have a full match, they
should pass the full name of the module preceded by a ^. This is the
least ambigious way.

When running the test case with the old code, all the test cases with ^
will fail, which is fine, since ^ was not working anyway. At the same
time, all test cases not using ^ pass, which means they are backwards
compatible.
2025-03-13 12:53:27 +01:00
githubnemo 461f6426ef Trainable Tokens: Support for Weight Tying (#2399)
This is a follow-up PR of #2376 to add support for weight-tying.

Some models, such as gpt2, tie the weights between the LM head and the input embeddings for various reasons. If we use the trainable tokens adapter, we're changing the result of the forward() of the input embeddings but we do not change the weights (unless we merge()). This means that the changes are not reflected in the tied weights, such as the LM head, leading to wrong results when training.

The current approach is searching for tied layers and putting TrainableTokensLayer adapters on them as well but initialized to use the parameters from the embedding layer's TrainableTokensLayer. This is done via the tied_adapter argument of TrailableTokensLayer.__init__().

Notable other changes:

* Implement weight-tying for encoder-decoder models

Notably we are removing the duplication filter of `named_modules` when searching for
the (tied) target modules since tied weights are by definition duplicates.

* Implement embedding name inference

It's now possible to let the adapter decide which is the input embedding layer based on the output
of `model.get_input_embeddings()`. If that fails, the default is still `embed_tokens`.

* Refactor getattr in AuxiliaryTrainingWrapper

Before this change only the selection of the module that was supposed to have the queried
attribute was given to the wrapper implemention (via `_{has,get}attr_wrapped`). Now the full
`getattr()` call is done by the implementation.

This change is motivated by the need for access to `embedding.weight` at certain times which,
for `ModulesToSaveWrapper` is not a problem - but it is for `TrainableTokensWrapper` since
the original module's weights differ from the current weights, at least potentially.

What we do now is to merge the weights and return those when `embedding.weight` is accessed.
No other attributes are currently forwarded.

* initialization from buffers was broken since `persistent` flag was set too late
  (update() is called before setting the flag)

* update from other BufferDict was broken since it was assumed that BufferDict was
  a mapping collection object. we cannot simply change it to a Mapping since it
  then will break pytorch code which assumes that modules are hashable.

---------

Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com>
2025-03-06 14:09:01 +01:00
githubnemo f51203f3e4 Standalone Custom Tokens Tuner and integrated into LoRA (#2376)
This change is based on the nifty addition of @marcusinthesky from #1541.

When adding tokens or fine-tuning the representation of specific tokens we currently have little choice but to retrain the whole embedding matrix which can be huge and adds to the memory footprint (in RAM but also on disk). This method creates a sparse matrix of shape (n, embed_dim) where n is the number of tokens to be customized and only trains these few values.

This change introduces two ways of using it:

```
peft_config = TrainableTokensConfig(target_modules=['embed_tokens'], token_indices=[0, 1, 2])
peft_model = get_peft_model(model, peft_config)
```

and with LoRA

```
peft_config = LoraConfig(
    target_modules='all-linear',
    trainable_token_indices={'embed_tokens': [0, 1, 2]},
)
peft_model = get_peft_model(model, peft_config)
```

Adding this feature to adapters other than LoRA should be relatively easy, mostly adding the `trainable_token_indices` config option and some debugging.

To make this change it was necessary to change the `modules_to_save` infrastructure as combining this feature with LoRA is quite similar. This refactoring entailed moving most of the basic functionality of `ModulesToSave` to the `AuxiliaryTrainingWrapper` class. This also changes the logic how `modules_to_save` is loaded/saved from from the state dict, so there could still be bugs here.

This implementation does not entail support for weight-tied layers yet. This will follow in a future change.

---

Notable commits in this squash:

* Use unload_and_optionally_merge_module protocol

With `AuxiliaryTrainingWrapper` as abstraction it is probably a good idea to
have support for `unload_and_optionally_merge_module`.

Since the wrapper is more akin to a PEFT layer than a model the name semantics
are fine and it does basically the same job.

* trainable tokens is also trained in certain adapters

Before, the assumption was that modules_to_save was the only thing that
is trained alongside an adapter's parameters. Now there's also the
token_adapter delta tokens via `NewTokensWrapper`.

* Remove old modules_to_save handling

This is now all handled via the `AuxiliaryTrainingWrapper`.

* Fix modules_to_save module overwriting

The state dict imlementation of ModulesToSaveWrapper was incorrect in that
it did not include its own parameters, just the parameters it needs to overwrite
in the end. I.e. if layer `lin1` is modules to save wrapped,
`lin1.{weight,bias}` is saved and overwritten but `lin1.modules_to_save.<adpater_name>.[...]`
is not saved.

* Introduce a load key map for aux. train wrapper

Before this change it was only possible to remove a key prefix from the wrapper's
state dict (e.g., `modules_to_save.default.weight` -> `weight`); now it is possible
to restore such reduced value by mapping the key back
(i.e., `weight` -> `modules_to_save.default.weight`).

* Replace sparse matrix with dense + index_copy

This change is mostly because sparse matrices are not that beneficial in this case
(at least not from what we can see right now) and they do not solve the problem
of having to change the new tokens in-place to avoid outdated deltas when new token
vectors are initialized randomly after loading the deltas.

* Make peft_config.layers_to_transform optional

Before this change the base tuner class was forcing this attribute
to be present on the config class even though the attribute is not
specified in the base config.

* Implement missing key logic in `_set_trainable`

Before this it was not checked if the targeted module by `modules_to_save` or `trainable_token_indices` existed
or not (when used in conjunction with a PEFT method). In this case an error message similar to the `inject_adapter`
error is raised when no module is found.

---------

Co-authored-by: Marcus Gawronsky <marcus.g@myrunway.co.za>
Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com>
2025-02-26 16:51:45 +01:00
Benjamin Bossan 5e03d058b8 DOC: Explain uninitialized weights warning (#2369)
Users sometimes get confused by the warning from transformers that some
weights are uninitialized and need to be trained when they use models
for classification. A recent example is #2367.

Even though the warning does not come from PEFT, let's add a section to
the docs to explain this warning, as the situation is a bit different
here.
---------

Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2025-02-10 12:00:58 +01:00
Benjamin Bossan 6538e56e13 TST: Update torch.compile tests and docs (#2332)
We have tests to check if torch.compile works for various PEFT methods
and "advanced" features (QLoRA, merging, ...). These tests are not run
on a regular basis, but are triggered manually. As such, it was time to
revisit them.

So far, a few of these tests were marked as xfailing. All these tests
are passing now. The reasons for this:

- Presumably: New PyTorch version (I haven't checked older)
- Loosening some tolerances
- Remove a spurious argument added by torch.compile
- Slightly adjust order of when torch.compile is called

The docs have been updated to reflect these new findings.
2025-01-24 15:21:28 +01:00
jiqing-feng 6e30991e97 FEAT Add gptqmodel support (#2247)
Add support for gptqmodel quantization. This is a replacement for
auto-gptq.

For now, both packages are supported, but since auto-gptq is no longer
being developed, it will be deprecated and removed at some point in the
future.

---------

Signed-off-by: jiqing-feng <jiqing.feng@intel.com>
Co-authored-by: LRL-ModelCloud <165116337+LRL-ModelCloud@users.noreply.github.com>
Co-authored-by: Qubitium-ModelCloud <qubitium@modelcloud.ai>
Co-authored-by: ZX-ModelCloud <165115237+ZX-ModelCloud@users.noreply.github.com>
Co-authored-by: LRL <lrl@lbx.dev>
Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2025-01-23 14:00:11 +01:00
Benjamin Bossan 1b9bcb200b DOC Add entry to solve unknown config argument (#2340)
There have been multiple issues and forum posts in the past asking about
errors like:

TypeError: LoraConfig.__init__() got an unexpected keyword argument ...

This error can occur when the adapter that is being loaded is trained
with a more recent PEFT version than the one currently being used. I
thus added a section to the Troubleshooting part of our docs to describe
the solutions.

Note that we already added changes to PEFT in #2038 to make configs
forward compatible. But since users who encounter this problem have, by
definition, older PEFT versions, they don't benefit from this.

---------

Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
2025-01-23 12:41:51 +01:00
bing fdf36d28da DOC FIX Add resize_token_embeddings (#2290) 2025-01-07 12:20:45 +01:00
Yibo Yang 6d458b300f FEAT Adding CorDA as an optional initialization method of LoRA (#2231)
Implements the paper "CorDA: Context-Oriented Decomposition Adaptation of Large Language Models for Task-Aware Parameter-Efficient Fine-tuning" (https://arxiv.org/abs/2406.05223)

This initialization method can be used for building task-aware LoRA adapters from weight decomposition oriented by the context of the task using examples from data.

---------

Co-authored-by: 5eqn <491100866@qq.com>
2024-12-19 13:33:37 +01:00
sirluk 3a8afbe2aa [FIX] EVA meta device fix, multi-gpu functionality (#2218)
- important bugfix for meta device check
- add multi gpu functionality and example
- update docs
2024-11-18 16:31:48 +01:00