三份 YAML 逐行对照:字段是怎么串成一条闭环的
本文所有事实以
hiyouga/LlamaFactory官方仓库 2026-08-09 的内容为准。我们没有安装、训练或部署过任何模型,文中所有字段与取值都是仓库里 YAML 文件的原文。
LlamaFactory 的 README Quickstart 只给了三条命令。三条命令分别指向三份 YAML,而这三份 YAML 在仓库里放在三个不同的目录下、恰好同名。很多人是分别打开、分别照抄的——于是也就分别改错。
真正值得花十分钟的做法是把它们并排摆开逐行读一遍。因为这三份文件的字段不是三套互不相干的配置,而是一条链:训练那份写下的某几个值,会被后面两份原样引用。看懂了引用关系,你就知道改哪一处必须同步改哪几处;看不懂,就只能靠报错来发现。
先定位这三份文件
它们不在同一个目录里。examples/ 下的目录树是这样分的:
examples/
README.md README_zh.md
accelerate/ ascend/ deepspeed/ extras/ inference/ ktransformers/
megatron/ megatron_bridge/ merge_lora/ train_full/ train_lora/ train_qlora/ v1/
本文要对照的三份,分别是 examples/train_lora/qwen3_lora_sft.yaml、examples/inference/qwen3_lora_sft.yaml、examples/merge_lora/qwen3_lora_sft.yaml。三个目录下都有一个叫 qwen3_lora_sft.yaml 的文件,文件名一模一样,内容完全不同——这是第一个容易搞混的地方,粘贴路径时看清中间那一级目录名。
对应的三条命令,README 原文是:
llamafactory-cli train examples/train_lora/qwen3_lora_sft.yaml
llamafactory-cli chat examples/inference/qwen3_lora_sft.yaml
llamafactory-cli export examples/merge_lora/qwen3_lora_sft.yaml
字段并集:谁出现在哪一份里
先不看具体取值,只看字段在三份文件里的出没情况。这张表是我们把三份 YAML 逐行对照数出来的:
| 字段 | 训练 | 推理 | 合并导出 |
|---|---|---|---|
model_name_or_path | 有 | 有 | 有 |
template | 有 | 有 | 有 |
trust_remote_code | 有 | 有 | 有 |
adapter_name_or_path | 无 | 有 | 有 |
output_dir | 有 | 无 | 无 |
stage / finetuning_type / lora_rank / lora_target | 有 | 无 | 无 |
dataset / cutoff_len / max_samples | 有 | 无 | 无 |
infer_backend | 无 | 有 | 无 |
export_dir / export_size / export_device / export_legacy_format | 无 | 无 | 有 |
这张表要读出三层意思。
第一层:三份共有的只有三个字段——model_name_or_path、template、trust_remote_code。它们描述的是”这是哪个模型、按什么模板拼对话、要不要信任远程代码”,属于全程不变的身份信息。
第二层:adapter_name_or_path 出现在后两份、不出现在训练那份。 原因在字段语义本身:训练阶段适配器还不存在,是产出物;推理和合并阶段它是输入。
第三层:真正的一次性字段集中在两端。 训练那份独占数据与方法相关的一整片(stage、finetuning_type、lora_rank、lora_target、dataset、cutoff_len、max_samples 等),合并那份独占 export_* 一族。中间的推理配置反而最瘦——全文只有 5 行。
四个标识符把三份文件锁成一条链
把取值填回去,链路就浮出来了。三份 YAML 共享的是这四组值:
- 同一个基座:
model_name_or_path: Qwen/Qwen3-4B-Instruct-2507,三份里一字不差。 - 同一个模板:
template: qwen3_nothink,三份里也一字不差。 - 训练的产出目录变成后两份的输入:训练配置写
output_dir: saves/qwen3-4b/lora/sft,推理和合并配置写的是adapter_name_or_path: saves/qwen3-4b/lora/sft——同一个路径字符串,换了个字段名。 - 合并的落点是新的一处:
export_dir: saves/qwen3_sft_merged。
这就是这条链的全部粘合剂。README 把”训练 → 推理 → 合并导出”抬到 Quickstart 位置,靠的就是这四组值严格对齐。反过来说,你改动其中任何一处而没有同步另外几处,链就断在那里:
- 换基座模型,三份里的
model_name_or_path都要改; - 改
template,训练和推理两侧必须一致,合并那份里也写着同一个值。这一条不是我们的建议,是三份示例文件本身就这么写的。至于qwen3_nothink这个名字里的_nothink后缀是什么规则,我们另有一篇专门讲; - 改训练的
output_dir,推理和合并的adapter_name_or_path就得跟着改成同一个新值。
训练那份:五个块,外加一个被注释掉的块
examples/train_lora/qwen3_lora_sft.yaml 用 ### 注释把自己切成了几段:### model、### method、### dataset、### output、### train,一共五个生效的块,然后是第六个块 ### eval——它整块都被 # 注释掉了。
被注释掉的那五行原文是 eval_dataset、val_size、per_device_eval_batch_size、eval_strategy、eval_steps。也就是说,这份示例默认不做验证集评估,跟 data_args.py 里 val_size 默认 0.0 是一致的。这一点值得单独记一下,因为很多人跑完发现日志里没有 eval 曲线,以为是哪里配错了——它本来就没开,注释掉的这几行就是开关所在。
其余几个块里,几个值得对照着看的取值:
dataset: identity,alpaca_en_demo——用逗号分隔多个数据集,这里同时挂了两个;max_samples: 1000——这是一份演示用配置,只取 1000 条样本;lora_rank: 8、lora_target: all、finetuning_type: lora、stage: sft;cutoff_len: 2048;per_device_train_batch_size: 1和gradient_accumulation_steps: 8写在两行里,是有效批大小的两个因子;learning_rate: 1.0e-4、num_train_epochs: 3.0、lr_scheduler_type: cosine、warmup_ratio: 0.1、bf16: true;preprocessing_num_workers: 16与dataloader_num_workers: 4——这是两个不同的并行度,名字长得像但管的不是同一件事,改的时候别当成一个;ddp_timeout: 180000000——一个非常大的数。单位见 transformers 那边的定义,我们没有核实过,所以不换算、也不推断它等于多久;report_to: none,注释里直接列出了全部可选值[none, wandb, tensorboard, swanlab, mlflow]。
需要说清楚的是:上面这些数字是这份示例文件里写的值,不是推荐值。lora_rank 该设 8 还是别的、learning_rate 该多少、num_train_epochs 跑几轮,取决于你的数据和硬件,官方没有给通用值,我们也没有训练过任何模型,不会替你填。这份 YAML 的价值在于它是一份跑得通的、字段名正确的骨架,不在于它的每个数值适合你。
推理那份:为什么只有 5 行
examples/inference/qwen3_lora_sft.yaml 全文只有 5 行:
model_name_or_path: Qwen/Qwen3-4B-Instruct-2507
adapter_name_or_path: saves/qwen3-4b/lora/sft
template: qwen3_nothink
infer_backend: huggingface # choices: [huggingface, vllm, sglang, ktransformers]
trust_remote_code: true
对照上面那张字段表,这 5 行正好是”身份三件套 + 适配器路径 + 后端选择”。没有数据、没有方法、没有超参——推理阶段这些都不需要,训练时的选择已经固化进适配器里了。
唯一属于这一份的字段是 infer_backend,示例里写的取值是 huggingface(源码层面这个字段的默认值写作 EngineName.HF),四个可选值 [huggingface, vllm, sglang, ktransformers] 就写在同一行的注释里。这四个后端各自要装什么、各自的差异如何,本文的事实范围内没有依据,不展开。
合并那份:首行是一条全大写的禁令
examples/merge_lora/qwen3_lora_sft.yaml 打开第一行不是配置,是一句注释:
### Note: DO NOT use quantized model or quantization_bit when merging lora adapters
原文用的是全大写的 DO NOT——合并 LoRA 适配器时不要使用量化模型或 quantization_bit。这句话我们原样引用,不改写成”建议不要”,也不替它解释背后的机制,因为文件里没写。它被放在整份文件的第一行、放在任何配置项之前,位置本身就说明了它的分量。
这份文件的其余部分分成 ### model 和 ### export 两块。model 块里是身份三件套加 adapter_name_or_path;export 块四行:
export_dir: saves/qwen3_sft_merged——合并产物的落点,是这条链上唯一的新路径;export_size: 5——这个值与源码里的默认值一致;export_device: cpu,注释里给了两个可选值[cpu, auto];export_legacy_format: false。
注意这里的 template: qwen3_nothink 又出现了一次。合并这一步同样带着模板走,三份文件在这个字段上是完全一致的。
关于 trust_remote_code: true
三份示例 YAML 里都写着 trust_remote_code: true。这是仓库示例文件的原文,我们如实转述。这个开关在源码层面的默认值是多少、与示例文件写的是否一致,我们另有一篇专门讲参数层次的文章。要不要在你的环境里打开它,取决于你对模型来源的信任程度和你所在组织的规定,本文不给结论。
这三份之外的目录,我们没读过
examples/ 下还有 accelerate/、ascend/、deepspeed/、ktransformers/、megatron/、megatron_bridge/、v1/ 这些目录,以及 train_full/、train_qlora/。仓库为这些后端和训练方式各准备了独立的示例目录,这是目录树上的事实;但里面每一份 YAML 的具体内容我们没有逐一读过,所以本文不描述它们。
另外有一处结构性的对应关系值得一提:examples/extras/ 下有 18 个子目录,与 finetuning_args.py 里的一批算法开关几乎一一对应——换句话说,每个高级算法都配了一份可跑的示例配置。这个对应关系是从两处文件名交叉读出来的(这 18 个目录逐一对应哪些开关,我们另有一篇专门讲配方矩阵的文章);至于这些算法各自是什么、效果如何,我们没有读过它们的实现,不做任何描述。
说这一条,是因为它能改变你读本文这三份 YAML 的方式:三份主线配置是”骨架 + 一条闭环”,而 extras/ 里的每一份都是在这个骨架上多加几个字段。你把主线这三份的字段归属关系吃透了,再去看任何一份 extras 配置,都能一眼分出哪些是骨架里就有的、哪些是那个算法自己带来的新字段。
落到操作上
如果你要把这三份配置改成自己的,最省事的顺序是先定四个标识符,再填其它:
- 定
model_name_or_path,三份同步; - 定
template,三份同步; - 定训练的
output_dir,然后把这个值抄进另外两份的adapter_name_or_path; - 定
export_dir; - 剩下的数据、方法、超参只在训练那份里改;
infer_backend只在推理那份里改;export_*只在合并那份里改。
改完之后怎么确认没串错?最直接的办法是把三份文件并排打开,只核对上面那四组值是不是字符串级别相等。这四处是三份文件之间仅有的共享点,也就是唯一需要人工保持同步的地方;除此之外的字段各管各的,改错了只会影响它所在的那一份。
至于每个参数具体该设成多少,前面已经说过:取决于你的数据和硬件,官方没给通用值,我们没有实测数据,也不替你猜。
本文依据 LlamaFactory 官方仓库(github.com/hiyouga/LlamaFactory)的 README、data/README.md、examples/ 下的配置与 src/llamafactory/hparams/ 的参数定义整理,核对日 2026-08-09。本文内容为仓库源码与文档口径,我们没有安装、训练或部署过任何模型,文中显存数字均为官方标注的估算值(README 原文标 * estimated)而非实测占用。参数与默认值随版本变动,请以 llamafactory-cli train -h 的实际输出为准。安全相关做法请结合自身环境评估,本文不构成安全方案建议。