投机采样的显性化——OpenAI新feature:Predicted Outputs

文摘   2024-11-05 23:25   新加坡  

关于投机采样speculative decoding我就不特别详细解释了

我在这里简单描述一下

小模型生成了接下来的n个标记,然后在大模型上进行n个并行推理,具体为:Prompt,Prompt + ST1,Prompt + ST1 + ST2 … Prompt + ST1 + ST2 … + STn。

(ST = 推测标记)

需要了解整个详细背景的,请看我原来的文章

OpenAI,Claude,Gemini御三家线上推理的杀手锏(Speculative Decoding)

这玩意本来大家都在用,因为省算力,同时降延迟。

但是OpenAI真的是一个非常产品化的公司,这点毋庸置疑,它居然把这么后台的东西都能做到前台feature来...

这个东西叫Predicted Outputs

其实投机采样的本质就是大模型给你checking小模型你decoding的对不,我们都知道decoding在现在的Transformer的体系里面,它就没个并行,因为是自回归的机制,别说Vllm,这块要是还不理解,建议理解一下Kv-cache的加速机理。

对同等遗传序列由于小模型Parameter少,层少,深度潜,那前向肯定比大模型快,这毋庸置疑。

但是有没有我连小模型都懒得用,直接上去checking

你别说,还真有可能,就是你把你认为高度重复的部分告诉我,那我把这个记住,你只要在prompt里标注出来它是被prediction的,那我就对这段不用复杂的自回归了,直接并行,咔一下就出结果了

也就是上来就来下面这样

Prompt,Prompt + ST1,Prompt + ST1 + ST2 … Prompt + ST1 + ST2 … + STn。

对用户的好处,那自然不必说,因为模型分为input和output token,你把本来应该output,token by token推理的output,给转成input了,input就可以prefill也就是玩kv-cache,也就可以被并行计算,那你说快不快,这也就节省了推理延迟,同时理论上,是省钱的,因为input token便宜,output贵。

其实道理就这么简单。

比如以下这段代码,你也不想改啥,你就想把username的部分,改成email

/// <summary>/// Represents a user with a first name, last name, and username./// </summary>public class User{    /// <summary>    /// Gets or sets the user's first name.    /// </summary>    public string FirstName { get; set; }
/// <summary> /// Gets or sets the user's last name. /// </summary> public string LastName { get; set; }
/// <summary> /// Gets or sets the user's username. /// </summary> public string Username { get; set; }}


那就直接把这个包进prediction里

import OpenAI from "openai";
const code = `/// <summary>/// Represents a user with a first name, last name, and username./// </summary>public class User{ /// <summary> /// Gets or sets the user's first name. /// </summary> public string FirstName { get; set; }
/// <summary> /// Gets or sets the user's last name. /// </summary> public string LastName { get; set; }
/// <summary> /// Gets or sets the user's username. /// </summary> public string Username { get; set; }}`;
const openai = new OpenAI();
const completion = await openai.chat.completions.create({ model: "gpt-4o", messages: [ { role: "user", content: "Replace the Username property with an Email property. Respond only with code, and with no markdown formatting." }, { role: "user", content: code } ], prediction: { type: "content", content: code }});
// Inspect returned dataconsole.log(completion);


然后llm拿到了直接上来就投机采样checking了,关于这部分被包进来的内容,那自然是比推理快的。

费用和时间的对比:

对比还是挺明显的,返回结果从5.2s降到了3.3s,快省1半了,那是相当的快了,但是这个省钱并没有,反而比原来贵了0.1555 cents到0.2675 cents,贵了小一半。那不对呀,本来应该output变input我便宜了才对啊

OpenAI的人的解释是

如果预测是100%准确的,那么你不会看到费用差异。当模型与你的推测有差异时,我们会进行额外采样以“发现”新的标记,这就是我们为什么按完成时间费率对被拒绝的标记收费的原因。(果然是黑店

不过确实是快,到是真的,这东西用好了,再加上其他的一些降低延迟的方法,例如端输出微调,并行回答,并行化投机采样的串行任务全都加上的话,那么你的LLM任务确实能达到非常好的优化,这本来是一门很科学的方法论,我们以后有时间再讲。

还是挺感慨和欣赏OpenAI做产品的力度和先进度的,所以随手写了一个小短文。很少有人能想到把这么后台的玩意变到前台来使用,还能赚钱


熵减AI
科技类博客