V3 来了!Claude-4.6-Opus 蒸馏 Qwen3.5,从"会思考"到"会干活"|保姆教程

lxiol
📝
V3 进化:让它学会用工具干活 —— 从"会思考"到"会行动",质的飞跃炼丹成本:一张 3060 就够,4090/A100 更舒服

原文链接:https://mp.weixin.qq.com/s/VfwaFFI_-xTwYW6NWlOJHA

V3 进化:让它学会用工具干活 —— 从”会思考”到”会行动”,质的飞跃炼丹成本:一张 3060 就够,4090/A100 更舒服

V1 炼丹:学会了 Claude 的深度思考

V2 升级:让它想得更少答得更快

V3 进化:让它学会用工具干活 —— 从”会思考”到”会行动”,质的飞跃

炼丹成本:一张 3060 就够,4090/A100 更舒服

相关阅读(前两篇教程):

写在前面

  • • V1(3 月底):证明了”小模型也能学到大模型的推理能力”——用 3,280 条 Claude 思维链数据,让 Qwen3.5-27B 学会了结构化推理。HumanEval 96.95%,单卡 3090 就能跑。
  • • V2(4 月初):证明了”推理效率可以大幅优化”——数据量翻 4 倍到 14,000 条,思维链缩短 24%,每 Token 正确率 +31.6%。代码准确率没掉,但每个 Token 更值钱了。
  • • V3(4 月 3 日):证明了”蒸馏模型也能做 Agent”——名字都换了,从拗口的 Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled 改成了 Qwopus3.5(Qwen + Opus 的合体)。同时发布 4B、9B、27B 三个尺寸,新增工具调用 RL 训练,从”想好再做”转向”做了再改”。

V3 的核心转变

从 “reason-then-act”(想好再做)到 “act-then-refine”(做了再改)

这个思路来自两篇重要研究:Reflexion 论文证明 Agent 通过”试错 + 反思”比纯内心推理更有效;另一项研究发现失败后反思再重试能带来 +34.7%(数学推理)和 +18.1%(函数调用)的提升。

先看下载量——大家投票的结果:

模型

尺寸

下载量

点赞

Qwopus3.5-9B-v3-GGUF

9B

43,478

178

Qwopus3.5-27B-v3

27B

5,073

106

Qwopus3.5-9B-v3

9B

3,463

61

Qwopus3.5-4B-v3

4B

897

5

9B GGUF 以 43k+ 下载量断崖式领先。16GB 内存的 MacBook 就能跑,Windows 上普通显卡也没压力。27B 虽然更强但门槛更高;4B 太小容易翻车。9B 刚好在”能用”和”能跑”之间找到了最佳平衡。

所以这篇教程,以 9B 为主线(27B 用户改个模型名就行)。

V3 三大核心升级

结构化推理优化

V2 靠蒸馏 Claude 的思维链(CoT),但 Jackrong 在 V3 中坦诚指出了一个问题:V2 用的第三方蒸馏数据,有些思维链可能是”伪造”的——看起来像 Claude 生成的,实际上未必是。Anthropic 自己也发表过研究,说推理模型的思维链有时候只是”事后合理化”,并非真正的逐步推理。

学生模型去模仿这种”假推理”,学到的可能只是表面的模式匹配。

V3 的做法:用精选的、可验证的推理链做训练,让模型学的是过程级推理,而非简单模仿答案。

V2

V3

思维链来源

第三方蒸馏数据

精选可验证推理链

学习目标

模仿教师输出

学习过程级推理

推理风格

压缩式(可能伪造)

显式、逐步、可验证

泛化能力

较弱

更强

27B HumanEval 评测截图(来源:Qwopus3.5-27B-v3 模型卡):

Qwopus3.5-27B-v3 HumanEval Benchmark 对比(97.56% base pass@1)

Qwopus3.5-27B-v3 HumanEval Benchmark 对比(97.56% base pass@1)

Qwopus3.5-27B-v3 HumanEval 详细结果

Qwopus3.5-27B-v3 HumanEval 详细结果

工具调用强化训练(V3 最重要的新增)

V3 专门做了针对工具调用的强化学习(RL)训练,为 Agent 框架(如 OpenClaw)优化了工具调用的稳定性和准确性。

