核心概念:6 类 args / template / stage / data registry
第 3 章你看到的那份 YAML 之所以"分成 5 个区段",是因为 LLaMA-Factory 内部把所有配置切成了 6 类 dataclass,YAML 里看到的每一行都会被分发到这 6 个 args 对象里。本章先把这 6 类讲清楚,再讲三个最容易让初学者卡住的概念:template、stage、data registry。
4.1 六类 args 是什么、文件在哪
进入仓库:
ls src/llamafactory/hparams/
# data_args.py evaluation_args.py finetuning_args.py
# generating_args.py model_args.py training_args.py
# parser.py __init__.py
这 6 个 dataclass 各自负责一类配置,互不重叠:
| Args 类 | 文件 | 管什么 | YAML 典型字段 |
|---|---|---|---|
ModelArguments | model_args.py | 选模型、tokenizer、量化、信任远程代码 | model_name_or_path、trust_remote_code、quantization_bit |
DataArguments | data_args.py | 选数据集、模板、切块、cutoff | dataset、template、cutoff_len、max_samples |
FinetuningArguments | finetuning_args.py | 选训练算法 + 算法专属超参 | stage、finetuning_type、lora_rank、pref_beta、ppo_* |
TrainingArguments | training_args.py | 复用 HF Trainer 的训练循环超参 | per_device_train_batch_size、learning_rate、bf16、output_dir |
GeneratingArguments | generating_args.py | 推理 / chat / api 时的生成参数 | temperature、top_p、max_new_tokens |
EvaluationArguments | evaluation_args.py | 评测任务参数 | task、lang、n_shot |
hparams/parser.py 里的 get_train_args() / get_infer_args() / get_eval_args() 是 YAML/CLI → 这 6 个对象的统一解析入口。当你看到任何"YAML 字段不识别"的报错,第一步永远是去这 6 个文件里搜该字段名,能立刻定位它属于哪一类、默认值是什么。
TrainingArguments 是直接继承 HuggingFace transformers.TrainingArguments 的,因此你能用的字段集 = HF Trainer 全部字段 + LLaMA-Factory 加的几个。
4.2 stage:5 个训练阶段
FinetuningArguments.stage 这一个字段决定你跑哪个训练管线:
stage 值 | 干什么 | 对应代码 |
|---|---|---|
pt | 继续预训练 (Pre-Training) | src/llamafactory/train/pt/ |
sft | 监督微调 (Supervised Fine-Tuning) | src/llamafactory/train/sft/ |
rm | 奖励模型训练 (Reward Modeling) | src/llamafactory/train/rm/ |
ppo | PPO(在线 RL) | src/llamafactory/train/ppo/ |
dpo / kto / orpo / simpo | 偏好优化(具体看 pref_loss) | src/llamafactory/train/dpo/ |
记忆口诀:stage 选大方向、pref_loss 选 DPO 系内部的具体算法。
4.3 finetuning_type:怎么"动"模型
正交于 stage 的第二维:选全参 / LoRA / 冻结:
finetuning_type | 含义 |
|---|---|
full | 全参微调,更新所有权重 |
lora | LoRA 低秩微调,只更新 LoRA 矩阵(最常用) |
freeze | 冻结大部分层,只放开少数 transformer block |
加上量化 quantization_bit: 4 就是 QLoRA。
4.4 template:对话格式适配器
这是 LLaMA-Factory 最有特色、也最容易被踩坑的概念。
问题背景:每个对话模型都有自己的 prompt 拼接格式。Llama-3 用 <|begin_of_text|><|start_header_id|>user<|end_header_id|>...;Qwen 用 ChatML;ChatGLM 用 <|user|> <|assistant|>;Mistral / Yi / DeepSeek / InternLM 各有各的写法。如果你用 Llama-3 的格式去训 Qwen,模型不会报错,但会被训坏。
LLaMA-Factory 的解决:在 src/llamafactory/data/template.py 里维护一个"模板注册表"。你在 YAML 里写 template: qwen3_nothink,框架就会拿对应模板去拼接对话。
# 想看支持哪些模板,grep 一下:
grep -E "^_register_template|^register_template" \
src/llamafactory/data/template.py | head -20
template必须和model_name_or_path匹配:选错模板 = 训坏;- chat / api / export 时也要传同一个 template,否则推理结果会乱码或质量塌方。
4.5 dataset registry:data/dataset_info.json
LLaMA-Factory 不让你"指定一个 jsonl 文件路径",而是要求你先把数据集注册到 data/dataset_info.json,然后 YAML 里用注册名引用。
注册项的最简形式(见仓库 data/dataset_info.json):
{
"alpaca_en_demo": {
"file_name": "alpaca_en_demo.json"
}
}
更复杂的:
{
"glaive_toolcall_en_demo": {
"file_name": "glaive_toolcall_en_demo.json",
"formatting": "sharegpt", // alpaca 还是 sharegpt 格式
"columns": { // 列名映射
"messages": "conversations",
"tools": "tools"
}
}
}
两种内置格式:
| formatting | 典型 schema | 适合 |
|---|---|---|
alpaca | {"instruction":..., "input":..., "output":...} | 单轮 SFT 数据 |
sharegpt | {"conversations":[{"from":"user","value":...}, ...]} | 多轮对话 |
YAML 里 dataset: identity,alpaca_en_demo 这种逗号分隔写法 = 多个数据集同时喂、自动拼接。
4.6 stage / finetuning_type / template / dataset 的相互约束
这四个字段经常一起出错,记下面这张"必须同时改"清单:
- 换基座模型 →
template通常要换 - 换
template→ 数据集格式可能要换(多轮 vs 单轮) - 换
stage→ 数据集格式 必须 换:sft 用 alpaca/sharegpt、dpo 用 preference 格式、rm 用 pairwise
例子(错误诊断):你把 examples/train_lora/qwen3_lora_dpo.yaml 改成 SFT 但忘了换数据集 → dataset: dpo_en_demo 是 preference 格式,SFT 处理不了 → 启动报错 "missing field 'output'"。
4.7 launcher:CLI 到底是怎么调度的
src/llamafactory/launcher.py 的 launch() 函数大致流程:
(多卡 / DeepSpeed)"} chkTr -->|是| torchrun["用 torchrun
重新拉起 child"] chkTr -->|否| inproc["in-process 调
train.workflow.run_exp()"] sw -->|chat| cli_chat["cli_chat"] sw -->|webui| webui_app["webui_app"] sw -->|api| api_app["api_app"] sw -->|export| export_model["export_model"]
这就是为什么有的命令需要 FORCE_TORCHRUN=1:单卡时框架会跳过 torchrun,但有时即使单卡你也想用 torchrun(比如 DeepSpeed 单卡 ZeRO-Offload),就强制打开。
v1/ 目录是一套新的入口(启用环境变量 USE_V1=1),是仓库正在向 1.0 API 演进的产物,新功能会先在 v1 里出现。
4.8 一图收尾
dataset_info.json 拼数据"] FA --> PickTr["按 stage + finetuning_type
选 train/<stage>/"] TA --> Loop["HF Trainer 训练循环"] Load --> Loop DataPipe --> Loop PickTr --> Loop
记住这张图,后续配置、PEFT、DeepSpeed、多模态、加速集成等高级章节都只是在某一格里加细节。
4.9 6 类 args 的真实 dataclass 锚点
本节给"哪个字段在哪个文件的哪行定义"的查表。下次看到 YAML 字段不识别时去对应行 grep:
| dataclass | file:line | 继承 / 组合关系 |
|---|---|---|
ModelArguments | hparams/model_args.py:542 | 聚合 BaseModelArguments / QuantizationArguments / ProcessorArguments / ExportArguments / VllmArguments / SGLangArguments / KTransformersArguments 七个 mixin |
DataArguments | hparams/data_args.py:23 | 独立 dataclass;__post_init__(189) 自动启用 packing |
TrainingArguments | hparams/training_args.py:143 | 继承 HF Seq2SeqTrainingArguments(或 USE_MCA=1 时的 McaSeq2SeqTrainingArguments)+ ProfilerArguments / Fp8Arguments / RayArguments |
FinetuningArguments | hparams/finetuning_args.py:444 | 聚合 FreezeArguments / LoraArguments / OFTArguments / RLHFArguments / GaloreArguments / ApolloArguments / BAdamArgument / SwanLabArguments 八个 mixin |
GeneratingArguments | hparams/generating_args.py:22 | 独立;to_dict(obey_generation_config)(70) 过滤 HF 不认的字段 |
EvaluationArguments | hparams/evaluation_args.py | 独立 |
统一入口:hparams/parser.py 的 get_train_args() / get_infer_args() / get_eval_args()(line 304–534),内部用 HfArgumentParser([ModelArguments, DataArguments, TrainingArguments, FinetuningArguments, GeneratingArguments])。
4.10 "派生字段":YAML 里不写但运行时存在的字段
读源码经常会看到 model_args.compute_dtype 之类,但 YAML 里从来没见这个字段——它是 get_train_args() 在 line 512–519 自动算出来的:
| 派生字段 | 计算规则 |
|---|---|
model_args.compute_dtype | torch.bfloat16 if bf16 else torch.float16 if fp16 else None |
model_args.device_map | {"": get_current_device()}(单卡时) |
model_args.model_max_length | data_args.cutoff_len |
model_args.block_diag_attn | data_args.neat_packing |
finetuning_args.lora_alpha | lora_rank * 2 当用户没传时(finetuning_args.py:568) |
finetuning_args.use_ref_model | stage == "dpo" and pref_loss not in ["orpo", "simpo"](line 574) |
data_args.packing | True 当 stage == "pt"(data_args.py:189);neat_packing=True 时也自动设 True 并 cutoff_len -= 1 |
这些"看不见的派生字段"是新手最容易踩的坑:你以为只动了 bf16: true,实际上整条 dtype 链路都跟着变;改了 lora_rank 但忘了 lora_alpha——其实框架自动给你算了 2 * lora_rank。
4.11 template 注册:_register_template 真实签名
4.4 提到了 template 概念,这里展开 register 函数的真实签名(data/template.py:490 的 register_template()):
register_template(
name, # 模板名,YAML 用
format_user, # 用户消息 Formatter
format_assistant, # 助手消息 Formatter
format_system, # system 消息 Formatter
format_function, # function call Formatter
format_observation, # tool 结果 Formatter
format_tools, # tools 列表 Formatter
format_prefix, # 整段对话前缀
default_system, # 默认 system prompt
stop_words, # 额外的停止词
thought_words, # <think></think> 等思考标记
tool_call_words, # tool call 触发词
efficient_eos, # 是否把 eos_token 嵌进 slots
replace_eos, # 替换 tokenizer 的 EOS
enable_thinking,
preserve_thinking,
mm_plugin, # 多模态 plugin 对象
)
所有 Formatter 都是 StringFormatter(slots=[...]) 形式,slots 里能塞 "<|im_start|>user\n" 这种字面量,或 {"content"} 这种占位符。 line 487 的 TEMPLATES 全局 dict 是注册表,YAML template: qwen3_nothink 就是查这个 dict。
"自动从 tokenizer 的 chat_template 推 template"也支持(get_template_and_fix_tokenizer at line 630–641)—— 当 YAML 不写 template 字段时,框架会尝试解析 tokenizer 自带的 chat_template;但生产环境强烈建议写明确名字。
4.12 DatasetAttr:dataset_info.json 的真实字段
4.5 给了 dataset_info 的两个例子,下面是 data/parser.py:27 DatasetAttr 的全字段——把它和 dataset_info.json 的 JSON 对照看,你会发现 JSON 字段都是 dataclass 字段的镜像:
| 字段 | 默认 | 含义 |
|---|---|---|
load_from | — | hf_hub / ms_hub / om_hub / script / file |
dataset_name | — | HF / MS / Modelers Hub 仓库 ID 或文件名 |
formatting | "alpaca" | alpaca / sharegpt / openai |
ranking | False | 是否是 pairwise(DPO / RM)数据 |
subset | None | HF dataset 的 subset |
split | "train" | — |
folder | None | 子目录 |
num_samples | None | 采样数量上限 |
prompt / query / response | instruction / input / output | alpaca 格式列名映射 |
history / messages | None / conversations | 多轮对话字段 |
role_tag / content_tag | from / value | sharegpt 格式标签 |
user_tag / assistant_tag / system_tag / observation_tag / function_tag | human / gpt / system / observation / function_call | sharegpt 角色名 |
chosen / rejected / kto_tag | — | DPO / KTO 的偏好字段 |
images / videos / audios | — | 多模态字段名 |
"我自定义了一份数据,列名不一样要怎么用?" → 不改数据,改 dataset_info.json 的 columns 字段映射上去即可,不用动 LLaMA-Factory 任何 Python 代码。