Skip to content

单卡蒸馏 Claude Opus 4.6 到 Qwen3.5-27B:保姆级教程

原文链接:https://mp.weixin.qq.com/s/a-7HD4clgAu6bsX3ag9oyQ 版权声明:本文版权归原文作者所有,仅供参考学习

🔥 手把手教你炼丹!单卡 3090 蒸馏 Claude-4.6-Opus 到 Qwen3.5-27B

🧪 炼丹配方:Unsloth + LoRA + SFT + train_on_responses_only 💰 炼丹成本:一张 3090 + 几小时电费 + 一杯咖啡的时间 🎯 炼丹成果:让 27B 小模型学会 Claude Opus 的"深度思考"


写在前面

花几百块 API 费才能用上的 Claude Opus 4.6 推理能力,其实可以蒸馏到本地模型里。

思路很简单:让 Claude 把解题过程写成思维链数据,然后拿这些数据训练 Qwen3.5-27B。学术上叫知识蒸馏,说白了就是「抄学霸笔记」。

整个流程只需要一张 3090 + 几小时,从环境搭建到本地部署,这篇全覆盖。


1️⃣ 硬件要求

最低配置 vs 推荐配置

项目最低配置 🥉推荐配置 🥇
GPU1× RTX 3090 (24GB)1× A100 (80GB)
内存32GB64GB+
磁盘100GB SSD200GB+ NVMe SSD
CUDA12.1+12.4+

最低一张 3090,门槛不高。

三种训练方式

方式显存需求适合谁类比
QLoRA (4-bit) 🌟~18GB穷学生、独立开发者用微波炉做饭
LoRA (16-bit)~55GB有 A100 的大户用燃气灶炒菜
Full Fine-tuning~120GB+土豪公司开五星级后厨

本教程以 QLoRA (4-bit) 为主线,一张 3090 就够。A100 用户把 load_in_4bit 改成 False 即可。


2️⃣ 环境安装

配环境的程序员坑我都踩过了,跟着复制粘贴就行。

Step 1:创建虚拟环境

bash
conda create -n distill python=3.11 -y
conda activate distill

建议别在 base 环境里搞,依赖冲突很烦。

Step 2:安装 PyTorch

bash
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

CUDA 12.4 用户(推荐):

bash
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

不知道自己 CUDA 版本?跑一下 nvidia-smi,右上角写着呢~

Step 3:安装 Unsloth

bash
pip install unsloth

Unsloth 让训练速度快 2 倍、显存省 60%。没有它,3090 跑不动 27B 模型。

Step 4:安装其他依赖

bash
pip install datasets accelerate bitsandbytes trl peft huggingface_hub

Step 5:验证一下

python
import torch
print(f'🔥 PyTorch: {torch.__version__}')
print(f'🎮 CUDA: {torch.cuda.is_available()}')
print(f'💪 GPU: {torch.cuda.get_device_name(0)}')
print(f'🧠 显存: {torch.cuda.get_device_properties(0).total_mem / 1024**3:.1f} GB')
print('✅ 环境就绪,可以开始炼丹了!')

看到 ✅ 环境就绪 就说明成功了。

Step 6:登录 HuggingFace

bash
huggingface-cli login

https://huggingface.co/settings/tokens 拿你的 token,粘贴到终端里就行。

🇨🇳 国内用户注意:如果下载模型巨慢,先跑这行设置镜像:

bash
export HF_ENDPOINT=https://hf-mirror.com

3️⃣ 下载基座模型

Unsloth 提供了预量化版本,开箱即用。

QLoRA 方案(你大概率用这个):unsloth/Qwen3.5-27B-unsloth-bnb-4bit

训练代码会自动下载,不用手动操作。不过建议提前下载到本地,省得训练时断网重来 👇

提前下载到本地(推荐)

python
from huggingface_hub import snapshot_download

snapshot_download('unsloth/Qwen3.5-27B-unsloth-bnb-4bit',
    local_dir='./models/Qwen3.5-27B-4bit')
print('✅ 模型下载完成!')

4-bit 版约 15GB,不会太久。LoRA 16-bit 用户用 unsloth/Qwen3.5-27B,约 55GB。


4️⃣ 准备数据集

这一步是整个蒸馏的灵魂——你得给模型高质量的思维链数据,让它学会 Claude 怎么一步步推导的。

数据集清单

Jackrong 用了 3 份数据集,合计约 3,280 条:

数据集数量一句话介绍
📚 nohurry/Opus-4.6-Reasoning-3000x-filtered~2,326 条主力数据集,Claude 的深度推理轨迹
🧠 TeichAI/claude-4.5-opus-high-reasoning-250x~250 条高难度硬核推理样本
🔧 Jackrong/Qwen3.5-reasoning-700x~700 条补充多样性,防止模型偏科

