|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 | import tempfile |
15 | | -import unittest |
16 | 15 |
|
17 | 16 | import torch |
| 17 | +from transformers import AutoModelForCausalLM, AutoTokenizer |
18 | 18 |
|
19 | 19 | from peft import ( |
20 | 20 | AutoPeftModel, |
|
24 | 24 | AutoPeftModelForSeq2SeqLM, |
25 | 25 | AutoPeftModelForSequenceClassification, |
26 | 26 | AutoPeftModelForTokenClassification, |
| 27 | + LoraConfig, |
27 | 28 | PeftModel, |
28 | 29 | PeftModelForCausalLM, |
29 | 30 | PeftModelForFeatureExtraction, |
30 | 31 | PeftModelForQuestionAnswering, |
31 | 32 | PeftModelForSeq2SeqLM, |
32 | 33 | PeftModelForSequenceClassification, |
33 | 34 | PeftModelForTokenClassification, |
| 35 | + get_peft_model, |
34 | 36 | ) |
35 | 37 | from peft.utils import infer_device |
36 | 38 |
|
37 | 39 |
|
38 | | -class PeftAutoModelTester(unittest.TestCase): |
| 40 | +class TestPeftAutoModel: |
39 | 41 | dtype = torch.float16 if infer_device() == "mps" else torch.bfloat16 |
40 | 42 |
|
41 | 43 | def test_peft_causal_lm(self): |
@@ -207,3 +209,23 @@ def test_peft_whisper(self): |
207 | 209 | is_trainable = False |
208 | 210 | # This should work |
209 | 211 | _ = AutoPeftModel.from_pretrained(model_id, adapter_name, is_trainable, torch_dtype=self.dtype) |
| 212 | + |
| 213 | + def test_embedding_size_not_reduced_if_greater_vocab_size(self, tmp_path): |
| 214 | + # See 2415 |
| 215 | + # There was a bug in AutoPeftModels where the embedding was always resized to the vocab size of the tokenizer |
| 216 | + # when the tokenizer was found. This makes sense if the vocabulary was extended, but some models like Qwen |
| 217 | + # already start out with "spare" embeddings, i.e. the embedding size is larger than the vocab size. This could |
| 218 | + # result in the embedding being shrunk, which in turn resulted in an error when loading the weights. |
| 219 | + |
| 220 | + # first create a checkpoint; it is important that the tokenizer is also saved in the same location |
| 221 | + model_id = "Qwen/Qwen2-0.5B" |
| 222 | + model = AutoModelForCausalLM.from_pretrained(model_id) |
| 223 | + tokenizer = AutoTokenizer.from_pretrained(model_id) |
| 224 | + model = get_peft_model(model, LoraConfig(modules_to_save=["lm_head", "embed_token"])) |
| 225 | + model.save_pretrained(tmp_path) |
| 226 | + tokenizer.save_pretrained(tmp_path) |
| 227 | + |
| 228 | + # does not raise; without the fix, it raises: |
| 229 | + # > size mismatch for base_model.model.lm_head.modules_to_save.default.weight: copying a param with shape |
| 230 | + # torch.Size([151936, 896]) from checkpoint, the shape in current model is torch.Size([151646, 896]). |
| 231 | + AutoPeftModelForCausalLM.from_pretrained(tmp_path) |
0 commit comments