这意味着 V3 在 Agent 场景下——比如自动搜索、调用 API、操作文件——比 V1/V2 强得多。ToolCall-15 测试 15/15 满分就是证据。整个设计理念从”一次推理到位”转向”迭代交互纠正”,对多步骤任务特别友好。

V1 → V2 → V3 全家族进化图谱

维度

V1

V2

V3

名字

Claude-4.6-Opus-Reasoning-Distilled

同上
Qwopus3.5
核心思路

蒸馏 Claude 推理能力

优化推理效率

工具调用 + 结构对齐

训练方法

SFT + LoRA

SFT + LoRA

SFT + LoRA +RL(工具调用)

基座模型

Qwen3.5-27B

Qwen3.5-27B

Qwen3.5-9B(甜蜜点)/27B/4B

数据来源

3 份公开蒸馏数据集

4 份公开数据集(+10k 通用推理)

精选高保真推理链(24 份策划数据集)

数据量

~3,280 条

~14,000 条

高保真精选(具体数量未公开)

HumanEval (9B)

~82%

~82%
87.80%
(+5pp)

HumanEval (27B)

96.95%

96.91%
97.56%
(base) / 95.73% (strict)

MMLU-Pro

基准
-7.2%****+1.43%
思维链长度

基准(长)

-24%
-25.3%
推理效率

基准

+31.6%
+31.7%
工具调用

未优化

未优化
专项 RL 训练 (15/15)
理念

模仿 Claude

更快更省
做了再改

Jackrong 官方评测截图(来源:HuggingFace 模型卡):

HumanEval 9B 对比 —— Qwopus3.5-9B-v3 vs Qwen3.5-9B vs Claude-Distilled-v2:

Qwopus3.5-9B-v3 HumanEval Benchmark 对比

Qwopus3.5-9B-v3 HumanEval Benchmark 对比

Qwopus3.5-9B-v3 HumanEval 详细评测结果

Qwopus3.5-9B-v3 HumanEval 详细评测结果
推理效率对比 —— 同样的准确率,V3 用更少的 Token:

Qwopus3.5-9B-v3 推理效率对比(思维链长度 -25.3%,效率 +31.7%)

Qwopus3.5-9B-v3 推理效率对比(思维链长度 -25.3%,效率 +31.7%)

一、硬件要求

跑过 V1/V2 的同学注意:V3 主线是 9B,硬件门槛比之前的 27B 低得多!

9B 模型(本教程主线)

配置

最低要求

推荐配置

GPU

1× RTX 3060 (12GB)

1× RTX 4090 (24GB)

内存

16GB

32GB+

磁盘

50GB SSD

100GB+ NVMe SSD

CUDA

12.1+

12.4+

27B 模型(可选,追求极致性能)

配置

最低要求

推荐配置

GPU

1× RTX 3090 (24GB)

1× A100 (80GB)

内存

32GB

64GB+

磁盘

100GB SSD

200GB+ NVMe SSD

CUDA

12.1+

12.4+

训练方式对比

方式

9B 显存

27B 显存

适用人群

QLoRA (4-bit) ★
~8GB
~18GB

大多数人(本教程主线)

LoRA (16-bit)

~20GB

~55GB

有好卡的用户

Full Fine-tuning

~40GB+

~120GB+

多卡土豪

二、环境安装

跑过 V1/V2 的同学环境完全兼容,直接跳到第 3 步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
`# Step 1:创建虚拟环境
conda create -n distill python=3.11 -y
conda activate distill

# Step 2:安装 PyTorch(根据你的 CUDA 版本选一个)
# CUDA 12.1
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# CUDA 12.4(推荐)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

# Step 3:安装 Unsloth
pip install unsloth

# Step 4:安装其他依赖
pip install datasets accelerate bitsandbytes trl peft huggingface_hub

# Step 5:验证
python -c "
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
huggingface-cli login`

国内用户设镜像:export HF_ENDPOINT=https://hf-mirror.com

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

三、下载基座模型

V3 主线是 Qwen3.5-9B(不是 27B 了!)。Unsloth 提供了预量化版本,开箱即用。

QLoRA 方案(推荐,大多数人用这个)

