📝
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 详细结果
工具调用强化训练(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 详细评测结果推理效率对比 —— 同样的准确率,V3 用更少的 Token:
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 等顶级模型,涵盖:
类别
代表数据集
用途
推理 & CoTJackrong/Qwen3.5-reasoning-700x 、Natural-Reasoning-gpt-oss-120B-S1
逐步推理能力
数学 & STEMDeepSeek-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 工具调用强化训练完成!")`
重要说明 :
GRPO 训练是可选步骤 。如果你只需要推理能力(不需要 Agent/工具调用),阶段一的 SFT 就够了。
上面的奖励函数是简化版示例。Jackrong 的实际 RL 训练使用了更复杂的奖励信号,针对 OpenClaw 等 Agent 框架做了专项优化。
Jackrong 的 GitHub 仓库(R6410418/Jackrong-llm-finetuning-guide)的 Roadmap 显示 GRPO pipeline 已 Released,完整训练 notebook 在 train_code/Qwopus3-5-27b-Colab.ipynb 中。
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)`
验证要点:
回复里有 <think>...</think> 结构化思维链 → 蒸馏成功
思维链是结构化的 (列大纲、分步骤),而非”长篇自言自语” → V3 特性生效
代码答案正确 → 推理能力迁移成功
方式二: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 兼容接口。
这是 V3 教程的特色环节——验证你训练的模型在工具调用场景下的表现。
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。
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_M23 Qwopus3.5-27B-v2
Q4_K_M
22Qwopus3.5-9B-v3 Q8_017 Qwen3.5-9B(基线)
—
5
9B 蒸馏版拿到 17 分,是基线 Qwen3.5-9B(5 分)的 3.4 倍。27B 版本 23 分接近满分。
量化精度对比 :
模型
TQ3_4S Perplexity
Qwopus3.5-9B-v36.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 团队、老章、以及所有数据集贡献者。
💬 本文评论区已开启,但暂无读者留言。
本文转载自微信公众号,如有侵权请联系删除。