总共才 3,280 条数据就蒸馏出了很强的效果,数据质量远比数量重要

数据长什么样?

每条数据都是这样的 messages 格式:

json
{
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "请解释量子纠缠的原理..."},
    {"role": "assistant", "content": "<think>\nLet me analyze this carefully:\n1. First...\n2. The key insight...\n3. Therefore...\n</think>\n\n量子纠缠是...(最终答案)"}
  ]
}

🔑 关键是 <thinking> 标签——Claude 的内心推理过程。我们要让 Qwen 学会的就是这种结构化思维。

一键下载 & 合并

python
from datasets import load_dataset, concatenate_datasets

print('📥 正在下载学霸笔记...')
ds1 = load_dataset('nohurry/Opus-4.6-Reasoning-3000x-filtered', split='train')
print(f'  📚 数据集 1: {len(ds1)} 条 ✅')
ds2 = load_dataset('TeichAI/claude-4.5-opus-high-reasoning-250x', split='train')
print(f'  🧠 数据集 2: {len(ds2)} 条 ✅')
ds3 = load_dataset('Jackrong/Qwen3.5-reasoning-700x', split='train')
print(f'  🔧 数据集 3: {len(ds3)} 条 ✅')

combined = concatenate_datasets([ds1, ds2, ds3])
combined.save_to_disk('./data/combined_opus_reasoning')
print(f'🎉 合并完成!共 {len(combined)} 条学霸笔记,已保存到 ./data/')

5️⃣ 训练代码(核心)

这是整篇教程最重要的部分。创建文件 train.py,把下面的代码依次粘贴进去:

Part 1:配置区(改这里就行,其他不用动)

python
# ============================================================
# 🔥 train.py - Claude-4.6-Opus 蒸馏 Qwen3.5-27B
# 使用方法:改完配置区,直接 python train.py
# 预计时间:3090 约 2-4 小时,4090 约 1-2 小时
# ============================================================
from unsloth import FastLanguageModel
from datasets import load_dataset, concatenate_datasets
from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

# ╔══════════════════════════════════════════════════════════╗
# ║                    🎛️  配置区                            ║
# ║           只需要改这里!其他代码不用动!                     ║
# ╚══════════════════════════════════════════════════════════╝

# --- 🖥️ 模型配置 ---
MODEL_NAME = "unsloth/Qwen3.5-27B-unsloth-bnb-4bit"  # 3090 用这个
# MODEL_NAME = "unsloth/Qwen3.5-27B"  # A100 土豪用这个
MAX_SEQ_LENGTH = 4096  # 序列长度(显存不够就改 2048)
LOAD_IN_4BIT = True  # True = QLoRA(省显存), False = LoRA(需大显存)

# --- 🧬 LoRA 配置 ---
LORA_R = 64  # LoRA Rank,原作者就是用的 64
LORA_ALPHA = 64  # 一般跟 r 保持一致
LORA_DROPOUT = 0  # Unsloth 优化过了,放心填 0

# --- 📊 训练超参数 ---
NUM_EPOCHS = 3  # 训练 3 轮(多了容易过拟合)
BATCH_SIZE = 2  # 每批 2 条(显存小就改 1)
GRAD_ACCUM = 4  # 梯度累积 4 步(等效 batch = 8)
LEARNING_RATE = 2e-4
WARMUP_STEPS = 10
OUTPUT_DIR = "./output"
LOGGING_STEPS = 5

3090 用户上面的配置直接用就行,不用改。

Part 2:加载模型

python
# ==================== 📦 加载基座模型 ====================
print("🚀 正在加载模型,请稍候...")
print("   (第一次运行会自动下载,可能需要几分钟)")

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name=MODEL_NAME,
    max_seq_length=MAX_SEQ_LENGTH,
    dtype=None,  # 自动检测最佳精度
    load_in_4bit=LOAD_IN_4BIT,
)
print(f"✅ 模型加载完成:{MODEL_NAME}")

Part 3:挂上 LoRA 适配器

python
# ==================== 🧬 配置 LoRA ====================
model = FastLanguageModel.get_peft_model(
    model,
    r=LORA_R,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",  # 注意力模块
                    "gate_proj", "up_proj", "down_proj"],  # FFN 模块
    lora_alpha=LORA_ALPHA,
    lora_dropout=LORA_DROPOUT,
    bias="none",
    use_gradient_checkpointing="unsloth",  # 省 30% 显存的魔法
    random_state=3407,
    use_rslora=False,
    loftq_config=None,
)
model.print_trainable_parameters()
# 你会看到类似:trainable params: 83M || all params: 27B || 0.31%