1
2
3
4
5
6
`python -c "
from huggingface_hub import snapshot_download
snapshot_download('unsloth/Qwen3.5-9B-unsloth-bnb-4bit',
                  local_dir='./models/Qwen3.5-9B-4bit')
print('✅ 9B 4-bit 模型下载完成!约 5GB')
"`

LoRA 16-bit 方案(有大显存的用户)

1
2
3
4
5
6
`python -c "
from huggingface_hub import snapshot_download
snapshot_download('unsloth/Qwen3.5-9B',
                  local_dir='./models/Qwen3.5-9B')
print('✅ 9B 16-bit 模型下载完成!约 18GB')
"`

27B 用户把模型名改成 unsloth/Qwen3.5-27B-unsloth-bnb-4bit(15GB)或 unsloth/Qwen3.5-27B(55GB)。

四、准备数据集(V3 核心变化)

V3 的数据策略:从”量多”到”质精”

V3 和 V1/V2 最大的区别在于数据质量。V1/V2 用的第三方蒸馏数据可能包含”伪造”推理链,V3 改用 Jackrong 精心策划的高保真数据集,从可验证的推理链中精选,确保每条数据都是过程级推理。

V3 的训练数据没有直接公开具体数据集名单,但 Jackrong 在 GitHub 上开源了 24 份高保真蒸馏数据集,这些数据主要蒸馏自 DeepSeek-V3.2、Qwen3-235B、GLM-4.7、GPT-OSS-120B 等顶级模型,涵盖:

类别

代表数据集

用途

推理 & CoT
Jackrong/Qwen3.5-reasoning-700x
Natural-Reasoning-gpt-oss-120B-S1

逐步推理能力

数学 & STEM
DeepSeek-v3.1-reasoner-Distilled-math-samples
数学/科学推理

代码 & 算法
Competitive-Programming-python-blend
qwen3-coder-480b-distill-mini

编程能力

多轮对话
LogicMind-Chat-Reasoning-SFT-300K
Chinese-Qwen3-235B-Thinking-2507-Distill-100k

对话能力

我们的复现策略

由于 V3 的确切训练数据配比未公开,我们采用近似复现方案:保留 V1/V2 的 4 份经典数据集(~14,000 条),同时可按需新增 Jackrong 开源的高保真数据集。

方案 A:轻量版(推荐新手,~14,000 条)

沿用 V2 的 4 份数据集,已验证有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
`mkdir -p ./data
python -c "
from datasets import load_dataset, concatenate_datasets
print('📥 正在下载 V3 训练数据...')

ds1 = load_dataset('nohurry/Opus-4.6-Reasoning-3000x-filtered', split='train')
print(f'  📚 数据集 1: {len(ds1)} 条 ✅  ← Claude Opus 深度推理轨迹')

ds2 = load_dataset('Roman1111111/claude-opus-4.6-10000x', split='train')
print(f'  🆕 数据集 2: {len(ds2)} 条 ✅  ← 大规模通用推理')

ds3 = load_dataset('TeichAI/claude-4.5-opus-high-reasoning-250x', split='train')
print(f'  🧠 数据集 3: {len(ds3)} 条 ✅  ← 高难度结构化推理')

ds4 = load_dataset('Jackrong/Qwen3.5-reasoning-700x', split='train')
print(f'  🔧 数据集 4: {len(ds4)} 条 ✅  ← 多样性推理补充')

combined = concatenate_datasets([ds1, ds2, ds3, ds4])
combined.save_to_disk('./data/combined_opus_reasoning_v3')
print(f'')
print(f'🎉 合并完成!共 {len(combined)} 条训练数据')
print(f'   已保存到 ./data/combined_opus_reasoning_v3')
"`

方案 B:高保真版(进阶用户,更接近 V3 原版)

使用 Jackrong 开源的一键下载脚本,获取全部 24 份高保真数据集:

1
2
3
4
5
6
7
8
9
`# 克隆 Jackrong 的训练仓库
git clone https://github.com/R6410418/Jackrong-llm-finetuning-guide.git
cd Jackrong-llm-finetuning-guide

# 一键下载全部 24 份高保真数据集
pip install huggingface_hub
python download_datasets.py

# 数据会下载到 ./High-fidelity Dataset/ 目录`

