跳转到内容

torchtune — PyTorch 官方 LLM 微调库

待复核

torchtune 是 PyTorch 官方出的”大模型后训练(post-training)库”——拿一个已经训练好的 Llama / Qwen / Mistral,再花你几张 GPU 把它调成你想要的样子。日常类比:像 pytorch-lightning 是”搬家公司”、fastai 是”半成品车”,那 torchtune 是**“已经写好的训练剧本本”**——每种微调玩法(QLoRA / 全参 / DPO)都给你一份可以直接读、直接改的 Python 训练脚本,配一份 YAML 调参。

你写:

Terminal window
tune run lora_finetune_single_device --config llama3_2/1B_lora

一行命令就拿到一个用 LoRA 微调 Llama 3.2 1B 的完整训练。背后不是黑盒——lora_finetune_single_device.py 就是一个 400 行的普通 Python 脚本,你能从头读到尾,不喜欢哪行复制一份改掉就行。

这套”recipe(脚本)+ config(YAML)“的组合,是 torchtune 跟 HuggingFace TRL / PEFT 最大的差异点。

不理解 torchtune 的设计,下面这些事都没法解释:

  • 为什么 PyTorch 团队 2024 年要再造一个轮子——HuggingFace Trainer 已经够用了,他们却故意做 Trainer 抽象
  • 为什么”研究者友好”和”开箱即用”要二选一——torchtune 选了前者,HuggingFace 选了后者
  • 为什么一份 recipe 切换 QLoRA / 全参 / DPO 不是改一个参数,而是换一个 recipe 文件——这是它对”可读性 > 复用”的取舍
  • 为什么 2025 年项目”wound down”(停止积极维护)后代码还有人在用——脚本本身就是文档,不靠官方维护也能跑

torchtune 的能力可以拆成 四块

  1. Recipe(训练剧本):每种训练任务一个独立 Python 脚本,从数据加载到 backward 全在一份文件里。不是类继承、不是 hook——就是一段你能读完的代码。

  2. Config(YAML 调参):把 recipe 的所有可调参数(lr / batch_size / model 路径 / dtype)抽进一份 YAML,CLI 用 key=value 临时覆盖。

  3. tune CLItune run <recipe> --config <yaml> 是唯一入口。tune cp 复制 recipe 到本地改,tune download 从 HuggingFace 抓权重。

  4. 内存优化套件:packed dataset、torch.compile、activation checkpoint、activation offload、8-bit optimizer。叠加用能省 ~82% 显存、提速 ~284%。

案例 1:单卡 QLoRA 微调 Llama 3.2 1B

Section titled “案例 1:单卡 QLoRA 微调 Llama 3.2 1B”
Terminal window
tune download meta-llama/Llama-3.2-1B-Instruct \
--output-dir /tmp/Llama-3.2-1B
tune run lora_finetune_single_device \
--config llama3_2/1B_qlora_single_device \
dataset.source=yahma/alpaca-cleaned \
epochs=1

