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
+45
View File
@@ -0,0 +1,45 @@
def test_model_arch():
import random
from transformers import PretrainedConfig
from swift.model import MODEL_MAPPING
from swift.utils import JsonlWriter, safe_snapshot_download
jsonl_writer = JsonlWriter('model_arch.jsonl')
for i, (model_type, model_meta) in enumerate(MODEL_MAPPING.items()):
if i < 0:
continue
arch_list = model_meta.architectures
for model_group in model_meta.model_groups:
model = random.choice(model_group.models).ms_model_id
config_dict = None
try:
model_dir = safe_snapshot_download(model, download_model=False)
config_dict = PretrainedConfig.get_config_dict(model_dir)[0]
except Exception:
pass
finally:
msg = None
if config_dict:
arch = config_dict.get('architectures')
if arch and arch[0] not in arch_list:
msg = {
'model_type': model_type,
'model': model,
'config_arch': arch,
'architectures': arch_list
}
elif not arch and arch_list:
msg = {
'model_type': model_type,
'model': model,
'config_arch': arch,
'architectures': arch_list
}
else:
msg = {'msg': 'error', 'model_type': model_type, 'model': model, 'arch_list': arch_list}
if msg:
jsonl_writer.append(msg)
if __name__ == '__main__':
test_model_arch()
+207
View File
@@ -0,0 +1,207 @@
import unittest
from swift.dataset import EncodePreprocessor, MessagesPreprocessor, PackingDataset, load_dataset
from swift.model import get_processor
from swift.template import get_template
class TestDataPreprocess(unittest.TestCase):
"""Lightweight data preprocessing tests (no model forward/backward).
These are fast tests suitable for CI. They cover:
- SFT dataset encode (input_ids/labels)
- Truncation/max_length
- Data collator padding (attention_mask)
- Multi-turn messages
- Tool message
- Packing dataset
Why these tests are needed:
- Swift's data preprocessing pipeline is complex (template -> encode -> collate -> pack).
NPU training failures often stem from shape/mask/label mismatches before the model
even sees the data, not from operator issues.
- The original tests/general/test_dataset.py and test_template.py use top-level
functions and remote 7B models, so they are never run by unittest discovery
and are too heavy for CI.
"""
MODEL_PATH = 'Qwen/Qwen2-0.5B'
@classmethod
def setUpClass(cls):
cls.processor = get_processor(cls.MODEL_PATH)
cls.template = get_template(cls.processor)
cls.template.mode = 'train'
cls.template.init_processor(cls.processor)
def _encode_dataset(self, dataset):
encode_preprocessor = EncodePreprocessor(self.template)
return encode_preprocessor(dataset, num_proc=1, load_from_cache_file=False, strict=False)
def test_sft_dataset_encode(self):
dataset, _ = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#20'], num_proc=1, strict=False)
self.assertGreater(len(dataset), 0)
encoded_dataset = self._encode_dataset(dataset)
first = encoded_dataset[0]
self.assertIn('input_ids', first)
self.assertIn('labels', first)
self.assertEqual(len(first['input_ids']), len(first['labels']))
def test_truncation_max_length(self):
self.template.max_length = 128
dataset, _ = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#20'], num_proc=1, strict=False)
encoded_dataset = self._encode_dataset(dataset)
for row in encoded_dataset:
self.assertLessEqual(len(row['input_ids']), self.template.max_length)
self.template.max_length = None
def test_data_collator_padding(self):
dataset, _ = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#20'], num_proc=1, strict=False)
encoded_dataset = self._encode_dataset(dataset)
batch = [encoded_dataset[i] for i in range(4)]
collated = self.template.data_collator(batch)
self.assertIn('input_ids', collated)
self.assertIn('labels', collated)
self.assertIn('attention_mask', collated)
self.assertEqual(collated['input_ids'].shape[0], 4)
def test_multi_turn_messages(self):
multi_turn_row = {
'messages': [
{
'role': 'user',
'content': 'What is Python?'
},
{
'role': 'assistant',
'content': 'Python is a programming language.'
},
{
'role': 'user',
'content': 'What are its advantages?'
},
{
'role': 'assistant',
'content': 'Python is easy to learn and use.'
},
]
}
encoded = self.template.encode(multi_turn_row, return_length=True)
self.assertIn('input_ids', encoded)
self.assertIn('labels', encoded)
self.assertGreater(len(encoded['input_ids']), 0)
self.assertEqual(len(encoded['input_ids']), len(encoded['labels']))
def test_tool_message(self):
tool_row = {
'messages': [
{
'role': 'user',
'content': 'What is the weather in Beijing?'
},
{
'role':
'assistant',
'content':
'',
'tool_calls': [{
'type': 'function',
'function': {
'name': 'get_weather',
'arguments': '{"city": "Beijing"}'
}
}]
},
{
'role': 'tool',
'content': '{"temperature": 25, "condition": "sunny"}'
},
{
'role': 'assistant',
'content': 'The weather in Beijing is sunny with a temperature of 25 degrees.'
},
]
}
encoded = self.template.encode(tool_row, return_length=True)
self.assertIn('input_ids', encoded)
self.assertIn('labels', encoded)
self.assertGreater(len(encoded['input_ids']), 0)
def test_packing_dataset(self):
dataset, _ = load_dataset(['AI-ModelScope/alpaca-gpt4-data-zh#20'], num_proc=1, strict=False)
encoded_dataset = self._encode_dataset(dataset)
packing_dataset = PackingDataset(
self.template,
encoded_dataset,
num_proc=1,
strict=False,
load_from_cache_file=False,
packing_length=512,
packing_num_proc=1,
)
self.assertGreater(len(packing_dataset), 0)
packed = packing_dataset[0]
self.assertIsInstance(packed, list)
self.assertGreater(len(packed), 0)
self.assertIn('input_ids', packed[0])
self.assertIn('labels', packed[0])
class TestRejectedMessagesPreprocess(unittest.TestCase):
"""MessagesPreprocessor handling of rejected_messages (no model required)."""
def test_empty_rejected_messages_does_not_crash(self):
"""A DPO row whose rejected_messages repair to empty must not crash.
The recursive preprocess() call returns None when rejected_messages is
empty (the same graceful-skip path used for the main messages list), so
subscripting it with ['messages'] raised TypeError and aborted the whole
dataset map. Downstream already treats rejected_messages is None as
'no rejected', so the row should fall back to None instead.
"""
row = {
'messages': [
{
'role': 'user',
'content': 'Q'
},
{
'role': 'assistant',
'content': 'good'
},
],
'rejected_messages': [],
}
result = MessagesPreprocessor().preprocess(row)
self.assertIsNotNone(result)
self.assertIsNone(result['rejected_messages'])
def test_valid_rejected_messages_preserved(self):
row = {
'messages': [
{
'role': 'user',
'content': 'Q'
},
{
'role': 'assistant',
'content': 'good'
},
],
'rejected_messages': [
{
'role': 'user',
'content': 'Q'
},
{
'role': 'assistant',
'content': 'bad'
},
],
}
result = MessagesPreprocessor().preprocess(row)
self.assertEqual(result['rejected_messages'][-1]['content'], 'bad')
if __name__ == '__main__':
unittest.main()
+90
View File
@@ -0,0 +1,90 @@
from typing import List
from swift.dataset import load_dataset
def _test_dataset(datasets: List[str], num_proc: int = 1, strict: bool = False, **kwargs):
dataset = load_dataset(datasets, num_proc=num_proc, strict=strict, **kwargs)
print(f'dataset[0]: {dataset[0]}')
print(f'dataset[1]: {dataset[1]}')
def test_sft():
# swift/SlimOrca swift/cosmopedia-100k
# _test_dataset(['lvjianjin/AdvertiseGen'])
# _test_dataset(['AI-ModelScope/Duet-v0.5'])
# _test_dataset(['swift/SlimOrca', 'swift/cosmopedia-100k'])
# _test_dataset(['OmniData/Zhihu-KOL-More-Than-100-Upvotes'])
# _test_dataset(['OmniData/Zhihu-KOL'])
_test_dataset([
'AI-ModelScope/alpaca-gpt4-data-zh#1000', 'AI-ModelScope/alpaca-gpt4-data-en#1000',
'AI-ModelScope/LongAlpaca-12k#1000'
])
# _test_dataset(['swift/Infinity-Instruct:all'])
# _test_dataset(['swift/sharegpt:all'])
# _test_dataset(['AI-ModelScope/sharegpt_gpt4:all'])
# _test_dataset(['iic/ms_bench'])
# _test_dataset(['swift/tagengo-gpt4'])
def test_mllm():
# _test_dataset(['AI-ModelScope/ShareGPT4V:all'])
# _test_dataset(['AI-ModelScope/LLaVA-Pretrain'])
# _test_dataset(['swift/TextCaps'])
# _test_dataset(['swift/RLAIF-V-Dataset:all'])
# _test_dataset(['swift/OK-VQA_train'])
# _test_dataset(['swift/OCR-VQA'])
# _test_dataset(['swift/A-OKVQA'])
# _test_dataset(['AI-ModelScope/MovieChat-1K-test'])
_test_dataset([
'AI-ModelScope/LaTeX_OCR:all', 'modelscope/coco_2014_caption:validation',
'speech_asr/speech_asr_aishell1_trainsets:validation'
],
strict=False)
# _test_dataset(['swift/VideoChatGPT:all'])
# _test_dataset(['speech_asr/speech_asr_aishell1_trainsets:validation'])
# _test_dataset(['AI-ModelScope/captcha-images'])
# _test_dataset(['swift/gpt4v-dataset:all'])
# _test_dataset(['modelscope/coco_2014_caption:validation'])
# _test_dataset(['AI-ModelScope/LLaVA-Instruct-150K'], num_proc=16)
def test_agent():
_test_dataset(['swift/ToolBench'])
# _test_dataset(['AI-ModelScope/ms_agent_for_agentfabric:all'])
def test_dpo():
_test_dataset(['AI-ModelScope/orpo-dpo-mix-40k'])
_test_dataset(['AI-ModelScope/hh-rlhf:all'])
_test_dataset(['AI-ModelScope/hh_rlhf_cn:all'])
_test_dataset(['hjh0119/shareAI-Llama3-DPO-zh-en-emoji:all'])
def test_kto():
_test_dataset(['AI-ModelScope/ultrafeedback-binarized-preferences-cleaned-kto'])
def test_pretrain():
_test_dataset(['AI-ModelScope/ruozhiba:all'])
def test_dataset_info():
_test_dataset(['swift/self-cognition#500'], model_name='xiao huang', model_author='swift')
# _test_dataset(['codefuse-ai/CodeExercise-Python-27k'])
def test_cls():
_test_dataset(['simpleai/HC3-Chinese:baike'])
_test_dataset(['simpleai/HC3-Chinese:baike_cls'])
if __name__ == '__main__':
# test_sft()
# test_agent()
# test_dpo()
# test_kto()
test_mllm()
# test_pretrain()
# test_dataset_info()
# test_cls()
+53
View File
@@ -0,0 +1,53 @@
import os
import torch
import unittest
from swift.utils import get_device
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
def test_qwen2():
import os
from swift.model import get_model_processor
model, tokenizer = get_model_processor('Qwen/Qwen2-7B-Instruct', load_model=False)
print(f'model: {model}, tokenizer: {tokenizer}')
# test hf
model, tokenizer = get_model_processor('Qwen/Qwen2-7B-Instruct', load_model=False, use_hf=True)
model, tokenizer = get_model_processor(
'Qwen/Qwen2-7B-Instruct', torch_dtype=torch.float32, device_map=get_device(), attn_impl='flash_attn')
print(f'model: {model}, tokenizer: {tokenizer}')
def test_modelscope_hub():
from swift.model import get_model_processor
model, tokenizer = get_model_processor('Qwen/Qwen2___5-Math-1___5B-Instruct/', load_model=False)
class TestMolmo2Registration(unittest.TestCase):
def test_registration(self):
from swift.model import MODEL_MAPPING, MLLMModelType
from swift.template import TEMPLATE_MAPPING, TemplateType
model_meta = MODEL_MAPPING[MLLMModelType.molmo2]
self.assertEqual(model_meta.template, TemplateType.molmo2)
self.assertEqual(model_meta.model_arch.arch_name, 'molmo')
self.assertIn('Molmo2ForConditionalGeneration', model_meta.architectures)
hf_model_ids = []
for group in model_meta.model_groups:
for model in group.models:
hf_model_ids.append(model.hf_model_id)
self.assertIn('allenai/Molmo2-4B', hf_model_ids)
self.assertIn('allenai/Molmo2-8B', hf_model_ids)
self.assertIn('allenai/Molmo2-O-7B', hf_model_ids)
self.assertIn(TemplateType.molmo2, TEMPLATE_MAPPING)
if __name__ == '__main__':
test_qwen2()
# test_modelscope_hub()
+20
View File
@@ -0,0 +1,20 @@
from swift.dataset import load_dataset
def test_local_dataset():
# please use git clone
from swift.utils import git_clone_github
model_dir = git_clone_github('https://www.modelscope.cn/datasets/swift/swift-sft-mixture.git')
dataset = load_dataset(datasets=[f'{model_dir}:firefly'], streaming=True)[0]
print(next(iter(dataset)))
def test_hub_dataset():
local_dataset = 'swift/swift-sft-mixture:firefly'
dataset = load_dataset(datasets=[local_dataset], streaming=True)[0]
print(next(iter(dataset)))
if __name__ == '__main__':
test_local_dataset()
# test_hub_dataset()
+79
View File
@@ -0,0 +1,79 @@
from swift.dataset import EncodePreprocessor, load_dataset
from swift.model import get_processor
from swift.template import TemplateInputs, get_template
def test_template():
tokenizer = get_processor('Qwen/Qwen2-7B-Instruct')
template = get_template(tokenizer)
template_inputs = TemplateInputs.from_dict({
'messages': [{
'role': 'system',
'content': 'AAA'
}, {
'role': 'user',
'content': 'BBB'
}, {
'role': 'assistant',
'content': 'CCC'
}, {
'role': 'user',
'content': 'DDD'
}]
})
inputs = template.encode(template_inputs)
print(f'inputs.keys(): {inputs.keys()}')
print(tokenizer.decode(inputs['input_ids']))
def test_mllm():
processor = get_processor('Qwen/Qwen2-VL-7B-Instruct')
template = get_template(processor)
template_inputs = TemplateInputs(
chosen={
'messages': [{
'role': 'system',
'content': 'AAA'
}, {
'role': 'user',
'content': '<image>BBB'
}, {
'role': 'assistant',
'content': 'CCC'
}, {
'role': 'user',
'content': 'DDD'
}],
'images': ['http://modelscope-open.oss-cn-hangzhou.aliyuncs.com/images/cat.png']
})
inputs = template.encode(template_inputs)
print(f'inputs.keys(): {inputs.keys()}')
print(template.safe_decode(inputs['input_ids']))
def _test_dataset_map(model_id: str, dataset_id: str):
tokenizer = get_processor(model_id)
template = get_template(tokenizer)
dataset = load_dataset([dataset_id], num_proc=2)[0]
# 1: 1500
# 16: 10766.36 examples/s
new_dataset = EncodePreprocessor(template)(dataset, num_proc=4)
print(f'new_dataset: {new_dataset}')
print(template.safe_decode(new_dataset[0]['input_ids']))
print(template.safe_decode(new_dataset[1]['input_ids']))
def test_llm_dataset_map():
_test_dataset_map('Qwen/Qwen2-7B-Instruct', 'AI-ModelScope/alpaca-gpt4-data-zh')
def test_mllm_dataset_map():
_test_dataset_map('Qwen/Qwen2-VL-7B-Instruct', 'modelscope/coco_2014_caption:validation#100')
if __name__ == '__main__':
test_template()
test_mllm()
test_llm_dataset_map()
test_mllm_dataset_map()
+22
View File
@@ -0,0 +1,22 @@
# Copyright (c) ModelScope Contributors. All rights reserved.
from swift.template import TemplateMeta
def test_replace_system_preserves_non_string_elements():
"""_replace_system must not drop list elements like ['bos_token_id'].
Templates such as ziya, bluelm and emu3_chat use
``prefix=[['bos_token_id'], '{{SYSTEM}}']``. When no system message is
provided the prefix is produced by _replace_system, which should keep every
non-string element intact and only strip the placeholder from strings.
"""
meta = TemplateMeta(
template_type='_test_replace_system_bug',
prefix=[['bos_token_id'], '{{SYSTEM}}'],
prompt=['{{QUERY}}'],
chat_sep=['\n'],
)
# __post_init__ moves prefix to system_prefix and builds a no-system prefix
# via _replace_system. The list element must survive.
assert any(isinstance(p, list) for p in meta.prefix), (f'_replace_system dropped the bos_token_id list; '
f'meta.prefix={meta.prefix!r}')