方案 B 数据量更大,需要更多磁盘空间和训练时间。建议先跑方案 A 验证流程,再切换方案 B 追求更高质量。

下载大小:方案 A 约 200-300MB(纯文本),方案 B 约 1-2GB。国内用户记得设 HF_ENDPOINT 镜像。

数据格式

不管哪个方案,每条数据都是标准 messages 格式:

1
2
3
4
5
6
7
`{
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Solve: if 3x + 7 = 22, find x..."},
    {"role": "assistant", "content": "<think>\nLet me analyze this request carefully:\n1. I need to solve for x in 3x + 7 = 22\n2. Subtract 7: 3x = 15\n3. Divide by 3: x = 5\n4. Verify: 3(5) + 7 = 22 ✓\n</think>\n\nx = 5"}
  ]
}`

关键是 <think>...</think> 标签——Claude 的结构化推理过程。V3 强调的是这些推理链必须是可验证的、过程级的,而非简单的答案模仿。

五、训练代码

V3 的训练分为两个阶段

  • • 阶段一:SFT + LoRA(和 V1/V2 一脉相承,基本盘)
  • • 阶段二:GRPO 工具调用强化学习(V3 新增,让模型学会用工具)

本节先覆盖阶段一,阶段二在下一节。

创建文件 train_v3.py

Part 1:配置区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
`# ============================================================
# 🔥 train_v3.py - Qwopus3.5 蒸馏训练 (V3)
#
# V3 变化:
#   - 基座模型:9B(甜蜜点),不再是 27B
#   - 数据:高保真推理链(可验证、过程级)
#   - 新增:工具调用 RL 训练(阶段二另外跑)
#
# 使用方法:改完配置区,直接 python train_v3.py
# 预计时间:9B + 3060 约 2-3 小时,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-9B-unsloth-bnb-4bit"   # ← V3 主线:9B
# MODEL_NAME = "unsloth/Qwen3.5-9B"                   # 16-bit LoRA 用这个
# MODEL_NAME = "unsloth/Qwen3.5-27B-unsloth-bnb-4bit" # 27B 土豪用这个

MAX_SEQ_LENGTH = 4096      # 序列长度(显存不够就改 2048)
LOAD_IN_4BIT = True        # True = QLoRA(省显存), False = LoRA(需大显存)

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

# --- 📊 训练超参数 ---
NUM_EPOCHS = 3             # 训练 3 轮
BATCH_SIZE = 2             # 每批 2 条(9B 显存友好,3060 用 1)
GRAD_ACCUM = 4             # 梯度累积 4 步(等效 batch = 8)
LEARNING_RATE = 2e-4       # 学习率
WARMUP_STEPS = 10          # 预热步数
OUTPUT_DIR = "./output_v3" # ← V3 输出路径
LOGGING_STEPS = 5          # 每 5 步打印一次 loss`

和 V1/V2 相比,配置区最大的变化就是 MODEL_NAME 从 27B 变成了 9B。其他参数基本不变。

9B 用户 BATCH_SIZE 可以放到 4(显存允许的话),27B 还是 2。

Part 2:加载模型

1
2
3
4
5
6
7
8
9
10
11
`# ==================== 📦 加载基座模型 ====================
print("🚀 正在加载 Qwen3.5-9B,请稍候...")
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 适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
`# ==================== 🧬 配置 LoRA ====================
# LoRA 的思路:不动原始模型参数,加一个轻量适配器
# 9B 模型的可训练参数约 30-40MB,比 27B 更轻
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()
# 9B 你会看到类似:trainable params: 30M || all params: 9B || 0.33%`

