Chapter 04

核心概念:ModelType / Template / Dataset

📌 commit b58b1bdms-swift 200+ 模型的统一抽象

ms-swift 能"一键支持 200+ 模型"靠三个核心抽象:ModelType(哪个模型)、Template(chat 模板)、Dataset(数据格式)。本章拆开讲。

4.1ModelType:模型注册表

每个支持的模型在 swift/llm/model/ 下有一个 register 文件。看简化版:

# swift/llm/model/model/qwen.py
register_model(
    ModelMeta(
        model_type="qwen2",
        model_groups=[
            ModelGroup([
                Model("Qwen/Qwen2-7B-Instruct", "Qwen/Qwen2-7B-Instruct"),
                Model("Qwen/Qwen2-72B-Instruct", "Qwen/Qwen2-72B-Instruct"),
                ...
            ]),
        ],
        template="qwen",                # 关联 template
        get_function=get_model_tokenizer_with_flash_attn,
        architectures=["Qwen2ForCausalLM"],
    )
)

register 决定:

4.2当前支持的 ModelType(节选)

类别type
Qwen 家族qwen / qwen2 / qwen2_5 / qwen2_moe / qwen3 / qwen2_vl / qwen2_audio
LLaMA 家族llama / llama2 / llama3 / llama3_1 / llama3_2_vl
DeepSeekdeepseek / deepseek2 / deepseek_vl / deepseek_v2 / deepseek_r1
GLMchatglm2 / chatglm3 / glm4 / glm4v
InternLMinternlm / internlm2 / internlm3 / internvl2
MiniCPMminicpm / minicpm_v_2_5 / minicpm_v_2_6
Mistralmistral / mixtral / pixtral
Gemmagemma / gemma2 / paligemma
Yiyi / yi_coder / yi_vl

全部清单:swift list-models

4.3Template:chat 模板

每个 chat 模型有自己的对话格式,ms-swift 把 ~50 种格式抽象成 Template。看 swift/llm/template/template/qwen.py

register_template(
    TemplateMeta(
        template_type="qwen",
        prefix=["<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n"],
        prompt=["<|im_start|>user\n{{QUERY}}<|im_end|>\n<|im_start|>assistant\n"],
        chat_sep=["<|im_end|>\n"],
        suffix=["<|im_end|>"],
        system_prefix=["<|im_start|>system\n{{SYSTEM}}<|im_end|>\n"],
    )
)

Template 负责:

  1. 把 messages 拼接成完整 prompt;
  2. 决定哪些 token 算 loss、哪些 mask;
  3. 处理 system / user / assistant / tool 等角色;
  4. 多模态时插入 image / audio token。

4.4Dataset:数据加载

支持四种数据来源:

来源例子
魔搭 dataset_id--dataset AI-ModelScope/alpaca-gpt4-data-zh
HuggingFace dataset_idUSE_HF=1 --dataset HuggingFaceH4/no_robots
本地 jsonl / csv / json--dataset ./mydata.jsonl
多个混合--dataset ds1 ds2 ds3#5000(#5000 取前 5000 条)

本地数据格式

每行 JSON,三种格式之一:

# 1) messages 风格(推荐)
{"messages": [{"role":"user","content":"..."},{"role":"assistant","content":"..."}]}

# 2) instruction / output
{"instruction":"...","input":"...","output":"..."}

# 3) query / response
{"query":"...","response":"..."}

ms-swift 自动识别格式(看 swift/llm/dataset/preprocessor/)。

4.5三抽象的协作

--model Qwen/Qwen2.5-7B-Instruct
        │
        └─→ 在 register 里查 model_type = "qwen2_5"
                │
                └─→ 关联 template = "qwen"
                        │
                        └─→ 读 dataset,应用 template 转 input_ids
                                │
                                └─→ 喂给 Trainer 训

4.6自定义模型 / template / dataset

新模型

# 在自己代码里
from swift.llm import register_model, ModelMeta, ModelGroup, Model

register_model(ModelMeta(
    model_type="my_model",
    model_groups=[ModelGroup([Model("my/model", "my/model")])],
    template="default",
    architectures=["MyModelForCausalLM"],
))

新 template

from swift.llm import register_template, TemplateMeta

