GPT 现状(State of GPT)
演讲者: Andrej Karpathy(安德烈·卡帕西) 来源: Microsoft Build 2023 — BRK216HFS
演讲者: Andrej Karpathy(安德烈·卡帕西)
来源: Microsoft Build 2023 — BRK216HFS
本稿依据官方英文(美国)字幕完整翻译。已删除时间轴和字幕断行,未作摘要或内容压缩;在保持原意与论述顺序的前提下,采用中国大陆 AI、LLM 与大型语言模型算法领域的常用专业术语,并保留关键英文原词。
主持人
有请 AI 研究员、OpenAI 创始成员 Andrej Karpathy。
Andrej Karpathy
大家好。很高兴来到这里,向各位介绍 GPT 的现状,以及更广泛意义上正在快速发展的“大语言模型”(Large Language Model,LLM)生态。我想把这次演讲分成两部分:第一部分介绍如何训练 GPT 助手(GPT assistant);第二部分讨论如何在实际应用中有效使用这些助手。首先,看目前逐渐形成的 GPT 助手训练方法。需要注意的是,这一切都非常新,而且仍在快速演进;但就目前而言,训练流程大致如下。这张幻灯片比较复杂,我会逐项说明。概括而言,整个流程包含四个依次进行的主要阶段:预训练(pre-training)、监督微调(Supervised Fine-Tuning,SFT)、奖励建模(reward modeling)和强化学习(Reinforcement Learning,RL)。每个阶段都有一套为其提供支撑的数据集。
每个阶段还需要相应的算法;就这里而言,它包括训练神经网络所使用的目标函数(objective)和优化器(optimizer)。训练完成后会得到对应的模型,幻灯片底部还列有一些补充说明。我们先从预训练阶段讲起。预训练在这张图中比较特殊,而且整张图并不是按实际规模绘制的,因为几乎所有计算工作都发生在这一阶段:它大约占总训练计算时间和浮点运算量(FLOPs)的 99%。这一阶段处理的是互联网规模的数据集,可能需要超级计算机中的数千块 GPU,并持续训练数月。其余三个阶段都属于微调阶段,通常只需少量 GPU,耗时为数小时或数天。下面来看如何通过预训练得到一个基础模型(base model)。
首先,我们要收集大量数据。这里展示的是一个所谓“数据混合”(data mixture)的示例,来自 Meta 发布 LLaMA 模型时发表的论文。图中大致列出了纳入该数据集合的各类数据集,包括网页抓取数据 Common Crawl、同样源自 Common Crawl 的 C4,以及一些高质量数据集,例如 GitHub、Wikipedia、Books、arXiv、Stack Exchange 等。所有数据会混合在一起,再按照给定比例采样,最终构成 GPT 的训练集。在真正开始训练之前,还需要完成一个预处理步骤:分词(tokenization)。
分词本质上是把从互联网上抓取的原始文本转换成整数序列,因为整数序列才是 GPT 工作时使用的原生表示。文本片段、词元(token)与整数之间可以进行无损转换,这一步有多种可用算法。例如,可以采用字节对编码(Byte Pair Encoding,BPE),通过迭代合并文本片段,将其组合成 token。这里展示了若干 token 片段,以及实际输入 Transformer 的原始整数序列。图中还给出了两个模型在这一阶段所采用的超参数(hyperparameter)示例。关于 GPT-4 的具体训练方式,我们没有公开太多信息,因此这里使用的是 GPT-3 的数据;当然,GPT-3 到当时已经是大约三年前的模型。LLaMA 则是 Meta 当时发布不久的模型。
这些数字大致体现了预训练所涉及的数量级。词表大小(vocabulary size)通常是数万个 token;上下文长度(context length)一般为 2,000、4,000,而如今甚至可以达到 100,000。它决定了 GPT 在预测序列中的下一个整数时,最多能够查看多少个整数。参数规模方面,LLaMA 约为 650 亿。虽然 LLaMA 只有 650 亿参数,而 GPT-3 有 1,750 亿参数,但 LLaMA 的能力明显更强。直观地说,这是因为 LLaMA 接受了长得多的训练:它使用了 1.4 万亿个 token,而不是 3,000 亿个。因此,不能只根据参数数量判断模型能力。
下面的表格列出了配置 Transformer 神经网络时通常会用到的一些大致超参数,例如注意力头数量(number of heads)、维度大小(dimension size)、网络层数(number of layers)等;底部则列出了一些训练超参数。例如,为了训练 650 亿参数的模型,Meta 使用了 2,000 块 GPU,训练约 21 天,成本大致为数百万美元。这就是理解预训练阶段时应当建立的数量级概念。那么,实际进行预训练时究竟发生了什么?概括来说,我们会把 token 排列成数据批次(data batch),构造出送入 Transformer 的数组。这些数组的形状是 B×T:B 表示批次大小(batch size),各行堆叠的是彼此独立的样本;T 表示最大上下文长度。为了便于绘图,图中的上下文长度只有 10,而实际值可能是 2,000、4,000 等。
因此,真实数组的每一行都非常长。我们把文档打包进这些行,并使用特殊的“文本结束”词元(end-of-text token)作为分隔符,告诉 Transformer 新文档从哪里开始。这里展示了几个文档示例,以及将它们展开后得到的输入。接下来,我们把所有这些数字输入 Transformer。先只关注其中一个单元格;图中每个单元格都会执行同样的过程。以绿色单元格为例,它会查看此前的所有 token,也就是所有黄色 token。我们把这一整段上下文输入 Transformer 神经网络,再由 Transformer 尝试预测序列中的下一个 token,也就是图中的红色 token。
遗憾的是,我没有足够时间详细解释 Transformer 的完整神经网络架构。对本次演讲而言,可以把它理解成一大团神经网络组件,通常包含数百亿参数。调整这些参数时,每个单元格所产生的预测分布都会略有不同。例如,假设词表大小为 50,257 个 token,我们就需要得到同样数量的数值,因为必须为下一个 token 的所有可能取值定义一个概率分布(probability distribution)。也每一种后续 token 都对应一个概率。在这个具体示例的特定单元格中,下一个 token 的真实编号是 513,因此可以把它作为监督信号,用于更新 Transformer 的权重。这个过程会并行应用于所有单元格;我们不断更换批次,训练 Transformer 正确预测序列中的下一个 token。下面用一个更具体的例子说明模型训练过程。
这个示例来自《纽约时报》:他们使用莎士比亚文本训练了一个小型 GPT。这里给出了一小段莎士比亚作品,并用它训练 GPT。初始化时,GPT 的权重完全随机,因此输出也是完全随机的。但随着训练时间增加,模型生成的样本会越来越连贯、越来越一致。采样过程是:先预测下一个 token,从预测分布中采样,再把采样结果反馈回模型,如此反复,便可以生成很长的序列。到最后,可以看到 Transformer 已经学会了词语,也知道应该在哪里添加空格、逗号等。随着训练进行,模型的预测会越来越一致。
进行模型预训练时,我们会观察这类曲线。实际上,关注的是损失函数(loss function)随训练时间的变化。损失越低,意味着 Transformer 为序列中正确的下一个整数分配的概率越高。假设训练一个月后得到模型,接下来要怎么使用它?整个领域首先注意到的是:模型在进行语言建模(language modeling)的过程中,会学习到非常强大的通用表征(general representation),因此可以非常高效地针对任意感兴趣的下游任务(downstream task)进行微调。例如,如果要做情感分类,传统方法是收集大量正样本和负样本,再为此训练一个 NLP 模型;新方法则是暂时忽略情感分类本身,先开展大语言模型预训练,训练一个大型 Transformer。随后,即使只有少量任务样本,也可以非常高效地把模型微调到情感分类任务上。实践证明,这种方法效果很好。
原因在于,在语言建模任务中,Transformer 实际上被迫同时处理海量任务。为了预测下一个 token,它必须理解文本结构以及其中包含的各种概念。这就是 GPT-1 阶段的情况。到 GPT-2 前后,人们发现,还有一种方法甚至比微调更有效:可以通过提示(prompt)高效驱动模型。这些模型是语言模型,其目标是续写文档,因此可以通过构造一份虚拟文档,“诱导”它们执行任务。例如,先给出一段文本,再依次安排“问题—答案、问题—答案、问题—答案”,这叫作少样本提示(few-shot prompt);最后只给出一个问题。Transformer 在尝试续写这份文档时,实际上就会回答最后的问题。这就是基于提示工程(prompt engineering)的方法:让模型认为自己正在模仿并续写一份文档,从而使其完成指定任务。
我认为,这开启了“提示优先于微调”的时代。即使完全不训练神经网络、不进行微调,提示也能在许多问题上取得非常好的效果。此后,我们看到了各种团队训练出的基础模型逐渐形成一棵完整的演化树。并非所有模型都可以获得,例如 GPT-4 的基础模型从未发布。你通过 API 交互的 GPT-4 并不是基础模型,而是助手模型(assistant model);稍后我们会介绍如何得到助手模型。GPT-3 基础模型曾通过 API 以 Davinci 的名称提供,GPT-2 基础模型甚至以权重形式发布在 OpenAI 的 GitHub 仓库中。在演讲当时,可获得的最佳基础模型可能是 Meta 的 LLaMA 系列,尽管它并未获得商业使用许可。这里需要特别指出:基础模型并不是助手。
基础模型的目标不是回答问题,而是续写文档。如果你让它“写一首关于面包和奶酪的诗”,它可能继续生成更多问题,因为它是在续写自己所理解的文档。不过,对于基础模型,可以采用一种更容易奏效的提示方式。例如写下“这是一首关于面包和奶酪的诗:”,此时模型就能正确续写。你甚至可以把基础模型“诱导”成助手:构造一个特定的少样本提示,使其看起来像一份人类与助手来回交流的对话文档,再在末尾放入你的查询。基础模型会据此调整生成分布,以一个乐于助人的助手身份回答。但这种方法不太可靠,实际效果也并不理想,尽管技术上确实可以做到。
要得到真正的 GPT 助手,而不是只会续写文档的基础模型,我们采用另一条路径,也就是监督微调。在监督微调阶段,需要收集规模较小但质量很高的数据集。具体做法是让人工标注人员收集“提示(prompt)+理想回答(ideal response)”形式的数据,通常要收集数万条。随后仍然在这些数据上执行语言建模;算法本身没有变化,只是替换了训练集。原来的训练集是数量巨大、质量较低的互联网文档,现在则换成数量较少、质量较高的提示—回答数据。
我们仍然执行语言建模,训练后得到监督微调模型(SFT model)。这类模型可以直接部署;它们已经是真正的助手,并且在一定程度上能够正常工作。下面来看一条示范数据可能是什么样子。人工标注人员先拟定一个随机提示,例如:“能否简要介绍‘买方垄断(monopsony)’这一术语的重要性?”
随后,标注人员还要写出理想回答。他们在撰写回答时,会遵循非常详细的标注规范,并被要求使回答做到有帮助(helpful)、真实(truthful)且无害(harmless)。这里展示的标注说明可能小得让你看不清,我也看不清,但它们非常长。标注人员就是依照这些说明完成提示。数据集大致就是这样,我们可以用它训练模型,并取得一定效果。在此基础上,还可以继续推进整个训练流水线,进入基于人类反馈的强化学习(Reinforcement Learning from Human Feedback,RLHF)。RLHF 同时包括奖励建模和强化学习两个阶段。
我先讲解这两个阶段,随后再回来说明为什么值得增加这些步骤,以及 RLHF 模型与 SFT 模型有何区别。在奖励建模阶段,我们会把数据收集方式改成“比较”(comparison)。这里展示了一条数据样例:顶部是同一个提示,要求助手编写程序或函数,检查给定字符串是否为回文(palindrome)。接着,我们使用已经训练好的 SFT 模型生成多个续写结果(completion)。这个例子中,模型生成了三个结果,然后我们请人类对它们进行排序。需要说明的是,比较这些预测结果可能非常困难。
对于一组提示—续写结果(prompt-completion pair),人工标注人员甚至可能花费数小时。假设经过比较,我们认为其中一个结果明显优于其他结果,并据此完成排序。随后,可以针对这些结果两两组成的所有可能组合,执行一种非常类似二分类的操作。具体来说,我们把提示排成多行,三行中的提示完全相同,但续写结果各不相同。黄色 token 来自 SFT 模型。然后,在每一行末尾附加一个特殊的奖励读出词元(reward readout token),并且只在这个绿色 token 的位置对 Transformer 施加监督。
Transformer 会预测一个奖励值,用来衡量某个续写结果对于该提示而言有多好,也就是估计每个结果的质量。模型为所有结果给出预测后,我们还有表示真实排序的基准标签(ground truth)。因此,可以约束其中一些数值必须显著高于另一些数值。我们把这种约束写成损失函数,再训练模型,使其奖励预测与人工比较得到的真实排序保持一致。这就是奖励模型(reward model)的训练方法。训练完成后,它可以为某一提示的续写质量打分。奖励模型本身不适合作为助手直接部署,但对随后的强化学习阶段非常有用。
有了奖励模型,就可以评价任意提示下任意续写结果的质量。在强化学习阶段,我们再次收集大量提示,并围绕奖励模型进行强化学习。过程如下:取出一个提示,将它排成多行;使用待训练模型生成图中的黄色续写。这个模型以 SFT 模型进行初始化。随后,再次在末尾附加奖励 token,并用此时已经冻结、不再更新的奖励模型读出奖励值。奖励模型会告诉我们每条提示下每个续写结果的质量。接下来仍然可以使用同样的语言建模损失函数训练黄色 token,但要根据奖励模型给出的奖励,对语言建模目标进行加权。
例如,在第一行中,奖励模型认为这个续写结果得分较高,因此这一行采样出的所有 token 都会得到强化,未来被采样到的概率随之提高。相反,奖励模型非常不喜欢第二行的结果,给出的奖励是 −1.2,因此第二行中采样出的每个 token,未来的概率都会略微下降。我们在许多提示和许多批次上反复执行这一过程,最终得到一个生成黄色 token 的策略(policy);它生成的续写结果会在上一阶段训练得到的奖励模型下取得较高分数。这就是 RLHF 流水线,最终得到的是一个可以部署的模型。
例如,ChatGPT 是一个 RLHF 模型,而你可能见过的 Vicuna-13B 等其他模型则属于 SFT 模型。因此,模型大致可以分为基础模型、SFT 模型和 RLHF 模型。这就是当时的整体情况。那么,为什么要做 RLHF?一个不算特别有趣、但非常直接的答案是:它的效果更好。这里的数据来自 InstructGPT 论文。在这些较早的实验中,图里的 PPO 模型就是 RLHF 模型。
把不同模型的结果交给人类比较时,可以看到 RLHF 模型在大量比较中更受偏好。相比 SFT 模型以及通过提示扮演助手的基础模型,人类更喜欢 RLHF 模型生成的 token。简单地说,它的效果就是更好。但为什么更好?我认为社区还没有形成一个唯一且非常完美的答案,不过可以给出一种可能的解释:从计算和认知难度来看,“比较”与“生成”之间存在不对称性。我们以创作俳句为例。
假设我让模型写一首关于回形针的俳句。如果你是负责收集 SFT 阶段训练数据的标注人员,要怎样凭空写出一首优秀的回形针俳句?你可能并不擅长。但如果我给你几首候选俳句,你很可能很容易看出其中一些明显优于另一些。判断哪一首更好,要比亲自生成一首容易得多。正是这种不对称性,使“比较”能够更有效地利用人的判断,从而训练出稍好的模型。不过,在某些方面,RLHF 模型并非严格优于基础模型。我们尤其注意到,RLHF 模型会损失一部分熵(entropy)。
这意味着其输出分布更加尖锐(peaky),生成样本的变化程度低于基础模型。基础模型具有较高的熵,因此能给出更加多样的输出。例如,有一类场景我仍然更喜欢使用基础模型:已有 n 个事物,希望继续生成更多同类事物。这里是我临时构造的一个例子。我想生成一些很酷的 Pokémon 名称,于是给出七个名称,让基础模型续写文档,它又生成了许多名称。
这些名称是虚构的。我尝试搜索过,它们应该不是真实存在的 Pokémon。这类任务非常适合基础模型,因为它仍然保有较高的熵,能够生成大量多样、新颖,同时又与前置示例相似的内容。说完这些,图中列出的就是演讲当时大概可以使用的助手模型。伯克利有一个团队对许多可用的助手模型进行了排名,并给出了 Elo 评分。
当时最优秀的模型显然包括 GPT-4,而且我认为它遥遥领先;其后是 Claude、GPT-3.5,以及其他一些模型。其中部分模型可能提供权重,例如 Vicuna、Koala 等。图中的前三行都是 RLHF 模型;据我所知,其余模型应该都是 SFT 模型。以上从高层视角说明了这些模型如何训练。下面转换话题,看看怎样把 GPT 助手模型更有效地应用到你的问题中。为便于说明,我想从一个具体例子入手。假设你正在撰写文章或博客,并准备在其中写下这样一句话:
“加利福尼亚州的人口是阿拉斯加州的 53 倍。”出于某种原因,你需要比较这两个州的人口。请想一想,为了生成这一句最终文本,你的大脑内部进行了多么丰富的内在独白(internal monologue)和工具调用,又完成了多少计算工作。大脑中的过程可能大致如下:“博客的下一句话要比较两个州的人口。首先,显然需要查到两者各自的人口。我知道自己无法直接回忆出准确数字,也我能意识到自己的知识边界。”于是,我开始使用工具,打开 Wikipedia,分别查询加利福尼亚州和阿拉斯加州的人口。
接下来,我知道应该用两个人口数相除,但我也知道,靠心算完成 39.2÷0.74 很难成功,这不是我擅长在脑中直接计算的任务。因此,我会借助计算器,输入数字,得到约为 53 的结果。随后,我可能在脑中进行反思和合理性检查(sanity check):53 倍合理吗?这个倍数确实相当大,但加利福尼亚州是人口最多的州,所以似乎也说得通。至此,我已经掌握了所需信息,可以进入创造性的写作环节。我可能先写出“加利福尼亚州有 53× 倍更多……”之类的句子,然后意识到这种表达非常别扭,于是删掉重写。在写作过程中,仿佛还有一个独立进程始终在检查文字、判断表达是否恰当;我可能删除、改写,直到对最终结果满意。
简而言之,人在生成这样一句话时,内在独白所包含的后台过程非常复杂。那么,训练 GPT 时,这句话对模型来说是什么样子?从 GPT 的视角看,它只是一串 token。GPT 读取或生成这些 token 时,只是一个片段接一个片段地向前推进,每生成一个 token 所投入的计算量大致相同。Transformer 并不是很浅的网络,它可能有大约 80 层,可以执行一定程度的推理;但 80 层仍然算不上非常深。Transformer 会尽力模仿训练数据,可这个过程显然与人类刚才经历的过程十分不同。尤其是,人类最终写成并放入数据集、再提供给 LLM 的成品文本,已经完全删去了所有内在对话。与人类不同,GPT 会逐个处理 token,并在每个 token 上投入近似相同的计算量。
因此,不能指望它在每个 token 上完成太多工作。更具体地说,Transformer 本质上很像 token 模拟器:它们“不知道自己不知道什么”,只是模仿下一个 token。它们不知道自己擅长什么、不擅长什么,只会尽力预测下一个 token;不会在循环中主动反思,不会执行合理性检查,也不会在生成过程中自行纠正错误。
默认情况下,它们只是对 token 序列进行采样。它们的“头脑”中没有一条独立的内在独白流,能够在旁边持续评估正在发生的事情。不过,我认为它们也有一些认知优势。首先,由于模型可能拥有数百亿参数,因此确实在广泛领域中储存了非常庞大的事实性知识;如此多的参数能够容纳大量事实。其次,它们拥有相对庞大而且近乎完美的工作记忆(working memory)。任何能够放进上下文窗口(context window)的内容,都可以通过 Transformer 内部的自注意力机制(self-attention)立即访问。因此,这种记忆虽然容量有限,却近乎完美;Transformer 可以直接访问上下文窗口中的内容,并无损地记住其中任何信息。
这就是我对人脑与 LLM 这两种系统的比较。之所以介绍这些,是因为我认为,提示在很大程度上就是为了弥补人脑架构与 LLM 架构之间的这种认知差异,几乎可以从这个角度理解提示。实践中,人们发现了一些效果很好的方法。尤其当任务需要推理时,不能期待 Transformer 在单个 token 内完成太多推理,必须把推理展开到更多 token 上。例如,不能向 Transformer 提出一个非常复杂的问题,却要求它用一个 token 直接给出答案;它根本没有足够的计算过程。
我有时会说:“Transformer 需要 token 才能思考。”一种有效做法是,在少样本提示中展示完整推导过程,让 Transformer 明白回答问题时应当写出解题步骤(show its work)。给出几个示例后,模型会模仿这种模板,最终在评测中取得更好的结果。还可以直接说“让我们一步一步思考(Let’s think step by step)”,以诱导模型表现出这种行为。这会让 Transformer 进入展示推导过程的模式,在更多 token 上展开更多计算;由于推理过程被放慢并沿时间展开,任务成功率也会提高。另一个例子称为自洽性(self-consistency)。人类写作时,如果第一次没有成功,可以重新尝试多次,再从中选出最好的结果。
采用这类方法时,不必只采样一次,而可以多次采样,再通过某种流程找出较好的结果,只保留这些样本,或者进行多数投票(majority vote)。和人一样,Transformer 在预测下一个 token 的过程中也可能“运气不好”,采样到一个不理想的 token,随后在推理上走入死胡同。与人类不同的是,它无法自行恢复。它必须接受自己已经采样出的每一个 token;即使已经进入不会成功的序列,也只能继续生成。因此,应当赋予模型回看、检查或绕开问题重新采样的能力。还有一种技巧:事实证明,LLM 往往知道自己犯了错误。例如,你要求模型生成一首不押韵的诗,它可能生成了一首实际押韵的诗。
但对于 GPT-4 这样规模较大的模型,只要追问一句“你完成要求了吗?”,它通常很清楚自己并没有完成要求。它只是采样时运气不好,会回答:“没有,我实际上没有满足这项要求,让我再试一次。”如果没有外部提示,它不会主动回看。因此,需要在 prompt 中补上这一步,要求模型进行检查;如果不要求,它就不会自行检查,因为它只是一个 token 模拟器。更一般地说,这些技术大多可以归入“为模型重建人类的系统 2(System 2)”这一类别。大家可能熟悉人类认知中的系统 1(System 1)和系统 2。
系统 1 是快速、自动的过程,我认为它对应于 LLM 直接采样 token;系统 2 则是大脑中速度较慢、更加审慎的规划过程。这里展示的是一篇就在演讲前一周发表的论文,因为这个领域的发展非常快。论文名为《思维树》(Tree of Thoughts)。作者提出:对于给定提示,同时维护多个续写分支,并在生成过程中持续为它们评分,只保留进展良好的分支。许多人都在尝试通过提示工程,把人脑具备的部分能力重新引入 LLM。这里需要注意的是,这已经不只是一个 prompt,而是多个 prompt 与 Python 胶水代码(glue code)的组合。因为系统必须同时维护多个 prompt,还要运行树搜索算法,决定接下来扩展哪些分支。
这实际上是 Python 胶水代码与单个 prompt 的协同:各个 prompt 在 while 循环或更大的算法框架中被反复调用。这里还可以与 AlphaGo 做一个很有意思的类比。AlphaGo 有一个决定围棋下一步落子位置的策略(policy),该策略最初通过模仿人类训练得到;但除了策略本身,它还会执行蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS),在内部推演多种可能性,对所有路径进行评估,只保留效果好的路径。可以把前面的方法理解为文本领域的 AlphaGo。与思维树类似,人们正在探索更通用的方法:不再满足于简单的“问题—回答”式 prompt,而是使用 Python 胶水代码,把许多 prompt 串联成更复杂的系统。
右侧展示的是 ReAct 论文中的例子。它把对提示的回答组织成“思考—行动—观察”(thought–action–observation)的循环序列,形成一次完整展开(rollout)和完整思考过程,最终回答查询。在“行动”步骤中,模型还可以调用工具。左侧是 AutoGPT 的例子。AutoGPT 当时获得了非常高的关注度,但我觉得它更主要的价值是提供启发。它允许 LLM 维护任务列表,并持续递归地拆分任务。我认为它在当时的实际效果并不好,也不建议大家把它用于生产应用;但从技术未来的发展方向看,它仍然值得借鉴。
这些方法相当于为模型赋予系统 2 式思考。接下来还有一个很有意思、近乎心理学特征的 LLM 现象:LLM 并不“想要成功”,它只“想要模仿”。真正想要成功的是你,因此你必须明确要求它成功。Transformer 的训练集包含从低到高的完整质量谱。例如,同一个物理问题的提示,在数据中可能对应一份完全错误的学生解答,也可能对应一份非常正确的专家答案。Transformer 既接触过低质量答案,也接触过高质量答案;但默认情况下,它想模仿的是全部数据,因为训练目标只是语言建模。到了测试或推理阶段(test time / inference time),你必须明确要求它给出高质量结果。
论文中的实验比较了多种提示。“让我们一步一步思考”非常有效,因为它把推理展开到了多个 token 上。但效果更好的一句话是:“让我们一步一步解决这个问题,确保得到正确答案。”这相当于让模型以“得到正确答案”为条件进行生成,因此 Transformer 的表现会更好;它不再需要把一部分概率质量(probability mass)分配给低质量答案,尽管听上去有些荒谬。总之,可以直接要求模型给出高水平方案,例如:“你是这个领域的顶尖专家”“假设你的 IQ 是 120”等。
不过,不要要求过高的 IQ。如果你写 IQ 400,输入可能落到分布外(out of distribution);更糟的是,它也可能落入科幻文本的数据分布,使模型开始采用科幻或角色扮演风格。因此,需要找到合适的 IQ 水平,我认为这里可能存在一条 U 形曲线。接下来,正如人类解决问题时知道自己擅长什么、不擅长什么,并会在计算上借助工具一样,也应该让 LLM 这样做。可以为模型提供计算器、代码解释器、搜索工具等;实现方式有很多。仍需注意的是,Transformer 默认可能并不知道自己不知道什么。
甚至可以在 prompt 中直接告诉 Transformer:“你不擅长心算。每当需要进行大数加法、乘法或其他类似计算时,请改用这个计算器。计算器应当通过以下 token 组合调用……”这些要求必须明确写出来,因为模型默认并不一定知道自己擅长或不擅长什么,而人类通常具有这种自我认知。另一个有意思的方向是:我们过去处在一个完全依赖检索(retrieval-only)的世界,随后钟摆又摆向另一个极端,变成 LLM 完全依赖参数记忆(memory-only)。但在两者之间,其实还有完整的检索增强模型空间,而且实践效果非常好。正如前面所说,Transformer 的上下文窗口就是它的工作记忆。
如果能把与任务有关的任何信息载入工作记忆,模型的表现会非常好,因为它可以立即访问这些内容。因此,很多人都在关注检索增强生成(Retrieval-Augmented Generation,RAG)。幻灯片底部展示了 LlamaIndex,它是一种连接多类数据的数据连接器(data connector)。可以对所有数据建立索引,使 LLM 能够访问它们。逐渐形成的典型流程是:获取相关文档,把它们切分成文本块(chunk),分别生成嵌入(embedding),得到表示这些数据的嵌入向量(embedding vector),再将其存入向量数据库(vector store)。推理时,系统向向量数据库发起查询,检索可能与当前任务有关的文本块,把它们填入 prompt,然后执行生成。实践中,这套方法效果很好。
这与人类解决问题的过程相似。人不可能完全依赖记忆完成所有事情;虽然 Transformer 也拥有庞大、广泛的参数记忆,但引用一手文档仍然非常有帮助。当你发现自己需要重新翻阅教科书,或者返回某个库的文档查询细节时,Transformer 也同样需要这样做。你可能凭记忆大致知道一个库的文档如何使用,但实际查阅文档往往更可靠;模型也是如此。接下来,我想简要介绍约束提示(constraint prompting),这也是一个很有意思的方向。
约束提示是强制 LLM 输出遵循特定模板的一类技术。Microsoft 的 Guidance 就是一个例子。这里,我们强制 LLM 输出 JSON。它可以保证输出严格采用指定格式,因为系统会干预 Transformer 输出的各个 token 的概率,对允许或禁止的 token 施加约束,使 Transformer 只能填充模板中的空白;还可以进一步限制每个空白位置允许填入什么内容。这会非常有帮助,我认为约束采样(constrained sampling)同样很值得关注。下面再谈几句微调。通过提示工程确实可以走得很远,但也可以考虑对模型进行微调(fine-tuning)。
微调意味着真正修改模型权重。由于近来出现了多种新技术及其配套库,实际进行微调已经越来越容易。例如,LoRA 这样的参数高效微调(Parameter-Efficient Fine-Tuning,PEFT)技术,只训练模型中少量、稀疏的部分。模型大部分参数都保持为基础模型的冻结状态,只有部分参数允许变化。经验上,这种方式仍然很有效,而且只调整模型的一小部分,成本要低得多。由于模型大部分权重被冻结,不会被梯度下降更新,因此对这些部分进行计算时还可以采用非常低精度的推理,从而进一步提高整体效率。此外,当时已经出现了一批高质量的开源基础模型。正如前面提到的,我认为 LLaMA 很不错,不过它在当时似乎没有获得商业使用许可。
需要注意的是,微调在技术上复杂得多,需要更强的专业能力才能正确实施。它往往需要人工数据标注团队来构建数据集,也可能需要相当复杂的合成数据流水线(synthetic data pipeline),因此会显著拖慢迭代周期。从较高层次看,SFT 是可以实现的,因为它只是延续语言建模任务,整体相对直接;RLHF 则仍然属于研究领域,难度高得多。我不建议缺少经验的团队直接自行实现一套 RLHF。它的训练过程相当不稳定、训练难度很高,对初学者并不友好,而且技术本身仍可能快速变化。这就是我在演讲当时给出的默认建议。
我建议把任务分成两个主要阶段,并严格按照顺序进行:第一,先达到最佳性能;第二,再优化性能与成本。要获得最佳性能,在当时应首先选择 GPT-4,它的能力明显领先。prompt 要写得非常详细,包含充分的任务背景、相关信息和明确指令。可以这样思考:如果把任务交给一个无法通过电子邮件向你追问的外包人员,你会一次性告诉他哪些信息?但同时也要记住,外包人员是人类,拥有内在独白并且很聪明,而 LLM 并不具备完全相同的能力。
因此,需要理解 LLM 特有的“心理机制”,并针对它设计 prompt。检索并加入与任务有关的上下文和信息,充分采用各种提示工程技术。前面的幻灯片只介绍了其中一部分,而这个领域非常庞大,建议继续查阅更多提示工程方法。可以积极尝试少样本示例(few-shot example)。
这里的关键是:只“告诉”模型还不够,只要条件允许,还应当“展示”给它看。尽可能提供示例,帮助模型准确理解你的意图。还应尝试工具和插件,把 LLM 原生不擅长的任务卸载给外部组件。不要只考虑一次 prompt 和一次回答,还要考虑可能的调用链(chain)、反思(reflection)、多个环节如何组合,以及怎样生成多个样本并筛选。最后,如果你认为提示工程已经挖掘到极限——我建议先在提示工程阶段坚持较长时间——再考虑针对应用微调模型,但要预期这会慢得多、涉及的工作也更多。再往后是由专家处理、相对脆弱的研究区域,也就是 RLHF。如果能够把 RLHF 训练好,它的效果确实可能略优于 SFT,但实现过程相当复杂。至于成本优化,则可以尝试能力较低的模型、缩短 prompt 等办法。
最后,我还想谈谈 LLM 在当时适合哪些应用场景。必须注意,LLM 存在大量局限;在设计所有应用时都应把这些限制考虑在内。这个主题本身足以单独讲一场,因此这里无法完整展开。模型可能带有偏见,可能编造或产生幻觉(hallucination),可能犯推理错误,也可能在某些完整的任务类别上表现不佳。模型还存在知识截止时间(knowledge cutoff),例如可能不了解 2021 年 9 月之后的信息。它们也容易受到大量攻击;当时 Twitter 上几乎每天都会出现新方法,包括提示注入(prompt injection)、越狱攻击(jailbreak)和数据投毒(data poisoning)等。因此,我当时的建议是:把 LLM 用于低风险场景(low-stakes application)。
始终配合人工监督(human oversight)使用 LLM。把它作为灵感和建议的来源,将其定位为副驾驶(copilot),而不是让完全自治的智能体(autonomous agent)在某处独立执行整个任务;当时的模型是否已经具备这种能力,还很不确定。最后我想说,GPT-4 是一项惊人的技术成果。我非常感谢它能够存在,也认为它很美。它在众多领域拥有海量知识,能够处理数学、代码等任务。
与此同时,围绕它还有一个蓬勃发展的生态,许多系统正在构建并被纳入其中。前面已经介绍了部分组件,而所有这些能力都触手可及。幻灯片上的代码,就是向 GPT-4 提问、发送 prompt 并获得响应所需的全部代码。在这个例子中,我问它:“你能否说几句话,鼓舞 Microsoft Build 2023 的观众?”我把问题输入 Python,GPT-4 逐字给出了下面的回答。顺便说一句,我当时并不知道主题演讲也使用了这种方式;我还以为自己的想法很巧妙,但 GPT-4 的确非常擅长这一点。它说:
“女士们、先生们,各位创新者与开拓者,欢迎来到 Microsoft Build 2023!欢迎参加这场汇聚非凡智慧的盛会。你们是未来的建筑师,是塑造人类赖以繁荣发展的数字世界的远见者。拥抱技术带来的无限可能,让你们的创意像想象力一样自由翱翔。让我们携手为后世创造一个连接更紧密、更卓越、更包容的世界。准备好释放创造力,探索未知,把梦想变为现实。你们的旅程,从今天开始!”