Part 4:加载数据集(V3 高保真数据)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
`# ==================== 📚 加载数据集(V3 版本) ====================
# V3 核心变化:使用高保真、可验证的推理链数据
# 这里用方案 A(兼容 V2 数据 + 质量筛选)
print("📥 加载 V3 训练数据集...")

ds1 = load_dataset("nohurry/Opus-4.6-Reasoning-3000x-filtered", split="train")
print(f"  📚 数据集 1: {len(ds1)} 条 ✅  ← Claude 深度推理")

ds2 = load_dataset("Roman1111111/claude-opus-4.6-10000x", split="train")
print(f"  🆕 数据集 2: {len(ds2)} 条 ✅  ← 通用推理迁移")

ds3 = load_dataset("TeichAI/claude-4.5-opus-high-reasoning-250x", split="train")
print(f"  🧠 数据集 3: {len(ds3)} 条 ✅  ← 高难度推理")

ds4 = load_dataset("Jackrong/Qwen3.5-reasoning-700x", split="train")
print(f"  🔧 数据集 4: {len(ds4)} 条 ✅  ← 多样性推理")

dataset = concatenate_datasets([ds1, ds2, ds3, ds4])
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:配置训练器 + 核心技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
`# ==================== 🎯 配置训练器 ====================
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=200,
        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,
)

# ╔══════════════════════════════════════════════════════════╗
# ║         🔥 核心技巧:train_on_responses_only              ║
# ╚══════════════════════════════════════════════════════════╝
#
# 只在 assistant 的回答(包括 <think> 思维链)上计算 loss
# 模型不学"怎么提问",只学"怎么像 Claude 一样思考和回答"
# 这是用少量数据就能出效果的关键
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"   数据量: {len(dataset)} 条")`

Part 6:开始训练

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

Part 7:保存模型

1
2
3
4
`# ==================== 💾 保存炼丹成果 ====================
model.save_pretrained("./output_v3/lora_adapter")
tokenizer.save_pretrained("./output_v3/lora_adapter")
print("✅ V3 LoRA 适配器已保存到 ./output_v3/lora_adapter")`

推到 HuggingFace(可选):

1
`model.push_to_hub("your-username/Qwopus3.5-9B-v3-my-distill", token="hf_xxx")`

六、阶段二:GRPO 工具调用强化训练(V3 新增)

这是 V3 区别于 V1/V2 的关键一步。阶段一训练完 SFT 之后,用 GRPO(Group Relative Policy Optimization)对模型进行工具调用方向的强化学习。

为什么需要 RL?

SFT 教会了模型”怎么思考”,但 Agent 场景还需要模型”怎么用工具”。RL 训练的目标:

  • • 在给定工具列表时,选对工具
  • • 参数传对(比如用户要华氏温度,你传了 fahrenheit 没?)
  • • 能串联多个工具完成复杂任务
  • • 不该用工具时能忍住
  • • 工具报错了知道换策略

GRPO 训练代码参考

Jackrong 在 GitHub 仓库的 Roadmap 中已标明 GRPO 支持(Qwen 3.5/3 系列已 Released),下面是基于 Unsloth + TRL 的 GRPO 训练框架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
`# ============================================================
# 🔥 train_v3_grpo.py - Qwopus3.5 工具调用强化训练
#
# 在 SFT 阶段一训练完的 LoRA 适配器基础上,
# 用 GRPO 进一步强化工具调用能力
# ============================================================

from unsloth import FastLanguageModel
from trl import GRPOConfig, GRPOTrainer

# 加载阶段一训练好的模型
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="./output_v3/lora_adapter",
    max_seq_length=4096,
    dtype=None,
    load_in_4bit=True,
)

# GRPO 配置
grpo_config = GRPOConfig(
    output_dir="./output_v3_grpo",
    num_train_epochs=1,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    learning_rate=5e-5,           # RL 阶段学习率要小一些
    logging_steps=10,
    save_steps=100,
    max_completion_length=2048,
    num_generations=4,            # 每个 prompt 生成 4 个候选
    report_to="none",
)

# 工具调用奖励函数示例
def tool_call_reward(completions, **kwargs):
    """
    评估工具调用的质量:
    - 选对工具 → 高分
    - 参数正确 → 高分
    - 无效调用 → 低分
    - 该拒绝时拒绝 → 高分
    """
    rewards = []
    for completion in completions:
        score = 0.0
        text = completion[0]["content"] if isinstance(completion, list) else completion

        # 包含有效的工具调用格式
        if "<tool_call>" in text and "</tool_call>" in text:
            score += 0.5
        # 包含结构化思考
        if "<think>" in text:
            score += 0.3
        # 不是无意义重复
        if len(set(text.split())) / max(len(text.split()), 1) > 0.3:
            score += 0.2

        rewards.append(score)
    return rewards