Part 4:加载数据集 & 格式化

python
# ==================== 📚 加载学霸笔记 ====================
print("📥 加载数据集中...")
ds1 = load_dataset("nohurry/Opus-4.6-Reasoning-3000x-filtered", split="train")
ds2 = load_dataset("TeichAI/claude-4.5-opus-high-reasoning-250x", split="train")
ds3 = load_dataset("Jackrong/Qwen3.5-reasoning-700x", split="train")
dataset = concatenate_datasets([ds1, ds2, ds3])
print(f"📊 共加载 {len(dataset)} 条训练数据")

# ==================== 🔄 格式化数据 ====================
def formatting_prompts_func(examples):
    convos = examples["messages"]
    texts = []
    for convo in convos:
        text = tokenizer.apply_chat_template(convo, tokenize=False, add_generation_prompt=False)
        texts.append(text)
    return {"text": texts}

dataset = dataset.map(formatting_prompts_func, batched=True)
print(f"✅ 数据格式化完成!")

Part 5:配置训练器 + 核心技巧

python
# ==================== 🎯 配置训练器 ====================
from unsloth import train_on_responses_only

trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    args=TrainingArguments(
        output_dir=OUTPUT_DIR,
        num_train_epochs=NUM_EPOCHS,
        per_device_train_batch_size=BATCH_SIZE,
        gradient_accumulation_steps=GRAD_ACCUM,
        learning_rate=LEARNING_RATE,
        warmup_steps=WARMUP_STEPS,
        lr_scheduler_type="cosine",
        fp16=not is_bfloat16_supported(),
        bf16=is_bfloat16_supported(),
        optim="adamw_8bit",
        logging_steps=LOGGING_STEPS,
        save_strategy="steps",
        save_steps=100,
        save_total_limit=3,
        weight_decay=0.01,
        max_grad_norm=1.0,
        seed=3407,
        report_to="none",
    ),
    dataset_text_field="text",
    max_seq_length=MAX_SEQ_LENGTH,
    packing=False,  # 蒸馏场景关闭 packing
)

⭐ 核心技巧:train_on_responses_only

python
trainer = train_on_responses_only(
    trainer,
    instruction_part="<|im_start|>user\n",
    response_part="<|im_start|>assistant\n",
)
print("✅ 训练器配置完成!")
print(f" 等效 Batch Size: {BATCH_SIZE * GRAD_ACCUM}")
print(f" 训练轮数:{NUM_EPOCHS}")
print(f" LoRA Rank: {LORA_R}")

train_on_responses_only 一句话总结:只让模型学"怎么答",不学"怎么问",把注意力集中在 <thinking> 思维链和最终回答上。这是用少量数据就能出效果的关键。

Part 6:开始训练

python
# ==================== 🔥 开始训练 ====================
print("🔥 开始训练...")
trainer_stats = trainer.train()
print(f"🎉 训练完成!最终 Loss: {trainer_stats.training_loss:.4f}")
print(f"📊 总步数:{trainer_stats.global_step}")

Part 7:保存模型

python
# ==================== 💾 保存炼丹成果 ====================
model.save_pretrained("./output/lora_adapter")
tokenizer.save_pretrained("./output/lora_adapter")
print("✅ LoRA 适配器已保存到 ./output/lora_adapter")

可选:推到 HuggingFace 分享你的模型:

python
model.push_to_hub("your-username/my-opus-distill", token="hf_xxx")

6️⃣ 启动训练

等待训练

直接运行:

bash
conda activate distill
python train.py

后台运行(推荐,防止 SSH 断开翻车):

方式一:nohup

bash
nohup python train.py > train.log 2>&1 &
tail -f train.log

方式二:tmux(强烈推荐)

bash
tmux new -s distill
python train.py

Ctrl+B, D 脱离会话(训练继续跑),之后用 tmux attach -t distill 回来看。

一定要用 tmux 或 nohup,SSH 断了就白跑了。

训练时间参考

你的显卡预计时间
RTX 30902-4 小时
RTX 40901-2 小时
A100 80GB1-2 小时

怎么看训练是否正常?

Loss 日志大致是这样的走势:

Step 5   | Loss: 2.34  ← 刚开始,偏高正常
Step 50  | Loss: 0.85  ← 开始收敛
Step 200 | Loss: 0.51  ← 趋于稳定
最终      | Loss: 0.4~0.8  ← 理想范围
  • 持续下降 → 正常
  • 降到 0 → 过拟合了,减少 epochs 或加数据
  • 纹丝不动 → 检查数据格式和学习率

7️⃣ 模型导出

训练完拿到的是 LoRA 适配器(约 100MB),还需要导出成可部署的格式。

方式一:合并为完整模型(通用部署)

