-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
FIX: Adding 2 adapters when target_modules is a str fails #1111
Merged
pacman100
merged 3 commits into
huggingface:main
from
BenjaminBossan:fix-issue-adding-two-adapters-target-modules-str
Nov 14, 2023
Merged
FIX: Adding 2 adapters when target_modules is a str fails #1111
pacman100
merged 3 commits into
huggingface:main
from
BenjaminBossan:fix-issue-adding-two-adapters-target-modules-str
Nov 14, 2023
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Problem description Adding two adapters (e.g. LoRA) when using a list for `target_mdules` works but passing a str fails. The issue is that for str, we do a `re.fullmatch`, whereas for list, we just check `endswith`. After adding the first adapter, though, the naming pattern of the modules changes. In the example above, the name for the linear layer changes from `"lin0"` to `"base_model.model.lin0"`, which is why the `fullmatch` fails but the `endswith` still works. Reproduction from peft import LoraConfig, get_peft_model from torch import nn class MLP(nn.Module): def __init__(self, bias=True): super().__init__() self.lin0 = nn.Linear(10, 20, bias=bias) def test_target_modules_list(): config = LoraConfig(target_modules=["lin0"]) test_it(config) print("Adding two adapters with target_module being a list works") def test_target_modules_str(): config = LoraConfig(target_modules="lin0") test_it(config) def test_it(config): model = MLP() model = get_peft_model(model, config, "adapter0") model.add_adapter("adapter1", config) print("Adding two adapters with target_module being a str works") if __name__ == "__main__": # works test_target_modules_list() # ValueError: Target modules lin0 not found in the base model test_target_modules_str() I think that most users would be surprised that: 1. Adding the first adapter works but adding the second fails, even though they use the same config. 2. Using `target_modules=["lin0"]` works but `target_modules="lin0"` fails for the 2nd adapter. Solution We could change the logic of not using `re.fullmatch` for str, but I think that could be tricky to achieve without breaking BC. Instead, I chose to change the inject_adapter call in add_adapter to pass the base model, not the whole peft model. This way, the naming pattern is preserved. Tests I haven't added extra tests for this. The script above could serve as a test. However, it will be sufficient to remove the guard added in huggingface#1105: if isinstance(config.target_str, modules): # TODO this should be doable self.skipTest("Multiple adapters cannot currently be added when target_modules is a string.") as that will test exactly this behavior and was how the bug was originally uncovered. Depending on what PR lands first, the guard has to removed in this PR or in huggingface#1105.
The documentation is not available anymore as the PR was closed or merged. |
pacman100
approved these changes
Nov 14, 2023
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @BenjaminBossan for fixing this bug! Nice find.
younesbelkada
approved these changes
Nov 14, 2023
BenjaminBossan
deleted the
fix-issue-adding-two-adapters-target-modules-str
branch
November 14, 2023 11:48
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem description
Adding two adapters (e.g. LoRA) when using a list for
target_mdules
works but passing a str fails. The issue is that for str, we do are.fullmatch
, whereas for list, we just checkendswith
. After adding the first adapter, though, the naming pattern of the modules changes. In the example above, the name for the linear layer changes from"lin0"
to"base_model.model.lin0"
, which is why thefullmatch
fails but theendswith
still works.Reproduction
I think that most users would be surprised that:
target_modules=["lin0"]
works buttarget_modules="lin0"
fails for the 2nd adapter.Solution
We could change the logic of not using
re.fullmatch
for str, but I think that could be tricky to achieve without breaking BC. Instead, I chose to change the inject_adapter call in add_adapter to pass the base model, not the whole peft model. This way, the naming pattern is preserved.Tests
Tests were added by removing the guard from #1105. This guard was added because of this bug and was how it was discovered first.