投机解码是一种给大模型生成文本提速的方法:先让一个小得多的草稿模型一口气猜出接下来几个词,再让大模型在一次计算里同时验算这几个候选,猜对的直接收下,第一个猜错的位置作废、从那里重新生成。它改的是生成时的计算组织方式,不改大模型的权重,也不换一个小模型来代写——用规范的拒绝采样做验证时,最终文本的概率分布和大模型自己逐词生成完全一致。先记住这一条,后面所有取舍都围绕它展开。
先看慢在哪:逐词生成是一场串行等待
大模型写文本是自回归的:写出一个词,把它拼回输入,再写下一个词。麻烦在于每写一个词,都要把整个大模型完整跑一遍,而单步计算的数据量又很小,显卡的大量并行算力其实在等着把模型权重从显存里搬进来。换句话说,生成慢很多时候不是算不过来,而是被一步一步的串行节奏拖住:前一个词没定下来,后一个词就没法开始。投机解码想利用的,正是这份闲置——既然大模型跑一次能同时处理多个位置,为什么不让它一次多验几个词?
一轮投机解码具体怎么跑
一轮流程可以拆成三步。第一步,草稿模型抢跑:它参数少、速度快,沿着当前文本连猜若干个词,比如连猜四个,凑出一小段草稿。第二步,目标大模型验证:把这段草稿拼到文本后面,只跑一次,就能同时得到每个位置上大模型自己认为各候选词的概率有多大——并行验算四个位置,花的接近平时写一个词的时间。第三步,逐个裁决:从第一个候选开始,按拒绝采样规则决定收还是不收;前面的都通过,就整段收下,而且因为大模型在草稿末尾之后的位置也顺带算出了分布,还能白赚一个额外词;一旦某个位置被拒,这个位置改由大模型按修正后的分布亲自写一个词,它后面的草稿全部作废,下一轮从这里重新抢跑。
这里最容易看漏的是裁决规则。接受一个候选词的概率,取决于大模型和草稿模型对这个词的概率之比:大模型越认可,越容易通过;草稿特别爱写、但大模型并不待见的词,大概率被拦下。被拦下的位置也不是随便换个词,而是按两个分布的差额重新采样。正是这套规则在数学上保证了:不管草稿模型猜得多离谱,最后产出的文本都严格服从大模型的分布。草稿影响的只有速度,从来不是答案本身。用贪心生成打比方更直观:验证就是核对草稿写的词,是不是大模型在那个位置最想写的那个,是就收,不是就换成大模型的版本。
它和量化、KV 缓存、蒸馏不是一回事
推理优化里几个名字经常被混在一起,其实动的地方完全不同。模型量化动的是权重精度:把参数用更少的比特存和算,模型变小变快,但输出会有细微变化。KV 缓存动的是重复计算:把前面词算过的键和值存下来免得重算,省的是同一步之内的浪费。模型蒸馏动的是模型本身:用大模型的输出训练一个小模型来替代它,输出分布从此是学生的,不再是老师的。投机解码哪个都不动:权重不压、模型不换,只是在生成流程里加了一个先猜后验的环节。所以它能和前几项叠加使用——量化的模型照样可以配草稿模型抢跑,KV 缓存也照常工作;它和蒸馏唯一的交集是,草稿模型常常借助蒸馏来贴近大模型的口味,但那只是草稿的来历,不改变验证环节的性质。
提速由接受率决定,草稿模型不是越小越好
一轮能推进几个词,取决于草稿被接受的比例,也就是接受率。接受率高,等于大模型每跑一次就批发出去好几个词,提速明显;接受率低,草稿写十个废八个,验证的功夫大半白费,还搭上草稿模型自己的耗时,整体可能比老实逐词生成还慢。接受率由三件事决定:草稿模型和大模型的口味有多接近、文本本身有多好猜、采样温度有多高。代码、套话、格式固定的文本规律性强,草稿容易连中;天马行空的创意写作和高温采样下,大模型自己都摇摆,草稿自然猜不准。草稿模型的选择也是平衡题:太弱,猜不准;太强,它自己就慢,抢跑省下的时间又还回去。工程上通常选同系列的小一号模型,或者给大模型加装专门的预测头——Medusa、EAGLE 这类变体就是把草稿能力直接长在目标模型身上,连独立草稿模型都省了,但代价是要额外训练这部分组件。
三个流传很广的误解
第一个误解是投机解码等于让小模型代写、答案会变差。每个最终落笔的词,要么被大模型按分布规则认可,要么直接由大模型在那个位置采样产生,小模型只有提名权,没有决定权。第二个误解是它在任何场景都能快上两三倍。公开报告里的漂亮倍数,大多来自单个请求、显卡算力有富余的场合;到了高并发服务,显卡本来就被一批请求喂满,并行验算省不出空闲算力,收益会明显缩水甚至为负,它省的是等待,不是总计算量。第三个误解是它会多占很多显存因而不值得。草稿模型通常只有目标模型的几十分之一到几分之一,占用相对有限;真正要算的账是接受率撑不撑得起这份额外开销,而不是先被多一个模型吓退。
什么场景值得用,什么场景先别指望
最适合投机解码的,是延迟敏感、低并发、生成又长的场合:本地跑开源模型聊天、写代码补全、一次生成大段文本,这时显卡有闲、用户在等字往外蹦,接受率也往往不低,主流推理框架如 vLLM、llama.cpp 等都已内置支持,打开开关再配一个同系列小模型就能试。不太值得指望的,是吞吐已经打满的在线服务、输出只有十几个词的短问答,以及手边根本没有口味相近草稿模型的情况——流程刚搭起来就结束,或草稿全靠蒙,加速无从谈起。判断顺序很简单:先确认自己的瓶颈是单请求延迟而不是总吞吐,再看文本类型容不容易猜中,最后才轮到挑草稿模型和调每轮抢跑的步数。