我们把视线放回到一个很容易被忽视但又很关键的问题上当我们需要让大模型稳定掌握一项能力时到底是把能力写成提示词更可靠还是把能力融进模型权重更可靠这篇文章要聊的研究方向标题很长但翻译过来很直白将技能蒸馏到权重中而不是塞进提示词抽象技能作为策略内自蒸馏的特权信号。简单说它解决的是“如何让模型真正学会技能而不是靠提示词临时假装会”。核心途径是在训练阶段使用“抽象技能”作为特权信号配合 on-policy 自蒸馏把一个技能从“可读的提示词描述”变成“模型内部权重里已经编码的行为”。在直接讲方法前先把最适合这篇文章的读者画个像关注 LLM 微调、蒸馏、RL 训练的技术同学被长提示词、复杂 few-shot 提示词搞到体感很差想尝试“把技能沉淀进模型”的工程师对 PPO 为什么是 on-policy、自蒸馏数据怎么组织、特权信号怎么用有概念但想系统梳理一遍的人。如果你属于其中任何一类这篇文章可以收藏后慢慢对着实验框架看。1. 核心概念速览先把这套方法的关键属性放在最前面能力项说明方法类型蒸馏 特权学习 策略内自蒸馏on-policy self-distillation核心主张技能应该融进模型权重而不是长期依赖提示词训练信号抽象技能标签作为 privileged signal训练阶段可见推理阶段不可见数据来源当前模型自身采样得到的 on-policy 轨迹与 PPO 的关系数据收集策略与 PPO 保持一致强调分布匹配与 RLHF/DPO 的关系可以独立使用也可以作为 RL 微调的前置蒸馏阶段推荐验证硬件视基座模型规模而定7B~13B 级模型需要 24G 以上单卡或量化方案是否需要显式提示词训练时可借助提示词辅助推理时目标是不依赖技能提示词适合场景高频、稳定、可重复的技能沉淀降低提示词长度和调用成本这里的参数不属于某个已开源项目的实测值。实际上这套思路更多来自 ACL/ICML 序列里对“distillation privileged information”的长期研究并没有统一的一键启动包。所以下面会按“方法拆解 - 训练框架 - 实验设计 - 工程化落地”的路径来讲而不是给安装命令。2. 为什么“提示词承载技能”这件事是靠不住的先看日常现象。现在很多大模型应用为了让模型做对一件事会把大量“技能”塞进提示词few-shot 示例动不动占上千 token把完整工作流写成自然语言指令塞进 system prompt每次调用都重复传同一段风格要求、格式要求、安全约束。这种做法的优点是灵活改提示词就能改行为。但缺点也很明显。第一提示词有上下文窗口上限。技能描述越长留给真实任务内容的 token 就越少。如果你需要一个 5000 token 的技能包而输入任务文本有 8000 token那基本就顶到窗口边缘了处理质量会迅速下降。第二提示词是位置敏感的。同一个技能描述放在 system 位置和放在用户消息末尾效果不一样放在超长文本中间还可能被模型忽略。模型对提示词的服从并不是稳定的换个模板结果就漂移。第三提示词有成本和延迟问题。每次请求都携带同样的大段技能描述意味着每次的 prefill 计算量都在增加TTFT 升高、成本上升。对高频接口调用来说这是很实际的压力。第四提示词是可泄露的。如果技能包里包含私有工作流、内部规则甚至敏感数据每次把提示词发给模型就会有被日志记录、被外部系统捕获的风险。把技能融进权重至少能减少一部分“明文暴露”面积。所以“技能放进权重而不是提示词”这个方向解决的不是“提示词能不能用”而是“能不能让模型在无提示场景下也能稳定执行技能”。3. 问题定义技能、特权信号和自蒸馏要理解这套方法先统一三个概念。3.1 抽象技能所谓抽象技能是指不绑定具体输入输出格式的高层能力描述。比如“先定位问题根因再给出修复方案”“按照时间线重排事件并区分事实与观点”“生成代码前先写测试用例”。它不等于“一步一步怎么做”的低级指令也不等于一段具体的 few-shot 示例。抽象技能更接近人类说的“我会用这个套路”而不是“我照着这个模板写”。3.2 特权信号“特权信号”来自 privileged information 这个经典概念。简单说训练的时候模型可以额外看到一个标签或者高级信息但在推理的时候这个信息不出现。最常见的例子就是“老师模型”和“学生模型”。老师模型在训练时能看到正确答案做辅助学生模型不能直接看到正确答案只能通过老师的输出分布来学习。在这套思路里模型训练时会被明确告知“这条轨迹对应的是技能 A”。这个技能标签就是特权信号。推理时模型并不知道技能标签它必须靠自己学出来的权重完成同样的行为。关键区别就在这里提示词方案是在推理时也把技能名或技能描述输入给模型特权信号方案只在训练时利用技能信号推理时不输入。3.3 自蒸馏自蒸馏简单说就是让模型自己教自己。如果模型当前生成的结果不够好但通过某种筛选、纠错、加约束得到了一批高质量轨迹就可以用这批轨迹继续训练模型自身。这里强调“自”是因为数据不需要外部大模型或者人工全部重写主要来自模型自身采样和基于自身分布的重建。成本更低而且分布与当前策略更匹配。3.4 组合起来把三者组合就是题目说的结构模型用当前策略生成一批轨迹每条轨迹被赋予一个抽象技能标签技能标签作为特权信号参与训练目标是在推理时不输入该信号模型也能复现对应技能行为。这是一个循环生成轨迹 - 标注技能 - 自蒸馏 - 更新策略 - 再生成轨迹。因为每一轮数据都来自当前策略所以是 on-policy 的自我提升闭环。4. 方法拆解以抽象技能为特权信号的策略内自蒸馏下面给出一个可以落地验证的方法框架。注意这不是复述某篇论文的精确公式而是根据这套思路整理出的通用实现路径。4.1 整体流程整个训练流程可以分成 4 步轨迹采样on-policy generation技能标注privileged labeling蒸馏目标计算distillation loss参数更新与循环。可以用下面的伪代码描述# 伪代码按论文思路整理的训练循环示意 model load_model(base_llm) skill_memory [] for iteration in range(N): # 1. on-policy 采样从当前策略生成轨迹 prompts sample_tasks(batch_size64) trajectories model.generate(prompts) # 2. 为每条轨迹标注抽象技能特权信号仅供训练使用 # 实际工程中可由规则分类器、小型标注模型或人工标签完成 skill_labels annotate_skills(trajectories) # 3. 构造“教师提示”训练时把技能作为提示辅助生成参考分布 teacher_input apply_skill_prompt(prompts, skill_labels) teacher_logits model.forward(teacher_input) # 4. 学生输入推理形态不注入技能提示 student_input prompts # 或者仅保留最基础的任务格式 # 5. 蒸馏让学生分布逼近教师分布 loss kl_divergence( student_logitsmodel(student_input), teacher_logitsteacher_logits ) # 也可以叠加 SFT / 偏好损失取决于任务类型 loss.backward() optimizer.step()这个循环的重点是每一步数据都来自当前模型而不是历史版本或者外部固定数据集这保证了数据分布与策略的一致性。4.2 教师提示怎么设计训练阶段可以“作弊”把技能写进提示词让模型先得到一个有技能引导的输出分布。这个分布称为教师分布。但在损失计算时学生输入不包含技能描述模型必须依靠权重内编码的能力去逼近教师分布。为什么不能直接微调“模型输出与目标文本”的交叉熵因为如果只有一个目标文本模型可能只是机械记忆。用教师分布做软目标学生能学到技能标签带来的“行为倾向”而不是死记某个答案。蒸馏的软标签信息量更大。4.3 技能标注来源给轨迹标注抽象技能工程上有三种可行方式规则匹配如果任务类型固定可以用规则直接映射。小型分类模型训练一个轻量分类器输入轨迹输出技能类别。LLM 自标注让一个额外模型或当前模型本身判断“这条轨迹更像哪个技能”注意这里需要防止信息泄漏标注结果只进训练损失不进推理输入。如果你的场景本身就有明确技能分类比如“代码审查”“SQL 生成”“报告摘要”最稳妥的做法是先用规则保证标签准确再逐步引入模型标注。4.4 推理阶段使用方式训练完成后推理阶段应该做到输入用户问题 输出模型直接给出符合技能要求的结果 不输入技能描述、few-shot 示例、步骤清单为了验证是否真的做到了可以设计这样一个实验对照组 A提示词中包含完整技能描述对照组 B提示词为空只有任务本身实验组使用蒸馏后的模型提示词为空只给任务本身。如果实验组的表现接近甚至超过对照组 A说明技能已经成功融进了权重。5. 为什么说 PPO 是 on-policy这对自蒸馏到底意味着什么热搜词里有“为什么说 PPO 是 on-policy”这里单独展开。因为不理解 on-policy就很难理解这套自蒸馏方法为什么强调数据来自当前策略。5.1 PPO 的 on-policy 含义PPO 的优化对象是当前策略。每一轮更新时它先让当前策略与环境交互采集一批轨迹然后用这批轨迹计算优势函数更新策略。更新完之后这批轨迹最好直接扔掉因为旧策略产生的数据已经不能准确反映新策略的行为分布。换句话说on-policy数据来自当前策略用一次就作废off-policy数据来自旧策略可以通过经验回放反复利用。PPO 通过重要性采样系数来控制新旧策略的偏差同时对更新步长做裁剪防止一次更新太猛。但归根结底它并不追求高效复用旧数据而是追求“每一步数据都与当前策略尽量匹配”。5.2 on-policy 对自蒸馏的影响自蒸馏如果使用历史版本模型生成的旧数据会有分布偏移问题。旧策略的语言风格、错误模式、思考方式都和新策略不同。如果蒸馏目标中混入大量旧数据模型会被拉向一个已经过时的行为分布。而 on-policy 自蒸馏要求模型在每一轮训练前重新生成轨迹。这样数据分布与当前策略一致模型不会学到一个“过期的自己”蒸馏信号能准确反映当前策略下的能力边界。这也是为什么这套方法会把 on-policy 作为核心词放在标题里。它借鉴的是强化学习中数据分布匹配的思想而不是单纯把蒸馏当离线数据处理来做。5.3 on-policy 的代价on-policy 的代价很直接每一轮都要重新采样推理开销巨大。对 7B 模型来说生成 1 万条轨迹可能需要几百 A100 小时。实际做的时候建议先缩小任务集和轨迹数量验证蒸馏效果后再扩容。6. 实验设计怎样验证“技能真的进入了权重”这一节给出一个可执行的验证方案不依赖外部基准适合你用自己的数据和场景跑通。6.1 选择技能组建议从 3 个方向各选一个技能结构化技能例如“输出必须包含背景、问题、方案、风险四段”推理技能例如“先拆解问题再给出结论”风格技能例如“用简洁中文回答不出现专业术语”。把技能描述写成标签比如skill_structure_4part、skill_reasoning_first、skill_plain_language。6.2 蒸馏前评估在蒸馏前先用基础模型做一组 baseline无提示词生成效果完整技能提示词生成效果部分技能提示词生成效果。记录三项指标格式符合率、语义正确率、关键点覆盖率。这样蒸馏后可以直接用同一套评估脚本对比。6.3 蒸馏后评估蒸馏后评估分三组无提示词输入输入一段无关提示词观察技能是否被干扰输入与技能相反的提示词观察技能稳定性。如果第 1 组接近 baseline 的完整技能提示词效果说明技能已经内化。第 2 组和第 3 组能帮你判断技能是“真正写入权重”还是“只是恰好记住了训练数据里的固定输入格式”。6.4 判断成功的标准一个合理的成功标准是无提示词效果达到完整技能提示词效果的 80% 以上在无关提示词干扰下技能效果不下降超过 10%模型在未见过的同类型任务上也能保持该技能。如果你的测试达不到这个标准先别急着加数据检查技能标签是否准确、教师分布是否稳定、训练步数是否足够。7. 训练框架与工程实现建议这个方向目前没有统一开源框架但可以基于常见训练工具搭一套最小实现。7.1 推荐技术栈组件建议基础模型7B~13B 开源模型例如 Qwen 系列、Llama 系列训练框架PyTorch Transformers TRL 或自写训练循环数据管理JSONL 格式存储 prompts、trajectories、skill_labels分布式训练单机多卡优先DeepSpeed ZeRO-2/3采样加速vLLM 或 SGLang 用于轨迹生成监控wandb 或 tensorboard7.2 数据格式示例建议把轨迹、技能标签、训练状态分开记录{ prompt: 请为上面的日志分析给出排查建议, trajectory: 第一先确认错误码..., skill_label: skill_reasoning_first, teacher_prompt: 技能说明先拆解问题再给出结论。用户问题请为上面的日志分析给出排查建议, student_prompt: 请为上面的日志分析给出排查建议, is_valid: true }这里要注意teacher_prompt和student_prompt都保留训练时用 teacher 的 logits 作为蒸馏目标只有 student 的 logits 参与梯度更新。7.3 损失函数设计实际的蒸馏损失可以拆成三部分loss ( alpha * kl_loss(student_logits, teacher_logits) beta * ce_loss(student_logits, reference_answer) gamma * skill_contrastive_loss(student_logits, negative_skill_logits) )参数说明kl_loss软蒸馏主损失ce_loss如果有标准答案加上监督信号skill_contrastive_loss可选让模型明确区分当前技能与其他技能的差异。最优参数需要按任务调试不建议直接照搬。7.4 训练稳定性控制蒸馏训练里最常遇到的问题是“学生输出退化”。控制训练稳定性有几个建议教师分布使用带温度的 softmax温度不宜太高通常 1.0~2.0对 KL 损失设置阈值如果学生与教师差异过大先暂停更新或降低学习率保留一份“冻结版本”模型每轮采样时用它当参考防止策略崩坏如果发现模型输出开始重复需要检查训练数据多样性并适当降低蒸馏权重。8. 资源占用与性能观察重点这里不给出具体显存数字因为和基座模型、序列长度、批量大小直接相关但可以给出观察方法和降载手段。8.1 观察什么训练过程中重点观察单卡显存占用以及是否出现 OOM每轮采样时间判断 on-policy 数据生产是否成为瓶颈KL 损失曲线判断学生是否稳定接近教师生成结果多样性防止 collapse。8.2 如何降显存在 24G 显存的单卡上7B 模型训练是比较紧张的选择。可以这样做使用 LoRA/QLoRA 做参数高效微调只训练 adapter把教师 logits 提前计算保存到磁盘避免训练时重复前向轨迹生成用 vLLM 的离线批处理训练时用浅层模型加载权重减少序列长度必要时对轨迹做截断。如果条件允许最舒服的配置是双卡 48G 以上一张卡跑采样一张卡跑训练或者用流水线并行。8.3 训练与推理的解耦一个常见问题是训练轮次多但采样和训练耦合导致 GPU 利用率很低。工程上建议把采样和训练拆成两个进程进程 A定时加载最新权重生成新轨迹进程 B消费轨迹训练模型两个进程通过文件系统或消息队列传递数据。这样可以让采样和训练各自用满 GPU而不是交替等待。9. 常见困惑与排查方法问题现象可能原因排查方式解决思路蒸馏后模型输出没变化KL 权重太低教师信号没有影响检查 loss 曲线中 KL 项是否下降调大 KL 系数提高训练步数无提示词时技能失效学生只在教师提示存在的输入分布上学到了对比 student_prompt 与 teacher_prompt 的数据结构增强 student_prompt 与真实推理输入的一致性模型开始复读蒸馏温度过高或数据多样性不足观察生成文本的 n-gram 重复率降低温度增加采样温度或轨迹数量技能 A 学会了技能 B 丢失训练数据中两个技能类别不均衡检查 skill_label 分布按技能类别加权采样或补充技能 B 轨迹on-policy 采样成本太高每轮重新生成大量轨迹统计单条轨迹平均生成耗时先小批量验证再用 vLLM 并行采样训练时显存 OOM序列过长或 teacher logits 占用查看显存监控截断轨迹、保存 logits、LoRA推理时发现技能提示词仍被需要训练没有完成真正的“去提示化”检查训练时 student_prompt 是否包含了技能描述确保 student_prompt 不含技能提示重复微调10. 设计 Engineering 思维把这个思路用在自己的系统里如果你不做论文实验只把“技能融进权重而不是提示词”当成一种产品设计思路同样有短期可落地的路径。10.1 什么场景适合“提示词转权重”技能稳定且长期不变调用频率很高token 成本敏感技能描述属于私有知识或安全规则不希望每次明文传输提示词已经长到影响效果比如超过 2K token 的技能包。10.2 什么场景不适合技能还在快速迭代每周都在变用权重更新跟不上技能只在一小部分请求中用到做成权重徒增存储和微调成本;技能强依赖外部实时信息本身无法完全靠模型权重承载团队没有微调基础设施只有 API 调用能力。10.3 渐进式落地建议计划可以分三步先把你系统里最稳定、最高频的一段技能提示词抽出来单独测效果用 on-policy 自蒸馏方式做一个技能蒸馏实验保留对照数据用 A/B 测试比较“提示词版”和“权重版”的效果、成本、延迟和稳定性。如果第一步和第二步效果稳定再扩展到更多技能。这里需要强调一点如果技能涉及隐私数据、他人版权内容或者人脸/声音等敏感信息训练数据收集和蒸馏过程必须确认已获得合法授权并且对数据访问权限做控制。不要把未授权的用户数据直接用于模型蒸馏。11. 总结与下一步这个方向值得尝试的核心点在于它把“提示词工程”问题重新拉回到“模型能力构建”层面。技能不再是一段写在请求里的文本而是模型参数中可被调用的行为模式。如果你的目标是降低接口调用成本、缩短提示词长度、让私有技能以更安全的方式部署那么“技能蒸馏到权重”非常值得做一轮小规模验证。最先应该验证的功能是选一个你手头最高频且稳定的技能用 on-policy 数据完成一轮蒸馏然后对比“无提示词 蒸馏模型”和“完整提示词 基础模型”的效果。这个对比能直接告诉你权重承载技能这条路在你场景里到底走不走得通。最容易踩的坑是训练时偷偷把技能标签传进了 student_prompt导致推理时没有技能提示就失效。这个坑手动检查 prompt 字段就能避开。后面的扩展方向也很清楚技能仓库统一管理、多技能蒸馏、蒸馏RLHF 结合以及把蒸馏后的模型封装成轻量 API 服务。每一步都能独立验证也都能复用本文这套评估思路。