chore: import upstream snapshot with attribution
Lint test / lint (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:34:58 +08:00
commit a203934033
1368 changed files with 175001 additions and 0 deletions
View File
+5
View File
@@ -0,0 +1,5 @@
{
"ckpt_dir": "/mnt/workspace/yzhao/modelscope/swift/output/pai_test/checkpoint-6",
"val_dataset_sample": 2,
"load_dataset_config": true
}
+7
View File
@@ -0,0 +1,7 @@
{
"model_type": "qwen-1_8b-chat",
"dataset": "jd-sentiment-zh",
"output_dir": "output/pai_test",
"train_dataset_sample": 100,
"eval_steps": 5
}
+4
View File
@@ -0,0 +1,4 @@
system,instruction,input,output
00000,11111,22222,3.3
,aaaaa,,ccccc
,AAAAA,BBBBB,CCCCC
1 system instruction input output
2 00000 11111 22222 3.3
3 aaaaa ccccc
4 AAAAA BBBBB CCCCC
+3
View File
@@ -0,0 +1,3 @@
{"instruction": "11111", "input": "22222", "output": "33333", "history": [["aaaaa", "bbbbb"]], "system": "system123"}
{"instruction": "aaaaa", "output": "ccccc"}
{"instruction": "AAAAA", "input": "BBBBB", "output": "CCCCC"}
+4
View File
@@ -0,0 +1,4 @@
instruction,output
11111,33333
aaaaa,ccccc
AAAAA,CCCCC
1 instruction output
2 11111 33333
3 aaaaa ccccc
4 AAAAA CCCCC
+3
View File
@@ -0,0 +1,3 @@
{"messages": [{"role": "system", "content": "00000"}, {"role": "user", "content": "11111"}, {"role": "assistant", "content": "22222"}]}
{"messages": [{"role": "user", "content": "aaaaa"}, {"role": "assistant", "content": "bbbbb"}, {"role": "user", "content": "ccccc"}, {"role": "assistant", "content": "ddddd"}]}
{"messages": [{"role": "user", "content": "AAAAA"}, {"role": "assistant", "content": "BBBBB"}, {"role": "user", "content": "CCCCC"}, {"role": "assistant", "content": "DDDDD"}]}
+3
View File
@@ -0,0 +1,3 @@
{"conversations": [{"from": "system", "value": "00000"}, {"from": "user", "value": "11111"}, {"from": "assistant", "value": "22222"}]}
{"conversations": [{"from": "user", "value": "aaaaa"}, {"from": "assistant", "value": "bbbbb"}, {"from": "user", "value": "ccccc"}, {"from": "assistant", "value": "ddddd"}]}
{"conversations": [{"from": "user", "value": "AAAAA"}, {"from": "assistant", "value": "BBBBB"}, {"from": "user", "value": "CCCCC"}, {"from": "assistant", "value": "DDDDD"}]}
+3
View File
@@ -0,0 +1,3 @@
{"query": "<img>https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg</img>55555", "response": "66666"}
{"query": "<img>https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg</img><img>https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg</img>eeeee", "response": "fffff", "history": [["hello", "123"]]}
{"query": "EEEEE", "response": "FFFFF", "history": [["AAAAA", "BBBBB"], ["CCCCC", "DDDDD"]]}
+3
View File
@@ -0,0 +1,3 @@
{"query": "55555", "response": "66666", "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
{"query": "eeeee", "response": "fffff", "history": [], "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
{"query": "EEEEE", "response": "FFFFF", "history": [["AAAAA", "BBBBB"], ["CCCCC", "DDDDD"]], "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
+3
View File
@@ -0,0 +1,3 @@
{"query": "55555", "response": "66666", "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
{"query": "eeeee", "response": "fffff", "history": [], "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
{"query": "EEEEE", "response": "FFFFF", "history": [["AAAAA", "BBBBB"], ["CCCCC", "DDDDD"]], "images": ["https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"]}
+3
View File
@@ -0,0 +1,3 @@
{"system": "00000", "conversation": [{"human": "11111", "assistant": "22222"}]}
{"conversation": [{"human": "aaaaa", "assistant": "bbbbb"}]}
{"conversation": [{"human": "AAAAA", "assistant": "BBBBB"}, {"human": "CCCCC", "assistant": "DDDDD"}, {"human": "EEEEE", "assistant": "FFFFF"}]}
+3
View File
@@ -0,0 +1,3 @@
[{"system": "00000", "query": "55555", "response": "66666"},
{"query": "eeeee", "response": "fffff", "history": []},
{"query": "EEEEE", "response": "FFFFF", "history": [["AAAAA", "BBBBB"], ["CCCCC", "DDDDD"]]}]
+3
View File
@@ -0,0 +1,3 @@
{"system": "00000", "query": "55555", "response": "66666"}
{"query": "eeeee", "response": "fffff", "history": []}
{"query": "EEEEE", "response": "FFFFF", "history": [["AAAAA", "BBBBB"], ["CCCCC", "DDDDD"]]}
+4
View File
@@ -0,0 +1,4 @@
response
11111
aaaaa
AAAAA
1 response
2 11111
3 aaaaa
4 AAAAA
+3
View File
@@ -0,0 +1,3 @@
{"response": "11111"}
{"response": "aaaaa"}
{"response": "AAAAA"}
+4
View File
@@ -0,0 +1,4 @@
system,query,response
00000,11111,22222
,aaaaa,bbbbb
,AAAAA,BBBBB
1 system query response
2 00000 11111 22222
3 aaaaa bbbbb
4 AAAAA BBBBB
+3
View File
@@ -0,0 +1,3 @@
{"system": "00000", "query": "11111", "response": "22222"}
{"query": "aaaaa", "response": "bbbbb"}
{"query": "AAAAA", "response": "BBBBB"}
+73
View File
@@ -0,0 +1,73 @@
# Copyright (c) ModelScope Contributors. All rights reserved.
import torch
import unittest
from typing import Any, Dict, Optional
from swift.dataset import DatasetMeta, ResponsePreprocessor, load_dataset, register_dataset
from swift.infer_engine import InferRequest, RequestConfig, TransformersEngine
from swift.model import Model, ModelGroup, ModelMeta, register_model
from swift.template import TemplateMeta, register_template
class CustomPreprocessor(ResponsePreprocessor):
prompt = """Task: Based on the given two sentences, provide a similarity score between 0.0 and 5.0.
Sentence 1: {text1}
Sentence 2: {text2}
Similarity score: """
def preprocess(self, row: Dict[str, Any]) -> Optional[Dict[str, Any]]:
return super().preprocess({
'query': self.prompt.format(text1=row['text1'], text2=row['text2']),
'response': f"{row['label']:.1f}"
})
register_dataset(
DatasetMeta(
ms_dataset_id='swift/stsb',
hf_dataset_id='SetFit/stsb',
preprocess_func=CustomPreprocessor(),
))
register_template(
TemplateMeta(
template_type='custom',
prefix=['<extra_id_0>System\n{{SYSTEM}}\n'],
prompt=['<extra_id_1>User\n{{QUERY}}\n<extra_id_1>Assistant\n'],
chat_sep=['\n']))
register_model(
ModelMeta(
model_type='custom',
model_groups=[
ModelGroup([Model('AI-ModelScope/Nemotron-Mini-4B-Instruct', 'nvidia/Nemotron-Mini-4B-Instruct')])
],
template='custom',
ignore_patterns=['nemo']))
class TestCustom(unittest.TestCase):
def test_custom_model(self):
infer_request = InferRequest(messages=[{'role': 'user', 'content': 'who are you?'}])
request_config = RequestConfig(max_tokens=512, temperature=0)
engine = TransformersEngine('AI-ModelScope/Nemotron-Mini-4B-Instruct', torch_dtype=torch.float16)
response = engine.infer([infer_request], request_config)
swift_response = response[0].choices[0].message.content
engine.template.template_backend = 'jinja'
response = engine.infer([infer_request], request_config)
jinja_response = response[0].choices[0].message.content
assert swift_response == jinja_response, (f'swift_response: {swift_response}\njinja_response: {jinja_response}')
print(f'response: {swift_response}')
def test_custom_dataset(self):
dataset = load_dataset(['swift/stsb'])[0]
assert len(dataset) == 5749
assert list(dataset[0].keys()) == ['messages', 'dataset']
print(f'dataset: {dataset}')
print(f'dataset[0]: {dataset[0]}')
if __name__ == '__main__':
unittest.main()
+19
View File
@@ -0,0 +1,19 @@
import unittest
from swift.dataset import load_dataset
class TestDataset(unittest.TestCase):
def test_load_v_dataset(self):
if not __name__ == '__main__':
# ignore citest error in github
return
for ds in ['m3it#1000', 'mantis-instruct#1000', 'llava-med-zh-instruct#1000']:
ds = load_dataset(ds)
assert len(ds[0]) > 800
if __name__ == '__main__':
unittest.main()
+80
View File
@@ -0,0 +1,80 @@
import os
import shutil
import tempfile
import transformers
import unittest
from packaging import version
from swift import ExportArguments, export_main
if __name__ == '__main__':
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
os.environ['ASCEND_RT_VISIBLE_DEVICES'] = '0'
class TestTemplate(unittest.TestCase):
def setUp(self):
print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
self.tmp_dir = tempfile.TemporaryDirectory().name
def tearDown(self):
if os.path.exists(self.tmp_dir):
shutil.rmtree(self.tmp_dir)
super().tearDown()
@unittest.skip('swift2.0')
def test_llama3(self):
args = ExportArguments(model_type='llama3-8b-instruct', to_ollama=True, ollama_output_dir=self.tmp_dir)
export_main(args)
template = ('TEMPLATE """{{ if .System }}<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\n'
'{{ .System }}<|eot_id|>{{ else }}<|begin_of_text|>{{ end }}{{ if .Prompt }}<|start_header_id|>user'
'<|end_header_id|>\n\n{{ .Prompt }}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n'
'{{ end }}{{ .Response }}<|eot_id|>"""')
stop = 'PARAMETER stop "<|eot_id|>"'
with open(os.path.join(self.tmp_dir, 'Modelfile'), 'r') as f:
content = f.read()
self.assertTrue(template in content)
self.assertTrue(stop in content)
@unittest.skip('swift2.0')
def test_chatglm4(self):
if version.parse(transformers.__version__) >= version.parse('4.45'):
return
args = ExportArguments(model_type='glm4-9b-chat', to_ollama=True, ollama_output_dir=self.tmp_dir)
export_main(args)
template = ('TEMPLATE """{{ if .System }}[gMASK] <sop><|system|>\n{{ .System }}{{ else }}'
'[gMASK] <sop>{{ end }}{{ if .Prompt }}<|user|>\n{{ .Prompt }}<|assistant|>\n'
'{{ end }}{{ .Response }}<|user|>"""')
stop = 'PARAMETER stop "<|user|>"'
with open(os.path.join(self.tmp_dir, 'Modelfile'), 'r') as f:
content = f.read()
self.assertTrue(template in content)
self.assertTrue(stop in content)
@unittest.skip('swift2.0')
def test_qwen2(self):
args = ExportArguments(model_type='qwen2-7b-instruct', to_ollama=True, ollama_output_dir=self.tmp_dir)
export_main(args)
template = ('TEMPLATE """{{ if .System }}<|im_start|>system\n{{ .System }}<|im_end|>\n{{ else }}{{ end }}'
'{{ if .Prompt }}<|im_start|>user\n{{ .Prompt }}<|im_end|>\n<|im_start|>assistant\n'
'{{ end }}{{ .Response }}<|im_end|>"""')
stop = 'PARAMETER stop "<|im_end|>"'
with open(os.path.join(self.tmp_dir, 'Modelfile'), 'r') as f:
content = f.read()
self.assertTrue(template in content)
self.assertTrue(stop in content)
if __name__ == '__main__':
unittest.main()
+458
View File
@@ -0,0 +1,458 @@
if __name__ == '__main__':
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
os.environ['ASCEND_RT_VISIBLE_DEVICES'] = '0'
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
import os
import shutil
import tempfile
import torch
import unittest
from datasets import Dataset as HfDataset
from functools import partial
from modelscope import Model, MsDataset, snapshot_download
from torch.nn.utils.rnn import pad_sequence
from transformers import AutoTokenizer
from typing import Any, Dict, List
from swift import (InferArguments, RLHFArguments, SftArguments, Trainer, TrainingArguments, get_logger, infer_main,
rlhf_main, sft_main)
NO_EVAL_HUMAN = True
logger = get_logger()
kwargs = {
'per_device_train_batch_size': 2,
'per_device_eval_batch_size': 2,
'save_steps': 5,
'gradient_accumulation_steps': 4,
'num_train_epochs': 1,
}
class TestRun(unittest.TestCase):
def setUp(self):
print(f'Testing {type(self).__name__}.{self._testMethodName}')
self._tmp_dir = tempfile.TemporaryDirectory()
self.tmp_dir = self._tmp_dir.name
def tearDown(self):
shutil.rmtree(self.tmp_dir)
def test_template(self):
if not __name__ == '__main__':
# ignore citest error in github
return
torch.cuda.empty_cache()
output = sft_main(
SftArguments(
model='Qwen/Qwen1.5-0.5B',
tuner_type='full',
dataset='DAMO_NLP/jd',
val_dataset='DAMO_NLP/jd#20',
streaming=True,
max_steps=12,
**kwargs))
last_model_checkpoint = output['last_model_checkpoint']
torch.cuda.empty_cache()
result = infer_main(InferArguments(model=last_model_checkpoint, load_data_args=True, val_dataset_sample=2))
assert len(result[0]['response']) < 20
def test_hf_hub(self):
if not __name__ == '__main__':
# ignore citest error in github
return
torch.cuda.empty_cache()
train_dataset_fnames = [
'alpaca.csv', 'chatml.jsonl', 'swift_pre.jsonl', 'swift_single.csv', 'swift_multi.jsonl',
'swift_multi.json#2'
]
folder = os.path.join(os.path.dirname(__file__), 'data')
dataset = [
'llm-wizard/alpaca-gpt4-data-zh#20',
'shibing624/alpaca-zh#20',
] + [os.path.join(folder, fname) for fname in train_dataset_fnames]
output = sft_main(
SftArguments(
model='Qwen/Qwen1.5-0.5B-Chat-GPTQ-Int4', tuner_type='lora', dataset=dataset, use_hf=True, **kwargs))
last_model_checkpoint = output['last_model_checkpoint']
torch.cuda.empty_cache()
infer_main(InferArguments(adapters=last_model_checkpoint, load_data_args=True, val_dataset_sample=2))
@unittest.skip('avoid ci error')
def test_basic(self):
output_dir = 'output'
quant_bits_list = [0, 4]
train_dataset_fnames = [
'alpaca.csv', 'chatml.jsonl', 'swift_pre.jsonl', 'swift_single.csv', 'swift_multi.jsonl',
'swift_multi.json#2'
]
folder = os.path.join(os.path.dirname(__file__), 'data')
dataset = [
'AI-ModelScope/alpaca-gpt4-data-zh#20',
'hurner/alpaca-gpt4-data-zh#20',
] + [os.path.join(folder, fname) for fname in train_dataset_fnames]
if not __name__ == '__main__':
output_dir = self.tmp_dir
quant_bits_list = [4]
dataset = dataset[:2]
for quant_bits in quant_bits_list:
if quant_bits == 0:
predict_with_generate = False
quant_method = None
else:
predict_with_generate = True
quant_method = 'bnb'
sft_args = SftArguments(
model='Qwen/Qwen2-0.5B-Instruct',
quant_bits=quant_bits,
eval_steps=5,
adam_beta2=0.95,
quant_method=quant_method,
predict_with_generate=predict_with_generate,
dataset=dataset,
val_dataset='DAMO_NLP/jd#20',
output_dir=output_dir,
download_mode='force_redownload',
include_num_input_tokens_seen=True,
gradient_checkpointing=True,
**kwargs)
torch.cuda.empty_cache()
output = sft_main(sft_args)
print(output)
best_model_checkpoint = output['best_model_checkpoint']
print(f'best_model_checkpoint: {best_model_checkpoint}')
if __name__ == '__main__':
infer_args = InferArguments(
adapters=best_model_checkpoint,
merge_lora={
0: True,
4: False
}[quant_bits],
load_data_args=NO_EVAL_HUMAN,
val_dataset_sample=5)
torch.cuda.empty_cache()
result = infer_main(infer_args)
print(result)
# if __name__ == '__main__':
# app_ui_main(infer_args)
def test_vl_audio(self):
output_dir = 'output'
if not __name__ == '__main__':
# ignore citest error in github
return
model_type_list = ['Qwen/Qwen-VL-Chat', 'Qwen/Qwen-Audio-Chat']
dataset_list = [
'modelscope/coco_2014_caption:validation#100', 'speech_asr/speech_asr_aishell1_trainsets:validation#100'
]
for model, dataset in zip(model_type_list, dataset_list):
sft_args = SftArguments(
model=model,
eval_steps=5,
dataset=[dataset],
output_dir=output_dir,
gradient_checkpointing=True,
lazy_tokenize=True,
disable_tqdm=True,
**kwargs)
torch.cuda.empty_cache()
output = sft_main(sft_args)
print(output)
best_model_checkpoint = output['best_model_checkpoint']
print(f'best_model_checkpoint: {best_model_checkpoint}')
infer_args = InferArguments(
adapters=best_model_checkpoint,
load_data_args=True,
stream={
'Qwen/Qwen-VL-Chat': True,
'Qwen/Qwen-Audio-Chat': False
}[model],
val_dataset_sample=5)
torch.cuda.empty_cache()
result = infer_main(infer_args)
print(result)
def test_custom_dataset(self):
if not __name__ == '__main__':
# ignore citest error in github
return
train_dataset_fnames = [
'alpaca.csv', 'chatml.jsonl', 'swift_pre.jsonl', 'swift_single.csv', 'swift_multi.jsonl',
'swift_multi.json', 'sharegpt.jsonl'
]
val_dataset_fnames = [
'alpaca.jsonl',
'alpaca2.csv',
'conversations.jsonl',
'swift_pre.csv',
'swift_single.jsonl',
# 'swift_#:#.jsonl#3'
]
folder = os.path.join(os.path.dirname(__file__), 'data')
resume_from_checkpoint = None
train_kwargs = kwargs.copy()
train_kwargs.pop('num_train_epochs')
for num_train_epochs in [1, 2]:
sft_args = SftArguments(
model='Qwen/Qwen-7B-Chat',
dataset=['swift/self-cognition#20'] + [os.path.join(folder, fname) for fname in train_dataset_fnames],
val_dataset=[os.path.join(folder, fname) for fname in val_dataset_fnames],
resume_from_checkpoint=resume_from_checkpoint,
num_train_epochs=num_train_epochs,
model_name='小黄',
model_author='魔搭',
**train_kwargs)
torch.cuda.empty_cache()
result = sft_main(sft_args)
best_model_checkpoint = result['best_model_checkpoint']
resume_from_checkpoint = result['last_model_checkpoint']
for load_args in [True, False]:
infer_kwargs = {}
if load_args is False:
args_json = os.path.join(best_model_checkpoint, 'args.json')
assert os.path.exists(args_json)
os.remove(args_json)
infer_kwargs = {'model': 'Qwen/Qwen-7B-Chat'}
infer_args = InferArguments(
adapters=best_model_checkpoint,
load_data_args=load_args and NO_EVAL_HUMAN,
merge_lora=load_args,
val_dataset=[os.path.join(folder, fname) for fname in val_dataset_fnames],
**infer_kwargs)
torch.cuda.empty_cache()
infer_main(infer_args)
def test_rlhf(self):
if not __name__ == '__main__':
# ignore citest error in github
return
torch.cuda.empty_cache()
# llm rlhf
#
rlhf_types = ['dpo', 'orpo', 'simpo', 'kto', 'cpo', 'rm', 'ppo']
for rlhf_type in rlhf_types:
dataset = ('AI-ModelScope/hh_rlhf_cn:harmless_base_cn#100'
if rlhf_type != 'kto' else 'AI-ModelScope/ultrafeedback-binarized-preferences-cleaned-kto#100')
train_kwargs = {}
if rlhf_type == 'ppo':
train_kwargs['reward_model'] = 'Qwen/Qwen2-1.5B-Instruct'
output = rlhf_main(
RLHFArguments(
rlhf_type=rlhf_type,
model='Qwen/Qwen2-1.5B-Instruct',
dataset=dataset,
eval_steps=5,
split_dataset_ratio=0.05,
**train_kwargs,
**kwargs))
if rlhf_type == 'ppo':
model_checkpoint = output['last_model_checkpoint']
else:
model_checkpoint = output['best_model_checkpoint']
torch.cuda.empty_cache()
infer_main(InferArguments(adapters=model_checkpoint, load_data_args=True))
# mllm rlhf
visual_rlhf_types = ['dpo', 'orpo', 'simpo', 'cpo', 'rm']
test_model = [
'OpenGVLab/InternVL2-2B', 'Qwen/Qwen2-VL-2B-Instruct', 'llava-hf/llava-v1.6-mistral-7b-hf',
'AI-ModelScope/Florence-2-base-ft'
] # decoder only and encoder-decoder
for rlhf_type in visual_rlhf_types:
for model in test_model:
dataset_name = 'swift/RLAIF-V-Dataset#100'
output = rlhf_main(
RLHFArguments(
rlhf_type=rlhf_type,
model=model,
dataset=dataset_name,
eval_steps=5,
dataset_num_proc=16,
**kwargs))
best_model_checkpoint = output['best_model_checkpoint']
torch.cuda.empty_cache()
infer_main(InferArguments(adapters=best_model_checkpoint, load_data_args=True, val_dataset_sample=2))
def test_loss_matching(self):
output_dir = 'output'
if not __name__ == '__main__':
# ignore citest error in github
return
losses = []
for use_swift_lora in [False, True]:
bool_var = use_swift_lora
torch.cuda.empty_cache()
output = sft_main([
'--model', 'Qwen/Qwen-7B-Chat', '--save_steps', '5', '--dataset',
'AI-ModelScope/leetcode-solutions-python#200', '--output_dir', output_dir, '--gradient_checkpointing',
'true', '--max_new_tokens', '100', '--attn_impl', 'flash_attn', '--target_modules', 'all-linear',
'--seed', '0', '--lora_bias', 'all', '--modules_to_save', 'lm_head', '--use_swift_lora',
str(use_swift_lora), '--num_train_epochs', '1', '--gradient_accumulation_steps', '16'
])
best_model_checkpoint = output['best_model_checkpoint']
print(f'best_model_checkpoint: {best_model_checkpoint}')
load_data_args = str(bool_var or NO_EVAL_HUMAN)
if load_data_args:
val_dataset_sample = 2
else:
val_dataset_sample = -1
torch.cuda.empty_cache()
infer_main([
'--adapters', best_model_checkpoint, '--val_dataset_sample',
str(val_dataset_sample), '--max_new_tokens', '100', '--attn_impl', 'eager', '--merge_lora',
str(bool_var), '--load_data_args',
str(load_data_args)
])
loss = output['log_history'][-1]['train_loss']
losses.append(loss)
self.assertTrue(abs(losses[0] - losses[1]) < 5e-4)
print(f'swift_loss: {losses[0]}')
print(f'peft_loss: {losses[1]}')
self.assertTrue(0.95 <= losses[0] <= 1)
def test_pai_compat(self):
if not __name__ == '__main__':
# ignore citest error in github
return
from swift import infer_main, sft_main
os.environ['PAI_TRAINING_JOB_ID'] = '123456'
folder = os.path.join(os.path.dirname(__file__), 'config')
tensorboard_dir = os.path.join('output/pai_test', 'pai_tensorboard')
os.environ['PAI_OUTPUT_TENSORBOARD'] = tensorboard_dir
sft_json = os.path.join(folder, 'sft.json')
infer_json = os.path.join(folder, 'infer.json')
torch.cuda.empty_cache()
output = sft_main([sft_json])
print()
infer_args = {
'adapters': output['best_model_checkpoint'],
'val_dataset_sample': 2,
'load_data_args': True,
}
import json
with open(infer_json, 'w') as f:
json.dump(infer_args, f, ensure_ascii=False, indent=4)
torch.cuda.empty_cache()
infer_main([infer_json])
os.environ.pop('PAI_TRAINING_JOB_ID')
def data_collate_fn(batch: List[Dict[str, Any]], tokenizer) -> Dict[str, torch.Tensor]:
# text-classification
assert tokenizer.pad_token_id is not None
input_ids = [torch.tensor(b['input_ids']) for b in batch]
labels = torch.tensor([b['labels'] for b in batch])
attention_mask = [torch.ones(len(input_ids[i]), dtype=torch.int64) for i in range(len(input_ids))]
input_ids = pad_sequence(input_ids, batch_first=True, padding_value=tokenizer.pad_token_id)
attention_mask = pad_sequence(attention_mask, batch_first=True, padding_value=0)
return {'input_ids': input_ids, 'attention_mask': attention_mask, 'labels': labels}
class BertTrainer(Trainer):
def compute_loss(self, model, inputs, return_outputs=False):
outputs = model(**inputs)
loss = outputs.loss
if loss is None:
logits, loss = list(outputs.logits)
return (loss, outputs) if return_outputs else loss
class TestTrainer(unittest.TestCase):
def setUp(self):
self._tmp_dir = tempfile.TemporaryDirectory()
self.tmp_dir = self._tmp_dir.name
# self.tmp_dir = 'test'
logger.info(f'self.tmp_dir: {self.tmp_dir}')
def tearDown(self):
if os.path.isdir(self.tmp_dir):
shutil.rmtree(self.tmp_dir)
# api = HubApi()
# api.delete_model(self.hub_model_id)
# logger.info(f'delete model: {self.hub_model_id}')
def test_trainer(self):
self.hub_model_id = 'test_trainer2'
logger.info(f'self.hub_model_id: {self.hub_model_id}')
self.tmp_dir = 'output/damo/nlp_structbert_backbone_base_std'
push_to_hub = True
if not __name__ == '__main__':
# ignore citest error in github
return
model_id = 'damo/nlp_structbert_backbone_base_std'
model_dir = snapshot_download(model_id, 'master')
tokenizer = AutoTokenizer.from_pretrained(model_dir)
dataset = MsDataset.load('clue', subset_name='tnews')
num_labels = max(dataset['train']['label']) + 1
model = Model.from_pretrained(model_dir, task='text-classification', num_labels=num_labels)
train_dataset, val_dataset = dataset['train'].to_hf_dataset(), dataset['validation'].to_hf_dataset()
train_dataset: HfDataset = train_dataset.select(range(100))
val_dataset: HfDataset = val_dataset.select(range(20))
#
def tokenize_func(examples):
data = tokenizer(examples['sentence'], return_attention_mask=False)
examples['input_ids'] = data['input_ids']
examples['labels'] = examples['label']
del examples['sentence'], examples['label']
return examples
train_dataset = train_dataset.map(tokenize_func)
val_dataset = val_dataset.map(tokenize_func)
data_collator = partial(data_collate_fn, tokenizer=tokenizer)
for save_only_model in [True, False]:
trainer_args = TrainingArguments(
self.tmp_dir,
do_train=True,
do_eval=True,
num_train_epochs=1,
evaluation_strategy='steps',
save_strategy='steps',
per_device_train_batch_size=4,
per_device_eval_batch_size=4,
push_to_hub=push_to_hub,
hub_token=None, # use env var
hub_private_repo=True,
hub_strategy='every_save',
hub_model_id=self.hub_model_id,
overwrite_output_dir=True,
save_steps=10,
save_total_limit=2,
metric_for_best_model='loss',
greater_is_better=False,
report_to=['tensorboard'],
gradient_accumulation_steps=1,
logging_steps=5,
eval_steps=10,
save_safetensors=False,
save_only_model=save_only_model)
trainer_args._n_gpu = 1
trainer = BertTrainer(model, trainer_args, data_collator, train_dataset, val_dataset, tokenizer)
self.hub_model_id = trainer_args.hub_model_id
trainer.train()
if trainer_args.push_to_hub:
trainer.push_to_hub()
if __name__ == '__main__':
# TestRun().test_template()
# TestRun().test_hf_hub()
# TestRun().test_basic()
# TestRun().test_custom_dataset()
# TestRun().test_vl_audio()
# TestRun().test_loss_matching()
#
# TestRun().test_rlhf()
unittest.main()
+109
View File
@@ -0,0 +1,109 @@
import os
import torch
import unittest
from swift.infer_engine import RequestConfig, TransformersEngine
from swift.model import get_processor
from swift.template import get_template
from swift.utils import get_logger, seed_everything
# os.environ['CUDA_VISIBLE_DEVICES'] = '0'
# os.environ['ASCEND_RT_VISIBLE_DEVICES'] = '0'
os.environ['SWIFT_DEBUG'] = '1'
logger = get_logger()
def _infer_model(engine, system=None, messages=None):
seed_everything(42)
request_config = RequestConfig(max_tokens=128, temperature=0)
if messages is None:
messages = []
if system is not None:
messages += [{'role': 'system', 'content': system}]
messages += [{'role': 'user', 'content': '你好'}]
resp = engine.infer([{'messages': messages}], request_config=request_config)
response = resp[0].choices[0].message.content
messages += [{'role': 'assistant', 'content': response}, {'role': 'user', 'content': '<image>这是什么'}]
resp = engine.infer([{
'messages': messages,
}], request_config=request_config)
response = resp[0].choices[0].message.content
messages += [{'role': 'assistant', 'content': response}]
logger.info(f'model: {engine.model_info.model_name}, messages: {messages}')
return response
class TestTemplate(unittest.TestCase):
@unittest.skipIf(not torch.cuda.is_available(), reason='GPTQ is only available on GPU')
def test_template(self):
engine = TransformersEngine('Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4')
response = _infer_model(engine)
engine.template.template_backend = 'jinja'
response2 = _infer_model(engine)
assert response == response2
def test_tool_message_join(self):
from copy import deepcopy
from swift.agent_template import agent_template_map
messages = [
# first round
{
'role': 'user',
'content': 'user1'
},
{
'role': 'assistant',
'content': 'assistant1'
},
{
'role': 'assistant',
'content': 'assistant2'
},
{
'role': 'tool',
'content': 'tool1'
},
# second round
{
'role': 'assistant',
'content': 'assistant3'
},
{
'role': 'tool',
'content': 'tool2'
},
{
'role': 'tool',
'content': 'tool3'
},
]
# testing two template type.
tokenizer = get_processor('Qwen/Qwen2.5-7B-Instruct')
template = get_template(tokenizer)
for agent_template_type in ('react_zh', 'qwen_zh'):
template._agent_template = agent_template_type
agent_template = template.agent_template
observation = agent_template.keyword.observation
test_messages = deepcopy(messages)
test_messages[2]['content'] = 'assistant2' + observation
test_messages[4]['content'] = (
agent_template.keyword.action + agent_template.keyword.action_input + 'assistant3' + observation)
encoded = template.encode({'messages': test_messages})
res = template.safe_decode(encoded['input_ids'])
ground_truth = (
'<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n'
'<|im_start|>user\nuser1<|im_end|>\n'
f'<|im_start|>assistant\nassistant1assistant2{observation}tool1'
f'{agent_template.keyword.action}{agent_template.keyword.action_input}assistant3'
f'{observation}tool2\n{observation}tool3\n')
assert res == ground_truth
if __name__ == '__main__':
unittest.main()
+28
View File
@@ -0,0 +1,28 @@
import unittest
from swift.dataset import load_dataset
from swift.utils import lower_bound
class TestLlmUtils(unittest.TestCase):
def test_count_startswith(self):
arr = [-100] * 1000 + list(range(1000))
self.assertTrue(lower_bound(0, len(arr), lambda i: arr[i] != -100) == 1000)
def test_count_endswith(self):
arr = list(range(1000)) + [-100] * 1000
self.assertTrue(lower_bound(0, len(arr), lambda i: arr[i] == -100) == 1000)
@unittest.skip('avoid ci error')
def test_dataset(self):
dataset = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#1000', 'AI-ModelScope/alpaca-gpt4-data-en#200'],
num_proc=4,
strict=False,
download_mode='force_redownload')
print(f'dataset[0]: {dataset[0]}')
print(f'dataset[1]: {dataset[1]}')
if __name__ == '__main__':
unittest.main()
+5
View File
@@ -0,0 +1,5 @@
from swift.arguments import WebUIArguments
from swift.ui import webui_main
if __name__ == '__main__':
webui_main(WebUIArguments())