python
model.save_pretrained_merged("./output/merged_model", tokenizer, save_method="merged_16bit")  # 约 55GB
print("✅ 完整模型已保存!")

方式二:导出 GGUF(用 Ollama 跑起来)⭐ 推荐

python
model.save_pretrained_gguf("./output/gguf", tokenizer, quantization_method="q4_k_m")
print("✅ GGUF 模型已导出!可以用 Ollama 跑了!")

量化方式怎么选?

格式大小显存精度推荐度
Q4_K_M~16GB~16.5GB⭐⭐⭐🏆 首选
Q5_K_M~19GB~20GB⭐⭐⭐⭐有余量就用
Q8_0~28GB~29GB⭐⭐⭐⭐⭐追求精度

方式三:推到 HuggingFace 开源(可选)

python
model.push_to_hub_gguf("your-username/Qwen3.5-27B-Opus-Distilled-GGUF",
    tokenizer, quantization_method="q4_k_m", token="hf_xxx")

8️⃣ 推理测试

看看训练效果如何。

方式一:用 Unsloth 直接推理

python
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="./output/lora_adapter",
    max_seq_length=4096, dtype=None, load_in_4bit=True,
)
FastLanguageModel.for_inference(model)

messages = [
    {"role": "system", "content": "You are a helpful assistant that thinks step by step."},
    {"role": "user", "content": "请用 Python 实现一个线程安全的单例模式,并解释每一步的设计考量"},
]
inputs = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt").to("cuda")
outputs = model.generate(input_ids=inputs, max_new_tokens=4096, temperature=0.6, top_p=0.95, top_k=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

如果回复里出现了 <thinking> 结构化思维链,说明蒸馏成功了。

方式二:用 Ollama 一键起飞(日常使用推荐)🚀

Step 1:安装 Ollama

bash
curl -fsSL https://ollama.com/install.sh | sh

Step 2:创建 Modelfile

FROM ./output/gguf/unsloth.Q4_K_M.gguf
PARAMETER temperature 0.6
PARAMETER top_p 0.95
PARAMETER top_k 20
PARAMETER num_ctx 32768
SYSTEM "You are a helpful assistant that thinks step by step."

Step 3:创建并运行模型

bash
ollama create my-opus-distill -f Modelfile
ollama run my-opus-distill

到这里你就有了一个本地版的「类 Claude Opus」,不花 API 钱。29-35 tok/s,262K 上下文,支持 Claude Code 和 OpenCode。

推理参数速查表

场景temperaturetop_p建议 max_tokens适用情况
💬 日常对话1.00.9532,768聊天、创意写作
💻 写代码0.60.9532,768精确逻辑、Web 开发
🧮 竞赛难题1.00.9581,920数学/编程竞赛

🔧 附录:常见问题

CUDA out of memory:把 MAX_SEQ_LENGTH 改成 2048,BATCH_SIZE 改成 1,确认 LOAD_IN_4BIT = True

Loss 不下降:检查数据集有没有 messages 字段,chat template 是否正确,学习率调小到 5e-5 试试。

推理没有 <thinking> 思维链temperature 不要设 0(用 0.6 或 1.0),max_new_tokens 至少 4096,system prompt 加上 "think step by step"

导出 GGUF 报错:先 pip install llama-cpp-python,然后先 merge 成 16-bit 再转 GGUF。


📎 资源链接汇总

资源链接
🤗 Jackrong 模型https://huggingface.co/Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled
🤗 TeichAI 模型https://huggingface.co/TeichAI/Qwen3.5-27B-Claude-Opus-4.6-Distill
📚 核心数据集https://huggingface.co/datasets/nohurry/Opus-4.6-Reasoning-3000x-filtered
🦥 Unslothhttps://github.com/unslothai/unsloth
📓 官方 Notebookhttps://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen_3_5_27B_A100(80GB).ipynb
📖 Unsloth 文档https://docs.unsloth.ai

写在最后

大功告成 🎉

回顾一下:用 3,280 条数据 + 一张 3090 + 几小时,把 Claude Opus 4.6 的推理能力迁移到了 Qwen3.5-27B 里。

蒸馏模型当然有局限——没有多模态能力,边界场景可能翻车——但在纯文本推理、代码、数学方面,确实能打。

觉得有用的话欢迎转发。有问题评论区见。

基于 Jackrong 和 TeichAI 的开源工作整理,感谢 Unsloth 团队。

#蒸馏 #Qwen3.5 #Claude-Opus #LoRA #Unsloth #本地部署


版权声明:本文版权归原文作者所有 原文链接:https://mp.weixin.qq.com/s/a-7HD4clgAu6bsX3ag9oyQ

Released under the MIT License.