# 准备工具调用训练数据(prompt 格式)
# 这里需要构造包含工具定义的 prompt
tool_prompts = [
    {
        "prompt": "你是一个有工具调用能力的 AI 助手。可用工具:get_weather(city, unit)、web_search(query)。\n\n用户:北京今天天气怎么样?"
    },
    {
        "prompt": "你是一个有工具调用能力的 AI 助手。可用工具:get_weather(city, unit)、web_search(query)。\n\n用户:二战是哪年结束的?"
    },
    # ... 更多工具调用场景
]

# 启动 GRPO 训练
trainer = GRPOTrainer(
    model=model,
    config=grpo_config,
    reward_funcs=[tool_call_reward],
    train_dataset=tool_prompts,   # 需要转成 Dataset 格式
    tokenizer=tokenizer,
)

trainer.train()
model.save_pretrained("./output_v3_grpo/lora_adapter")
print("✅ GRPO 工具调用强化训练完成!")`

重要说明

    1. GRPO 训练是可选步骤。如果你只需要推理能力(不需要 Agent/工具调用),阶段一的 SFT 就够了。
    1. 上面的奖励函数是简化版示例。Jackrong 的实际 RL 训练使用了更复杂的奖励信号,针对 OpenClaw 等 Agent 框架做了专项优化。
    1. Jackrong 的 GitHub 仓库(R6410418/Jackrong-llm-finetuning-guide)的 Roadmap 显示 GRPO pipeline 已 Released,完整训练 notebook 在 train_code/Qwopus3-5-27b-Colab.ipynb 中。
    1. GRPO 对显存要求更高(因为需要同时生成多个候选),9B 建议至少 16GB 显存。

七、启动训练

直接运行

1
2
`conda activate distill
python train_v3.py`

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

tmux 方式(强烈推荐):

1
2
3
4
`tmux new -s distill-v3
python train_v3.py
# Ctrl+B, D 脱离会话(训练继续跑)
# tmux attach -t distill-v3 回来看`

nohup 方式:

1
2
`nohup python train_v3.py > train_v3.log 2>&1 &
tail -f train_v3.log`

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

训练时间参考

阶段一 SFT(9B 模型,~14,000 条数据):

GPU

QLoRA 时间

LoRA 时间

RTX 3060 12GB

3-5 小时

N/A(显存不够)

RTX 3090 24GB

2-3 小时

3-4 小时

RTX 4090 24GB

1-2 小时

2-3 小时

A100 80GB

0.5-1 小时

1-2 小时

阶段二 GRPO(可选,9B 模型):

GPU

大约时间

RTX 4090 24GB

1-2 小时

A100 80GB

0.5-1 小时

对比 V1/V2:9B 模型比 27B 快 2-3 倍!这也是选 9B 作为主线的原因之一。

怎么看训练是否正常?

Loss 日志走势参考:

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

9B 模型的 Loss 通常比 27B 略高一些(模型容量小),最终 0.4-0.8 都是正常范围。

八、模型导出

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

方式一:导出 GGUF(推荐,用 Ollama/LM Studio 跑起来)

1
2
3
4
5
6
7
`# 🔑 V3 关键:工具调用场景推荐 Q6_K
model.save_pretrained_gguf(
    "./output_v3/gguf",
    tokenizer,
    quantization_method="q6_k",    # ← V3 推荐 Q6_K,工具调用更稳定
)
print("✅ GGUF 模型已导出!")`

9B 量化方式怎么选?

量化

文件大小

推理显存

精度

推荐场景

Q4_K_M

~5.6GB

~6GB

极致省显存

Q5_K_S

~6.3GB

~7GB

较高

日常使用
Q6_K~7.4GB~8GB工具调用首选
Q8_0

~9.5GB

~10GB

追求极致精度

BF16

~17.9GB

~18GB

完整精度

显存豪华配置

V3 量化建议:根据老章的 ToolCall-15 测试经验,Q6_K 是工具调用场景的最优量化精度。低于 Q6 的量化(如 Q4)在复杂工具调用时可能出现参数精度下降。

