关于 unsloth-training
unsloth-training 是面向使用 Unsloth 微调大模型的开发者指南,涵盖 GRPO、SFT 和视觉训练,也提供环境设置、故障排查以及模型导出和部署路径。
主要功能
- 01提供 GRPO 和 SFT 训练指导
- 02说明视觉模型微调方法
- 03配置 FP8 训练和数据打包
- 04排查训练问题并设计奖励函数
- 05将模型导出为 GGUF 等格式
适用场景
- 01使用奖励函数微调模型
- 02用输入输出样例训练模型
- 03微调视觉语言模型
- 04准备将训练后的模型部署到移动设备
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scientiacapital/ skills --skill unsloth-training安装后在 Claude Code 中输入/unsloth-training确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.jsonreference/advanced-training.mddeployment.mddomain-examples.mdexport-formats.mdfp8-training.mdhyperparameters.mdmobile-deployment.mdreward-design.mdtroubleshooting.mdvision-training.mdreference/grpo/basic_grpo.pyhyperparameters.pyreward_functions.pyreference/sft/generate_training_data.pysales_extractor_training.pyseed_examples.json详细介绍
- GRPO - 使用奖励函数进行 RL(无需标注输出)
- SFT - 使用输入/输出对进行监督微调
- Vision - VLM 微调(Qwen3-VL、Gemma3、Llama 3.2 Vision)
主要功能:
- FP8 Training - 显存占用减少 60%,速度提升 1.4 倍(RTX 40+、H100)
- 3x Packing - 自动加速 2-5 倍,适用于长度混合的数据
- Docker - 官方
unsloth/unsloth镜像 - Mobile - QAT → ExecuTorch → iOS/Android(约 40 tok/s)
- Export - GGUF、Ollama、vLLM、LM Studio、SGLang
<quick_start> 使用 FP8 进行 GRPO(显存占用减少 60%):
import os
os.environ['UNSLOTH_VLLM_STANDBY'] = "1" # Shared memory
from unsloth import FastLanguageModel
from trl import GRPOConfig, GRPOTrainer
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3-8B",
max_seq_length=2048, load_in_fp8=True, fast_inference=True,
)
model = FastLanguageModel.get_peft_model(
model, r=64,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
use_gradient_checkpointing="unsloth",
)
def correctness_reward(completions, answer, **kwargs):
return [2.0 if extract_answer(c) == a else 0.0
for c, a in zip(completions, answer)]
trainer = GRPOTrainer(
model=model,
args=GRPOConfig(num_generations=4, beta=0.04, learning_rate=5e-6),
train_dataset=dataset, reward_funcs=[correctness_reward],
)
trainer.train()
使用 Packing 进行 SFT(速度提升 2-5 倍):
from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
model=model, train_dataset=dataset, processing_class=tokenizer,
args=SFTConfig(
per_device_train_batch_size=2, num_train_epochs=3,
learning_rate=2e-4, packing=True, # 2-5x speedup
),
)
trainer.train()
</quick_start>
<success_criteria> 满足以下条件即表示训练成功:
- 模型加载时没有 OOM 错误
- 奖励(GRPO)或损失(SFT)呈改善趋势
- 生成的输出符合预期格式
- 模型已导出为所需格式(LoRA、合并模型、GGUF)
- 测试推理能生成合理的输出 </success_criteria>
<activation_triggers> 显式触发词:
/unsloth grpo- GRPO(RL)训练/unsloth sft- SFT 训练/unsloth fp8- FP8 训练设置/unsloth vision- VLM 微调/unsloth mobile- 手机部署(QAT)/unsloth docker- Docker 容器设置/unsloth troubleshoot- 调试问题
自然语言:
- “使用 GRPO 训练”、“微调”、“奖励函数”
- “FP8 训练”、“fp8”、“更少显存”
- “视觉微调”、“VLM”、“图像训练”
- “手机部署”、“移动端 LLM”、“ExecuTorch”
- “docker 训练”、“容器”、“unsloth docker”
- “packing”、“更快的训练”、“500k 上下文”
- “导出 GGUF”、“Ollama”、“vLLM”、“SGLang” </activation_triggers>
<file_locations> 核心参考资料:
reference/reward-design.md- 奖励函数模式reference/domain-examples.md- 语音 AI、销售 Agent 示例reference/hyperparameters.md- GRPOConfig 参考reference/troubleshooting.md- 常见问题修复方法
新功能参考资料:
reference/fp8-training.md- FP8 设置、显存节省reference/deployment.md- Docker、vLLM、LoRA 热切换、SGLangreference/export-formats.md- GGUF、Ollama、LM Studio、Dynamic 2.0reference/advanced-training.md- 500K 上下文、packing、检查点reference/vision-training.md- VLM 微调reference/mobile-deployment.md- QAT、ExecuTorch、iOS/Android
代码示例: reference/grpo/、reference/sft/
</file_locations>
<core_concepts>
何时使用 GRPO 或 SFT
| 方法 | 适用场景 | 所需数据 |
|---|---|---|
| GRPO | 提升推理质量 | 提示词 + 可验证的答案 |
| GRPO | 根据偏好调整行为 | 奖励函数 |
| GRPO | 能够验证正确性时 | 可验证的输出 |
| SFT | 教授特定的输出格式 | 输入/输出对 |
| SFT | 遵循新指令 | 对话示例 |
| SFT | 学习领域知识 | 标注示例 |
模型选择
| 模型 | 大小 | 显存 | 用途 |
|---|---|---|---|
unsloth/Qwen2.5-0.5B-Instruct | 0.5B | 5GB | 移动端部署(约 200MB GGUF) |
unsloth/Qwen2.5-1.5B-Instruct | 1.5B | 5GB | 学习/原型开发 |
Qwen/Qwen2.5-3B-Instruct | 3B | 8GB | 良好的平衡(推荐从此开始) |
unsloth/Qwen2.5-7B-Instruct | 7B | 16GB | 生产级质量 |
unsloth/Phi-4 | 14B | 20GB | 强大的推理能力 |
核心超参数
GRPO(RL):
GRPOConfig(
num_generations=4, # Completions per prompt (2-8)
beta=0.04, # KL penalty (0.01-0.1)
learning_rate=5e-6, # 10x smaller than SFT!
max_completion_length=512,
max_steps=300, # Minimum for results
)
SFT:
TrainingArguments(
learning_rate=2e-4, # Standard SFT rate
num_train_epochs=3, # 2-4 typical
per_device_train_batch_size=2,
)
</core_concepts>
<reward_functions>
奖励函数设计
奖励函数是 GRPO 的核心。对于每个补全内容,奖励函数都会返回一个浮点数列表。
模式 1:正确性(主要信号)
def correctness_reward(completions, answer, **kwargs):
"""
+2.0 for correct answer, 0.0 otherwise.
This should be your highest-weighted reward.
"""
rewards = []
for completion, true_answer in zip(completions, answer):
extracted = extract_answer(completion)
try:
pred = float(extracted.replace(",", "").strip())
true = float(true_answer.replace(",", "").strip())
reward = 2.0 if abs(pred - true) < 0.01 else 0.0
except ValueError:
reward = 2.0 if extracted.strip() == str(true_answer).strip() else 0.0
rewards.append(reward)
return rewards
模式 2:格式合规性
def format_reward(completions, **kwargs):
"""
+0.5 for proper XML structure with reasoning and answer tags.
"""
rewards = []
for completion in completions:
has_reasoning = bool(re.search(r"<reasoning>.*?</reasoning>", completion, re.DOTALL))
has_answer = bool(re.search(r"<answer>.*?</answer>", completion, re.DOTALL))
if has_reasoning and has_answer:
rewards.append(0.5)
elif has_answer:
rewards.append(0.2)
else:
rewards.append(0.0)
return rewards
模式 3:推理质量
def reasoning_length_reward(completions, **kwargs):
"""
+0.3 for substantive reasoning (30-200 words).
"""
rewards = []
for completion in completions:
reasoning = extract_reasoning(completion)
word_count = len(reasoning.split()) if reasoning else 0
if 30 <= word_count <= 200:
rewards.append(0.3)
elif 15 <= word_count < 30:
rewards.append(0.1)
else:
rewards.append(0.0)
return rewards
模式 4:负向约束
def no_hedging_reward(completions, **kwargs):
"""
-0.3 penalty for uncertainty language.
"""
hedging = ["i think", "maybe", "perhaps", "possibly", "i'm not sure"]
rewards = []
for completion in completions:
has_hedging = any(phrase in completion.lower() for phrase in hedging)
rewards.append(-0.3 if has_hedging else 0.0)
return rewards
</reward_functions>
典型奖励组合
reward_funcs = [
correctness_reward, # +2.0 max (primary signal)
format_reward, # +0.5 max (structure)
reasoning_length_reward, # +0.3 max (quality)
no_hedging_reward, # -0.3 max (constraint)
]
# Total range: -0.3 to +2.8
针对特定领域的奖励: Voice AI、Sales Agent 和 Support 模式请参阅
reference/domain-examples.md。 </reward_functions>
<prompt_format>
提示词结构
带 XML 标签的系统提示词
SYSTEM_PROMPT = """You are a helpful assistant that thinks step-by-step.
Always respond in this exact format:
<reasoning>
[Your step-by-step thinking process]
</reasoning>
<answer>
[Your final answer - just the number or short response]
</answer>
"""
提取辅助函数
import re
def extract_answer(text: str) -> str:
"""Extract answer from XML tags"""
match = re.search(r"<answer>(.*?)</answer>", text, re.DOTALL)
return match.group(1).strip() if match else ""
def extract_reasoning(text: str) -> str:
"""Extract reasoning from XML tags"""
match = re.search(r"<reasoning>(.*?)</reasoning>", text, re.DOTALL)
return match.group(1).strip() if match else ""
数据集格式
GRPO(仅提示词):
dataset = dataset.map(lambda ex: {
"prompt": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": ex["question"]}
],
"answer": ex["answer"] # Ground truth for verification
})
SFT(完整对话):
dataset = dataset.map(lambda ex: {
"conversations": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": ex["input"]},
{"role": "assistant", "content": ex["output"]}
]
})
</prompt_format>
<model_export>
保存和部署
仅保存 LoRA(约 100MB)
model.save_lora("grpo_lora")
合并并保存完整模型
model.save_pretrained_merged(
"grpo_merged", tokenizer,
save_method="merged_16bit",
)
导出为 GGUF 以用于 Ollama
model.save_pretrained_gguf(
"grpo_gguf", tokenizer,
quantization_method="q4_k_m", # Options: q4_k_m, q8_0, q5_k_m
)
使用 Ollama 测试
# Create Modelfile
cat > Modelfile << EOF
FROM ./grpo_gguf/unsloth.Q4_K_M.gguf
TEMPLATE """{{ .System }}
User: {{ .Prompt }}
Assistant: """
PARAMETER temperature 0.7
EOF
ollama create my-model -f Modelfile
ollama run my-model "Solve: 15 + 27 = ?"
</model_export>
## 请求路由GRPO 训练: → GRPOConfig、奖励函数、数据集准备
→ 参考:reference/grpo/basic_grpo.py
SFT 训练: → SFTTrainer、数据集格式化
→ 参考:reference/sft/sales_extractor_training.py
奖励函数设计: → 4 种模式(正确性、格式、质量、约束)
→ 参考:reference/reward-design.md、reference/domain-examples.md
FP8 训练: → 节省 60% VRAM、环境变量、预量化模型
→ 参考:reference/fp8-training.md
Docker 设置: → 官方镜像、卷、Jupyter/SSH
→ 参考:reference/deployment.md
视觉微调: → FastVisionModel、VLM 数据格式
→ 参考:reference/vision-training.md
移动端部署: → QAT、ExecuTorch、iOS/Android
→ 参考:reference/mobile-deployment.md
长上下文 / 打包: → 500K 上下文、提速 2-5 倍
→ 参考:reference/advanced-training.md
导出格式: → GGUF 方法、Ollama、vLLM、SGLang
→ 参考:reference/export-formats.md
训练问题: → reference/troubleshooting.md
<troubleshooting_quick>
快速故障排查
| 症状 | 修复方法 |
|---|---|
| 奖励没有提升 | 等待 300+ 步,然后将 learning_rate 提高 2 倍 |
| 奖励波动 / 不稳定 | 将 learning_rate 降低至 0.5 倍,提高 beta |
| 模型输出乱码 | 将 beta 提高 2-4 倍,检查提示词格式 |
| 内存不足 | 降低 max_completion_length,设置 num_generations=2 |
| 没有出现推理内容 | 训练 500+ 步,使用 >= 1.5B 的模型 |
详细故障排查: 请参阅
reference/troubleshooting.md</troubleshooting_quick>
<training_checklist>
训练前检查清单
GRPO:
- 模型加载时不会出现 OOM
- LoRA 已使用
use_gradient_checkpointing="unsloth"配置 - 数据集包含
prompt和answer字段 - 至少定义并测试了一个奖励函数
-
num_generations >= 2 - 已设置
beta(0.01-0.1,建议从 0.04 开始) - 已设置
learning_rate(1e-6 至 1e-5) - 计划至少训练 300 步
SFT:
- 模型加载时不会出现 OOM
- 数据集包含对话或文本字段
- 聊天模板已正确应用
-
learning_rate约为 2e-4 - 计划训练 2-4 个周期 </training_checklist>
<cost_estimates>
成本估算
训练数据生成:
- 50 个种子 x 10 种变化 x 约 1000 个令牌 = 约 500K 个令牌
- Claude Sonnet:约 $1.50
- GPT-4o-mini:约 $0.30
训练计算:
- Google Colab T4:免费(1000 个示例需 30-60 分钟)
- RunPod A40(48GB):约 $0.79/小时
每次实验总计: 在 RunPod 上约 $0.50-$1.00 </cost_estimates>
<example_session>
示例会话
用户:“我想训练一个能给出简洁语音回复的模型”
Claude:
- 首先,我们来设置模型:
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="Qwen/Qwen2.5-3B-Instruct",
max_seq_length=1024, load_in_4bit=True,
)
- 对于 Voice AI,你需要简洁度奖励。以下是一个自定义组合:
def brevity_reward(completions, **kwargs):
"""Voice responses under 50 words get +0.5"""
return [0.5 if len(c.split()) <= 50 else -0.3 for c in completions]
def speakable_reward(completions, **kwargs):
"""Penalize markdown that sounds bad spoken"""
bad = ["**", "- ", "```", "http"]
return [-0.2 * sum(1 for b in bad if b in c) for c in completions]
reward_funcs = [correctness_reward, brevity_reward, speakable_reward]
- 完整的 Voice AI 奖励模式请参阅
reference/domain-examples.md。
输出结果旁路文件
最后一步,将内容写入 ~/.claude/skill-analytics/last-outcome-unsloth-training.json:
{"ts":"[UTC ISO8601]","skill":"unsloth-training","version":"1.0.0","variant":"default",
"status":"[success|partial|error]","runtime_ms":[estimated ms from start],
"metrics":{"models_trained":[n],"epochs_completed":[n],"exports_generated":[n]},
"error":null,"session_id":"[YYYY-MM-DD]"}
如果某些阶段失败但已生成结果,请使用状态 "partial"。只有在未生成任何输出时才使用 "error"。 </example_session>