逐部分解释

  • tune download ...:从 HuggingFace 拉权重到本地目录(gated 模型要先设 HF_TOKEN
  • --config llama3_2/1B_qlora_single_device:选官方 YAML——模型路径、lr、batch 都写在里面
  • dataset.source=... / epochs=1:CLI 临时覆盖 YAML,不用改文件就能换数据集
  • QLoRA = 4-bit 量化底座 + LoRA 旁路;一张 24GB 4090 跑得动 1B 级模型

案例 2:从 LoRA 切到全参——换 recipe,不是换参数

Section titled “案例 2:从 LoRA 切到全参——换 recipe,不是换参数”
Terminal window
# LoRA:只更新少量旁路矩阵,显存省
tune run lora_finetune_distributed --config llama3_1/8B_lora
# 全参:更新所有权重,通常要 8 卡 A100
tune run full_finetune_distributed --config llama3_1/8B_full

逐部分解释

  • 注意 recipe 名:lora_finetune_* vs full_finetune_*——是两份独立脚本,不是同一个脚本里翻开关
  • 设计取舍:与其在 1500 行全能循环里塞 if lora,不如各写各的、各读各的
  • 你要改训练逻辑时:tune cp 复制对应 recipe,改约 100 行即可
Terminal window
# 数据每行大致是:prompt + chosen(更好回答)+ rejected(更差回答)
tune run lora_dpo_single_device --config llama3_1/8B_lora_dpo

逐部分解释

  • DPO(Direct Preference Optimization)= 用”更好/更差”成对回答教模型偏好,不另训 reward model
  • 数据必须自备 chosen / rejected 字段;普通指令微调数据集(只有 instruction/output)直接跑会报字段缺失
  • loss 和普通 LoRA recipe 不同——所以 torchtune 新开一份 lora_dpo_* recipe;点开就能看到完整 DPO loss,不用翻继承链
  1. CLI override 用 = 不是空格tune run xxx --config yyy epochs=3 对,tune run xxx --config yyy epochs 3 错。Hydra 风格语法,新人易混。

  2. tune download 下载失败常是 HuggingFace token 没设HF_TOKEN=hf_xxx tune download ...,否则 Llama 这种 gated 模型直接 401。

  3. recipe 找不到模型路径:YAML 里 tokenizer.path / checkpointer.checkpoint_dir 经常和实际下载路径不一致——tune download --output-dir /a 但 config 默认 /tmp/Llama-...,要么改 config 要么用 CLI 覆盖。

  4. FSDP2 比 FSDP1 新但 bug 也新:torchtune 默认 FSDP2,遇到 _unflatten_params 之类奇怪错误时降到单卡先排查问题。

  5. 2025 年起项目 wound down:官方说不再积极维护。代码能跑、社区 fork 在续,但新模型支持要靠你自己加——把它当”高质量参考实现”用,比当”长期维护的库”用更稳。

  6. packed dataset 不是默认开:YAML 里 dataset.packed=True 能把多条短样本拼成一条长序列,提速 ~135%,但它需要 tokenizer.max_seq_len 一起配置;忘了配会原样跑、白白浪费 GPU。

  7. activation offload + activation checkpoint 不同:前者把激活值搬到 CPU(省 GPU 显存、慢),后者重算激活值(省显存、慢但不靠总线)。同时开等于既慢又乱,按显存压力二选一。

适用

  • 想看清楚训练循环每一步、想改 backward 顺序的研究者
  • 已经熟 pytorch 训练循环、不想再学一层 Trainer 抽象
  • 单机 / 多机 GPU 微调主流开源 LLM(Llama / Qwen / Mistral / Gemma / Phi)
  • 把 recipe 当模板——复制一份改成自己的训练流程

不适用

  • 完全不想读 PyTorch 训练循环 → 用 HuggingFace Trainer / transformers.Trainer 更省心
  • 需要图形化实验管理 / 自动超参搜索 → 用 pytorch-lightning + Lightning AI 平台或 wandb sweeps
  • 要训练 vision / 推荐 / 时序模型 → torchtune 只做 LLM,跨域用 fastai 或裸 pytorch
  • 需要长期维护承诺的生产管线 → 项目已 wound down,关键路径慎用
  • 2024-04:PyTorch 官方在 PyTorch Conf 上首发 torchtune,定位”PyTorch-native LLM 微调”
  • 2024 年中:陆续支持 Llama 3 / Mistral / Gemma 2 / Qwen 2,引入 FSDP2 / torch.compile
  • 2024-12:DPO / PPO / 知识蒸馏 / 量化感知训练 (QAT) recipe 全部到位
  • 2025 年初:积累 150+ 贡献者、5.8k stars
  • 2025 年:项目 wound down——PyTorch 团队公开表示停止积极开发,但仓库保留、社区可 fork

短短一年从首发到 wound down——既见证了 LLM 微调工具的快速演进,也提示工具选型时**“官方”不等于”长期”**。

  1. 抽象不是越多越好——torchtune 故意不做 Trainer,研究者要的是”我能改每一行”,不是”我什么都不用写”
  2. recipe-as-script 是一种刻意的设计——比起”一套配置切所有玩法”,“一种玩法一份脚本”对可读性更友好
  3. YAML override 替代代码改动——跑实验时 95% 改的是超参,CLI 覆盖比改代码安全
  4. 官方 ≠ 长青——选 LLM 工具栈时除了功能,还要看维护承诺;torchtune 的 wound down 是个提醒
  5. PyTorch 生态分层pytorch 张量 / autograd → torchtune 训练剧本 → HuggingFace Hub 模型权重;每层职责清晰
  6. 可读性也是一种性能——研究者节省的不是 GPU 时间,是”读懂别人代码”的时间。recipe 短小自含 = 复现快
  • pytorch —— torchtune 是它官方的 LLM 后训练栈,所有张量 / autograd / FSDP 都直接用 PyTorch 原生 API
  • pytorch-lightning —— Lightning 把训练循环封装成 Trainer;torchtune 反其道而行——故意暴露完整循环
  • fastai —— fastai 用 Learner 抽象,torchtune 用 recipe 脚本;都站在 PyTorch 上但抽象哲学相反
  • trl —— HuggingFace 的 LLM 后训练库,走 Trainer 路线;和 torchtune 的 recipe 路线对照着读最清楚
  • accelerate —— 设备/分布式抽象层;torchtune 多卡主要靠 PyTorch FSDP2,思路不同但解决同一类问题
  • accelerate —— Accelerate — HuggingFace 设备/分布式抽象
  • axolotl —— Axolotl — YAML 驱动 LLM 微调
  • deepspeed —— DeepSpeed — 微软分布式训练库
  • fastai —— fastai — 三行代码做迁移学习
  • megatron-lm —— Megatron-LM — NVIDIA 张量并行库
  • trl —— TRL — RLHF / DPO / GRPO 训练库
  • unsloth —— Unsloth — 微调 2-5x 加速