novateur commited on
Commit
c8f17d3
·
verified ·
1 Parent(s): c8027be

Add files using upload-large-folder tool

Browse files
tests/tuners/__init__.py ADDED
File without changes
tests/tuners/test_extra_state_dict.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ import torch
7
+ from modelscope import Model
8
+
9
+ from swift import LoRAConfig, Swift
10
+ from swift.tuners.utils import ModulesToSaveWrapper
11
+
12
+
13
+ class TestExtraStateDict(unittest.TestCase):
14
+
15
+ def setUp(self):
16
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
17
+ self.tmp_dir = tempfile.TemporaryDirectory().name
18
+ if not os.path.exists(self.tmp_dir):
19
+ os.makedirs(self.tmp_dir)
20
+
21
+ def tearDown(self):
22
+ shutil.rmtree(self.tmp_dir)
23
+ super().tearDown()
24
+
25
+ def test_swift_extra_state_dict(self):
26
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
27
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
28
+ model = Swift.prepare_model(model, lora_config, extra_state_keys=['classifier.*'])
29
+ model.save_pretrained(self.tmp_dir)
30
+ self.assertTrue(os.path.isfile(os.path.join(self.tmp_dir, 'extra_states', 'adapter_model.bin')))
31
+ state_dict = torch.load(os.path.join(self.tmp_dir, 'extra_states', 'adapter_model.bin'))
32
+ self.assertTrue(any('classifier' in key for key in state_dict))
33
+ state_dict['classifier.weight'] = torch.ones_like(state_dict['classifier.weight']) * 2.0
34
+ with open(os.path.join(self.tmp_dir, 'extra_states', 'adapter_model.bin'), 'wb') as f:
35
+ torch.save(state_dict, f)
36
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
37
+ model = Swift.from_pretrained(model, self.tmp_dir, inference_mode=False)
38
+ names = [name for name, value in model.named_parameters() if value.requires_grad]
39
+ self.assertTrue(any('classifier' in name for name in names))
40
+ self.assertTrue(torch.allclose(state_dict['classifier.weight'], model.base_model.classifier.weight))
41
+
42
+ def test_swift_modules_to_save(self):
43
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
44
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'], modules_to_save=['classifier'])
45
+ lora_config2 = LoRAConfig(target_modules=['query', 'key', 'value'], modules_to_save=['classifier'])
46
+ model = Swift.prepare_model(model, {'lora1': lora_config, 'lora2': lora_config2})
47
+ model.set_active_adapters('lora1')
48
+ model.set_active_adapters('lora2')
49
+ self.assertTrue(isinstance(model.classifier, ModulesToSaveWrapper))
50
+ self.assertTrue(model.classifier.active_adapter == 'lora2')
51
+ model.save_pretrained(self.tmp_dir)
52
+ state_dict = torch.load(os.path.join(self.tmp_dir, 'lora2', 'adapter_model.bin'))
53
+ self.assertTrue(any('classifier' in key for key in state_dict))
54
+ state_dict['classifier.weight'] = torch.ones_like(state_dict['classifier.weight']) * 2.0
55
+ with open(os.path.join(self.tmp_dir, 'lora2', 'adapter_model.bin'), 'wb') as f:
56
+ torch.save(state_dict, f)
57
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
58
+ model = Swift.from_pretrained(model, self.tmp_dir, adapter_name='lora2')
59
+ names = [name for name, value in model.named_parameters() if value.requires_grad]
60
+ self.assertTrue(any('classifier' in name for name in names))
61
+ self.assertTrue(
62
+ torch.allclose(state_dict['classifier.weight'],
63
+ model.base_model.classifier.modules_to_save['lora2'].weight))
tests/tuners/test_merged_linear.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import unittest
3
+
4
+ import torch
5
+ from modelscope import Model, Preprocessor
6
+ from torch import nn
7
+
8
+ from swift import LoRAConfig, Swift
9
+
10
+
11
+ class TestMergedLinear(unittest.TestCase):
12
+
13
+ def test_swift_lora_forward(self):
14
+
15
+ from swift.tuners.lora import MergedLinear
16
+
17
+ def reset_parameters(self):
18
+ nn.Linear.reset_parameters(self)
19
+ if hasattr(self, 'lora_A'):
20
+ # initialize A the same way as the default for nn.Linear and B to zero
21
+ nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
22
+ nn.init.ones_(self.lora_B)
23
+
24
+ MergedLinear.reset_parameters = reset_parameters
25
+
26
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
27
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
28
+ inputs = preprocessor('how are you')
29
+ lora_config = LoRAConfig(
30
+ target_modules=['query', 'key', 'value'], use_merged_linear=True, enable_lora=[True, True, True])
31
+ outputs = model(**inputs)
32
+ model = Swift.prepare_model(model, config=lora_config)
33
+ model.eval()
34
+ outputs_lora = model(**inputs)
35
+ model.deactivate_adapter('default')
36
+ outputs_deactivate = model(**inputs)
37
+ model.activate_adapter('default')
38
+ outputs_reactivate = model(**inputs)
39
+ Swift.merge_and_unload(model)
40
+ outputs_merged = model(**inputs)
41
+ self.assertTrue(torch.allclose(outputs.logits, outputs_deactivate.logits))
42
+ self.assertTrue(not torch.allclose(outputs.logits, outputs_lora.logits))
43
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_reactivate.logits))
44
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_merged.logits, atol=1e-4))
tests/tuners/test_neft.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ import torch
7
+ from modelscope import AutoModel, Preprocessor
8
+ from peft.utils import WEIGHTS_NAME
9
+ from transformers import PreTrainedModel
10
+
11
+ from swift import LoRAConfig, Swift
12
+ from swift.tuners import NEFTuneConfig
13
+
14
+
15
+ class TestNEFT(unittest.TestCase):
16
+
17
+ def setUp(self):
18
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
19
+ self.tmp_dir = tempfile.TemporaryDirectory().name
20
+ if not os.path.exists(self.tmp_dir):
21
+ os.makedirs(self.tmp_dir)
22
+
23
+ def tearDown(self):
24
+ shutil.rmtree(self.tmp_dir)
25
+ super().tearDown()
26
+
27
+ def test_neft(self):
28
+ model = AutoModel.from_pretrained('AI-ModelScope/bert-base-uncased')
29
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
30
+ inputs = preprocessor('how are you')
31
+ config = NEFTuneConfig()
32
+
33
+ t1 = model.embeddings.word_embeddings(inputs['input_ids'])
34
+ model = Swift.prepare_model(model, config)
35
+ model.train()
36
+ t2 = model.embeddings.word_embeddings(inputs['input_ids'])
37
+ model.deactivate_adapter('default')
38
+ t3 = model.embeddings.word_embeddings(inputs['input_ids'])
39
+ self.assertTrue(torch.allclose(t1, t3))
40
+ self.assertFalse(torch.allclose(t1, t2))
41
+ model.save_pretrained(self.tmp_dir)
42
+ bin_file = os.path.join(self.tmp_dir, 'pytorch_model.bin')
43
+ self.assertTrue(os.path.isfile(bin_file))
44
+ model2 = AutoModel.from_pretrained(self.tmp_dir)
45
+
46
+ state_dict = model.state_dict()
47
+ state_dict2 = model2.state_dict()
48
+ self.assertTrue(len(state_dict) > 0)
49
+ for key in state_dict:
50
+ self.assertTrue(key in state_dict2)
51
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
52
+
53
+ shutil.rmtree(self.tmp_dir)
54
+ PreTrainedModel.origin_save_pretrained = PreTrainedModel.save_pretrained
55
+ delattr(PreTrainedModel, 'save_pretrained')
56
+ model.save_pretrained(self.tmp_dir)
57
+ bin_file = os.path.join(self.tmp_dir, WEIGHTS_NAME)
58
+ self.assertTrue(os.path.isfile(bin_file))
59
+ model_new = AutoModel.from_pretrained('AI-ModelScope/bert-base-uncased')
60
+ model_new_2 = Swift.from_pretrained(model_new, self.tmp_dir)
61
+
62
+ state_dict = model.state_dict()
63
+ state_dict2 = model_new_2.state_dict()
64
+ self.assertTrue(len(state_dict) > 0)
65
+ for key in state_dict:
66
+ self.assertTrue(key in state_dict2)
67
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
68
+ PreTrainedModel.save_pretrained = PreTrainedModel.origin_save_pretrained
69
+
70
+ def test_neft_lora(self):
71
+ model = AutoModel.from_pretrained('AI-ModelScope/bert-base-uncased')
72
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
73
+ inputs = preprocessor('how are you')
74
+ config = NEFTuneConfig()
75
+ config2 = LoRAConfig(target_modules=['query', 'key', 'value'])
76
+
77
+ t1 = model.embeddings.word_embeddings(inputs['input_ids'])
78
+ model = Swift.prepare_model(model, {'c1': config, 'c2': config2})
79
+ model.train()
80
+ t2 = model.embeddings.word_embeddings(inputs['input_ids'])
81
+ model.deactivate_adapter('c1')
82
+ t3 = model.embeddings.word_embeddings(inputs['input_ids'])
83
+ self.assertTrue(torch.allclose(t1, t3))
84
+ self.assertFalse(torch.allclose(t1, t2))
85
+ model.save_pretrained(self.tmp_dir)
86
+ bin_file = os.path.join(self.tmp_dir, 'c2', WEIGHTS_NAME)
87
+ self.assertTrue(os.path.isfile(bin_file))
88
+ bin_file = os.path.join(self.tmp_dir, 'c1', WEIGHTS_NAME)
89
+ self.assertTrue(not os.path.isfile(bin_file))
90
+ model_new = AutoModel.from_pretrained('AI-ModelScope/bert-base-uncased')
91
+ t1 = model_new.embeddings.word_embeddings(inputs['input_ids'])
92
+ model_new = Swift.from_pretrained(model_new, self.tmp_dir)
93
+ model_new.train()
94
+ t2 = model_new.embeddings.word_embeddings(inputs['input_ids'])
95
+ model_new.eval()
96
+ t4 = model_new.embeddings.word_embeddings(inputs['input_ids'])
97
+ model_new.train()
98
+ model_new.deactivate_adapter('c1')
99
+ t3 = model_new.embeddings.word_embeddings(inputs['input_ids'])
100
+ self.assertTrue(torch.allclose(t1, t3))
101
+ self.assertTrue(torch.allclose(t1, t4))
102
+ self.assertFalse(torch.allclose(t1, t2))
103
+
104
+ state_dict = model.state_dict()
105
+ state_dict2 = model_new.state_dict()
106
+ self.assertTrue(len(state_dict) > 0 and all(['lora' in key for key in state_dict.keys()]))
107
+ for key in state_dict:
108
+ self.assertTrue(key in state_dict2)
109
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
tests/tuners/test_peft.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import os
3
+ import shutil
4
+ import tempfile
5
+ import unittest
6
+
7
+ import peft
8
+ import torch
9
+ from modelscope import Preprocessor
10
+ from modelscope.models.nlp.structbert import SbertConfig, SbertForSequenceClassification
11
+ from peft import PeftModel, inject_adapter_in_model
12
+ from peft.config import PeftConfigMixin
13
+ from peft.tuners.lora import Linear
14
+ from peft.utils import WEIGHTS_NAME
15
+ from torch import nn
16
+
17
+ from swift import AdaLoraConfig, LoraConfig, LoRAConfig, Swift, get_peft_model
18
+
19
+
20
+ class TestPeft(unittest.TestCase):
21
+
22
+ def setUp(self):
23
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
24
+ self.tmp_dir = tempfile.TemporaryDirectory().name
25
+ if not os.path.exists(self.tmp_dir):
26
+ os.makedirs(self.tmp_dir)
27
+
28
+ def tearDown(self):
29
+ shutil.rmtree(self.tmp_dir)
30
+ super().tearDown()
31
+
32
+ def test_peft_lora_injection(self):
33
+ model = SbertForSequenceClassification(SbertConfig())
34
+ model2 = copy.deepcopy(model)
35
+ lora_config = LoraConfig(target_modules=['query', 'key', 'value'])
36
+ model = Swift.prepare_model(model, lora_config)
37
+ model.save_pretrained(self.tmp_dir, safe_serialization=False)
38
+ with open(os.path.join(self.tmp_dir, 'configuration.json'), 'w') as f:
39
+ f.write('{}')
40
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, WEIGHTS_NAME)))
41
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
42
+ state_dict = model.state_dict()
43
+ state_dict2 = model2.state_dict()
44
+ for key in state_dict:
45
+ self.assertTrue(key in state_dict2)
46
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
47
+
48
+ @unittest.skip
49
+ def test_lora_merge(self):
50
+
51
+ def reset_lora_parameters(self, adapter_name, init_lora_weights):
52
+ if init_lora_weights is False:
53
+ return
54
+
55
+ if adapter_name == 'default':
56
+ ratio = 1.0
57
+ elif adapter_name == 'second':
58
+ ratio = 2.0
59
+ else:
60
+ ratio = 3.0
61
+
62
+ if adapter_name in self.lora_A.keys():
63
+ nn.init.ones_(self.lora_A[adapter_name].weight)
64
+ self.lora_A[adapter_name].weight.data = self.lora_A[adapter_name].weight.data * ratio
65
+ nn.init.ones_(self.lora_B[adapter_name].weight)
66
+
67
+ Linear.reset_lora_parameters = reset_lora_parameters
68
+
69
+ model = SbertForSequenceClassification(SbertConfig())
70
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
71
+ model = Swift.prepare_model(model, lora_config)
72
+ lora_config2 = LoRAConfig(target_modules=['query', 'key', 'value'])
73
+ model = Swift.prepare_model(model, {'second': lora_config2})
74
+ model.add_weighted_adapter(['default', 'second'],
75
+ weights=[0.7, 0.3],
76
+ adapter_name='test',
77
+ combination_type='cat')
78
+ self.assertTrue(model.base_model.bert.encoder.layer[0].attention.self.key.active_adapter == ['test'])
79
+
80
+ model2 = SbertForSequenceClassification(SbertConfig())
81
+ lora_config = LoraConfig(target_modules=['query', 'key', 'value'])
82
+ model2 = get_peft_model(model2, lora_config)
83
+ lora_config2 = LoraConfig(target_modules=['query', 'key', 'value'])
84
+ inject_adapter_in_model(lora_config2, model2, adapter_name='second')
85
+ model2.add_weighted_adapter(['default', 'second'],
86
+ weights=[0.7, 0.3],
87
+ adapter_name='test',
88
+ combination_type='cat')
89
+ state_dict = model.state_dict()
90
+ state_dict2 = model2.state_dict()
91
+ state_dict2 = {key[len('base_model.model.'):]: value for key, value in state_dict2.items() if 'lora' in key}
92
+ for key in state_dict:
93
+ self.assertTrue(key in state_dict2)
94
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
95
+
96
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
97
+ inputs = preprocessor('how are you')
98
+ print(model(**inputs))
99
+ model.save_pretrained(self.tmp_dir)
100
+ model3 = SbertForSequenceClassification(SbertConfig())
101
+ model3 = Swift.from_pretrained(model3, self.tmp_dir)
102
+ state_dict3 = model3.state_dict()
103
+ for key in state_dict:
104
+ self.assertTrue(key in state_dict3)
105
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict3[key]).flatten().detach().cpu()))
106
+
107
+ def test_lora_reload_by_peft(self):
108
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
109
+ model = SbertForSequenceClassification(SbertConfig())
110
+ model2 = copy.deepcopy(model)
111
+ model = Swift.prepare_model(model, lora_config)
112
+ model.save_pretrained(self.tmp_dir, peft_format=True)
113
+ model2 = PeftModel.from_pretrained(model2, self.tmp_dir)
114
+ state_dict = model.state_dict()
115
+ state_dict2 = model2.state_dict()
116
+ state_dict2 = {key[len('base_model.model.'):]: value for key, value in state_dict2.items() if 'lora' in key}
117
+ for key in state_dict:
118
+ self.assertTrue(key in state_dict2)
119
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
120
+
121
+ def test_peft_adalora_injection(self):
122
+ model = SbertForSequenceClassification(SbertConfig())
123
+ model2 = copy.deepcopy(model)
124
+ adalora_config = AdaLoraConfig(target_modules=['query', 'key', 'value'], total_step=1)
125
+ model = Swift.prepare_model(model, adalora_config)
126
+ model.save_pretrained(self.tmp_dir, safe_serialization=False)
127
+ with open(os.path.join(self.tmp_dir, 'configuration.json'), 'w') as f:
128
+ f.write('{}')
129
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, WEIGHTS_NAME)))
130
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
131
+ state_dict = model.state_dict()
132
+ state_dict2 = model2.state_dict()
133
+ for key in state_dict:
134
+ self.assertTrue(key in state_dict2)
135
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
136
+
137
+ @unittest.skip
138
+ def test_peft_lora_dtype(self):
139
+ model = SbertForSequenceClassification(SbertConfig())
140
+ model2 = copy.deepcopy(model)
141
+ model3 = copy.deepcopy(model)
142
+ lora_config = LoraConfig(target_modules=['query', 'key', 'value'], lora_dtype='float16')
143
+ model = Swift.prepare_model(model, lora_config)
144
+ model.save_pretrained(self.tmp_dir, safe_serialization=False)
145
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'additional_config.json')))
146
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
147
+ self.assertTrue(model2.base_model.model.bert.encoder.layer[0].attention.self.key.lora_A.default.weight.dtype ==
148
+ torch.float16)
149
+ self.assertTrue(model2.peft_config['default'].lora_dtype == 'float16')
150
+ state_dict = model.state_dict()
151
+ state_dict2 = model2.state_dict()
152
+ for key in state_dict:
153
+ self.assertTrue(key in state_dict2)
154
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
155
+
156
+ PeftConfigMixin.from_pretrained = PeftConfigMixin.from_pretrained_origin
157
+ model3 = Swift.from_pretrained(model3, self.tmp_dir)
158
+ self.assertTrue(model3.base_model.model.bert.encoder.layer[0].attention.self.key.lora_A.default.weight.dtype ==
159
+ torch.float32)
160
+ self.assertTrue(isinstance(model3.peft_config['default'], peft.LoraConfig))
tests/tuners/test_scetuning.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import os
3
+ import shutil
4
+ import tempfile
5
+ import unittest
6
+
7
+ import torch
8
+ from modelscope import snapshot_download
9
+
10
+ from swift import SCETuningConfig, Swift
11
+ from swift.tuners.part import PartConfig
12
+
13
+
14
+ class TestSCETuning(unittest.TestCase):
15
+
16
+ def setUp(self):
17
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
18
+ self.tmp_dir = tempfile.TemporaryDirectory().name
19
+ if not os.path.exists(self.tmp_dir):
20
+ os.makedirs(self.tmp_dir)
21
+
22
+ def tearDown(self):
23
+ shutil.rmtree(self.tmp_dir)
24
+ super().tearDown()
25
+
26
+ def model_comparison(self, model, model2):
27
+ model_key = list(model.state_dict().keys())
28
+ model2_key = list(model2.state_dict().keys())
29
+ self.assertTrue(model_key == model2_key)
30
+ model_val = torch.sum(torch.stack([torch.sum(val) for val in model.state_dict().values()]))
31
+ model2_val = torch.sum(torch.stack([torch.sum(val) for val in model2.state_dict().values()]))
32
+ self.assertTrue(torch.isclose(model_val, model2_val))
33
+
34
+ def test_scetuning_on_diffusers_v1(self):
35
+ model_dir = snapshot_download('AI-ModelScope/stable-diffusion-v1-5')
36
+ from diffusers import UNet2DConditionModel
37
+ model = UNet2DConditionModel.from_pretrained(model_dir, subfolder='unet')
38
+ model.requires_grad_(False)
39
+ model_check = copy.deepcopy(model)
40
+ # module_keys = [key for key, _ in model.named_modules()]
41
+ scetuning_config = SCETuningConfig(
42
+ dims=[320, 320, 320, 320, 640, 640, 640, 1280, 1280, 1280, 1280, 1280],
43
+ tuner_mode='encoder',
44
+ target_modules=[
45
+ 'conv_in', 'down_blocks.0.attentions.0', 'down_blocks.0.attentions.1', 'down_blocks.0.downsamplers',
46
+ 'down_blocks.1.attentions.0', 'down_blocks.1.attentions.1', 'down_blocks.1.downsamplers',
47
+ 'down_blocks.2.attentions.0', 'down_blocks.2.attentions.1', 'down_blocks.2.downsamplers',
48
+ 'down_blocks.3.resnets.0', 'down_blocks.3.resnets.1'
49
+ ])
50
+ model = Swift.prepare_model(model, config=scetuning_config)
51
+ print(model.get_trainable_parameters())
52
+ input_data = {
53
+ 'sample': torch.ones((1, 4, 64, 64)),
54
+ 'timestep': 10,
55
+ 'encoder_hidden_states': torch.ones((1, 77, 768))
56
+ }
57
+ result = model(**input_data).sample
58
+ print(result.shape)
59
+ model.save_pretrained(self.tmp_dir)
60
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
61
+ model_check = Swift.from_pretrained(model_check, self.tmp_dir)
62
+ self.model_comparison(model, model_check)
63
+
64
+ def test_scetuning_part_mixin(self):
65
+ model_dir = snapshot_download('AI-ModelScope/stable-diffusion-v1-5')
66
+ from diffusers import UNet2DConditionModel
67
+ model = UNet2DConditionModel.from_pretrained(model_dir, subfolder='unet')
68
+ model.requires_grad_(False)
69
+ model_check = copy.deepcopy(model)
70
+ # module_keys = [key for key, _ in model.named_modules()]
71
+ scetuning_config = SCETuningConfig(
72
+ dims=[320, 320, 320, 320, 640, 640, 640, 1280, 1280, 1280, 1280, 1280],
73
+ tuner_mode='encoder',
74
+ target_modules=[
75
+ 'conv_in', 'down_blocks.0.attentions.0', 'down_blocks.0.attentions.1', 'down_blocks.0.downsamplers',
76
+ 'down_blocks.1.attentions.0', 'down_blocks.1.attentions.1', 'down_blocks.1.downsamplers',
77
+ 'down_blocks.2.attentions.0', 'down_blocks.2.attentions.1', 'down_blocks.2.downsamplers',
78
+ 'down_blocks.3.resnets.0', 'down_blocks.3.resnets.1'
79
+ ])
80
+ targets = r'.*(to_k|to_v).*'
81
+ part_config = PartConfig(target_modules=targets)
82
+ model = Swift.prepare_model(model, config=scetuning_config)
83
+ model = Swift.prepare_model(model, config={'part': part_config})
84
+ print(model.get_trainable_parameters())
85
+ input_data = {
86
+ 'sample': torch.ones((1, 4, 64, 64)),
87
+ 'timestep': 10,
88
+ 'encoder_hidden_states': torch.ones((1, 77, 768))
89
+ }
90
+ model.set_active_adapters('default')
91
+ model.set_active_adapters('part')
92
+ model.set_active_adapters('default')
93
+ result = model(**input_data).sample
94
+ print(result.shape)
95
+ model.save_pretrained(self.tmp_dir)
96
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
97
+ model_check = Swift.from_pretrained(model_check, self.tmp_dir)
98
+ self.model_comparison(model, model_check)
99
+
100
+ def test_scetuning_on_diffusers_v2(self):
101
+ model_dir = snapshot_download('AI-ModelScope/stable-diffusion-v1-5')
102
+ from diffusers import UNet2DConditionModel
103
+ model = UNet2DConditionModel.from_pretrained(model_dir, subfolder='unet')
104
+ model.requires_grad_(False)
105
+ model_check = copy.deepcopy(model)
106
+ # module_keys = [key for key, _ in model.named_modules()]
107
+ scetuning_config = SCETuningConfig(
108
+ dims=[1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320],
109
+ tuner_mode='decoder',
110
+ target_modules=[
111
+ 'up_blocks.0.resnets.0', 'up_blocks.0.resnets.1', 'up_blocks.0.resnets.2', 'up_blocks.1.resnets.0',
112
+ 'up_blocks.1.resnets.1', 'up_blocks.1.resnets.2', 'up_blocks.2.resnets.0', 'up_blocks.2.resnets.1',
113
+ 'up_blocks.2.resnets.2', 'up_blocks.3.resnets.0', 'up_blocks.3.resnets.1', 'up_blocks.3.resnets.2'
114
+ ])
115
+ model = Swift.prepare_model(model, config=scetuning_config)
116
+ print(model.get_trainable_parameters())
117
+ input_data = {
118
+ 'sample': torch.ones((1, 4, 64, 64)),
119
+ 'timestep': 10,
120
+ 'encoder_hidden_states': torch.ones((1, 77, 768))
121
+ }
122
+ result = model(**input_data).sample
123
+ print(result.shape)
124
+ model.save_pretrained(self.tmp_dir)
125
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
126
+ model_check = Swift.from_pretrained(model_check, self.tmp_dir)
127
+ self.model_comparison(model, model_check)
128
+
129
+
130
+ if __name__ == '__main__':
131
+ unittest.main()
tests/tuners/test_swift_base.py ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import math
3
+ import os
4
+ import re
5
+ import shutil
6
+ import tempfile
7
+ import unittest
8
+ from concurrent.futures import ThreadPoolExecutor
9
+
10
+ import peft
11
+ import torch
12
+ from modelscope import Model, Preprocessor
13
+ from modelscope.models.nlp.structbert import SbertConfig, SbertForSequenceClassification
14
+ from peft import PeftModel
15
+ from peft.utils import WEIGHTS_NAME
16
+ from torch import nn
17
+
18
+ from swift import AdapterConfig, LoRAConfig, PromptConfig, ResTuningConfig, SideConfig, Swift, SwiftModel
19
+ from swift.tuners.part import Part, PartConfig
20
+
21
+
22
+ class TestSwift(unittest.TestCase):
23
+
24
+ def setUp(self):
25
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
26
+ self.tmp_dir = tempfile.TemporaryDirectory().name
27
+ if not os.path.exists(self.tmp_dir):
28
+ os.makedirs(self.tmp_dir)
29
+
30
+ def tearDown(self):
31
+ shutil.rmtree(self.tmp_dir)
32
+ super().tearDown()
33
+
34
+ def test_swift_lora_forward(self):
35
+
36
+ from swift.tuners.lora import Linear
37
+
38
+ def reset_lora_parameters(self, adapter_name, init_lora_weights):
39
+ if init_lora_weights is False:
40
+ return
41
+
42
+ if adapter_name in self.lora_A.keys():
43
+ if init_lora_weights is True:
44
+ # initialize A the same way as the default for nn.Linear and B to zero
45
+ # https://github.com/microsoft/LoRA/blob/a0a92e0f26c067cf94747bdbf1ce73793fa44d19/loralib/layers.py#L124
46
+ nn.init.kaiming_uniform_(self.lora_A[adapter_name].weight, a=math.sqrt(5))
47
+ elif init_lora_weights.lower() == 'gaussian':
48
+ nn.init.normal_(self.lora_A[adapter_name].weight, std=1 / self.r[adapter_name])
49
+ else:
50
+ raise ValueError(f'Unknown initialization {init_lora_weights=}')
51
+ nn.init.ones_(self.lora_B[adapter_name].weight)
52
+ if adapter_name in self.lora_embedding_A.keys():
53
+ # initialize a the same way as the default for nn.linear and b to zero
54
+ nn.init.ones_(self.lora_embedding_A[adapter_name])
55
+ nn.init.normal_(self.lora_embedding_B[adapter_name])
56
+
57
+ Linear.reset_lora_parameters = reset_lora_parameters
58
+
59
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
60
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
61
+ inputs = preprocessor('how are you')
62
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
63
+ outputs = model(**inputs)
64
+ model = Swift.prepare_model(model, config=lora_config)
65
+ model.eval()
66
+ outputs_lora = model(**inputs)
67
+ model.deactivate_adapter('default')
68
+ outputs_deactivate = model(**inputs)
69
+ model.activate_adapter('default')
70
+ outputs_reactivate = model(**inputs)
71
+ self.assertTrue(torch.allclose(outputs.logits, outputs_deactivate.logits))
72
+ self.assertTrue(not torch.allclose(outputs.logits, outputs_lora.logits))
73
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_reactivate.logits))
74
+
75
+ def test_swift_adapter_forward(self):
76
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
77
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
78
+ inputs = preprocessor('how are you')
79
+ adapter_config = AdapterConfig(
80
+ dim=model.config.hidden_size,
81
+ target_modules=r'.*layer\.\d+$',
82
+ method_name='feed_forward_chunk',
83
+ hidden_pos=0)
84
+ outputs = model(**inputs)
85
+ model = Swift.prepare_model(model, config=adapter_config)
86
+ outputs_lora = model(**inputs)
87
+ model.deactivate_adapter('default')
88
+ outputs_deactivate = model(**inputs)
89
+ model.activate_adapter('default')
90
+ outputs_reactivate = model(**inputs)
91
+ self.assertTrue(torch.allclose(outputs.logits, outputs_deactivate.logits))
92
+ self.assertTrue(not torch.allclose(outputs.logits, outputs_lora.logits))
93
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_reactivate.logits))
94
+
95
+ def test_swift_prompt_forward(self):
96
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
97
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
98
+ inputs = preprocessor('how are you')
99
+ prompt_config = PromptConfig(
100
+ dim=model.config.hidden_size, target_modules=r'.*layer\.\d+$', embedding_pos=0, attention_mask_pos=1)
101
+ outputs = model(**inputs)
102
+ model = Swift.prepare_model(model, config=prompt_config)
103
+ outputs_lora = model(**inputs)
104
+ model.deactivate_adapter('default')
105
+ outputs_deactivate = model(**inputs)
106
+ model.activate_adapter('default')
107
+ outputs_reactivate = model(**inputs)
108
+ self.assertTrue(torch.allclose(outputs.logits, outputs_deactivate.logits))
109
+ self.assertTrue(not torch.allclose(outputs.logits, outputs_lora.logits))
110
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_reactivate.logits))
111
+
112
+ def test_swift_restuner_forward(self):
113
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
114
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
115
+ inputs = preprocessor('how are you')
116
+ restuner_config = ResTuningConfig(
117
+ dims=model.config.hidden_size,
118
+ root_modules=r'.*layer.0$',
119
+ stem_modules=r'.*layer\.\d+$',
120
+ target_modules=r'.*pooler',
121
+ target_modules_hook='input',
122
+ tuner_cfg='res_adapter',
123
+ )
124
+ outputs = model(**inputs)
125
+ model = Swift.prepare_model(model, config=restuner_config)
126
+ outputs_lora = model(**inputs)
127
+ model.deactivate_adapter('default')
128
+ outputs_deactivate = model(**inputs)
129
+ model.activate_adapter('default')
130
+ outputs_reactivate = model(**inputs)
131
+ self.assertTrue(torch.allclose(outputs.logits, outputs_deactivate.logits))
132
+ self.assertTrue(not torch.allclose(outputs.logits, outputs_lora.logits))
133
+ self.assertTrue(torch.allclose(outputs_lora.logits, outputs_reactivate.logits))
134
+
135
+ def lora_injection_with_dtype(self, dtype=torch.float32):
136
+ from swift.tuners.lora import Linear
137
+
138
+ def reset_lora_parameters(self, adapter_name, init_lora_weights):
139
+ if init_lora_weights is False:
140
+ return
141
+
142
+ if adapter_name in self.lora_A.keys():
143
+ if init_lora_weights is True:
144
+ nn.init.kaiming_uniform_(self.lora_A[adapter_name].weight, a=math.sqrt(5))
145
+ elif init_lora_weights.lower() == 'gaussian':
146
+ nn.init.normal_(self.lora_A[adapter_name].weight, std=1 / self.r[adapter_name])
147
+ else:
148
+ raise ValueError(f'Unknown initialization {init_lora_weights=}')
149
+ nn.init.ones_(self.lora_B[adapter_name].weight)
150
+ if adapter_name in self.lora_embedding_A.keys():
151
+ # initialize a the same way as the default for nn.linear and b to zero
152
+ nn.init.ones_(self.lora_embedding_A[adapter_name])
153
+ nn.init.normal_(self.lora_embedding_B[adapter_name])
154
+
155
+ Linear.reset_lora_parameters = reset_lora_parameters
156
+
157
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
158
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
159
+ input = preprocessor('this is a test')
160
+ model = model.to(dtype)
161
+ model2 = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
162
+ model2 = model2.to(dtype)
163
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
164
+ model = Swift.prepare_model(model, config=lora_config)
165
+ self.assertTrue(isinstance(model, SwiftModel))
166
+ output1 = model(**input)
167
+ model.save_pretrained(self.tmp_dir)
168
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
169
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default', WEIGHTS_NAME)))
170
+
171
+ model2 = Swift.from_pretrained(model2, self.tmp_dir, adapter_name={'default': 'test'})
172
+ self.assertTrue('test' in model2.adapters)
173
+ output2 = model2(**input)
174
+ self.assertTrue(torch.allclose(output1.logits, output2.logits))
175
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
176
+ state_dict = model.state_dict()
177
+ state_dict2 = model2.state_dict()
178
+ for key in state_dict:
179
+ self.assertTrue(key in state_dict2)
180
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
181
+
182
+ if dtype == torch.float32 and os.environ.get('USE_UNIQUE_THREAD') == '1':
183
+ Swift.merge_and_unload(model2)
184
+ output3 = model2(**input)
185
+ self.assertTrue(torch.allclose(output1.logits, output3.logits))
186
+
187
+ def test_swift_lora_injection(self):
188
+ self.lora_injection_with_dtype()
189
+
190
+ def test_swift_lora_injection_bf16(self):
191
+ self.lora_injection_with_dtype(torch.bfloat16)
192
+
193
+ def test_save_to_peft_mix(self):
194
+ model = SbertForSequenceClassification(SbertConfig())
195
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
196
+ adapter_config = AdapterConfig(
197
+ dim=model.config.hidden_size,
198
+ target_modules=r'.*layer\.\d+$',
199
+ method_name='feed_forward_chunk',
200
+ hidden_pos=0)
201
+ model = Swift.prepare_model(model, config={'lora': lora_config, 'adapter': adapter_config})
202
+ model.save_pretrained(os.path.join(self.tmp_dir, 'original'))
203
+ try:
204
+ Swift.save_to_peft_format(os.path.join(self.tmp_dir, 'original'), os.path.join(self.tmp_dir, 'converted'))
205
+ self.assertTrue(False)
206
+ except AssertionError as e:
207
+ print(e)
208
+ pass
209
+
210
+ def test_save_to_peft_param(self):
211
+ model = SbertForSequenceClassification(SbertConfig())
212
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'], lora_dtype='float16')
213
+ model = Swift.prepare_model(model, config={'lora': lora_config})
214
+ model.save_pretrained(os.path.join(self.tmp_dir, 'original'))
215
+ try:
216
+ Swift.save_to_peft_format(os.path.join(self.tmp_dir, 'original'), os.path.join(self.tmp_dir, 'converted'))
217
+ self.assertTrue(False)
218
+ except AssertionError as e:
219
+ print(e)
220
+ pass
221
+
222
+ def test_save_to_peft_ok(self):
223
+ model = SbertForSequenceClassification(SbertConfig())
224
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'], use_dora=True)
225
+ lora2_config = LoRAConfig(target_modules=['query', 'key', 'value'], use_dora=True)
226
+ model = Swift.prepare_model(model, config={'default': lora_config, 'lora': lora2_config})
227
+ model.save_pretrained(os.path.join(self.tmp_dir, 'original'))
228
+ Swift.save_to_peft_format(os.path.join(self.tmp_dir, 'original'), os.path.join(self.tmp_dir, 'converted'))
229
+ # A duplicate conversion
230
+ Swift.save_to_peft_format(os.path.join(self.tmp_dir, 'original'), os.path.join(self.tmp_dir, 'converted'))
231
+
232
+ # -------------------base case--------------------
233
+ model2 = SbertForSequenceClassification(SbertConfig())
234
+ model2 = PeftModel.from_pretrained(model2, os.path.join(self.tmp_dir, 'converted'))
235
+ model2.load_adapter(os.path.join(os.path.join(self.tmp_dir, 'converted'), 'lora'), 'lora')
236
+ state_dict = model.state_dict()
237
+ state_dict2 = {
238
+ key[len('base_model.model.'):]: value
239
+ for key, value in model2.state_dict().items() if 'lora' in key
240
+ }
241
+ for key in state_dict:
242
+ self.assertTrue(key in state_dict2)
243
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
244
+
245
+ # -------------------override case--------------------
246
+ Swift.save_to_peft_format(os.path.join(self.tmp_dir, 'converted'), os.path.join(self.tmp_dir, 'converted'))
247
+ model2 = SbertForSequenceClassification(SbertConfig())
248
+ model2 = PeftModel.from_pretrained(model2, os.path.join(self.tmp_dir, 'converted'))
249
+ model2.load_adapter(os.path.join(os.path.join(self.tmp_dir, 'converted'), 'lora'), 'lora')
250
+ state_dict = model.state_dict()
251
+ state_dict2 = {
252
+ key[len('base_model.model.'):]: value
253
+ for key, value in model2.state_dict().items() if 'lora' in key
254
+ }
255
+ for key in state_dict:
256
+ self.assertTrue(key in state_dict2)
257
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
258
+
259
+ def test_swift_multiple_adapters(self):
260
+ model = SbertForSequenceClassification(SbertConfig())
261
+ model2 = copy.deepcopy(model)
262
+ lora_config = LoRAConfig(target_modules=['query', 'key', 'value'])
263
+ adapter_config = AdapterConfig(
264
+ dim=model.config.hidden_size,
265
+ target_modules=r'.*layer\.\d+$',
266
+ method_name='feed_forward_chunk',
267
+ hidden_pos=0)
268
+ model = Swift.prepare_model(model, config={'lora': lora_config, 'adapter': adapter_config})
269
+ self.assertTrue(isinstance(model, SwiftModel))
270
+ model.save_pretrained(self.tmp_dir, adapter_name=['lora', 'adapter'])
271
+ with open(os.path.join(self.tmp_dir, 'configuration.json'), 'w') as f:
272
+ f.write('{}')
273
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'lora')))
274
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'lora', WEIGHTS_NAME)))
275
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'adapter')))
276
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'adapter', WEIGHTS_NAME)))
277
+ model2 = Swift.from_pretrained(model2, self.tmp_dir, adapter_name=['lora', 'adapter'])
278
+ state_dict = model.state_dict()
279
+ state_dict2 = model2.state_dict()
280
+ for key in state_dict:
281
+ self.assertTrue(key in state_dict2)
282
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
283
+
284
+ def test_part(self):
285
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
286
+ inputs = preprocessor('how are you')
287
+ model = SbertForSequenceClassification.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
288
+ model_origin = copy.deepcopy(model)
289
+ model2 = copy.deepcopy(model)
290
+ targets = r'.*(query|key|value).*'
291
+ part_config = PartConfig(target_modules=targets)
292
+ model = Swift.prepare_model(model, config={'part': part_config})
293
+ self.assertTrue(isinstance(model, SwiftModel))
294
+
295
+ model.base_model.encoder.encoder.layer[0].attention.self.query._part_part.weight.data = torch.ones_like(
296
+ model.base_model.encoder.encoder.layer[0].attention.self.query._part_part.weight.data)
297
+
298
+ for name, module in model.named_modules():
299
+ if re.fullmatch(targets, name) and '_part_' not in name:
300
+ self.assertTrue(not module.weight.requires_grad)
301
+ self.assertTrue(model.get_submodule(name + '._part_part').weight.requires_grad)
302
+
303
+ model.save_pretrained(self.tmp_dir, adapter_name=['part'])
304
+ with open(os.path.join(self.tmp_dir, 'configuration.json'), 'w') as f:
305
+ f.write('{}')
306
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'part')))
307
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'part', WEIGHTS_NAME)))
308
+ model2 = Swift.from_pretrained(model2, self.tmp_dir, adapter_name=['part'])
309
+ self.assertTrue(
310
+ all(
311
+ torch.isclose(model.base_model.encoder.encoder.layer[0].attention.self.query._part_part.weight.data,
312
+ model2.base_model.encoder.encoder.layer[0].attention.self.query._part_part.weight.data).
313
+ flatten().detach().cpu()))
314
+
315
+ state_dict = model.model.state_dict()
316
+ state_dict2 = model2.model.state_dict()
317
+ self.assertTrue(str(state_dict) == str(state_dict2))
318
+
319
+ output = model(**inputs)
320
+ output2 = model2(**inputs)
321
+ output_origin = model_origin(**inputs)
322
+ self.assertTrue(all(torch.isclose(output.logits, output2.logits).flatten().detach().cpu()))
323
+ self.assertTrue(not all(torch.isclose(output_origin.logits, output2.logits).flatten().detach().cpu()))
324
+
325
+ model2.deactivate_adapter('part')
326
+ output = model(**inputs)
327
+ output2 = model2(**inputs)
328
+ output_origin = model_origin(**inputs)
329
+ self.assertTrue(not all(torch.isclose(output.logits, output2.logits).flatten().detach().cpu()))
330
+ self.assertTrue(all(torch.isclose(output_origin.logits, output2.logits).flatten().detach().cpu()))
331
+
332
+ model2.activate_adapter('part')
333
+ output = model(**inputs)
334
+ output2 = model2(**inputs)
335
+ output_origin = model_origin(**inputs)
336
+ self.assertTrue(all(torch.isclose(output.logits, output2.logits).flatten().detach().cpu()))
337
+ self.assertTrue(not all(torch.isclose(output_origin.logits, output2.logits).flatten().detach().cpu()))
338
+
339
+ targets = r'.*(query|key|value).*'
340
+ part_config = PartConfig(target_modules=targets)
341
+ lora_config = LoRAConfig(target_modules=targets)
342
+ model2 = Swift.prepare_model(model2, config={'part2': part_config})
343
+ model2 = Swift.prepare_model(model2, config={'lora': lora_config})
344
+ model2 = Swift.prepare_model(model2, config={'part3': part_config})
345
+ model2.set_active_adapters('part2', offload='meta')
346
+ model2.set_active_adapters('part3', offload='meta')
347
+ model2.set_active_adapters('lora', offload='meta')
348
+ model2.set_active_adapters('part2', offload='meta')
349
+ self.assertTrue(
350
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part.activated)
351
+ self.assertTrue(
352
+ model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part2.activated)
353
+ model2.set_active_adapters('part', offload='meta')
354
+ self.assertTrue(
355
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part2.activated)
356
+ self.assertTrue(model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part.activated)
357
+ output = model(**inputs)
358
+ output2 = model2(**inputs)
359
+ output_origin = model_origin(**inputs)
360
+ self.assertTrue(all(torch.isclose(output.logits, output2.logits).flatten().detach().cpu()))
361
+ self.assertTrue(not all(torch.isclose(output_origin.logits, output2.logits).flatten().detach().cpu()))
362
+
363
+ model2.set_active_adapters('part2', offload='meta')
364
+ model2.deactivate_adapter('part2', offload='meta')
365
+ model2.deactivate_adapter('lora', offload='cpu')
366
+ self.assertTrue(
367
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part2.activated)
368
+ self.assertTrue(
369
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part.activated)
370
+ output = model(**inputs)
371
+ output2 = model2(**inputs)
372
+ output_origin = model_origin(**inputs)
373
+ self.assertTrue(not all(torch.isclose(output.logits, output2.logits).flatten().detach().cpu()))
374
+ self.assertTrue(all(torch.isclose(output_origin.logits, output2.logits).flatten().detach().cpu()))
375
+ model2.activate_adapter('lora')
376
+ self.assertTrue(
377
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part2.activated)
378
+ self.assertTrue(
379
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part.activated)
380
+ self.assertTrue(
381
+ not model2.base_model.encoder.encoder.layer[0].attention.self.query.base_layer._part_part3.activated)
382
+ self.assertTrue(model2.base_model.encoder.encoder.layer[0].attention.self.query.active_adapters == ['lora'])
383
+
384
+ def test_swift_multiple_adapters_switching(self):
385
+ from swift.tuners.lora import Linear
386
+ from swift.tuners.adapter import AdapterModule
387
+
388
+ def reset_lora_parameters(self, adapter_name, init_lora_weights):
389
+ if init_lora_weights is False:
390
+ return
391
+
392
+ if adapter_name in self.lora_A.keys():
393
+ if init_lora_weights is True:
394
+ # initialize A the same way as the default for nn.Linear and B to zero
395
+ # https://github.com/microsoft/LoRA/blob/a0a92e0f26c067cf94747bdbf1ce73793fa44d19/loralib/layers.py#L124
396
+ nn.init.ones_(self.lora_A[adapter_name].weight)
397
+ elif init_lora_weights.lower() == 'gaussian':
398
+ nn.init.normal_(self.lora_A[adapter_name].weight, std=1 / self.r[adapter_name])
399
+ else:
400
+ raise ValueError(f'Unknown initialization {init_lora_weights=}')
401
+ nn.init.ones_(self.lora_B[adapter_name].weight)
402
+ if adapter_name in self.lora_embedding_A.keys():
403
+ # initialize a the same way as the default for nn.linear and b to zero
404
+ nn.init.ones_(self.lora_embedding_A[adapter_name])
405
+ nn.init.normal_(self.lora_embedding_B[adapter_name])
406
+
407
+ Linear.reset_lora_parameters = reset_lora_parameters
408
+
409
+ def init_weights(self):
410
+
411
+ def _init_weights(m):
412
+ if isinstance(m, nn.Linear):
413
+ nn.init.ones_(m.weight)
414
+ nn.init.ones_(m.bias)
415
+
416
+ self.apply(_init_weights)
417
+
418
+ AdapterModule.init_weights = init_weights
419
+
420
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
421
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
422
+ inputs = preprocessor('how are you')
423
+ model1 = copy.deepcopy(model)
424
+ model2 = copy.deepcopy(model)
425
+ model1 = Swift.prepare_model(
426
+ model1,
427
+ config={
428
+ 'lora1':
429
+ LoRAConfig(target_modules=['query', 'key', 'value']),
430
+ 'adapter1':
431
+ AdapterConfig(
432
+ dim=model.config.hidden_size,
433
+ target_modules=r'.*layer\.\d+$',
434
+ method_name='feed_forward_chunk',
435
+ hidden_pos=0)
436
+ })
437
+ model2 = Swift.prepare_model(
438
+ model2,
439
+ config={
440
+ 'lora2':
441
+ LoRAConfig(target_modules=['query', 'key', 'value']),
442
+ 'adapter2':
443
+ AdapterConfig(
444
+ dim=model.config.hidden_size,
445
+ target_modules=r'.*layer\.\d+$',
446
+ method_name='feed_forward_chunk',
447
+ hidden_pos=0)
448
+ })
449
+ model = Swift.prepare_model(
450
+ model,
451
+ config={
452
+ 'lora1': LoRAConfig(target_modules=['query', 'key', 'value']),
453
+ 'lora2': LoRAConfig(target_modules=['query', 'key', 'value']),
454
+ })
455
+
456
+ model = Swift.prepare_model(
457
+ model,
458
+ config={
459
+ 'adapter1':
460
+ AdapterConfig(
461
+ dim=model.config.hidden_size,
462
+ target_modules=r'.*layer\.\d+$',
463
+ method_name='feed_forward_chunk',
464
+ hidden_pos=0),
465
+ 'adapter2':
466
+ AdapterConfig(
467
+ dim=model.config.hidden_size,
468
+ target_modules=r'.*layer\.\d+$',
469
+ method_name='feed_forward_chunk',
470
+ hidden_pos=0),
471
+ })
472
+
473
+ model.deactivate_adapter('adapter2', offload='meta')
474
+ model.deactivate_adapter('lora2', offload='meta')
475
+ outputs1 = model(**inputs)
476
+ outputs2 = model1(**inputs)
477
+ self.assertTrue(torch.allclose(outputs1.logits, outputs2.logits))
478
+ model.activate_adapter('adapter2')
479
+ model.activate_adapter('lora2')
480
+ model.deactivate_adapter('adapter1', offload='meta')
481
+ model.deactivate_adapter('lora1', offload='meta')
482
+ outputs1 = model(**inputs)
483
+ outputs2 = model2(**inputs)
484
+ self.assertTrue(torch.allclose(outputs1.logits, outputs2.logits))
485
+
486
+ if os.environ.get('USE_UNIQUE_THREAD') == '0':
487
+
488
+ def thread_func1():
489
+ model1.set_active_adapters(['lora1', 'adapter1'], offload=None)
490
+ model.set_active_adapters(['lora1', 'adapter1'], offload=None)
491
+ outputs_single = model1(**inputs)
492
+ outputs_t1 = model(**inputs)
493
+ self.assertTrue(torch.allclose(outputs_single.logits, outputs_t1.logits))
494
+
495
+ def thread_func2():
496
+ model2.set_active_adapters(['lora2', 'adapter2'], offload=None)
497
+ model.set_active_adapters(['lora2', 'adapter2'], offload=None)
498
+ outputs_single = model2(**inputs)
499
+ outputs_t2 = model(**inputs)
500
+ self.assertTrue(torch.allclose(outputs_single.logits, outputs_t2.logits))
501
+
502
+ with ThreadPoolExecutor(2) as executor:
503
+ f1 = executor.submit(thread_func1)
504
+ f2 = executor.submit(thread_func2)
505
+ e1 = f1.exception()
506
+ e2 = f2.exception()
507
+ if e1 is not None:
508
+ raise e1
509
+ if e2 is not None:
510
+ raise e2
511
+
512
+ def test_swift_side_bert(self):
513
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
514
+ preprocessor = Preprocessor.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
515
+ inputs = preprocessor('how are you')
516
+ model2 = copy.deepcopy(model)
517
+ result_origin = model(**inputs).logits
518
+ print(f'test_swift_side_bert result_origin shape: {result_origin.shape}, '
519
+ f'result_origin sum: {torch.sum(result_origin)}')
520
+
521
+ side_config = SideConfig(
522
+ dim=model.config.hidden_size,
523
+ target_modules=r'.*encoder.encoder',
524
+ side_module_name='mlp',
525
+ target_hidden_pos='last_hidden_state')
526
+
527
+ model = Swift.prepare_model(model, config=side_config)
528
+ result_activate = model(**inputs).logits
529
+ model.deactivate_adapter('default')
530
+ result_deactivate = model(**inputs).logits
531
+ model.activate_adapter('default')
532
+ result_reactivate = model(**inputs).logits
533
+ self.assertTrue(torch.allclose(result_origin, result_deactivate))
534
+ self.assertTrue(not torch.allclose(result_origin, result_activate))
535
+ self.assertTrue(torch.allclose(result_activate, result_reactivate))
536
+ print(f'test_swift_side_bert result shape: {result_origin.shape}, result sum: {torch.sum(result_origin)}')
537
+
538
+ self.assertTrue(isinstance(model, SwiftModel))
539
+ model.save_pretrained(self.tmp_dir)
540
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
541
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default', WEIGHTS_NAME)))
542
+
543
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
544
+
545
+ state_dict = model.state_dict()
546
+ state_dict2 = model2.state_dict()
547
+ for key in state_dict:
548
+ self.assertTrue(key in state_dict2)
549
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
550
+
551
+
552
+ if __name__ == '__main__':
553
+ unittest.main()
tests/tuners/test_swift_device_map.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ import torch
7
+ from modelscope import Model
8
+ from peft.utils import WEIGHTS_NAME
9
+
10
+ from swift import LoRAConfig, SwiftModel
11
+
12
+
13
+ @unittest.skip
14
+ class TestSwift(unittest.TestCase):
15
+
16
+ def setUp(self):
17
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
18
+ self.tmp_dir = tempfile.TemporaryDirectory().name
19
+ if not os.path.exists(self.tmp_dir):
20
+ os.makedirs(self.tmp_dir)
21
+
22
+ def tearDown(self):
23
+ shutil.rmtree(self.tmp_dir)
24
+ super().tearDown()
25
+
26
+ def test_swift_multiple_adapters(self):
27
+ model = Model.from_pretrained('modelscope/Llama-2-7b-ms', device_map='auto')
28
+ lora_config = LoRAConfig(target_modules=['q_proj', 'k_proj', 'v_proj'])
29
+ model: SwiftModel = SwiftModel(model, config={'lora': lora_config})
30
+ self.assertTrue(isinstance(model, SwiftModel))
31
+ model.save_pretrained(self.tmp_dir, adapter_name=['lora'])
32
+ state_dict = model.state_dict()
33
+ with open(os.path.join(self.tmp_dir, 'configuration.json'), 'w') as f:
34
+ f.write('{}')
35
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'lora')))
36
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'lora', WEIGHTS_NAME)))
37
+ model = Model.from_pretrained('modelscope/Llama-2-7b-ms', device_map='auto')
38
+ model = SwiftModel.from_pretrained(model, self.tmp_dir, adapter_name=['lora'], device_map='auto')
39
+
40
+ state_dict2 = model.state_dict()
41
+ for key in state_dict:
42
+ self.assertTrue(key in state_dict2)
43
+ self.assertTrue(all(torch.isclose(state_dict[key], state_dict2[key]).flatten().detach().cpu()))
44
+
45
+ self.assertTrue(len(set(model.hf_device_map.values())) == torch.cuda.device_count())
tests/tuners/test_swift_restuning.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import os
3
+ import shutil
4
+ import tempfile
5
+ import unittest
6
+
7
+ import torch
8
+ from modelscope import snapshot_download
9
+
10
+ from swift import ResTuningConfig, Swift, SwiftModel
11
+
12
+
13
+ class TestSwiftResTuning(unittest.TestCase):
14
+
15
+ def setUp(self):
16
+ print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
17
+ self.tmp_dir = tempfile.TemporaryDirectory().name
18
+ if not os.path.exists(self.tmp_dir):
19
+ os.makedirs(self.tmp_dir)
20
+
21
+ def tearDown(self):
22
+ shutil.rmtree(self.tmp_dir)
23
+ super().tearDown()
24
+
25
+ def set_random_seed(self, seed=123):
26
+ """Set random seed manually to get deterministic results"""
27
+ import random
28
+ import numpy as np
29
+ import torch
30
+ random.seed(seed)
31
+ np.random.seed(seed)
32
+ torch.manual_seed(seed)
33
+ torch.cuda.manual_seed(seed)
34
+ torch.cuda.manual_seed_all(seed)
35
+
36
+ def model_comparison(self, model, model2):
37
+ model_key = list(model.state_dict().keys())
38
+ model2_key = list(model2.state_dict().keys())
39
+ self.assertTrue(model_key == model2_key)
40
+ model_val = torch.sum(torch.stack([torch.sum(val) for val in model.state_dict().values()]))
41
+ model2_val = torch.sum(torch.stack([torch.sum(val) for val in model2.state_dict().values()]))
42
+ self.assertTrue(torch.isclose(model_val, model2_val))
43
+
44
+ def test_swift_restuning_vit(self):
45
+ model_dir = snapshot_download('AI-ModelScope/vit-base-patch16-224')
46
+ from transformers import AutoModelForImageClassification
47
+ model = AutoModelForImageClassification.from_pretrained(model_dir)
48
+ model_swift_1 = copy.deepcopy(model)
49
+ model_swift_2 = copy.deepcopy(model)
50
+ result_origin = model(torch.ones((1, 3, 224, 224))).logits
51
+ print(f'test_swift_restuning_vit result_origin shape: {result_origin.shape}, '
52
+ f'result_origin sum: {torch.sum(result_origin)}')
53
+
54
+ # load type - 1
55
+ self.set_random_seed()
56
+ restuning_config_1 = ResTuningConfig(
57
+ dims=768,
58
+ root_modules=r'.*vit.encoder.layer.0$',
59
+ stem_modules=r'.*vit.encoder.layer\.\d+$',
60
+ target_modules=r'.*vit.layernorm',
61
+ target_modules_hook='input',
62
+ tuner_cfg='res_adapter',
63
+ )
64
+ model_swift_1 = Swift.prepare_model(model_swift_1, config=restuning_config_1)
65
+ self.assertTrue(isinstance(model_swift_1, SwiftModel))
66
+ print(model_swift_1.get_trainable_parameters())
67
+ result_swift_1 = model_swift_1(torch.ones((1, 3, 224, 224))).logits
68
+ print(f'test_swift_restuning_vit result_swift_1 shape: {result_swift_1.shape}, '
69
+ f'result_swift_1 sum: {torch.sum(result_swift_1)}')
70
+
71
+ # load type - 2
72
+ self.set_random_seed()
73
+ restuning_config_2 = ResTuningConfig(
74
+ dims=768,
75
+ root_modules=r'.*vit.encoder.layer.0$',
76
+ stem_modules=r'.*vit.encoder.layer\.\d+$',
77
+ target_modules=r'.*vit.encoder',
78
+ target_modules_hook='output',
79
+ target_hidden_pos='last_hidden_state',
80
+ tuner_cfg='res_adapter',
81
+ )
82
+ model_swift_2 = Swift.prepare_model(model_swift_2, config=restuning_config_2)
83
+ self.assertTrue(isinstance(model_swift_2, SwiftModel))
84
+ print(model_swift_2.get_trainable_parameters())
85
+ result_swift_2 = model_swift_2(torch.ones((1, 3, 224, 224))).logits
86
+ print(f'test_swift_restuning_vit result_swift_2 shape: {result_swift_2.shape}, '
87
+ f'result_swift_2 sum: {torch.sum(result_swift_2)}')
88
+
89
+ self.assertTrue(all(torch.isclose(result_swift_1, result_swift_2).flatten()))
90
+
91
+ model_swift_1.save_pretrained(self.tmp_dir)
92
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
93
+ model_loaded = Swift.from_pretrained(model, self.tmp_dir)
94
+ self.model_comparison(model_swift_1, model_loaded)
95
+
96
+ def test_swift_restuning_diffusers_sd(self):
97
+ model_dir = snapshot_download('AI-ModelScope/stable-diffusion-v1-5')
98
+ from diffusers import UNet2DConditionModel
99
+ model = UNet2DConditionModel.from_pretrained(model_dir, subfolder='unet')
100
+ model.requires_grad_(False)
101
+ model2 = copy.deepcopy(model)
102
+ self.set_random_seed()
103
+ input_data = {
104
+ 'sample': torch.ones((1, 4, 64, 64)),
105
+ 'timestep': 10,
106
+ 'encoder_hidden_states': torch.ones((1, 77, 768))
107
+ }
108
+ result_origin = model(**input_data).sample
109
+ print(f'test_swift_restuning_diffusers_sd result_origin shape: {result_origin.shape}, '
110
+ f'result_origin sum: {torch.sum(result_origin)}')
111
+
112
+ self.set_random_seed()
113
+ restuning_config = ResTuningConfig(
114
+ dims=[1280, 1280, 1280, 640, 320],
115
+ root_modules='mid_block',
116
+ stem_modules=['mid_block', 'up_blocks.0', 'up_blocks.1', 'up_blocks.2', 'up_blocks.3'],
117
+ target_modules='conv_norm_out',
118
+ tuner_cfg='res_group_adapter',
119
+ use_upsample=True,
120
+ upsample_out_channels=[1280, 1280, 640, 320, None],
121
+ zero_init_last=True)
122
+
123
+ model = Swift.prepare_model(model, config=restuning_config)
124
+ self.assertTrue(isinstance(model, SwiftModel))
125
+ print(model.get_trainable_parameters())
126
+
127
+ result = model(**input_data).sample
128
+ print(f'test_swift_restuning_diffusers_sd result shape: {result.shape}, result sum: {torch.sum(result)}')
129
+ model.save_pretrained(self.tmp_dir)
130
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'default')))
131
+ model2 = Swift.from_pretrained(model2, self.tmp_dir)
132
+ self.model_comparison(model, model2)
133
+
134
+
135
+ if __name__ == '__main__':
136
+ unittest.main()
tests/utils/__init__.py ADDED
File without changes
tests/utils/test_file_utils.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ from swift.utils import copy_files_by_pattern
7
+
8
+
9
+ class TestFileUtils(unittest.TestCase):
10
+
11
+ def setUp(self):
12
+ self._tmp_dir = tempfile.TemporaryDirectory()
13
+ self.tmp_dir = self._tmp_dir.name
14
+
15
+ def tearDown(self):
16
+ shutil.rmtree(self.tmp_dir)
17
+
18
+ def test_copy_files(self):
19
+ os.makedirs(os.path.join(self.tmp_dir, 'source'))
20
+ os.makedirs(os.path.join(self.tmp_dir, 'source', 'subfolder'))
21
+ with open(os.path.join(self.tmp_dir, 'source', '1.txt'), 'w') as f:
22
+ f.write('')
23
+ with open(os.path.join(self.tmp_dir, 'source', 'subfolder', '2.txt'), 'w') as f:
24
+ f.write('')
25
+ copy_files_by_pattern(
26
+ os.path.join(self.tmp_dir, 'source'), os.path.join(self.tmp_dir, 'target'), ['*.txt', 'subfolder/*.txt'])
27
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'target', '1.txt')))
28
+ self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'target', 'subfolder', '2.txt')))
29
+
30
+
31
+ if __name__ == '__main__':
32
+ unittest.main()
tests/utils/test_io_utils.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ from swift.utils import append_to_jsonl, get_logger, read_from_jsonl, write_to_jsonl
7
+
8
+ logger = get_logger()
9
+
10
+
11
+ class TestIOUtils(unittest.TestCase):
12
+
13
+ def setUp(self):
14
+ self._tmp_dir = tempfile.TemporaryDirectory()
15
+ self.tmp_dir = self._tmp_dir.name
16
+ # self.tmp_dir = 'test'
17
+ logger.info(f'self.tmp_dir: {self.tmp_dir}')
18
+
19
+ def tearDown(self):
20
+ shutil.rmtree(self.tmp_dir)
21
+
22
+ def test_jsonl(self):
23
+ fpath = os.path.join(self.tmp_dir, '1.jsonl')
24
+ obj_list = [{'aaa': 'bbb'}, 111, [1.1]]
25
+ write_to_jsonl(fpath, obj_list)
26
+ new_obj = {'bbb': 'aaa'}
27
+ obj_list.append(new_obj)
28
+ append_to_jsonl(fpath, new_obj)
29
+ new_obj_list = read_from_jsonl(fpath)
30
+ self.assertTrue(new_obj_list == obj_list)
31
+
32
+ def test_jsonl2(self):
33
+ fpath = os.path.join(self.tmp_dir, '1.jsonl')
34
+ obj_list = [{'aaa': 'bbb'}, 111, [1.1]]
35
+ for obj in obj_list:
36
+ append_to_jsonl(fpath, obj)
37
+ new_obj_list = read_from_jsonl(fpath)
38
+ self.assertTrue(new_obj_list == obj_list)
39
+
40
+
41
+ if __name__ == '__main__':
42
+ unittest.main()
tests/utils/test_split_str_parts_by.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from swift.llm.template import split_str_parts_by
2
+
3
+
4
+ def test_split_str_parts_by():
5
+ print(split_str_parts_by('aaaAction:bb\nbAction Inputs:\nabbb', ['Action:', 'Action Inputs:'], regex_mode=False))
6
+ print(split_str_parts_by('aaaAction:bb\nbAction Inputs:\nabbb', ['Action:', 'Action Inputs:'], regex_mode=True))
7
+ print(split_str_parts_by('aaa<tool_call>bbb</tool_call>ccc', ['<tool_call>.+?</tool_call>'], regex_mode=True))
8
+ print(split_str_parts_by('aaa<image>\nbb\nb<audio>\nabbb', ['<image>', '<audio>', '<video>'], regex_mode=False))
9
+ print(split_str_parts_by('aaa<image>\nbb\nb<audio>\nabbb', ['<image>', '<audio>', '<video>'], regex_mode=True))
10
+
11
+
12
+ if __name__ == '__main__':
13
+ test_split_str_parts_by()
tests/utils/test_torch_utils.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import unittest
2
+
3
+ from modelscope import Model
4
+
5
+ from swift.utils.torch_utils import find_sub_module
6
+
7
+
8
+ class TestTorchUtils(unittest.TestCase):
9
+
10
+ def test_find_sub_module(self):
11
+ model = Model.from_pretrained('damo/nlp_structbert_sentence-similarity_chinese-base')
12
+ self.assertTrue(find_sub_module(model, 'query') is not None)
13
+
14
+
15
+ if __name__ == '__main__':
16
+ unittest.main()