这两天 AI 社区里流传最多的一份文档是一篇 116 页的论文主题不是某个新模型发布而是“蒸馏”。论文标题直接点到了 Claude、GPT 这些闭源大模型配合“女娲造人 skill”“蒸馏自己”“Claude Code 本地部署”这些讨论很多人都在问是不是真的可以拿闭源模型当老师蒸馏出一个自己的小模型是不是能放在本地跑要不要先学会 Claude Code先说结论模型蒸馏本身不是新概念Hinton 早在 2015 年就把“知识蒸馏”讲明白了它的核心是用大模型老师的输出去教一个小模型学生达到接近的效果。但这篇 116 页的论文之所以引起讨论是因为它把蒸馏讲得更像一套可操作的工程流程怎么生成数据、怎么清洗、怎么用软标签训练、怎么评估学生的能力而不是停在公式和概念层面。这篇文章我会从工程角度拆解蒸馏这件事。先讲核心能力和适用边界再给出一套可以在本地跑通的蒸馏实验流程包括环境准备、数据生成、软标签训练、显存观察、API 调用和批量任务示例。如果你关心的是“我能不能拿一个开源小模型学出更好的效果”这篇文章可以直接收藏。有一点要先说明论文标题里提到的模型名称是否对应某个已经公开的具体版本需要以实际发布的官方信息为准。我更建议把注意力放在蒸馏方法论上因为方法本身是可以迁移的。1. 核心能力速览能力项说明项目类型论文 / 技术方法论围绕大模型知识蒸馏属于 AI 模型压缩与能力迁移方向核心技术知识蒸馏、软标签、温度系数、数据增强、小模型微调主要功能用大模型生成高质量数据训练小模型降低推理成本提升小模型专项能力推荐硬件常见做法是准备一块 8G 及以上显存的 GPU纯 CPU 可以做数据生成但训练小模型会偏慢显存占用取决于学生模型规模和 batch size实际占用需按本机测试为准支持平台通用 Python 环境Windows / Linux / macOS 均可训练密集任务推荐 Linux 服务器启动方式非一键包需要命令行或脚本启动可分为数据生成、训练、评估三个阶段是否支持 API需要调用模型 API 生成蒸馏数据时可复用 OpenAI / Claude / 其他兼容接口是否支持批量任务支持建议用脚本 多线程或队列方式批量生成数据并增加失败重试适合场景小模型专项能力提升、推理成本压缩、离线部署、垂直场景定制、教学实验这里要强调一句蒸馏闭源模型的结果能用多少取决于数据质量、学生模型容量和合规边界。工具链可以跑通但不代表可以随意拿某个闭源模型的输出去训练商用模型。2. 蒸馏的适用场景与使用边界2.1 适合谁蒸馏适合三类人。第一类是有垂直场景需求的开发者。你不想每次都调用大模型 API希望模型能在没有网络的服务器上跑延迟低、成本低。这时候用一个 1B 到 7B 的开源小模型配合蒸馏数据和微调可以接近大模型在特定任务上的表现。第二类是做模型部署和成本优化的工程师。同一个任务直接用闭源模型接口按 token 计费量大了成本很高。如果蒸馏出的小模型能在本机或私有云上顶住 80% 的请求整体预算能降下来。第三类是研究和小白学习者。蒸馏是一套理解大模型能力边界的好实验。你可以亲手做一个“老师模型 学生模型”的蒸馏流程观察温度系数、数据量、学生模型规模对最终效果的影响。2.2 不适合谁如果你以为“读完这篇论文就能把 Claude 完全复制到本地”那大概率会失望。原因有三点闭源模型的权重不公开你只能拿到输出样例拿不到完整的内部表示。蒸馏出来的学生模型效果高度依赖任务范围和训练数据覆盖度无法做到全能力复制。很多模型的官方服务条款对输出数据再训练有限制商用前必须确认授权。2.3 版权、隐私与合规边界这是蒸馏实践中最容易被忽视的部分。使用公开 API 生成训练数据首先要检查该 API 的服务条款是否允许将输出用于模型训练。不同模型商的政策不完全一样有的明确禁止有的需要额外授权。尤其是涉及人脸、声音、版权文字和私有数据时必须确认是否有合法授权。不要把蒸馏思路用于绕过付费限制、破解访问控制、模拟他人身份、生成违规内容。技术讨论归技术讨论实际使用时要在合法合规的测试环境里验证不要上来就拿线上真实数据跑蒸馏。3. 模型蒸馏的基础原理与论文阅读思路3.1 什么是知识蒸馏知识蒸馏的核心思想是迁移能力。训练一个学生模型时我们不只用真实标签还使用老师模型输出的概率分布。老师模型在某个输入上不会只说“答案是 A”而是会输出“A 的概率 0.7B 的概率 0.2C 的概率 0.1”这就是软标签。软标签里包含的信息比硬标签更多比如对某个问题B 和 C 可能非常接近这种相似性就是老师带出来的隐藏知识。为了让软标签更“软”蒸馏里还会引入温度系数 T。温度越高输出的概率分布越平滑小模型更容易学到类别之间的相似关系。训练时学生模型同时对齐真实标签和老师模型的软标签目标函数通常是真实标签的交叉熵加上软标签的 KL 散度。3.2 116 页论文该怎么读拿到一份 116 页的蒸馏论文不要从头逐字啃。先按下面这个顺序看摘要和结论判断论文主要贡献是什么是提出了新的蒸馏框架还是某类任务的蒸馏实践。实验设置看用了什么老师模型、什么学生模型、什么数据集。数据生成部分看作者是如何组织输入输出如何处理错误输出。这一部分往往是工程落地价值最高的。训练细节学习率、batch size、训练步数、是否用了 LoRA。评估方法看学生模型最终是用什么指标评价的。从标题信息看这份论文很可能覆盖了从数据到训练再到评估的完整流程所以上述读法会比逐页阅读更快定位关键内容。3.3 蒸馏时的关键变量亲手做蒸馏实验时至少要盯住四个变量数据量蒸馏数据太少学生模型学不到稳定规律数据太多成本高。建议先从小批量开始观察收益曲线。温度系数 T经典初始化是 1.0但实际任务里可能需要调整到 2.0 到 5.0要看预测分布的平滑程度。学生模型容量不是容量越大越好容量过大容易过拟合老师输出里的噪声容量过小表达能力不足。数据质量老师模型虽然强但也会犯错。直接拿原始输出训练会把错误也学进去。这一步要做数据清洗和结果过滤。4. 环境准备与前置条件下面是一套可落地的本地蒸馏实验环境你可以根据实际设备裁剪。4.1 基础环境建议使用 Python 3.10 或以上版本配合 conda 或 venv 创建独立环境避免依赖冲突。conda create -n distill python3.10 -y conda activate distill4.2 安装训练依赖小模型微调和蒸馏可以用 Hugging Face Transformers PyTorch 完成。pip install torch transformers datasets accelerate peft bitsandbytes如果显存紧张可以额外安装flash-attn或使用bitsandbytes的 4bit / 8bit 量化加载学生模型。4.3 安装 API 调用依赖如果你需要调用闭源模型生成蒸馏数据需要安装openai或对应模型服务的 Python SDK。pip install openai requests注意接口地址、模型名、密钥都要按你实际使用的服务商说明填写。不同服务的base_url可能不同不要照搬。4.4 GPU 检查训练前先确认 CUDA 和显卡驱动可用。import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU only)如果torch.cuda.is_available()返回 False优先排查驱动版本和 PyTorch 是否匹配当前 CUDA 版本。常见做法是安装对应 CUDA 版本的 PyTorch而不仅仅是系统里装过 CUDA。4.5 端口与进程蒸馏实验不像 WebUI 服务那样依赖端口但如果你用 Jupyter Notebook 或启动本地 API 服务要注意端口占用。启动失败时优先检查端口是否被其他进程占用lsof -i:7860如果端口被占用换一个端口运行即可。5. 蒸馏实验完整流程这一部分从零开始演示一个完整的蒸馏实验。目的不是跑出论文级别的数据而是把“蒸馏”变成可以亲手验证的流程。整个流程分为四个阶段数据生成、数据处理、训练学生模型、评估效果。5.1 准备种子任务集先准备一组任务。这里以文本问答为例种子数据不需要很大50 条就足够做第一轮实验。每条数据包含instruction和input。保存为seed_data.jsonl{instruction: 用一句话解释什么是数据库索引, input: } {instruction: 写一个 Python 函数判断字符串是否是回文, input: } {instruction: 把下面这句话翻译成英文今天天气很好, input: }这组种子数据是蒸馏的起点。关键是任务范围要明确不要一开始就铺一个泛到不行的“AGI 数据集”。5.2 用老师模型生成蒸馏数据接下来调用大模型 API为每条种子任务生成高质量输出。这一环节要注意三点温度不要太高建议 0.7 以内增加角色提示让模型输出“适合教学”的答案保留原始输出后续清洗用。import openai import json client openai.OpenAI( api_keyYOUR_API_KEY, base_urlYOUR_API_BASE_URL ) def generate_answer(instruction, input_text): response client.chat.completions.create( modelYOUR_TEACHER_MODEL, messages[ { role: system, content: 你是一个高质量教学助手。请给出准确、清晰、结构完整的回答。 }, { role: user, content: f任务{instruction}\n输入{input_text} } ], temperature0.6, max_tokens1024 ) return response.choices[0].message.content with open(seed_data.jsonl, r, encodingutf-8) as f: lines f.readlines() results [] for idx, line in enumerate(lines): item json.loads(line) answer generate_answer(item[instruction], item.get(input, )) results.append({ instruction: item[instruction], input: item.get(input, ), output: answer }) print(f[{idx 1}/{len(lines)}] generated) with open(distill_data_raw.jsonl, w, encodingutf-8) as f: for r in results: f.write(json.dumps(r, ensure_asciiFalse) \n)说明上面的YOUR_API_KEY、YOUR_API_BASE_URL、YOUR_TEACHER_MODEL是占位符必须替换成你自己有权限访问的服务配置。不要使用不明来源的代理接口。5.3 清洗蒸馏数据老师模型的输出不全是可用的。常见的清洗手段包括删除空输出和明显截断的输出。删除包含敏感、隐私、版权风险的内容。对同一问题生成多次选择稳定的答案。长度过短或过长的数据做人工抽查。在商用前至少对 10% 到 20% 的数据做人工抽验。清洗脚本示例import json def clean_output(text: str) - str: if not text: return None text text.strip() if len(text) 10: return None return text results_clean [] with open(distill_data_raw.jsonl, r, encodingutf-8) as f: for line in f: item json.loads(line) output clean_output(item.get(output, )) if output is None: continue results_clean.append({ instruction: item[instruction], input: item.get(input, ), output: output }) with open(distill_data_clean.jsonl, w, encodingutf-8) as f: for r in results_clean: f.write(json.dumps(r, ensure_asciiFalse) \n) print(fclean data count: {len(results_clean)})这一步绝不能省。数据质量直接决定学生模型最终效果垃圾进垃圾出。5.4 训练学生模型学生模型建议从开源小模型起步比如 Qwen、Llama、Gemma 的 0.5B 到 3B 版本。不要一上来就选 7B 以上先跑通流程再升级模型规模。下面是一个用 Hugging FaceTrainer微调的简化脚本。实际训练时你需要根据学生模型类型完善分词器填充逻辑和模板。import torch from transformers import ( AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments ) model_name Qwen/Qwen2.5-0.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16 if torch.cuda.is_available() else torch.float32, device_mapauto ) train_texts [] with open(distill_data_clean.jsonl, r, encodingutf-8) as f: for line in f: item json.loads(line) text f任务{item[instruction]}\n输入{item[input]}\n回答{item[output]} train_texts.append(text) train_prompts tokenizer( train_texts, truncationTrue, paddingmax_length, max_length512, return_tensorspt ) args TrainingArguments( output_dir./student_model, per_device_train_batch_size2, gradient_accumulation_steps4, num_train_epochs3, learning_rate5e-5, fp16False, bf16torch.cuda.is_available(), save_steps500, logging_steps10, report_tonone ) trainer Trainer( modelmodel, argsargs, train_datasettrain_prompts.dataset ) trainer.train() trainer.save_model(./student_model_final)这里给的是 CausalLM 的通用写法。跑之前要确认数据集格式和分词器能正确处理尤其是padding和truncation设置。5.5 软标签蒸馏方式如果你不想只做普通微调而是真正做经典的知识蒸馏就需要让老师模型输出软标签。做法通常是取老师模型最后一层 logits除以温度 T再做 softmax得到概率分布然后与学生模型的 logits 计算 KL 散度。伪代码流程import torch import torch.nn.functional as F T 2.0 teacher_logits get_teacher_logits(input_ids) # 具体实现按模型接口调整 student_logits get_student_logits(input_ids) teacher_probs F.softmax(teacher_logits / T, dim-1) student_probs_log F.log_softmax(student_logits / T, dim-1) loss F.kl_div( student_probs_log, teacher_probs, reductionbatchmean ) * (T * T)这里T * T是蒸馏论文里的常见缩放为了平衡温度带来的梯度尺度变化。如果你想更省资源也可以用老师输出文本作为目标做序列生成蒸馏也就是把蒸馏数据当普通训练语料来微调。两种方式的核心差别在于是否保留概率分布信息。5.6 评估学生模型训练完成后要评估不能只看 loss 下降。评估可以从三个维度做任务正确率准备一批老师模型没见过的测试问题看学生模型能否答对。输出稳定性多次采样看结果是否稳定、是否频繁出现截断或重复。与老师模型对比把学生输出和老师输出放一起人工或让评估模型打分。下面是一个简易评估脚本调用本地学生模型回答测试问题from transformers import pipeline pipe pipeline( text-generation, model./student_model_final, tokenizer./student_model_final ) test_question 写一个 Python 函数判断字符串是否是回文 result pipe( f任务{test_question}\n输入\n回答, max_new_tokens256, do_sampleTrue, temperature0.3 ) print(result[0][generated_text])注意pipeline对模型输出格式要求较高如果结果异常先检查学生模型是否真正完成了保存。6. 接口 API 调用与批量任务蒸馏实验真正进入工程化阶段会遇到两个问题一是大量数据生成二是批量微调任务。这两块都需要脚本化和队列化。6.1 批量生成数据建议把待生成的图片或文本输入放在一个目录里脚本遍历目录逐条调用 API 生成数据并输出到指定目录。目录结构示例data/ input/ 001.jsonl 002.jsonl output/ raw/ cleaned/ logs/ generate_001.log批量任务脚本需要重点处理两类问题超时和部分失败。API 调用往往会因为网络超时、限流、上下文过长而失败所以要对单条任务做 try-except并把失败任务单独落盘。import openai import json import time import os client openai.OpenAI(api_keyYOUR_API_KEY, base_urlYOUR_API_BASE_URL) def process_one(instruction: str, input_text: str) - str: resp client.chat.completions.create( modelYOUR_TEACHER_MODEL, messages[ {role: system, content: 你是一个高质量教学助手。}, {role: user, content: f任务{instruction}\n输入{input_text}} ], temperature0.6, max_tokens1024, timeout60 ) return resp.choices[0].message.content def wait_and_retry(instruction: str, input_text: str, retries: int 3): for attempt in range(retries): try: return process_one(instruction, input_text) except Exception as e: print(fattempt {attempt 1} failed: {e}) time.sleep(5) raise RuntimeError(retry exhausted) input_dir ./data/input output_dir ./data/output/raw os.makedirs(output_dir, exist_okTrue) for filename in os.listdir(input_dir): if not filename.endswith(.jsonl): continue with open(os.path.join(input_dir, filename), r, encodingutf-8) as f: items [json.loads(line) for line in f] outputs [] for item in items: ans wait_and_retry(item[instruction], item.get(input, )) outputs.append({instruction: item[instruction], input: item.get(input, ), output: ans}) out_path os.path.join(output_dir, filename) with open(out_path, w, encodingutf-8) as f: for o in outputs: f.write(json.dumps(o, ensure_asciiFalse) \n) print(fprocessing {filename} done, count{len(outputs)})6.2 批量训练任务训练阶段如果要实验多个学生模型或多种超参数不要手动一次次跑。建议写一个参数列表循环启动训练脚本每次把输出目录分开。python train_student.py --model Qwen/Qwen2.5-0.5B-Instruct --data distill_data_clean.jsonl --output ./experiments/exp1 python train_student.py --model Qwen/Qwen2.5-0.5B-Instruct --data distill_data_clean.jsonl --output ./experiments/exp2 --epochs 5在train_student.py内部把--epochs、--learning_rate、--batch_size都做成参数传入方便自动化批量实验。6.3 失败重试和日志批量任务卡住是常见坑。建议每条任务写入日志记录开始时间、结束时间、耗时。失败任务单独放在failed目录下次只重跑失败任务。单条任务设置超时时间避免一个错误请求卡住整个队列。大批量任务先跑 10 条观察稳定性再放全量。7. 资源占用与性能观察蒸馏实验的资源占用主要体现在两个阶段数据生成阶段和模型训练阶段。7.1 数据生成阶段如果调用云端 API本机资源占用很小主要消耗是网络带宽和 token 配额。如果只是整理和处理数据CPU 就能扛住。7.2 训练阶段显存占用主要由三部分构成模型权重、优化器状态、中间激活值。具体数字和模型参数量、batch size、序列长度、是否梯度累积、是否量化相关不能给出一个通用固定值。建议观察方式nvidia-smi -l 1训练时可以开另一个终端执行这条命令实时观察显存变化。如果看到显存接近满载就调小per_device_train_batch_size或者开启gradient_accumulation_steps来稳住有效 batch size。7.3 降低资源占用的方法显存不足时按顺序尝试这几招减小per_device_train_batch_size到 1。开启gradient_accumulation_steps比如设为 8。使用bitsandbytes4bit 量化加载模型。缩短max_length比如从 1024 降到 512。换更小的学生模型比如从 3B 降到 0.5B。使用 LoRA 微调而不是全量微调。使用 LoRA 时peft库可以帮上忙from peft import LoraConfig, get_peft_model lora_config LoraConfig( r8, lora_alpha16, target_modules[q_proj, k_proj, v_proj, o_proj], lora_dropout0.05, ) model AutoModelForCausalLM.from_pretrained(...) model get_peft_model(model, lora_config) model.print_trainable_parameters()注意target_modules会因模型结构不同而变化需要查看实际模型的模块名不能直接套用到所有模型。7.4 端口冲突和进程残留如果你还会启动本地 API 或 Jupyter训练中断后要检查是否有残留进程占用显存。推荐用nvidia-smi查看占用显存的进程 PID然后按需结束。kill -9 PID结束进程前确认不影响其他任务。8. 常见问题与排查方法问题现象可能原因排查方式解决方案API 调用报 key 错误API Key 配置错误或权限不足检查环境变量和代码里的 key重新配置正确的 key确认账号有模型访问权限数据生成超时网络不稳定或 max_tokens 过长查看日志里的 timeout 信息缩短单次 max_tokens增加重试次数降低并发训练时显存不足 OOMbatch size 过大或模型过大nvidia-smi 观察显存占用调小 batch size开启梯度累积使用量化或 LoRAtorch.cuda.is_available() 返回 FalsePyTorch 与 CUDA 驱动不匹配检查torch.version.cuda和nvidia-smi安装匹配的 PyTorch CUDA 版本学生模型输出重复或乱码数据格式问题或温度设置不合适查看生成 prompt 和采样参数降低 temperature增加训练轮次检查 tokenizer 填充训练 loss 下降但效果差数据分布和评测任务分布不一致检查训练集合测试集分布增加任务多样性扩充数据清洗低质量输出批量任务中途卡住单条请求卡死或没有超时控制检查日志最后一条耗时给请求加 timeout失败任务单独落盘重跑失败项模型输出包含截断内容max_tokens 设置太小查看输出末尾是否不完整调大 max_tokens或清洗时截掉不完整样本端口被占用已有服务占用端口使用lsof -i:端口号查看更换端口或停止占用进程9. 蒸馏工程化的最佳实践9.1 先小后大先测后量第一次跑蒸馏不要直接准备十万条数据。先用 50 条种子数据生成 200 到 500 条蒸馏数据训练一个小模型跑通评估流程。确定流程没问题后再扩大到完整数据集。9.2 保留最小可运行配置把一整套能跑通的最小配置记录下来包括学生模型名称。数据文件格式。训练脚本参数。评估 prompt。API 调用限额。下次换任务时基于这套配置做增量修改。9.3 分目录管理数据输入数据、原始输出、清洗后数据、训练日志、模型权重要分目录存放。命名规则要包含日期和实验标识例如20250107_qwen05_exp1。这样版本对比和回溯都会容易很多。9.4 批量任务必须加日志和重试大批量数据生成时不要只打印进度条。每条任务记录日志失败任务单独落盘。正确做法是任务完成后统计成功数、失败数和平均耗时。只有达到预期才进入训练阶段。9.5 接口服务限制访问范围如果你把蒸馏数据生成做成一个 HTTP 接口要限制访问范围不要暴露到公网。建议在127.0.0.1监听并给接口加上基础鉴权。9.6 涉及人脸、声音、版权素材必须确认授权这一点放到任何环节都不能忘。蒸馏过程中如果涉及用户数据、人脸照片、语音、版权文本必须确认这些数据有再训练和再发布的授权。否则即使技术跑通风险也不会消失。9.7 商用前做效果复核学生模型上线前至少要人工抽验一批输出结果。不能只看离线指标要看真实业务场景里的表现。特别要关注输出里是否有偏见、有害内容、版权内容和个人信息。10. 总结与下一步这篇 116 页论文最值得关注的地方是把模型蒸馏从理论推到了工程流程。哪怕你没有完整读完也可以抓住一条主线老师模型生成数据、清洗数据、微调学生模型、评估效果。这套流程拿到任何小模型上都能跑通。最先要验证的功能不是直接蒸馏某个闭源模型而是先从开源模型开始做一轮最小实验。用 Qwen 0.5B 做学生用你本地能访问到的模型接口当老师生成 200 条数据微调训练测试 5 到 10 个问题观察效果有没有提升。这个过程会一次性验证你的环境、数据格式、训练脚本和评估流程是否可靠。最容易踩的坑有两个一个是数据质量差没清洗就直接训练另一个是显存不足时报错就放弃完全没想过调 batch size 或换 LoRA。这两个坑都是工程问题不是算法问题提前安排好就能避开。后续可以继续扩展的方向建议按这个顺序来先把基础蒸馏流程跑通再尝试用软标签做真正的概率蒸馏接着引入 LoRA 降低训练成本然后尝试多任务蒸馏看看一份数据能否让学生模型同时学会代码、翻译和问答最后再把蒸馏好的模型封装成 API 服务接进自己的工具链。如果你想跟最近社区里那些讨论对齐比如 Claude Code 本地部署、用 skill 蒸馏自己的知识、把一本书蒸馏进知识库本质上都要回到同一件事数据组织和模型微调。先把这里的基础实验跑一遍再去做那些复杂场景会顺很多。建议收藏备用后续需要时直接按流程操作。