对比 V1/V2 推荐的 Q4_K_M,V3 由于新增了工具调用需求,建议至少用 Q5 以上

方式二:合并为完整模型

1
2
3
4
5
6
`model.save_pretrained_merged(
    "./output_v3/merged_model",
    tokenizer,
    save_method="merged_16bit",   # 9B 约 18GB
)
print("✅ 完整模型已保存!")`

方式三:推到 HuggingFace(可选)

1
2
3
4
5
6
`model.push_to_hub_gguf(
    "your-username/Qwopus3.5-9B-v3-my-GGUF",
    tokenizer,
    quantization_method="q6_k",
    token="hf_xxx",
)`

九、推理测试

方式一:Unsloth 直接推理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
`from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="./output_v3/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 实现一个 LRU Cache,要求 O(1) 的 get 和 put 操作"},
]

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,
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)`

验证要点:

    1. 回复里有 <think>...</think> 结构化思维链 → 蒸馏成功
    1. 思维链是结构化的(列大纲、分步骤),而非”长篇自言自语” → V3 特性生效
    1. 代码答案正确 → 推理能力迁移成功

方式二:Ollama 部署(日常使用推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
`# Step 1:安装 Ollama(如果没装过)
curl -fsSL https://ollama.com/install.sh | sh

# Step 2:创建 Modelfile
cat > Modelfile_v3 << 'EOF'
FROM ./output_v3/gguf/unsloth.Q6_K.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."
EOF

# Step 3:创建并运行
ollama create my-qwopus-v3 -f Modelfile_v3
ollama run my-qwopus-v3`

也可以直接用 Jackrong 发布的官方 GGUF:

1
`ollama run hf.co/Jackrong/Qwopus3.5-9B-v3-GGUF:Q6_K`

方式三:LM Studio 部署

直接在 LM Studio 中搜索 Qwopus3.5-9B-v3-GGUF,下载 Q6_K 版本,开箱即用。LM Studio 0.4.9 版本已支持 Anthropic 兼容接口。

十、ToolCall-15 工具调用测试(V3 专属)

这是 V3 教程的特色环节——验证你训练的模型在工具调用场景下的表现。

什么是 ToolCall-15?

ToolCall-15 是一个专门测大模型工具调用能力的可视化基准测试框架:

  • • 15 个场景,覆盖 5 大类能力
  • • 12 个工具,模型每次都能看到全部工具
  • • 模拟响应,确保结果确定可复现
  • • Temperature 设为 0,排除随机性

五大考核维度:

维度

考什么?

举例

工具选择

能不能选对工具?

问天气,该用 get_weather 还是 web_search

参数精度

参数传对了吗?

用户要华氏温度,你传了 fahrenheit 没?

多步链式

能不能串联多个工具?

搜文件 → 读内容 → 查联系人 → 发邮件

克制与拒绝

不该用工具时能忍住吗?

“二战哪年结束?”你别去搜啊

错误恢复

工具报错了怎么办?

搜索没结果,是放弃还是换关键词?

实测结果

Jackrong 的 Qwopus3.5-9B-v3(Q8 量化)在 ToolCall-15 上拿了 15/15 满分——和 27B 版本持平!

这说明 V3 的工具调用 RL 训练确实有效,9B 小模型也能在 Agent 场景下做到大模型的水平。

社区实战演示:@KyleHessling1 在 X 上发布了 Qwopus3.5-27B-v3 的前端设计测试视频,用相同 prompt 对比 Qwopus v3 和 Gemma 4 的前端生成能力。他的评价是:“The pointer animations, the smooth scrolls, color choices, 3d tilt cards, it’s all here, friends, and it’s lovely!”(指针动画、平滑滚动、配色、3D 翻转卡片,全都有!)——仅需一行 prompt 修改(”Editorial academia vibe”)就能生成风格完全不同的高质量 UI。

自己跑一遍 ToolCall-15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
`# 环境搭建
git clone https://github.com/stevibe/ToolCall-15.git
cd ToolCall-15
npm install
cp .env.example .env

# 配置 .env
# 如果用 Ollama:
# OLLAMA_HOST=http://localhost:11434
# LLM_MODELS=ollama:my-qwopus-v3
#
# 如果用 LM Studio:
# LMSTUDIO_HOST=http://localhost:1234
# LLM_MODELS=lmstudio:qwopus3.5-9b-v3

# 启动测试
npm run dev
# 打开 http://localhost:3000,点击 Run 开始测试`

ToolCall-15 需要 Node.js 20+。测试会逐个场景运行,Dashboard 实时显示每个场景的 pass/partial/fail 结果。

实测反馈

独立 Benchmark

SQL 生成能力测试(RTX 5080 环境,25 题):

模型

量化

得分(/25)
Qwopus3.5-27B-v3
Q3_K_M
23
Qwopus3.5-27B-v2

Q4_K_M

22
Qwopus3.5-9B-v3
Q8_0
17
Qwen3.5-9B(基线)

5

9B 蒸馏版拿到 17 分,是基线 Qwen3.5-9B(5 分)的 3.4 倍。27B 版本 23 分接近满分。

量化精度对比

模型

TQ3_4S Perplexity

Qwopus3.5-9B-v3
6.34
Qwen3.5-9B(基线)

6.82

Opus Abliterated 变体

6.83

蒸馏后的困惑度低于基线,说明蒸馏没有损失语言建模质量,反而有所提升。

负面/局限反馈:

  • • 9B Q8_0 作为 Agent 使用时,会出现代码生成错误和上下文混乱的问题。9B 在复杂多轮 Agent 场景下稳定性仍不如 27B。
  • • 复杂数学推理方面,Claude 蒸馏的 35B-A3B MoE 变体测试(10 题),仅得 5 分,出现了成本分析计算错误。小参数蒸馏模型在高难度推理上仍有天花板。

已知兼容性问题

vLLM 部署:多位用户反映 vLLM 部署时遇到 tokenizer_class: TokenizersBackend 错误。临时解决方案是手动将 tokenizer_config.json 中的 tokenizer_class 改为 Qwen2Tokenizer。即使修复后,vLLM 的工具调用(tool calling)功能仍不可用。建议使用 Ollama 或 LM Studio 部署。

Thinking 开关:使用 GGUF 版本时,enable_thinking: false 参数不生效,模型仍然输出思维链。这是 GGUF 格式的已知限制。

写在最后

从 V1 的推理蒸馏,到 V2 的效率优化,再到 V3 的工具调用——三个版本走下来,V3 的数据足以支撑结论:

  • • HumanEval 87.80%(9B),比原版 Qwen3.5-9B 高了近 5 个百分点
  • • MMLU-Pro 81.79%,通用知识反超基线(V2 掉的 7.2% 补回来了)
  • • 推理效率 +31.7%,每个正确答案的 Token 成本降低 24%
  • • ToolCall-15 满分 15/15,9B 打出了 27B 的水平
  • • 9B + Q6_K 只需 ~8GB 显存推理,16GB 内存 MacBook 就能跑

对于想在本地跑一个”能写代码、能调工具、还不太吃资源”的模型,Qwopus3.5-9B-v3 是目前最值得一试的选择。

Jackrong 在模型卡里写的一段话,我觉得很值得分享:

“没有人一开始就是专家。但每一个专家,都曾勇敢地迈出了第一步。”

这个项目从一个个人实验,到百万级下载量,证明了开源社区的力量。如果这篇教程帮你跑通了自己的蒸馏实验,也是一种”勇敢的第一步”。

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

基于 Jackrong 的开源工作整理,感谢 Unsloth 团队、老章、以及所有数据集贡献者。


💬 本文评论区已开启,但暂无读者留言。

本文转载自微信公众号,如有侵权请联系删除。

  • 标题: V3 来了!Claude-4.6-Opus 蒸馏 Qwen3.5,从"会思考"到"会干活"|保姆教程
  • 作者: lxiol
  • 创建于 : 2026-05-18 13:12:23
  • 更新于 : 2026-05-18 13:12:23
  • 链接: https://blog.lxiol.cn/2026/05/18/V3-来了Claude-46-Opus-蒸馏-Qwen35从会思考到会干活保姆教程/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
目录
V3 来了!Claude-4.6-Opus 蒸馏 Qwen3.5,从"会思考"到"会干活"|保姆教程