
1. 蒸馏攻击到底在攻击什么从模型能力迁移说起第一次听到“蒸馏攻击”这个词很多人会下意识觉得是某种网络入侵手段比如往服务器里注入恶意代码。其实不是。它攻击的不是你的服务器而是你的模型能力边界。要理解这件事得先搞清楚一个前提知识蒸馏本身是合法的、被广泛使用的模型压缩技术而蒸馏攻击是把这套技术用在了未经授权的目标上。1.1 知识蒸馏的本来面目知识蒸馏的核心思路很朴素让一个小的学生模型去模仿一个大模型教师模型的输出分布。传统训练里学生模型学的是硬标签比如一张图是猫就是猫标签是one-hot的。而蒸馏学的是软标签也就是教师模型输出的概率分布比如“猫0.85、狗0.1、兔子0.05”。这个软分布里包含了类别之间的相似性信息学生模型能学到更多东西。具体到损失函数学生模型的训练目标通常由两部分组成# 蒸馏损失的核心结构示意 loss alpha * KL_divergence(student_logits/T, teacher_logits/T) * T*T \ (1 - alpha) * cross_entropy(student_logits, hard_labels)这里的T是温度系数温度越高教师输出的分布越平滑学生能看到的“暗知识”越多。alpha是权重控制软标签和硬标签的平衡。这套机制本来是为了让小模型在资源受限的设备上也能跑出接近大模型的效果属于正经的工程优化手段。1.2 当蒸馏变成“攻击”那蒸馏攻击是怎么来的关键在于教师模型的来源。正常蒸馏教师模型是你自己训练的或者你有明确授权使用的。而蒸馏攻击的场景是攻击者没有目标模型的训练数据、没有权重、没有授权但可以通过API接口大量调用目标模型拿到它的输出分布然后拿这些输出去训练自己的模型。说白了就是用别人的模型当老师教出自己的学生然后拿这个学生去替代老师。这种行为之所以叫“攻击”是因为它绕过了目标模型的知识产权保护把对方投入大量算力、数据、人力训练出来的能力用相对低的成本“复制”走了。我见过一个很典型的案例某团队做了一个垂直领域的问答模型效果不错对外提供API。结果几个月后发现市面上出现了一个功能高度相似的开源模型一问才知道有人用他们的API批量生成问答对然后拿这些数据微调了一个基座模型。这就是蒸馏攻击的完整链路。1.3 为什么这件事值得关注你可能会想API本来就是给人调用的人家调用你的接口生成数据有什么问题问题在于规模和目的。正常用户调用API是为了解决自己的业务问题调用量是有限的、分散的。而蒸馏攻击的调用是系统性的、大规模的、有明确指向的——攻击者会针对性地构造输入覆盖目标模型的各种能力维度目的就是尽可能完整地提取模型的能力。从防御角度看这件事的难点在于你很难从单次请求判断对方是在正常使用还是在做蒸馏。一个请求问“帮我写一段Python代码”和一个请求问“帮我写一段Python代码要求包含异常处理、日志记录、类型注解”在单次看来都是合理需求。但当这类请求以每天几十万次的规模、覆盖各种边界情况出现时性质就变了。注意蒸馏攻击的判定不看单次行为看的是调用模式的整体特征。这也是为什么防御方案必须建立在行为分析之上而不是简单的关键词过滤。2. 蒸馏攻击的完整链路拆解从探测到替代理解了蒸馏攻击是什么接下来要搞清楚它是怎么一步步实施的。我把整个链路拆成四个阶段每个阶段都有对应的技术手段和特征。你只有把链路看清楚了才知道在哪一环设防最有效。2.1 第一阶段能力探测与边界摸底攻击者拿到一个目标模型的API之后不会上来就大规模调用。第一步是摸底——搞清楚这个模型会什么、不会什么、在哪些任务上强、在哪些任务上弱。这个阶段的典型操作是构造一批探测性输入覆盖不同的任务类型文本生成、代码补全、数学推理、逻辑判断、多轮对话、指令遵循等。每个任务类型下再细分难度层级比如数学推理从小学应用题到高等数学代码补全从单行到完整函数。探测的目的是画出一张能力地图。这张地图决定了后续蒸馏的策略如果目标模型在代码任务上特别强那就重点蒸馏代码能力如果它在多轮对话上表现一般那就可以少花力气。从防御侧看这个阶段的特征是请求的任务类型分布异常均匀。正常用户的请求往往集中在自己的业务领域比如一个做电商客服的系统请求大多是退换货、物流查询这类。而探测阶段的请求会横跨十几个不相关的领域每个领域的请求量还差不多。2.2 第二阶段大规模数据采集摸底完成后进入数据采集阶段。这一步的核心是构造高质量的输入获取高质量的输出。攻击者不会随便问问题而是会精心设计prompt让目标模型输出尽可能丰富、准确、结构化的内容。常见的采集策略包括指令多样化同一个问题用不同的问法比如“解释一下注意力机制”和“用通俗的话讲讲Transformer里的attention是怎么回事”目的是获取不同角度、不同详细程度的回答。链式追问先问一个宽泛的问题再基于回答追问细节逐层深入把模型的深层知识挖出来。格式约束要求模型以特定格式输出比如JSON、表格、分步骤说明方便后续直接用于训练。对抗性采样故意问一些容易出错的边界问题观察模型的失败模式这些失败案例对训练学生模型同样有价值。这个阶段的数据量通常很大从几万到几百万条不等。采集到的数据会经过清洗、去重、质量筛选最终形成一份高质量的指令微调数据集。2.3 第三阶段学生模型训练有了数据接下来就是训练学生模型。这里的选择很关键是用一个开源基座模型做微调还是从头训练一个小模型绝大多数情况下攻击者会选择开源基座模型加指令微调的路线。原因很简单从头训练成本太高而开源基座模型比如各种7B、13B参数量的模型已经具备了不错的语言能力只需要用采集到的数据做指令微调就能在特定任务上逼近目标模型的效果。训练过程中攻击者还会做一些针对性的优化数据配比调整根据探测阶段的能力地图给不同任务类型的数据分配不同的权重。课程学习先训练简单任务再逐步加入复杂任务让模型平稳地学习。拒绝采样用目标模型的输出作为参考答案对学生模型的输出做筛选只保留高质量的样本继续训练。2.4 第四阶段效果对齐与替代训练完成后攻击者会拿学生模型和目标模型做对比测试。测试的维度包括任务准确率、输出风格相似度、指令遵循能力、多轮对话连贯性等。如果某些维度差距较大就回到数据采集阶段针对性地补充数据。当学生模型的效果达到目标模型的80%到90%时攻击者就会认为蒸馏成功。这个学生模型可以被部署到自己的服务器上对外提供服务而不再需要调用目标模型的API。从这一刻起目标模型在这个任务领域内的商业价值就被大幅稀释了。整个链路的周期从探测到替代快的话几周慢的话几个月。对于API开放度高、输出质量好的模型这个周期会更短。3. 防御方的困境为什么传统手段拦不住知道了攻击链路直觉上会觉得防御应该不难——检测异常调用、限制调用频率、加水印总有一款能用。但实际操作下来你会发现每种手段都有明显的局限。这一章我把常见的防御思路和它们的失效场景讲清楚。3.1 频率限制的边界在哪里最直接的防御是限制调用频率比如每分钟最多100次、每天最多1万次。这个手段对普通滥用有效但对蒸馏攻击基本无效。原因在于攻击者可以通过多账号轮换来绕过频率限制。注册100个账号每个账号每天调用1万次总量就是100万次而每个账号看起来都是正常用户。更麻烦的是频率限制会误伤正常的高频用户。比如一个做批量文档处理的企业客户每天确实需要调用几万次API你把它限了客户就跑了。所以频率限制只能作为辅助手段不能作为主要防御。3.2 输出水印的鲁棒性问题输出水印的思路是在模型的生成结果里嵌入一些隐蔽的标记比如特定的词序、标点模式、同义词选择偏好。如果发现某个模型的输出里频繁出现这些标记就说明它是蒸馏产物。这个思路理论上可行但实际落地有几个坑水印会影响输出质量为了嵌入水印模型可能被迫选择不是最优的词导致输出质量下降。水印可以被清洗攻击者拿到数据后可以做一轮改写把水印洗掉。比如用另一个模型把输出重新表述一遍水印就没了。水印的检测需要大量样本单条输出很难判断有没有水印需要统计大量输出的特征分布这就回到了行为分析的范畴。3.3 行为分析的误报率难题行为分析是目前相对靠谱的方向核心思路是监控调用模式识别异常。比如请求的任务类型是否过于分散输入prompt的构造是否有明显的模板化特征调用时间是否集中在特定时段输出是否被系统性地存储或转发但这些特征都有误报的可能。一个做多领域问答的研究团队请求类型天然就是分散的一个做数据标注的公司prompt本来就是模板化的。你把这些人误判为攻击者轻则影响体验重则流失客户。所以行为分析的关键不是找到“绝对异常”的模式而是建立风险评分体系把多个弱信号综合起来达到一定阈值才触发告警或限制。这需要大量的调参和运营经验。防御手段有效性主要局限适用场景频率限制低多账号可绕过误伤高频用户辅助手段输出水印中影响质量可被清洗事后追溯行为分析中高误报率难控制需持续调参主要防御调用审计中事后发现无法实时阻断合规留痕模型指纹中需要预先设计鲁棒性存疑版权证明3.4 一个容易被忽略的点输出质量的“过度对齐”还有一个隐蔽的问题如果你的模型输出质量太高、太稳定反而更容易被蒸馏。因为攻击者拿到的数据质量高训练出来的学生模型效果就好。相反如果模型输出有一些随机性、有一些小瑕疵蒸馏出来的学生模型也会继承这些问题效果就打折扣了。这不是说要把模型做差而是说在API输出层面可以做一些可控的扰动比如在非关键位置引入轻微的表达变化或者对某些类型的请求返回稍微保守的回答。这样既不影响正常用户体验又增加了蒸馏的难度。4. 实操层面的防御体系搭建前面讲了困境这一章讲怎么在实际系统里落地一套防御体系。我的经验是不要指望单一手段解决问题而是要搭建一个多层联动的防御架构。下面按层次拆解。4.1 第一层调用身份与配额管理最基础的一层是身份管理。每个调用方都要有明确的身份标识不能匿名调用。身份可以是API Key、OAuth Token或者企业证书。有了身份才能做配额管理和行为追踪。配额管理要分级免费层低配额比如每天1000次适合个人开发者试用。标准层中等配额比如每天10万次需要企业认证。企业层高配额比如每天100万次以上需要签合同、明确使用场景。分级的目的是让攻击者的成本变高。如果攻击者想用免费账号做蒸馏1000次每天的配额根本不够用想用企业账号又需要提供真实的企业信息和用途说明暴露风险大。同时配额管理要配合动态调整。如果某个账号的调用模式突然变化比如从每天几百次跳到几万次系统应该自动触发审核而不是直接放行。4.2 第二层请求特征实时分析这一层是核心。每次请求进来系统要实时提取一批特征判断风险等级。特征可以分为几类输入特征prompt长度分布任务类型标签通过一个轻量分类器实时打标是否包含模板化结构比如固定的前缀、后缀是否包含多轮对话的上下文行为特征单位时间内的请求量请求的时间分布是否集中在非工作时段任务类型的分散度熵值请求之间的相似度是否在系统性地覆盖某个空间输出特征输出是否被完整存储通过响应大小和后续行为推断输出是否被用于二次请求比如拿输出当输入再问这些特征综合起来形成一个风险评分。评分超过阈值就触发不同的处置策略低风险只记录中风险加验证码或限流高风险直接阻断并人工审核。# 风险评分示意简化版 def risk_score(request_features, behavior_features): score 0 # 任务分散度越高风险越高 score behavior_features[task_entropy] * 0.3 # 模板化程度越高风险越高 score request_features[template_score] * 0.25 # 非工作时段调用占比越高风险越高 score behavior_features[off_hours_ratio] * 0.2 # 请求量突增风险高 score behavior_features[volume_spike] * 0.25 return score4.3 第三层输出端的主动防护输出端的防护有两个方向一是增加蒸馏难度二是埋设追溯线索。增加蒸馏难度的手段包括输出长度控制对某些类型的请求限制最大输出长度避免攻击者一次性拿到太多内容。信息密度调整在非关键位置增加一些冗余表述降低单位token的信息密度。随机化表达对同一语义的输出在措辞上做轻微随机化让攻击者拿到的数据分布更分散。埋设追溯线索的手段主要是隐式指纹。比如在生成的文本中按照特定规则选择同义词、调整标点、插入不影响语义的虚词。这些指纹单条看不出来但统计大量输出就能识别。一旦发现某个模型的输出里频繁出现这些指纹就可以追溯到它蒸馏自哪个目标模型。注意输出端防护要把握好度。过度扰动会伤害正常用户体验指纹设计也要避免被轻易逆向。建议在内部做A/B测试找到防护效果和用户体验的平衡点。4.4 第四层事后审计与法律手段技术手段之外审计和法律是必要的补充。审计层面要完整记录每次调用的身份、输入、输出、时间戳保留至少半年。这样一旦发现蒸馏行为可以拿出完整的证据链。法律层面API服务条款里要明确禁止将输出用于训练竞争模型。虽然这条条款的执行有难度但它提供了法律依据。一旦发现大规模蒸馏可以发律师函、提起诉讼至少能起到威慑作用。我见过一个团队的做法值得参考他们在服务条款里写明了“禁止将本服务输出用于训练任何第三方模型”同时在技术层面做了调用审计。后来发现一个账号的行为高度符合蒸馏特征他们先发了警告邮件对方没停然后直接封号并保留了法律追诉的权利。这个案例在圈子里传开后类似的攻击明显少了。5. 几个真实场景下的判断与处置理论讲完了这一章我用几个模拟场景来说明实际怎么判断和处置。这些场景来自我和同行交流时听到的案例做了脱敏处理。5.1 场景一任务类型突然分散的账号某个企业账号之前半年的调用记录都是集中在“合同条款问答”这一个任务上每天调用量稳定在5000次左右。突然有一天调用量涨到3万次而且任务类型变成了代码生成、数学解题、文案写作、翻译等十几个不相关的领域。判断这是典型的蒸馏探测特征。任务类型分散度突然升高调用量突增且与历史行为不符。处置系统自动触发审核暂时限流到每天1万次同时发邮件要求账号所有者说明用途。对方回复说是“内部测试新功能”但无法提供具体的测试计划。进一步核查发现该账号的调用IP段和另一个被标记过的账号重合。最终决定封号。5.2 场景二输出被系统性存储的迹象某个免费层账号每天调用量不大只有几百次但每次请求的prompt都特别长而且要求模型输出结构化内容比如“请以JSON格式列出所有可能的解决方案”。更可疑的是这个账号从来不进行多轮对话每次都是独立的单轮请求且请求之间的间隔非常规律像是脚本自动执行的。判断这是在系统性地采集结构化数据。单轮、长prompt、结构化输出、规律间隔这几个特征组合起来蒸馏意图很明显。处置免费层账号本身配额就低直接限制其输出长度并在响应里加入隐式指纹。同时把这个账号的行为模式加入风控规则库用于识别同类账号。5.3 场景三蒸馏产物的追溯某团队发现市面上出现了一个开源模型在多个任务上的表现和他们的商用模型高度相似连一些特有的错误模式都一样。他们怀疑是蒸馏产物但对方不承认。处置团队拿出了之前埋设的隐式指纹证据。他们在模型输出中按照特定规则使用了某些同义词组合这些组合在自然语料中出现的概率极低。对那个开源模型的输出做统计分析发现这些指纹的出现频率显著高于随机水平。虽然不能100%证明但作为证据已经足够有说服力。后续通过法律途径解决了。5.4 场景四误报的处理一个做学术研究的账号被系统标记为高风险原因是它的请求任务类型非常分散涵盖了十几个学科领域。系统自动限流后研究者发邮件申诉提供了研究项目的说明和论文草稿。判断这是误报。学术研究确实需要跨领域调用任务分散是正常需求。处置人工审核后恢复配额并将该账号加入白名单。同时调整风控规则对已认证的学术机构账号降低任务分散度的权重。这个案例说明风控系统需要保留人工审核通道不能完全自动化。场景核心特征风险等级处置方式任务类型突增分散度升高、量突增高限流审核结构化采集单轮、长prompt、规律间隔中高限制输出指纹蒸馏产物追溯输出分布高度相似高证据固定法律学术研究误报分散但有理有据低白名单规则调整6. 从防御视角反推模型提供方的长期策略前面讲的都是具体的防御手段和处置流程。这一章我想跳出来从更长期的角度聊聊模型提供方应该怎么思考这件事。因为蒸馏攻击本质上是一个成本博弈——攻击者的成本越低攻击就越频繁。防御的核心思路应该是抬高攻击成本同时降低防御成本。6.1 把API设计成“不容易被蒸馏”的形态大多数API的设计目标是“方便调用”但从防蒸馏的角度有些设计反而是在帮攻击者。比如返回完整的概率分布有些API会返回top-k的logits或概率这对蒸馏来说是最理想的数据。如果不是必须建议只返回最终文本不返回分布信息。支持超长输出一次性返回几千token的输出攻击者一次调用就能拿到大量数据。可以考虑对单次输出长度做限制或者对超长输出做分段返回。无状态调用每次调用都是独立的攻击者可以随意构造输入。如果引入会话状态要求多轮交互才能获取完整信息攻击者的采集效率就会下降。这些设计调整可能会牺牲一点便利性但能显著增加蒸馏的难度和成本。6.2 建立行业协作机制蒸馏攻击的一个特点是攻击者往往不只针对一家。今天蒸馏A模型明天蒸馏B模型用的可能是同一套工具和流程。如果各家模型提供方能共享攻击特征库比如异常账号的IP段、典型的探测prompt模式、已知的蒸馏工具指纹防御效率会高很多。当然这里涉及商业机密和数据隐私的问题共享的粒度需要仔细设计。但至少可以在行业协会或标准组织的框架下建立一个威胁情报交换机制把不涉及用户隐私的攻击特征拿出来共享。6.3 把防御成本纳入商业模型最后一点也是最容易被忽略的防御是有成本的。风控系统的开发、运维、人工审核都需要投入。这些成本最终要反映在API的定价里。如果你的API定价过低吸引来的用户里攻击者的比例就会偏高防御成本摊薄到正常用户身上反而伤害了正常用户。所以合理的定价策略本身就是一种防御。价格高一点攻击者的蒸馏成本就高一点同时你也有更多资源投入到防御体系建设中。这是一个正向循环。6.4 一个我个人的判断跟几位做模型服务的朋友聊下来大家有一个共识蒸馏攻击不可能被完全杜绝。只要模型通过API对外提供服务输出就必然可被获取蒸馏就必然可能发生。防御的目标不是“零攻击”而是把攻击的成本抬到足够高让大多数攻击者觉得不划算从而把攻击规模控制在一个可接受的范围内。这个思路和网络安全里的很多问题是一样的没有绝对的安全只有成本和收益的平衡。作为模型提供方你需要做的是让攻击者的投入产出比变得不划算同时让自己的防御投入产出比保持合理。这中间的分寸需要在实践中不断调整。我在实际搭建风控体系时最大的体会是规则不要一次定死要留出迭代空间。攻击手法在变你的规则也要跟着变。每季度回顾一次风控规则的有效性看看哪些规则误报率高、哪些规则已经失效及时调整。这件事没有一劳永逸的方案持续运营才是关键。