【大模型12步学习路线 · 第10步 · ②代码篇】LLM 微调实战:Unsloth / Axolotl / LLaMA-Factory + DPO + 微调 retriever 全栈
系列定位:「大模型正确学习顺序」12 步系列第 10 步 · 微调的 ②代码篇。
前置阅读:①原理篇 —— PEFT 全谱 + LoRA 超参手册。
本篇产出:4 大微调框架对比 + Unsloth 5 分钟 QLoRA + Axolotl YAML + LLaMA-Factory Web UI + TRL DPO +BGE-M3 retriever 对比学习微调+ vLLM/SGLang 加载 LoRA + W&B 监控。
🚀 0. 4 大微调框架对比表
| 框架 | 速度 | VRAM 优化 | UI | 学习曲线 | 主要场景 | GitHub ★ |
|---|---|---|---|---|---|---|
| Unsloth | 2× HF Trainer | 最强 | Python API | 低 | 单 GPU 极致优化 | 30k+ |
| Axolotl | 标准 | 中 | YAML | 中 | 多 GPU + community 默认 | 9k+ |
| LLaMA-Factory | 标准 | 中 | Web UI | 极低 | 100+ 模型,中文友好 | 50k+ |
| TorchTune | 标准 | 中 | Python | 高 | Meta 出品,PyTorch native | 5k+ |
| TRL | 标准 | 低 | Python | 中 | DPO/RLHF/ORPO 官方 | 12k+(HF) |
💎Veri-Copilot 推荐组合:Unsloth(SFT)+ TRL(DPO)—— Unsloth 速度最快,TRL 是 DPO/GRPO 等偏好对齐的官方实现。
🦥 1. Unsloth 5 分钟 QLoRA(Qwen-Coder-7B,RTX 4090)
1.1 安装
pipinstall-Uunsloth# Unsloth 自带优化的 transformers / trl / peft / bitsandbytes1.2 完整训练脚本
# train_sva_lora.pyfromunslothimportFastLanguageModelfromdatasetsimportload_datasetfromtrlimportSFTTrainerfromtransformersimportTrainingArguments# === 1) 加载 4-bit 量化模型 ===model,tokenizer=FastLanguageModel.from_pretrained(model_name="Qwen/Qwen2.5-Coder-7B-Instruct",max_seq_length=4096,dtype=None,# auto 检测load_in_4bit=True,# QLoRA 关键!)# === 2) 挂 LoRA(必看:target_modules 选择最关键)===model=FastLanguageModel.get_peft_model(model,r=32,# rank,代码任务 16-32 甜点target_modules=[# ✅ 必须挂所有 attn + FFN"q_proj","k_proj","v_proj","o_proj",# attention"gate_proj","up_proj","down_proj",# FFN/MLP],lora_alpha=64,# = 2 × rlora_dropout=0,bias="none",use_gradient_checkpointing="unsloth",# Unsloth 优化版random_state=42,)# === 3) 准备 SVA 训练集 ===# 格式:{"instruction": ..., "input": ..., "output": ...}dataset=load_dataset("json",data_files="./data/sva_sft_train.jsonl",split="train")ALPACA_PROMPT="""### Instruction: {instruction} ### Input: {input} ### Response: {output}"""EOS=tokenizer.eos_tokendefformat_fn(examples):texts=[ALPACA_PROMPT.format(instruction=i,input=ip,output=o)+EOSfori,ip,oinzip(examples["instruction"],examples["input"],examples["output"])]return{"text":texts}dataset=dataset.map(format_fn,batched=True)# === 4) 训练 ===trainer=SFTTrainer(model=model,tokenizer=tokenizer,train_dataset=dataset,dataset_text_field="text",max_seq_length=4096,args=TrainingArguments(per_device_train_batch_size=2,gradient_accumulation_steps=8