Chapter 10
实战:训一个 Hermes 风格对话模型
NousResearch Hermes 系列是英文社区最受欢迎的对话模型之一,base 用 Llama-3 / Qwen2.5,数据用 Hermes 自家清洗的 SFT mix。本章复现一个简化版。
10.1Hermes 配方关键点
- base:Llama-3.1-8B / Qwen2.5-7B;
- chat 格式:ChatML(
<|im_start|>...<|im_end|>); - 数据:Hermes 系自家 1M+ 条 SFT,覆盖通用 / 推理 / function call / 角色扮演;
- 训练:全参微调 3 epoch;
- 对齐:可选 + DPO(用 Hermes preference data)。
10.2SFT 阶段 YAML
# hermes_sft.yml
base_model: meta-llama/Meta-Llama-3.1-8B
tokenizer_type: AutoTokenizer
chat_template: chatml # ★ Hermes 用 ChatML
datasets:
- path: teknium/OpenHermes-2.5 # Hermes 公开数据
type: chat_template
chat_template: chatml
field_messages: conversations
message_field_role: from
message_field_content: value
roles:
user: [human, user]
assistant: [gpt, assistant]
system: [system]
dataset_prepared_path: ./prepared_hermes
val_set_size: 0.005
sequence_len: 8192
sample_packing: true
pad_to_sequence_len: true
adapter: lora # 显存够可改 ""(全参)
lora_r: 64
lora_alpha: 128
lora_target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- up_proj
- down_proj
lora_modules_to_save: # ChatML 加了新 special token,必须训
- embed_tokens
- lm_head
micro_batch_size: 2
gradient_accumulation_steps: 8
num_epochs: 3
learning_rate: 1e-4
optimizer: adamw_torch_fused
lr_scheduler: cosine
warmup_ratio: 0.03
weight_decay: 0.0
max_grad_norm: 1.0
bf16: auto
tf32: true
flash_attention: true
gradient_checkpointing: true
deepspeed: deepspeed_configs/zero2.json
output_dir: ./out_hermes_sft
logging_steps: 10
save_steps: 500
save_total_limit: 3
evaluation_strategy: steps
eval_steps: 500
wandb_project: hermes-clone
wandb_name: llama3.1-8b-sft
10.3启动 SFT(8 卡)
accelerate launch -m axolotl.cli.train hermes_sft.yml --num-processes 8
时间预算:OpenHermes-2.5 约 1M 样本,8×A100-80GB、3 epoch ≈ 36-48 小时。
10.4DPO 阶段(可选)
# hermes_dpo.yml
base_model: ./out_hermes_sft # 用 SFT 结果起步
rl: dpo
rl_beta: 0.1
datasets:
- path: argilla/distilabel-capybara-dpo-7k-binarized
type: chatml.argilla # 数据格式跟 base 一致
split: train
sequence_len: 4096
adapter: lora
lora_r: 32
lora_target_modules: [q_proj,k_proj,v_proj,o_proj]
micro_batch_size: 1
gradient_accumulation_steps: 8
num_epochs: 1
learning_rate: 5e-7
optimizer: adamw_torch
lr_scheduler: cosine
warmup_ratio: 0.03
bf16: auto
flash_attention: true
gradient_checkpointing: true
deepspeed: deepspeed_configs/zero2.json
output_dir: ./out_hermes_dpo
时间预算:~8 小时 8×A100。
10.5合并 + 评估
# 合并 LoRA
axolotl merge-lora hermes_dpo.yml --lora_model_dir ./out_hermes_dpo
# 用 lm-eval-harness 评估
lm_eval --model hf \
--model_args pretrained=./out_hermes_dpo/merged \
--tasks mmlu,arc_easy,hellaswag,truthfulqa \
--batch_size 8
10.6推理 / 部署
# 单机测试
axolotl inference hermes_dpo.yml --lora_model_dir ./out_hermes_dpo
# 生产用 vLLM
vllm serve ./out_hermes_dpo/merged --port 8000
10.7成本
| 阶段 | 耗时 | 云成本 ($20/h 8 卡) |
|---|---|---|
| SFT 3 epoch(OpenHermes-2.5) | ~40 h | ~$800 |
| DPO 1 epoch(7k pairs) | ~8 h | ~$160 |
| 合并 + 评估 | ~3 h | ~$60 |
| 总 | ~51 h | ~$1,020 |
10.8性能加速三件套:multipack / Liger / cut_cross_entropy
Hermes 流水训得快的关键不是硬件,是这三个开关组合:
| 特性 | YAML 字段 | 原理 / 收益 |
|---|---|---|
| Sample Packing (multipack) | sample_packing: true + pad_to_sequence_len: true | 多条短样本拼到 seq_len,省 padding 浪费;典型 +30-50% 训练速度 |
| Liger Kernels | plugins: [axolotl.integrations.liger.LigerPlugin] | Triton fused RMSNorm / RoPE / SwiGLU / 交叉熵;峰值显存 -60% + 速度 +20% |
| Cut Cross Entropy | plugins: [axolotl.integrations.cut_cross_entropy.CutCrossEntropyPlugin] | 分块计算 lm_head logits + CE,避免 batch × seq × vocab 张量;省 70% 峰值显存 |
| 三连组合 | 都开 | 实测 Llama-3-8B SFT 提速 2-3×,OOM 边界往后挪一档 |
10.9sample_packing 的两条实现路径
开 sample_packing 时 Axolotl 内部会按"是否开 flash_attn"挑路径(来源 monkeypatch/multipack/):
| 配置 | 实际走的实现 |
|---|---|
sample_packing + flash_attention | Flash-attn 自带的 cu_seqlens(最快,无 mask 开销) |
sample_packing + 不开 flash_attention | 用 4D block-diag attention mask;速度慢一档,但任何 attention backend 都能跑 |
neat_packing(旧名) | v2025 之前的名字;现在统一叫 sample_packing |
"为什么我开了 sample_packing 没看到提速?"答:没配 flash-attn,packing 的 mask 开销吃掉了打包的收益。
10.10新优化器:Muon / Adam-mini / BAdam
2025-Q4 之后 Axolotl 跟进了一波新优化器。来源 schemas/enums.py CustomOptimizers:
| optimizer 值 | 含义 |
|---|---|
adamw_torch(默认) | HF 标准 |
adamw_bnb_8bit | BNB 8-bit Adam(QLoRA 必配) |
paged_adamw_8bit | QLoRA paged 优化器 |
adamw_torch_fused | PyTorch 2.x fused 算子 |
muon | 2025-04 引入,Newton-Schulz 风格二阶,2D 权重适用 |
distributed_muon | FSDP2 友好版 Muon(2025-12 加入) |
adam_mini | 2024-Q4 论文;省一半优化器状态 |
badam | 块坐标 Adam,省更多 |
galore_adamw / apollo_adamw | 低秩梯度优化 |
"长训练省显存"首选 Muon;"小模型快收敛"留 adamw_bnb_8bit。
10.11这章你需要带走的
- Hermes 风格 = ChatML + 大量 SFT + 可选 DPO;
- ChatML 加了 special token,
lora_modules_to_save必须包含 embed_tokens 和 lm_head; - 跨阶段一致:DPO 数据 type 用
chatml.*系列; - 3 epoch SFT + 1 epoch DPO 是大多数复刻配方的起点。