register_template(TemplateMeta(
    template_type="my_template",
    prompt=["USER: {{QUERY}}\nASSISTANT: "],
    suffix=["</s>"],
))

新数据集

实现一个 preprocessor 类,注册到 swift.llm.dataset.register_dataset。详见 swift/llm/dataset/preprocessor/core.py

4.7v4 真实模块路径速查

v4 把抽象拆到顶层,三大抽象的真实文件:

抽象v4 位置关键函数 / 类
ModelType / ModelMeta swift/model/ constant.py(212 个 ModelType 枚举)+ register.py:register_model() + model_meta.py:ModelMeta
Template / TemplateMeta swift/template/ base.py:Template(2,274 行)+ register.py:register_template() + 34 个 model 族独立文件
Dataset / DatasetMeta swift/dataset/ register.py:register_dataset() + dataset_info.json + dataset_meta.py:DatasetMeta

4.8ModelType 256 个注册的组织方式

swift/model/constant.py 把 ModelType 按"模型族"分组成嵌套类而不是平铺:

# constant.py 节选
class LLMModelType:
    qwen     = "qwen"
    qwen2    = "qwen2"
    qwen3    = "qwen3"
    llama    = "llama"
    llama3   = "llama3"
    deepseek = "deepseek"
    glm4     = "glm4"
    # ...

class MLLMModelType:
    qwen_vl       = "qwen_vl"
    qwen2_vl      = "qwen2_vl"
    qwen3_vl      = "qwen3_vl"
    internvl3     = "internvl3"
    minicpmv      = "minicpmv"
    # ...

class RMModelType:
    qwen2_reward = "qwen2_reward"
    # ...

每个 ModelType对应一份 ModelMeta,注册位置在 swift/model/model/<family>.py(qwen.py / llama.py / glm4.py / deepseek.py / ... 30+ 个文件)。"添加新模型族"就是新建 swift/model/model/<name>.py + 调 register_model()

4.9Template 256 注册的拆分

类似地 swift/template/templates/ 下有 34 个 .py 文件,每个负责一组 template:

文件注册的 template
qwen.py qwen / qwen2 / qwen3 / qwen3_5_think / qwen3_5_nothink / qwen3_6 ...
llama.py llama / llama3 / llama3_1 / llama3_2 / llama4 / ...
glm4.py glm4 / glm4_moe / glm4_5v / ...
deepseek.py deepseek / deepseek_v3 / deepseek_v3_1 / deepseek_v4 / ...
chatml.py chatml / chatml_zh / ...
vl/qwen_vl.py qwen_vl / qwen2_vl / qwen3_vl
vl/internvl.py internvl3 / internvl3_5
vl/minicpm_v.py minicpmv 系列
react.py react agent template
function_calling.pyfunction-calling 通用模板

Template 关键能力:

4.10DATASET_MAPPING 与 dataset_info.json

swift 不在代码里列 150+ 数据集,而是用一个集中 JSON 注册swift/dataset/data/dataset_info.json。schema:

{
  "my_dataset": {
    "ms_dataset_id": "AI-ModelScope/my-data",      // 魔搭仓库 ID
    "hf_dataset_id": "user/my-data",                // HF 仓库 ID(fallback)
    "dataset_path": "/local/path.jsonl",            // 本地路径(最高优先级)
    "subsets": [
      {"subset": "train", "split": ["train"], "preprocess_func": "alpaca"}
    ],
    "columns": {"input": "instruction", "output": "response"},
    "tags": ["chat", "zh"]
  }
}

swift 加载时优先级:dataset_path > ms_dataset_id(默认)> hf_dataset_idUSE_HF=1 时)。换网络环境只切环境变量,不用改训练命令

4.11preprocessor 自动识别 4 种格式

swift/dataset/preprocessor/(旧 v3 路径,v4 在 swift/dataset/ 顶层)的 AutoPreprocessor 看 dataset 列结构自动选 4 种之一:

格式关键列
Alpaca instruction / input / output 单轮 SFT
ShareGPT conversations: [{from, value}] 多轮对话
Messages messages: [{role, content}] OpenAI 风格,推荐
Multimodal 同上 + images / videos / audios VLM

所有格式都归一化到 Messages再进 template 编码。这样写新 dataset 不用纠结格式,把列名映射到上述任一种即可(YAML 字段 columns 做 mapping)。

4.12这章你需要带走的