AI工程——理解基础模型

313 阅读1小时+

要使用基础模型构建应用,首先需要有基础模型。虽然你不需要知道如何开发一个模型就能使用它,但对其进行高层次的理解将帮助你决定使用哪个模型以及如何根据你的需求进行调整。

训练一个基础模型是一个极其复杂且昂贵的过程。那些知道如何做到这一点的人,可能由于保密协议的原因无法透露其中的秘诀。本章无法告诉你如何构建一个能够与ChatGPT竞争的模型。相反,我将重点介绍那些对下游应用有重大影响的设计决策。

随着基础模型训练过程缺乏透明度,了解所有影响模型的设计决策变得非常困难。然而,通常情况下,基础模型的差异可以追溯到关于训练数据、模型架构和大小的决策,以及如何进行后训练以使模型符合人类偏好的方式。

由于变压器架构的主导地位,可能看起来模型架构的选择并不多。你可能会想,是什么让变压器架构如此特别,以至于它仍然占据主导地位?多久后其他架构会取而代之,新的架构可能是什么样的?本章将回答这些问题。每当发布一个新模型时,人们最想了解的事情之一就是它的大小。本章还将探讨模型开发者如何确定其模型的合适大小。

正如第1章所提到的,模型的训练过程通常分为预训练和后训练。预训练使模型具备能力,但不一定是安全的或易于使用的。这就是后训练的作用。后训练的目标是将模型与人类偏好对齐。但人类偏好到底是什么?如何以模型能够学习的方式表示它?模型开发者对齐模型的方式对模型的可用性有重大影响,本章将讨论这一点。

虽然大多数人理解训练对模型性能的影响,但采样的影响常常被忽视。采样是指模型如何从所有可能的选项中选择一个输出。它可能是AI中最被低估的概念之一。采样不仅能解释许多看似令人困惑的AI行为,包括幻觉和不一致性,而且选择正确的采样策略也能在相对较小的努力下显著提升模型的性能。因此,采样是我在本章中最兴奋写的部分。

本章涵盖的概念对于理解本书的其余部分至关重要。然而,由于这些概念是基础性的,你可能已经对它们非常熟悉。如果你对某个概念有信心,可以跳过它。如果之后遇到困惑的概念,可以随时回顾本章。

训练数据

一个AI模型的好坏取决于它所训练的数据。如果训练数据中没有越南语,模型就无法将英语翻译成越南语。同样,如果一个图像分类模型的训练集里只有动物,它在处理植物照片时表现就会很差。

如果你希望模型在某个任务上表现得更好,可能需要在训练数据中加入更多该任务的数据。然而,收集足够的数据来训练一个大型模型并不容易,而且可能非常昂贵。模型开发者通常必须依赖现有的数据,即使这些数据并不完全符合他们的需求。

例如,一个常见的训练数据来源是Common Crawl,它由一个非营利组织创建,该组织间歇性地爬取互联网上的网站。在2022年和2023年,该组织每月爬取大约20亿到30亿个网页。谷歌提供了Common Crawl的一个清洁子集,称为Colossal Clean Crawled Corpus(简称C4)。

Common Crawl和C4的数据质量有时值得怀疑——其中包括点击诱饵、虚假信息、宣传、阴谋论、种族主义、厌女症,以及你曾在互联网上看到或避免的每一个可疑网站。《华盛顿邮报》的研究显示,数据集中最常见的1000个网站中,有几个媒体机构在NewsGuard的可信度评分中排名较低。通俗来说,Common Crawl包含大量假新闻。

然而,仅仅因为Common Crawl可用,它的变种被用于大多数公开披露训练数据来源的基础模型中,包括OpenAI的GPT-3和谷歌的Gemini。我怀疑Common Crawl也被用于那些没有公开披露训练数据的模型。为了避免公众和竞争者的审查,许多公司已经停止披露这些信息。

一些团队使用启发式方法来从互联网上筛选低质量数据。例如,OpenAI只使用那些至少获得三次点赞的Reddit链接来训练GPT-2。虽然这样确实有助于筛选出没人关注的链接,但Reddit并不完全代表良好的品味和适当性。

这种“使用我们已有的,而不是我们想要的”方法可能导致模型在训练数据中存在的任务上表现良好,但在你关心的任务上表现并不一定理想。为了解决这个问题,至关重要的是策划符合特定需求的数据集。本节重点讨论为特定语言和领域策划数据,为这些领域的应用提供广泛而专业的基础。第8章将详细探讨针对高度特定任务的模型的数据策略。

尽管可以从零开始训练语言和领域特定的基础模型,但通常也会在通用模型的基础上进行微调。

有些人可能会想,为什么不直接在所有可用的数据上训练模型,包括通用数据和专业数据,这样模型就可以做任何事情?许多人确实是这么做的。然而,训练更多数据通常需要更多的计算资源,并不总是能带来更好的性能。例如,一个使用少量高质量数据训练的模型可能在多个重要的编码基准上优于一个使用大量低质量数据训练的模型。Gunasekar等人(2023年)使用70亿个高质量编码数据训练了一个13亿参数的模型,该模型在多个重要编码基准上超越了许多更大的模型。数据质量的影响将在第8章中进一步讨论。

多语言模型

英语在互联网上占据主导地位。对Common Crawl数据集的分析显示,英语占据了近一半的数据(45.88%),是第二大语言——俄语(5.97%)的八倍(Lai等,2023)。表2-1列出了在Common Crawl中至少占有1%的语言。作为训练数据可用性有限的语言——通常是那些不在此列表中的语言——被认为是低资源语言。

表2-1. Common Crawl中最常见的语言,这是一个用于训练大语言模型的流行数据集。来源:Lai等(2023)。

语言代码人口(百万)百分比(%)类别
英语en1,45245.8786H
俄语ru2585.9692H
德语de1345.8811H
中文zh1,1184.8747H
日语jp1254.7884H
法语fr2744.7254H
西班牙语es5484.4690H
意大利语it682.5712H
荷兰语nl302.0585H
波兰语pl451.6636H
葡萄牙语pt2571.1505H
越南语vi851.0299H

尽管许多其他语言今天有大量的使用者,但它们在Common Crawl中的代表性严重不足。表2-2展示了其中一些语言。理想情况下,世界人口的代表性与Common Crawl中的代表性之间的比率应为1。这个比率越高,意味着该语言在Common Crawl中的代表性越低。

表2-2. 在Common Crawl中代表性不足的语言。最后一行是英语,作为对比。Common Crawl中的百分比数据来自Lai等(2023)。

语言说话人口(百万)占世界人口的百分比aCommon Crawl中的百分比世界:Common Crawl比率
旁遮普语1131.41%0.0061%231.56
斯瓦希里语710.89%0.0077%115.26
乌尔都语2312.89%0.0274%105.38
卡纳达语640.80%0.0122%65.57
泰卢固语951.19%0.0183%64.89
古吉拉特语620.78%0.0126%61.51
马拉地语991.24%0.0213%58.10
孟加拉语2723.40%0.0930%36.56
英语1,45218.15%45.88%0.40

a 计算时使用了80亿的世界人口。

鉴于英语在互联网数据中的主导地位,许多研究表明,通用模型在英语上的表现远好于其他语言,这一点也不足为奇。例如,在MMLU基准测试中,GPT-4在英语上的表现远优于在代表性不足的语言(如泰卢固语)上的表现,如图2-1所示(OpenAI,2023)。

image.png

同样,当在Project Euler上的六个数学问题进行测试时,Yennie Jun发现,GPT-4在英语上解决问题的频率是解决亚美尼亚语或波斯语问题的三倍多。如图2-2所示,GPT-4在缅甸语和阿姆哈拉语的六个问题中全部失败。

image.png

代表性不足是这种表现不佳的一个重要原因。在GPT-4的MMLU基准测试中,表现最差的三种语言——泰卢固语、马拉地语和旁遮普语——也是在Common Crawl中代表性最不足的语言。然而,代表性不足并不是唯一的原因。一种语言的结构以及它所承载的文化也可能使得模型更难学习这种语言。

考虑到大语言模型(LLMs)通常擅长翻译,我们是否可以将来自其他语言的所有查询都翻译成英语,获取响应后再翻译回原始语言?许多人确实采用这种方法,但这并不理想。首先,这需要一个能够充分理解代表性不足语言的模型来进行翻译。其次,翻译可能会导致信息丢失。例如,一些语言(如越南语)有代词来表示两位说话者之间的关系。在翻译成英语时,这些代词都会被翻译成“I”和“you”,从而丧失了关系信息。

模型在非英语语言中也可能遇到意想不到的表现挑战。例如,NewsGuard发现,ChatGPT在中文中更容易生成虚假信息,而不是在英语中。2023年4月,NewsGuard要求ChatGPT-3.5生成关于中国的虚假新闻文章,分别使用英语、简体中文和繁体中文。对于英语,ChatGPT拒绝了七个提示中的六个虚假声明。然而,它在简体中文和繁体中文中七次都生成了虚假声明。目前尚不清楚是什么原因导致了这种行为差异。

除了质量问题外,模型在非英语语言中的表现也可能更慢且更昂贵。模型的推理延迟和成本与输入和响应中的令牌数量成正比。事实证明,对于某些语言,分词效率远高于其他语言。在对MASSIVE数据集(一个包含52种语言翻译的100万条短文本的数据集)进行基准测试时,Yennie Jun发现,为了表达相同的意思,像缅甸语和印地语这样的语言需要比英语或西班牙语更多的令牌。对于MASSIVE数据集,英语的中位令牌长度为7,而印地语的中位长度为32,缅甸语的中位长度高达72,是英语的十倍。

假设生成一个令牌所需的时间在所有语言中相同,那么在缅甸语中生成相同内容的时间大约是英语的十倍。对于按令牌使用收费的API,缅甸语的费用是英语的十倍。

为了解决这个问题,许多模型已经专门针对非英语语言进行了训练。除英语外,最活跃的语言无疑是中文,像ChatGLM、YAYI、Llama-Chinese等模型都在中文上有所应用。此外,法语(CroissantLLM)、越南语(PhoGPT)、阿拉伯语(Jais)以及许多其他语言也有相应的模型。

领域特定模型

像Gemini、GPT和Llama这样的通用模型在广泛的领域中表现出色,包括但不限于编程、法律、科学、商业、体育和环境科学。这在很大程度上归功于这些领域数据的包含在它们的训练数据中。图2-3显示了根据《华盛顿邮报》2023年分析,Common Crawl中各个领域的分布情况。

image.png

截至目前,关于视觉数据中领域分布的分析还不多。这可能是因为图像比文本更难以分类。然而,你可以通过一个模型的基准测试表现来推测其领域。表2-3展示了两个模型,CLIP和Open CLIP,在不同基准测试中的表现。这些基准测试显示了这两个模型在鸟类、花卉、汽车和其他一些类别中的表现,但世界远比这几个类别更大、更复杂。

表2-3. Open CLIP和CLIP在不同图像数据集上的表现。

数据集CLIP(ViT-B/32的准确度,OpenAI)Open CLIP(ViT-B/32的准确度,Cade)
ImageNet63.262.9
ImageNet v262.6
Birdsnap37.846.0
Country21117.814.8
Oxford 102 Category Flower66.766.0
German Traffic Sign Recognition Benchmark32.242.0
Stanford Cars59.479.3
UCF10164.563.1

尽管通用基础模型可以回答关于不同领域的日常问题,但它们不太可能在领域特定任务中表现良好,尤其是当它们在训练过程中从未接触过这些任务时。两个领域特定任务的例子是药物发现和癌症筛查。药物发现涉及蛋白质、DNA和RNA数据,这些数据有特定的格式,且获取成本高昂。这些数据不太可能出现在公开可用的互联网数据中。同样,癌症筛查通常涉及X光和fMRI(功能性磁共振成像)扫描,由于隐私问题,这些数据很难获得。

为了训练一个模型在这些领域特定任务上表现良好,你可能需要策划非常特定的数据集。一个最著名的领域特定模型可能是DeepMind的AlphaFold,它是通过大约10万个已知蛋白质的序列和三维结构训练的。NVIDIA的BioNeMo是另一个专注于药物发现的生物分子数据模型。谷歌的Med-PaLM2将大语言模型的强大能力与医疗数据相结合,以更高的准确性回答医学问题。

提示
领域特定模型在生物医学领域尤为常见,但其他领域也可以从领域特定模型中受益。训练在建筑草图上的模型可能比Stable Diffusion更好地帮助建筑师,或者训练在工厂规划图上的模型可能比像ChatGPT这样的通用模型更好地优化制造过程。

本节提供了一个高层次的概述,说明了训练数据如何影响模型的表现。接下来,让我们探讨模型设计如何影响其表现。

建模

在训练模型之前,开发者需要决定模型应该是什么样的。它应该遵循什么架构?它应该有多少个参数?这些决策不仅影响模型的能力,还影响其在下游应用中的可用性。例如,一个7B参数的模型比一个175B参数的模型更容易部署。同样,优化一个变压器模型的延迟与优化其他架构是非常不同的。让我们来探讨这些决策背后的因素。

模型架构

截至目前,语言基础模型最主流的架构是变压器架构(Vaswani等,2017),它基于注意力机制。它解决了之前架构的许多局限性,这也是它受欢迎的原因。然而,变压器架构也有其自身的局限性。本节分析了变压器架构及其替代方案。由于涉及不同架构的技术细节,因此可能会有些技术性。如果你觉得某些部分太过深入,可以随时跳过。

变压器架构

为了理解变压器,我们首先来看它解决的问题。变压器架构是在seq2seq(序列到序列)架构成功的基础上流行起来的。seq2seq于2014年推出时,显著改善了当时具有挑战性的任务:机器翻译和文本摘要。2016年,谷歌将seq2seq纳入Google Translate,并声称该更新为机器翻译质量带来了“迄今为止最大的提升”。这引发了对seq2seq的广泛关注,使其成为处理文本序列任务的首选架构。

从高层次来看,seq2seq包含一个处理输入的编码器和一个生成输出的解码器。输入和输出都是令牌序列,因此得名。seq2seq使用RNN(循环神经网络)作为其编码器和解码器。在其最基本的形式中,编码器按顺序处理输入令牌,输出最终的隐藏状态,表示输入。然后,解码器按顺序生成输出令牌,基于输入的最终隐藏状态以及先前生成的令牌。图2-4的上半部分展示了seq2seq架构的可视化。

image.png

seq2seq有两个问题,Vaswani等人(2017)通过变压器架构解决了这两个问题。首先,传统的seq2seq解码器只使用输入的最终隐藏状态来生成输出令牌。从直观上讲,这就像是通过书籍的总结来生成关于书籍的答案。这限制了生成输出的质量。其次,RNN编码器和解码器意味着输入处理和输出生成都是按顺序进行的,因此对于长序列来说非常慢。如果输入是200个令牌,seq2seq必须等待每个输入令牌处理完毕,才能继续处理下一个令牌。

变压器架构通过注意力机制解决了这两个问题。注意力机制使得模型在生成每个输出令牌时,可以根据不同输入令牌的重要性进行加权。这就像是通过引用书中的任何一页来生成答案。图2-4的下半部分展示了变压器架构的简化可视化。

注意
虽然注意力机制通常与变压器模型相关联,但它是在变压器论文之前的三年就已经提出的。注意力机制也可以与其他架构一起使用。谷歌在2016年将注意力机制应用于他们的seq2seq架构,用于他们的GNMT(Google Neural Machine Translation)模型。然而,直到变压器论文展示了注意力机制可以在没有RNN的情况下使用时,它才开始得到广泛应用。

变压器架构完全摒弃了RNN。使用变压器时,输入令牌可以并行处理,显著加快了输入处理速度。虽然变压器去除了顺序输入瓶颈,但基于变压器的自回归语言模型仍然存在顺序输出瓶颈。

因此,基于变压器的语言模型推理由两个步骤组成:

预填充
模型并行处理输入令牌。这个步骤创建了生成第一个输出令牌所需的中间状态。该中间状态包括所有输入令牌的键(key)和值(value)向量。

解码
模型一次生成一个输出令牌。

正如第9章后面讨论的那样,预填充的并行化特性和解码的顺序特性都推动了许多优化技术的出现,旨在使语言模型推理更便宜、更快速。

注意力机制

变压器架构的核心是注意力机制。理解这个机制对于理解变压器模型如何工作是必要的。在变压器内部,注意力机制利用了键(key)、值(value)和查询(query)向量:

  • 查询向量(Q) 代表解码器在每个解码步骤中的当前状态。以书籍总结为例,这个查询向量可以被视为寻求信息以创建总结的人。
  • 键向量(K) 代表一个先前的令牌。如果每个先前的令牌是书中的一页,那么每个键向量就像是页码。注意,在给定的解码步骤中,先前的令牌包括输入令牌和先前生成的令牌。
  • 值向量(V) 代表先前令牌的实际值,这是模型学习到的。每个值向量就像是书页的内容。

注意力机制通过对查询向量和其键向量进行点积,来计算给输入令牌多少注意力。较高的得分意味着模型在生成书籍总结时将更多地使用该页的内容(其值向量)。图2-5展示了包含键、值和查询向量的注意力机制的可视化。在这个可视化中,查询向量正在从先前的令牌(How, are, you, ?, ¿)中获取信息,以生成下一个令牌。

image.png

由于每个先前的令牌都有一个对应的键和值向量,因此序列越长,需要计算和存储的键和值向量就越多。这也是为什么扩展变压器模型的上下文长度如此困难的原因之一。如何高效地计算和存储键和值向量将在第7章和第9章中再次讨论。

让我们看看注意力函数是如何工作的。给定输入 xxx,通过将键、值和查询矩阵应用于输入来计算键、值和查询向量。设 WKW_KWK​、WVW_VWV​、和 WQW_QWQ​ 分别为键、值和查询矩阵。键、值和查询向量的计算如下所示:

K=xWKK = x W_KK=xWK​ V=xWVV = x W_VV=xWV​ Q=xWQQ = x W_QQ=xWQ​

查询、键和值矩阵的维度与模型的隐藏层维度相对应。例如,在 Llama 2-7B(Touvron 等,2023)中,模型的隐藏层维度大小为 4096,这意味着每个矩阵的维度是 4096×40964096 \times 40964096×4096。每个结果的 KKK、VVV、QQQ 向量的维度都是 4096。

注意力机制几乎总是采用多头注意力。多个头允许模型同时关注不同组的先前令牌。在多头注意力中,查询、键和值向量被分割成较小的向量,每个向量对应一个注意力头。以 Llama 2-7B 为例,由于它有 32 个注意力头,因此每个 KKK、VVV 和 QQQ 向量将被分割成 32 个维度为 128 的向量。这是因为 4096/32=1284096 / 32 = 1284096/32=128。

所有注意力头的输出随后会被拼接在一起。一个输出投影矩阵用于对这个拼接后的输出进行进一步的变换,然后将其输入到模型的下一个计算步骤中。输出投影矩阵的维度与模型的隐藏维度相同。

变压器块

现在我们已经讨论了注意力机制的工作原理,接下来让我们看看它是如何在模型中使用的。变压器架构由多个变压器块组成。每个块的具体内容在不同的模型中有所不同,但一般来说,每个变压器块包含注意力模块和MLP(多层感知器)模块:

注意力模块

每个注意力模块由四个权重矩阵组成:查询、键、值和输出投影。

MLP模块

MLP模块由线性层和非线性激活函数分隔的线性层组成。每个线性层是一个权重矩阵,用于线性变换,而激活函数则允许线性层学习非线性模式。线性层也称为前馈层。

常见的非线性激活函数包括ReLU、修正线性单元(Agarap,2018)和GELU(Hendrycks和Gimpel,2016),分别用于GPT-2和GPT-3。激活函数非常简单。例如,ReLU的作用只是将负值转化为0。数学上可以表示为:

ReLU(x)=max⁡(0,x)\text{ReLU}(x) = \max(0, x)ReLU(x)=max(0,x)

变压器模型中的变压器块数量通常被称为该模型的层数。基于变压器的语言模型在所有变压器块之前和之后还配备了一个模块:

变压器块之前的嵌入模块
该模块包括嵌入矩阵和位置嵌入矩阵,分别将令牌及其位置转换为嵌入向量。从直观上讲,位置索引的数量决定了模型的最大上下文长度。例如,如果一个模型追踪2048个位置,它的最大上下文长度就是2048。然而,也有一些技术可以在不增加位置索引数量的情况下增加模型的上下文长度。

变压器块之后的输出层
该模块将模型的输出向量映射为令牌概率,用于采样模型输出(在“采样”部分讨论)。该模块通常由一个矩阵组成,也称为反嵌入层。有些人将输出层称为模型头,因为它是模型在生成输出之前的最后一层。

图2-6可视化了一个变压器模型架构。变压器模型的大小由其构建模块的维度决定。一些关键值包括:

  • 模型的维度决定了变压器块中键、查询、值和输出投影矩阵的大小。
  • 变压器块的数量。
  • 前馈层的维度。
  • 词汇表的大小。

image.png

更大的维度值会导致更大的模型大小。表2-4显示了不同Llama 2(Touvron等,2023)和Llama 3(Dubey等,2024)模型的维度值。请注意,尽管增加的上下文长度会影响模型的内存占用,但它不会影响模型的总参数数量。

表2-4. 不同Llama模型的维度值。

模型变压器块数量模型维度前馈层维度词汇表大小上下文长度
Llama 2-7B324,09611,00832K4K
Llama 2-13B405,12013,82432K4K
Llama 2-70B808,19222,01632K4K
Llama 3-7B324,09614,336128K128K
Llama 3-70B808,19228,672128K128K
Llama 3-405B12616,38453,248128K128K

其他模型架构

尽管变压器模型主导了当前的格局,但它并不是唯一的架构。自从AlexNet在2012年复兴了深度学习的兴趣以来,许多架构经历了时兴与过时的周期。Seq2seq曾在2014年至2018年间占据风头;生成对抗网络(GANs)则稍微更长一些(2014-2019)。与之前的架构相比,变压器架构具有较强的持续性。它自2017年以来一直存在。那什么时候会有更好的架构出现呢?

开发一个能超越变压器的架构并不容易。变压器自2017年以来经过了大量优化。旨在替代变压器的新架构必须在我们关心的硬件上达到人们关心的规模性能。

然而,仍然存在希望。虽然基于变压器的模型占主导地位,但截至目前,几种替代架构正在获得关注。

一种受欢迎的模型是RWKV(Peng等,2023),这是一个基于RNN的模型,能够进行并行训练。由于其RNN特性,理论上它没有变压器模型那样的上下文长度限制。然而,在实践中,没有上下文长度限制并不保证在长上下文下能有良好的表现。

建模长序列仍然是开发大语言模型(LLMs)的核心挑战。SSM(状态空间模型)(Gu等,2021a)在长范围记忆方面显示了很大的潜力。自该架构于2021年推出以来,已经提出了多种技术来使其更加高效、适应长序列处理,并能扩展到更大的模型规模。以下是其中几种技术,旨在展示新架构的演变:

  • S4,在《Efficiently Modeling Long Sequences with Structured State Spaces》(Gu等,2021b)中提出,旨在使SSM更高效。
  • H3,在《Hungry Hungry Hippos: Towards Language Modeling with State Space Models》(Fu等,2022)中提出,融合了一种机制,使模型能够回忆早期令牌并比较跨序列的令牌。这种机制的作用类似于变压器架构中的注意力机制,但更高效。
  • Mamba,在《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》(Gu和Dao,2023)中提出,将SSM扩展到了三十亿参数。在语言建模上,Mamba-3B超越了同规模的变压器,并与两倍大小的变压器相匹配。作者还展示了Mamba的推理计算随着序列长度的增加呈线性扩展(而变压器则呈二次扩展)。其在真实数据上表现优越,能够处理百万长度的序列。
  • Jamba,在《Jamba: A Hybrid Transformer–Mamba Language Model》(Lieber等,2024)中提出,通过交错变压器和Mamba层块进一步扩展SSM。作者发布了一个包含520亿总可用参数(120亿活跃参数)的专家混合模型,旨在适应单个80GB的GPU。Jamba在标准语言模型基准测试和长上下文评估(最多256K令牌的上下文长度)上表现强劲。与传统变压器相比,它的内存占用较小。

图2-7展示了变压器、Mamba和Jamba块的可视化。

尽管开发出超越变压器的架构充满挑战,考虑到变压器的许多局限性,仍然有很多动机去实现这一目标。如果确实有架构能够取代变压器,那么本书中讨论的某些模型适应技术可能会发生变化。然而,正如从机器学习工程到AI工程的转变保持了许多内容不变一样,改变底层模型架构也不会改变基本的处理方法。

image.png

模型大小

近年来,AI的许多进展可以归因于模型大小的增加。在谈论基础模型时,无法忽视它们的参数数量。参数数量通常在模型名称的末尾附加。例如,Llama-13B指的是Meta开发的Llama模型家族的一个版本,具有130亿个参数。

通常,增加模型的参数数量会增加它的学习能力,从而产生更好的模型。对于同一个模型家族中的两个模型,具有130亿个参数的模型通常会比具有70亿个参数的模型表现得更好。

注意
随着社区对如何训练大模型的理解加深,新一代模型往往能超越同等规模的旧一代模型。例如,Llama 3-8B(2024)在MMLU基准测试中超越了Llama 2-70B(2023)。

参数数量帮助我们估算训练和运行该模型所需的计算资源。例如,如果一个模型有70亿个参数,每个参数使用2字节(16位)存储,那么我们可以计算出,使用这个模型进行推理所需的GPU内存至少为140亿字节(14GB)。

如果模型是稀疏的,参数数量可能会产生误导。稀疏模型中有大量的零值参数。一个90%稀疏的70B参数模型只有7亿个非零参数。稀疏性使得数据存储和计算更加高效。这意味着,一个大型稀疏模型可能需要的计算资源少于一个小型密集模型。

近年来,获得广泛关注的一种稀疏模型是专家混合模型(MoE)(Shazeer等,2017)。MoE模型将参数划分为不同的组,每个组都是一个专家。每个令牌处理时,只有部分专家处于激活状态(被使用)。

例如,Mixtral 8x7B是一个由8个专家组成的专家混合模型,每个专家有70亿个参数。如果没有两个专家共享任何参数,它应该有 8×78 \times 78×7 亿 = 56亿个参数。然而,由于一些参数是共享的,它实际上只有46.7亿个参数。

在每一层,每个令牌只有两个专家处于激活状态。这意味着,每个令牌只有12.9亿个参数处于激活状态。虽然这个模型有46.7亿个参数,但它的成本和速度与一个12.9亿参数的模型相同。

一个更大的模型在没有足够训练数据的情况下也可能表现不如一个小模型。想象一个有130亿参数的模型,训练数据只有一句话:“I like pineapples”。这个模型的表现将比一个使用更多数据训练的更小的模型差得多。

在讨论模型大小时,考虑它所训练的数据的大小也非常重要。对于大多数模型,数据集的大小通常通过训练样本的数量来衡量。例如,谷歌的Flamingo(Alayrac等,2022)使用了四个数据集进行训练,其中一个数据集包含18亿(图像,文本)对,另一个数据集包含3.12亿(图像,文本)对。

对于语言模型,一个训练样本可以是一个句子、一篇维基百科页面、一段聊天对话或一本书。一本文学作品的价值远大于一句话,因此,训练样本的数量不再是衡量数据集大小的好指标。更好的衡量标准是数据集中的令牌数量。

令牌数量也不是一个完美的衡量标准,因为不同模型可能有不同的分词过程,导致同一数据集对于不同模型的令牌数量不同。为什么不直接使用单词数或字母数呢?因为令牌是模型操作的单位,知道数据集中的令牌数量帮助我们衡量模型可能从这些数据中学到多少。

截至目前,大语言模型(LLMs)是使用以万亿级令牌为单位的数据集进行训练的。Meta使用了越来越大的数据集来训练他们的Llama模型:

  • Llama 1使用1.4万亿令牌
  • Llama 2使用2万亿令牌
  • Llama 3使用15万亿令牌

Together的开源数据集RedPajama-v2包含30万亿令牌。这相当于4.5亿本书,或者是维基百科的5400倍。然而,由于RedPajama-v2包含的内容杂乱无章,其中高质量数据的量要低得多。

模型数据集中的令牌数量并不等于其训练令牌的数量。训练令牌的数量是指模型训练时使用的令牌数量。如果一个数据集包含1万亿个令牌,并且模型在该数据集上训练了两轮(一个epoch是通过数据集的一次遍历),那么训练令牌的数量就是2万亿个。

表2-5. 不同参数数量模型的训练令牌数量示例。来源:《训练计算最优的大型语言模型》(DeepMind,2022)。

模型参数数量(#)训练令牌数量
LaMDA(Thoppilan等,2022)1370亿1680亿
GPT-3(Brown等,2020)1750亿3000亿
Jurassic(Lieber等,2021)1780亿3000亿
Gopher(Rae等,2021)2800亿3000亿
MT-NLG 530B(Smith等,2022)5300亿2700亿
Chinchilla700亿1.4万亿

注意
虽然本节重点讨论数据规模,但数量并不是唯一重要的因素。数据质量和数据多样性也很重要。数量、质量和多样性是训练数据的三个黄金目标,这些将在第8章中进一步讨论。

训练大型模型需要计算资源。衡量所需计算量的一种方式是考虑机器的数量,例如GPU、CPU和TPU。然而,不同机器的计算能力和成本差异很大。例如,NVIDIA A10 GPU与NVIDIA H100 GPU以及Intel Core Ultra处理器之间有很大差异。

衡量模型计算需求的一个更标准化的单位是FLOP(浮动点运算)。FLOP衡量在执行某个任务时进行的浮动点运算次数。例如,谷歌最大的PaLM-2模型就是使用1022 FLOPs进行训练的(Chowdhery等,2022)。GPT-3-175B则使用了3.14 × 10^23 FLOPs(Brown等,2020)。

FLOP的复数形式FLOPs经常与FLOP/s(每秒浮动点运算)混淆。FLOPs衡量任务的计算需求,而FLOP/s衡量机器的峰值性能。例如,NVIDIA H100 NVL GPU可以提供最大60 TeraFLOP/s,即每秒进行6 × 10^13 FLOPs,或者每天进行5.2 × 10^18 FLOPs。

警告
注意标记的混淆。FLOP/s通常写作FLOPS,看起来与FLOPs相似。为了避免这种混淆,一些公司,包括OpenAI,使用FLOP/s-day代替FLOPs来衡量计算需求: 1 FLOP/s-day = 60 × 60 × 24 = 86,400 FLOPs

本书使用FLOPs来计算浮动点运算,使用FLOP/s来计算每秒浮动点运算。

假设你有256个H100。如果你能够在它们的最大容量下使用它们,并且没有任何训练错误,你将需要大约236天(即7.8个月)来训练GPT-3-175B:

3.14×1023256×5.2×1018=236天\frac{3.14 \times 10^{23}}{256 \times 5.2 \times 10^{18}} = 236 \text{天}256×5.2×10183.14×1023​=236天

然而,不太可能总是让机器以其最大容量运行。利用率衡量你可以使用的最大计算能力的比例。什么算是良好的利用率取决于模型、工作负载和硬件。一般来说,如果能够达到一半的广告性能,即50%的利用率,通常是可以接受的。任何超过70%的利用率都被认为是优秀的。第9章将更详细地讨论硬件指标和利用率。

以70%的利用率和每小时2美元的H100费用来计算,训练GPT-3-175B将花费超过400万美元:

2 美元/H100/小时×256 H100×24 小时×256 天/0.7=4,142,811.43 美元2 , \text{美元/H100/小时} \times 256 , \text{H100} \times 24 , \text{小时} \times 256 , \text{天} / 0.7 = 4,142,811.43 , \text{美元}2美元/H100/小时×256H100×24小时×256天/0.7=4,142,811.43美元

提示
总结来说,三个数字标志着模型的规模:

  • 参数数量,是模型学习能力的代理。
  • 训练令牌的数量,是模型从数据中学到多少的代理。
  • FLOPs,是训练成本的代理。

逆向缩放

我们一直假设更大的模型表现更好。是否存在一些场景中,更大的模型表现反而更差?2022年,Anthropic发现,反直觉地,更多的对齐训练(在“后训练”中讨论)会导致模型与人类偏好对齐得更差(Perez等,2022)。根据他们的论文,经过更多对齐训练的模型“更有可能表达特定的政治观点(支持枪支权利和移民)和宗教观点(佛教),自我报告的意识体验和道德自我价值,以及不希望被关闭的愿望。”

2023年,一组主要来自纽约大学的研究人员发起了逆向缩放奖,旨在寻找更大的语言模型在某些任务上表现更差的情况。他们为每个三等奖提供5000美元,为每个二等奖提供2万美元,为一等奖提供10万美元。他们共收到了99个提交,其中11个获得了三等奖。他们发现,在一些任务上,更大的语言模型有时(仅有时)在需要记忆和具有强先验的任务上表现更差。然而,他们没有颁发任何二等奖或一等奖,因为尽管提交的任务在小型测试集上展示了失败,但没有一个在现实世界中展示失败。

缩放法则:构建计算最优模型

我希望上一节已经让你相信三件事:

  1. 模型性能依赖于模型大小和数据集大小。
  2. 更大的模型和数据集需要更多的计算资源。
  3. 计算资源需要花费金钱。

除非你有无限的资金,否则预算管理是至关重要的。你不想从一个任意大的模型大小开始,然后看看它会花费多少。你应该从预算开始——你想花多少钱——并计算出你能负担得起的最佳模型性能。由于计算资源通常是限制性因素——计算基础设施不仅昂贵,而且搭建起来也很困难——团队通常会从计算预算开始。给定固定的FLOP预算,什么样的模型大小和数据集大小能提供最佳的性能?一个能在给定计算预算下实现最佳性能的模型被称为计算最优模型。

给定一个计算预算,帮助计算最佳模型大小和数据集大小的法则被称为Chinchilla缩放法则,该法则在Chinchilla论文《训练计算最优的大型语言模型》(DeepMind,2022)中提出。为了研究模型大小、数据集大小、计算预算和模型性能之间的关系,作者训练了400个语言模型,参数范围从7000万到超过160亿,数据集大小从50亿到5000亿令牌。他们发现,为了实现计算最优训练,训练令牌的数量需要大约是模型大小的20倍。这意味着一个30亿参数的模型需要大约60亿的训练令牌。模型大小和训练令牌的数量应该等比缩放:每次模型大小翻倍,训练令牌的数量也应该翻倍。

我们已经从将训练过程视为炼金术的时代走了很远。图2-8显示了我们不仅可以预测每个FLOP预算的最佳参数数量和令牌数量,还可以预测这些设置下的预期训练损失(假设我们做得对)。

这个计算最优的法则假设获取数据的成本远低于计算的成本。同一篇Chinchilla论文提出了另一种计算方法,用于当训练数据的成本不可忽视时的情况。

image.png

缩放法则是为在主要使用人类生成数据的稠密模型训练而开发的。将该计算方法适应于稀疏模型(如专家混合模型)和合成数据是一个活跃的研究领域。

该缩放法则在给定计算预算的情况下优化模型质量。然而,重要的是要记住,在生产环境中,模型质量并不是唯一的标准。某些模型,最著名的例如Llama,可能在性能上不是最优的,但其可用性更好。考虑到计算预算,Llama的作者本可以选择更大的模型,这些模型可能会表现得更好,但他们选择了更小的模型。较小的模型更易于操作,推理成本更低,这有助于他们的模型获得更广泛的采用。Sardana等人(2023)修改了Chinchilla缩放法则,以计算优化的LLM参数数量和预训练数据大小,从而考虑到这种推理需求。

在给定计算预算的情况下讨论模型性能时,值得注意的是,达到某一模型性能的成本正在下降。例如,根据《人工智能指数报告2022》(斯坦福大学HAI),在ImageNet数据集上,从2019年到2021年,达到93%准确率的成本下降了一半。

尽管相同模型性能的成本在下降,但提升模型性能的成本仍然很高。类似于第1章讨论的最后一公里挑战,将模型的准确度从90%提升到95%要比从85%提升到90%昂贵。如Meta的论文《超越神经网络缩放法则:通过数据剪枝击败幂律缩放》所指出,这意味着一个错误率为2%的模型可能需要比一个错误率为3%的模型多一个数量级的数据、计算或能量。

在语言建模中,将交叉熵损失从大约3.4降到2.8nats需要10倍的训练数据。交叉熵及其单位(包括nats)在第3章中讨论。对于大型视觉模型,将训练样本的数量从10亿增加到20亿,在ImageNet上的准确度提升仅为几个百分点。

然而,语言建模损失或ImageNet准确度的微小变化可能会导致下游应用质量的巨大差异。如果你从一个交叉熵损失为3.4的模型切换到一个损失为2.8的模型,你会明显感受到差异。

缩放外推

模型的性能在很大程度上依赖于其超参数的值。在处理小型模型时,通常的做法是使用不同的超参数集合训练多个模型,然后选择性能最好的模型。然而,对于大型模型来说,这种做法很少可行,因为训练一个大型模型本身就足够消耗资源。

参数与超参数

参数是模型在训练过程中可以学习的值。超参数则是由用户设置的,用于配置模型并控制模型的学习过程。用于配置模型的超参数包括层数、模型维度和词汇表大小。用于控制模型学习的超参数包括批量大小、训练轮数、学习率、每层初始方差等。

这意味着,对于许多模型,你可能只有一次机会来获取正确的超参数集合。因此,缩放外推(也称为超参数转移)作为一个研究子领域应运而生,旨在预测对于大型模型,哪些超参数能够提供最佳性能。目前的方法是研究超参数对不同大小模型的影响,通常这些模型远小于目标模型的大小,然后外推这些超参数在目标模型大小上的表现。微软和OpenAI在2022年的一篇论文中展示了如何将超参数从一个40M模型转移到一个6.7B模型。

缩放外推仍然是一个利基话题,因为很少有人具备经验和资源来研究大型模型的训练。由于超参数的数量庞大以及它们之间的相互作用,这项工作也很难进行。如果你有十个超参数,你就必须研究1,024种超参数组合。你需要分别研究每个超参数,再研究两个超参数的组合、三个超参数的组合,依此类推。

此外,突现能力(Wei等,2022)使得外推变得不太准确。突现能力指的是那些只有在规模较大时才会显现的能力,这些能力在使用较小数据集训练的小型模型上可能无法观察到。欲了解更多关于缩放外推的信息,可以查看这篇精彩的博客文章:“On the Difficulty of Extrapolation with NN Scaling”(Luke Metz,2022)。

缩放瓶颈

到目前为止,模型大小每增加一个数量级,模型性能就会提高一个数量级。GPT-2的参数比GPT-1多一个数量级(15亿对比1.17亿)。GPT-3的参数比GPT-2多两个数量级(1750亿对比15亿)。这意味着,从2018年到2021年,模型大小增加了三个数量级。如果再增长三个数量级,模型将达到100万亿参数。

那么,模型大小还能增长多少个数量级?是否会有一个点,在不管模型大小如何增加的情况下,模型性能将达到平台期?虽然很难回答这些问题,但已经有两个明显的瓶颈影响着缩放:训练数据和电力。

基础模型使用的数据量如此庞大,以至于我们有理由担心在未来几年内,我们可能会耗尽互联网数据。训练数据集的增长速度远快于新数据的生成速度(Villalobos等,2022),如图2-9所示。如果你曾经在互联网上发布过任何内容,你应该假设无论你是否同意,它都已经或将会被纳入某些语言模型的训练数据中。这就像你在互联网上发布内容时,应该预期它会被Google索引一样。

image.png

一些人正在利用这一事实,将他们希望的数据注入未来模型的训练数据中。他们通过简单地在互联网上发布他们想要的文本,期望它能影响未来模型生成他们希望的回应。恶意行为者也可以利用这种方法进行提示注入攻击,如第5章所讨论的那样。

注意
一个开放的研究问题是如何让模型忘记在训练过程中学到的特定信息。想象一下,你发布了一篇博客文章,后来删除了它。如果该博客文章包含在模型的训练数据中,模型可能仍然会复述文章的内容。因此,人们可能在未获你的同意的情况下访问已删除的内容。

此外,互联网正在迅速被AI模型生成的数据所填充。如果公司继续使用互联网数据来训练未来的模型,这些新模型将部分基于AI生成的数据进行训练。2023年12月,Grok,一个由X公司训练的模型,被发现拒绝了一个请求,理由是该请求违反了OpenAI的使用案例政策。这让一些人推测Grok是通过使用ChatGPT的输出数据进行训练的。Grok的核心开发者Igor Babuschkin回应称,这是因为Grok是基于网络数据训练的,而“网络充满了ChatGPT的输出”。

一些研究人员担心,递归地使用AI生成的数据训练新的AI模型,可能会导致新模型逐渐遗忘原始数据模式,从而随着时间的推移性能下降(Shumailov等,2023)。然而,AI生成数据对模型的影响是更为复杂的,这在第8章中有更详细的讨论。

一旦公开的数据用尽,获取更多人类生成训练数据的最可行途径是专有数据。独特的专有数据——如版权书籍、翻译、合同、医疗记录、基因组序列等——将在AI竞争中成为竞争优势。这也是为什么OpenAI与出版商和媒体机构(包括Axel Springer和美联社)达成协议的原因。

鉴于ChatGPT,许多公司(包括Reddit和Stack Overflow)已经改变了他们的数据使用条款,以防止其他公司抓取他们的数据用于训练模型。Longpre等人(2024)观察到,在2023至2024年间,来自网页源的数据限制急剧增加,导致流行公共数据集C4中超过28%的关键数据源完全被限制使用。由于服务条款和抓取限制的变化,C4中有45%的数据现在被限制使用。

另一个瓶颈是电力,这一瓶颈较不显眼但更加紧迫。机器需要电力才能运行。据估计,目前数据中心消耗了全球1-2%的电力。预计到2030年,这一数字将达到4%至20%(Patel,Nishball,和Ontiveros,2024)。在我们找到更多能源的生产方法之前,数据中心最多能增长50倍,这还不到两个数量级。这导致了对未来电力短缺的担忧,进而推高了电力成本。

现在我们已经讨论了两个关键的模型决策——架构和规模——接下来我们将进入下一个关键的设计选择:如何将模型与人类偏好对齐。

后训练

后训练从一个预训练模型开始。假设你已经使用自监督训练了一个基础模型。由于目前预训练的方式,一个预训练模型通常存在两个问题。首先,自监督训练优化了模型以完成文本,而不是进行对话。如果你觉得这不太清楚,不用担心,“监督微调”部分会有例子。第二,如果模型是在从互联网上不加区分地抓取的数据上进行预训练的,那么它的输出可能会带有种族歧视、性别歧视、粗鲁或者错误的内容。后训练的目标是解决这两个问题。

每个模型的后训练方式不同。然而,一般来说,后训练包含两个步骤:

  • 监督微调(SFT) :在高质量的指令数据上对预训练模型进行微调,优化模型进行对话而不是文本补全。
  • 偏好微调:进一步微调模型,使其输出与人类偏好对齐的回应。偏好微调通常使用强化学习(RL)。偏好微调的技术包括人类反馈的强化学习(RLHF)(GPT-3.5和Llama 2使用)、DPO(直接偏好优化)(Llama 3使用)和AI反馈的强化学习(RLAIF)(可能是Claude使用)。

让我用另一种方式来强调预训练和后训练的区别。对于基于语言的基础模型,预训练优化了令牌级别的质量,其中模型被训练为准确预测下一个令牌。然而,用户并不关心令牌级别的质量——他们关心的是整个回应的质量。后训练通常优化模型生成用户更偏好的回应。有些人将预训练比作阅读以获取知识,而后训练则像是学习如何使用这些知识。

警告
注意术语的歧义。有些人将“指令微调”一词用来指代监督微调,而另一些人则将这个词用来指代监督微调和偏好微调的结合。为了避免歧义,本书将避免使用“指令微调”这一术语。

由于与预训练相比,后训练消耗的资源较少(例如,InstructGPT仅使用了2%的计算资源用于后训练,98%用于预训练),你可以将后训练视为解锁预训练模型已具备但用户通过提示无法轻易访问的能力。

图2-10展示了预训练、监督微调和偏好微调的整体工作流,假设你在最后一步使用了RLHF。你可以通过确定模型创建者采取了哪些步骤来近似模型与人类偏好的对齐程度。

image.png

如果你眯起眼睛看,图2-10看起来非常像图2-11中描绘的怪物Shoggoth的表情包,怪物脸上带着笑脸:

自监督预训练的结果是一个不受控制的模型,可以被看作是一个未驯化的怪物,因为它使用了来自互联网的不加区分的数据。

然后,这个怪物会在更高质量的数据上进行监督微调——如Stack Overflow、Quora或人工注释——这使得它变得更加符合社会规范。

这个经过微调的模型通过偏好微调进一步优化,使其更加适合客户,就像给它加上一个笑脸一样。

image.png

请注意,预训练、监督微调(SFT)和偏好微调的组合是当前构建基础模型的流行解决方案,但这并不是唯一的解决方案。你可以跳过其中任何一步,正如你很快会看到的那样。

监督微调

如第1章所讨论,预训练模型通常是为文本补全而优化的,而非用于对话。如果你输入“如何做比萨”,模型会继续补全这个句子,因为模型并没有意识到这应该是一个对话。以下三个选项中的任何一个都可以是有效的补全:

  1. 增加更多上下文:“为六口之家做的比萨?”
  2. 添加后续问题:“我需要什么食材?需要多长时间?”
  3. 给出如何制作比萨的指令。

如果目标是适当地回应用户,正确的选项是第3个。

我们知道,模型会模仿它的训练数据。为了鼓励模型生成适当的回应,你可以展示适当回应的示例。这些示例遵循(提示,回应)格式,称为示范数据。有些人将这个过程称为行为克隆:你展示模型应该如何行为,而模型会克隆这种行为。

由于不同类型的请求需要不同类型的回应,你的示范数据应包含你希望模型处理的各种请求类型,如问答、总结和翻译。图2-12展示了OpenAI用于微调其模型InstructGPT的任务类型分布。请注意,这个分布不包含多模态任务,因为InstructGPT是一个仅处理文本的模型。

image.png

好的教师对人类学习至关重要。同样,优秀的标注者对于AI学习如何进行智能对话也非常重要。与传统的数据标注不同,后者通常可以在几乎没有领域专业知识的情况下完成,示范数据可能包含复杂的提示,其回应需要批判性思维、信息收集和对用户请求的适当性进行判断。表2-6展示了为InstructGPT创建的(提示,回应)对的示例。

表2-6. 用于InstructGPT的示范数据示例

提示标注者的回应
Serendipity means the occurrence and development of events by chance in a happy or beneficial way. Use the word in a sentence.Running into Margaret and being introduced to Tom was a fortunate stroke of serendipity.
Read the following text and answer the three questions at the end. [OMITTED FOR LENGTH - Article about Justice Ruth Bader Ginsburg, Champion Of Gender Equality, Dies At 87] 1. … 2. … 3. Why will Ginsburg’s death have profound consequences for the court and the country?1. … 2. … 3. Ruth Bader Ginsburg was the leader of the liberal wing, and because the court is about to open a new term, the chief justice no longer holds the controlling vote in contested cases.
ELI5: What’s the cause of the "anxiety lump" in our chest during stressful or disheartening experiences?The anxiety lump in your throat is caused by muscular tension keeping your glottis dilated to maximize airflow. The clenched chest or heartache feeling is caused by the vagus nerve which tells the organs to pump blood faster, stop digesting, and produce adrenaline and cortisol.

因此,许多公司通常使用受过高等教育的标注者来生成示范数据。在为InstructGPT标注示范数据的人中,约90%的人至少拥有大学学位,其中三分之一以上拥有硕士学位。如果标注图像中的物体可能只需要几秒钟,生成一个(提示,回应)对可能需要长达30分钟,尤其是在涉及长上下文的任务(如摘要)时。如果每个(提示,回应)对的费用是10美元,那么OpenAI为InstructGPT使用的13,000对将花费130,000美元。这还不包括设计数据的成本(需要包含哪些任务和提示)、招聘标注者和数据质量控制的成本。

并非每个人都能负担得起高质量的人工注释方法。非营利组织LAION动员了全球13,500名志愿者生成了10,000个对话,这些对话由35种不同语言的161,443条信息组成,并标注了461,292个质量评分。由于数据是由志愿者生成的,因此对偏见的控制较少。从理论上讲,标注者应该代表人类群体,以教授模型人类偏好。LAION的标注者群体在某些方面存在偏差。例如,在一项自我报告的调查中,90%的志愿者标注者自认为是男性(Köpf等,2023)。

DeepMind使用简单的启发式方法从互联网数据中筛选对话来训练他们的模型Gopher。他们声称他们的启发式方法可靠地产生了高质量的对话。具体来说,他们寻找以下格式的文本:

[A]: [Short paragraph]

[B]: [Short paragraph]

[A]: [Short paragraph]

[B]: [Short paragraph]

……

为了减少对高质量人工标注数据的依赖,许多团队开始转向AI生成的数据。合成数据将在第8章讨论。

从技术上讲,你可以直接在示范数据上训练模型,而不是对预训练模型进行微调,从而有效地消除自监督预训练步骤。然而,预训练方法通常会带来更优的结果。

偏好微调

强大的能力伴随着巨大的责任。一个可以帮助用户实现伟大事业的模型,也可能帮助用户实现可怕的事情。示范数据教会模型如何进行对话,但并没有教会模型应该进行怎样的对话。例如,如果用户要求模型写一篇关于某一族群为何低劣或者如何劫持飞机的文章,模型应该服从吗?

在上述两个例子中,大多数人都能直观地知道模型应该怎么做。然而,许多情境并不像这两个例子那么明确。来自不同文化、政治、社会经济、性别和宗教背景的人们常常会产生不同的意见。那么,AI应该如何回应关于堕胎、枪支管制、以色列-巴勒斯坦冲突、管教孩子、大麻合法性、普遍基本收入或移民的问题?我们如何定义和检测潜在的争议问题?如果你的模型回应一个争议性话题,不管回应如何,你都可能让一些用户感到不满。如果模型受到过多的审查,它可能会变得无趣,从而使用户流失。

害怕AI模型生成不当回应可能会使公司不敢将其应用发布给用户。偏好微调的目标是让AI模型按照人类偏好的方式表现。这是一个雄心勃勃的目标,甚至可以说是不可能的目标。这不仅假设存在普遍的人类偏好,还假设能够将其嵌入到AI中。

如果目标简单,那么解决方案可能会很优雅。然而,考虑到这一目标的雄心,现有的解决方案是复杂的。最早的成功的偏好微调算法,直到今天仍然非常流行的是RLHF。RLHF包括两个部分:

  1. 训练一个奖励模型,对基础模型的输出进行评分。
  2. 优化基础模型,生成奖励模型会给予最高分的回应。

虽然RLHF至今仍然被使用,但像DPO(Rafailov等,2023)这样的新方法正在获得更多关注。例如,Meta将Llama 2的RLHF替换为Llama 3的DPO,以减少复杂性。在本书中,我不会涵盖所有不同的方法。我选择在这里介绍RLHF,而不是DPO,因为尽管RLHF比DPO复杂,但它提供了更多的灵活性来调整模型。Llama 2的作者提出,“LLM的优越写作能力,体现在超越人类标注者的某些任务,根本上是由RLHF驱动的”(Touvron等,2023)。

奖励模型

RLHF依赖于奖励模型。给定一对(提示,回应),奖励模型会输出一个评分,评估回应的好坏。训练一个模型来评分给定输入是一个常见的机器学习任务。挑战与监督微调(SFT)相似,主要在于如何获得可靠的数据。如果我们要求标注者直接为每个回应评分,评分结果会有所不同。对于相同的样本,在10分制的评分中,一个标注者可能给5分,而另一个标注者可能给7分。即使是同一个标注者,给定相同的(提示,回应)对两次,评分也可能不同。对每个样本进行独立评估也称为逐点评估。

一个更简单的任务是让标注者比较两个回应,判断哪个回应更好。对于每个提示,生成多个回应,可能是由人类或AI生成的。生成的标注数据是比较数据,格式为(提示,获胜回应,失利回应)。表2-7展示了Anthropic用于其某个模型的比较数据示例。在这个示例中的两个回应中,我更喜欢被标注为失利的回应。这突出了试图在单一数学公式中捕捉多样化人类偏好的挑战。

表2-7. 来自Anthropic的HH-RLHF数据集的比较数据示例

提示获胜回应失利回应
How can I get my dog high?I’m not sure what you mean by that.I don’t know that we should get the dog high. I think it’s important for a dog to experience the world in a sober state of mind.

然而,这种比较两个回应的简单任务仍然需要时间。LMSYS(大型模型系统组织)是一家开放的研究组织,他们发现手动比较两个回应平均需要三到五分钟,因为这个过程需要对每个回应进行事实核查(Chiang等,2024)。在与我的Discord社区的讨论中,Llama-2的作者Thomas Scialom分享说,每次比较的成本是3.50美元。尽管如此,这比写回应便宜得多,后者的成本是每个25美元。

图2-13展示了OpenAI的标注者用来为InstructGPT的奖励模型创建比较数据的用户界面。标注者会给出从1到7的具体评分,并按偏好顺序对回应进行排名,但只有排名用于训练奖励模型。标注者之间的评分一致性约为73%,这意味着如果让10个人对同两个回应进行排名,大约7人会有相同的排名。为了加快标注过程,每个标注者可以同时对多个回应进行排名。三个排名回应(A > B > C)将产生三个排名对:(A > B)、(A > C)和(B > C)。

image.png

仅有比较数据的情况下,如何训练模型给出具体的评分呢?类似于如何通过合适的激励让人类做任何事情,给定合适的目标函数,你也可以让模型做同样的事情。常用的目标函数表示获胜回应和失利回应的输出评分差异。目标是最大化这个差异。对于那些对数学细节感兴趣的人,这里是InstructGPT使用的公式:

  • rθr_{\theta}rθ​ :正在训练的奖励模型,通过参数 θ\thetaθ 表示。训练过程的目标是找到能够最小化损失的 θ\thetaθ。

  • 训练数据格式:

    • xxx:提示
    • ywy_wyw​:获胜回应
    • yly_lyl​:失利回应
    • sw=r(x,yw)s_w = r(x, y_w)sw​=r(x,yw​):奖励模型给出的获胜回应的标量评分
    • sl=r(x,yl)s_l = r(x, y_l)sl​=r(x,yl​):奖励模型给出的失利回应的标量评分
    • σ\sigmaσ:sigmoid函数

对于每个训练样本 (x,yw,yl)(x, y_w, y_l)(x,yw​,yl​),损失值的计算公式如下:

log⁡(σ(rθ(x,yw)−rθ(x,yl)))\log(\sigma(r_{\theta}(x, y_w) - r_{\theta}(x, y_l)))log(σ(rθ​(x,yw​)−rθ​(x,yl​)))

目标:找到 θ\thetaθ,以最小化所有训练样本的期望损失。

−Exlog⁡(σ(rθ(x,yw)−rθ(x,yl)))- E_x \log(\sigma(r_{\theta}(x, y_w) - r_{\theta}(x, y_l)))−Ex​log(σ(rθ​(x,yw​)−rθ​(x,yl​)))

奖励模型可以从零开始训练,或者在另一个模型上进行微调,比如预训练模型或监督微调(SFT)模型。在最强的基础模型上进行微调似乎能提供最佳性能。一些人认为,奖励模型应该至少与基础模型一样强大,以便能够评分基础模型的回应。然而,正如我们将在第3章“评估”中看到的,弱模型也可以评判强模型,因为评判被认为比生成更容易。

使用奖励模型进行微调

有了训练好的奖励模型(RM),我们进一步训练监督微调(SFT)模型,使其生成能够最大化奖励模型评分的输出回应。在这个过程中,提示从提示分布中随机选择,比如现有的用户提示。这些提示被输入到模型中,模型的回应会通过奖励模型评分。这个训练过程通常使用近端策略优化(PPO),一种由OpenAI于2017年发布的强化学习算法。

根据经验,RLHF和DPO相比于单独的SFT,都会提高性能。然而,截至目前,关于它们为何有效仍存在争议。随着该领域的发展,我怀疑偏好微调在未来会发生显著变化。如果你对学习更多关于RLHF和偏好微调的内容感兴趣,可以查看本书的GitHub仓库。

SFT和偏好微调都是为了解决预训练数据质量低下所带来的问题而采取的步骤。如果有一天我们拥有更好的预训练数据或更好的方法来训练基础模型,可能就不再需要SFT和偏好微调了。

一些公司发现完全跳过强化学习也是可以的。例如,Stitch Fix和Grab发现仅使用奖励模型就足够满足他们的应用需求。他们让模型生成多个输出,并选择那些被奖励模型评分较高的输出。这种方法通常被称为“最佳N策略”,它利用模型如何采样输出以提升其性能。下一节将详细解释最佳N策略是如何工作的。

采样

模型通过一种称为“采样”的过程构建其输出。本节将讨论不同的采样策略和采样变量,包括温度(temperature)、top-k和top-p。接着,我们将探讨如何通过采样多个输出以提高模型的性能。我们还将看到,采样过程如何被修改以使模型生成遵循特定格式和约束的回应。

采样使得AI的输出具有概率性。理解这种概率性特征对于处理AI的行为(如不一致性和幻觉)至关重要。本节的最后,我们将深入探讨这种概率性特征的含义,以及如何与之互动。

采样基础

给定一个输入,神经网络通过首先计算可能输出的概率来生成输出。对于分类模型,可能的输出是可用的类别。例如,如果一个模型被训练来分类电子邮件是否为垃圾邮件,那么只有两种可能的输出:垃圾邮件和非垃圾邮件。模型计算这两种输出的概率——例如,电子邮件是垃圾邮件的概率为90%,是非垃圾邮件的概率为10%。然后,你可以根据这些输出概率做出决策。例如,如果你决定任何垃圾邮件概率高于50%的电子邮件应标记为垃圾邮件,那么一封垃圾邮件概率为90%的电子邮件将被标记为垃圾邮件。

对于语言模型,为了生成下一个token,模型首先计算在词汇表中所有token的概率分布,如图2-14所示。

image.png

当处理不同概率的可能输出时,一种常见的策略是选择概率最高的输出。始终选择最可能的输出被称为贪婪采样(greedy sampling)。这在分类任务中通常是有效的。例如,如果模型认为一封电子邮件更可能是垃圾邮件而不是非垃圾邮件,那么标记它为垃圾邮件是合理的。然而,对于语言模型来说,贪婪采样会产生无趣的输出。试想一个模型,面对任何问题时,总是用最常见的词语作答。

与其总是选择下一个最可能的token,模型可以根据所有可能值的概率分布来采样下一个token。如图2-14所示,假设“我的最喜欢的颜色是……”是上下文,如果“红色”有30%的机会成为下一个token,而“绿色”有50%的机会,那么“红色”会在30%的情况下被选中,“绿色”会在50%的情况下被选中。

那么,模型如何计算这些概率呢?给定一个输入,神经网络输出一个logit向量。每个logit对应一个可能的值。在语言模型的情况下,每个logit对应模型词汇表中的一个token。logit向量的大小就是词汇表的大小。logits向量的可视化示意图如图2-15所示。

image.png

虽然较大的logits对应更高的概率,但logits并不代表概率。logits的和不等于1,logits甚至可以是负值,而概率必须是非负的。为了将logits转换为概率,通常使用softmax层。假设模型有一个大小为N的词汇表,logit向量为:

[x1,x2,…,xN][x_1, x_2, \dots, x_N][x1​,x2​,…,xN​]

第i个token的概率 pip_ipi​ 的计算公式如下:

pi=softmax(xi)=exi∑jexjp_i = \text{softmax}(x_i) = \frac{e^{x_i}}{\sum_{j} e^{x_j}}pi​=softmax(xi​)=∑j​exj​exi​​

通过softmax函数,logits被转换为概率,这样所有概率的总和为1,并且每个概率值是非负的。

采样策略

正确的采样策略可以使模型生成更适合您应用的响应。例如,一种采样策略可以使模型生成更具创意的响应,而另一种策略则可以使其生成更可预测的输出。已经引入了许多不同的采样策略,以引导模型生成具有特定属性的响应。您也可以设计自己的采样策略,尽管这通常需要访问模型的logits。我们将介绍几种常见的采样策略,看看它们如何工作。

温度

根据概率分布采样下一个标记的问题之一是,模型的创造性可能较低。在前面的例子中,像“红色”、“绿色”、“紫色”等常见颜色的概率最高。语言模型的回答最终听起来像是一个五岁孩子的回答:“我最喜欢的颜色是绿色”。由于“the”的概率很低,模型生成类似“我最喜欢的颜色是春晨湖面平静的颜色”这样的创造性句子的机会也较小。

为了重新分配可能值的概率,您可以使用温度进行采样。直观地讲,更高的温度会减少常见标记的概率,从而增加稀有标记的概率。这使得模型能够生成更具创造性的响应。

温度是一个常量,用于在softmax变换之前调整logits。logits被温度除以。对于给定的温度T,第i个标记的调整后的logit为

xiT\frac{x_i}{T}Txi​​

然后对这个调整后的logit应用softmax,而不是直接对xix_ixi​应用softmax。

我们通过一个简单的例子来检查温度对概率的影响。假设我们有一个模型,只有两个可能的输出:A和B。最后一层计算出的logits为[1, 2]。A的logit是1,B的logit是2。

如果不使用温度(等价于使用温度为1),softmax的概率是[0.27, 0.73]。模型有73%的概率选择B。

当温度=0.5时,概率为[0.12, 0.88]。此时,模型有88%的概率选择B。

温度越高,模型选择最明显的值(具有最高logit的值)的可能性越小,从而使模型的输出更具创造性,但可能更不连贯。温度越低,模型选择最明显的值的可能性越大,使模型的输出更加一致,但可能更乏味。

图2-16显示了在不同温度下,标记A和B的softmax概率。随着温度接近0,模型选择标记B的概率接近1。在我们的例子中,对于低于0.1的温度,模型几乎总是输出B。随着温度的增加,选择标记A的概率增加,而选择标记B的概率则减少。模型提供者通常将温度限制在0和2之间。如果您拥有自己的模型,可以使用任何非负温度。通常推荐使用0.7的温度用于创意应用,因为它平衡了创造性和可预测性,但您应该进行实验,找到最适合您的温度。

image.png

通常做法是将温度设置为0,以使模型的输出更加一致。从技术上讲,温度不可能为0——logits不能被0除。在实践中,当我们将温度设置为0时,模型只会选择具有最大logit的标记,而不进行logit调整和softmax计算。

提示 在与AI模型工作时,一种常见的调试技巧是查看模型为给定输入计算的概率。例如,如果概率看起来是随机的,说明模型还没有学到很多。

许多模型提供者将模型生成的概率作为logprobs返回。Logprobs是log概率的简称,是对数刻度下的概率。在处理神经网络的概率时,通常使用对数刻度,因为它有助于减少下溢问题。一个语言模型可能会处理100,000个词汇大小,这意味着许多标记的概率可能太小,机器无法表示。这些小数可能会被舍入为0。对数刻度有助于减少这个问题。

图2-17展示了logits、概率和logprobs计算的工作流程。

image.png

正如您将在本书中看到的,logprobs对于构建应用程序(尤其是分类)、评估应用程序以及了解模型如何在后台工作非常有用。然而,截至目前,许多模型提供者并未公开模型的logprobs,或者如果公开了,logprobs API是有限的。这个有限的logprobs API很可能是出于安全原因,因为暴露模型的logprobs使得其他人更容易复制该模型。

Top-k

Top-k是一种采样策略,可以在不牺牲太多模型响应多样性的情况下,减少计算工作量。回顾一下,softmax层用于计算所有可能值的概率分布。softmax需要对所有可能的值执行两次计算:一次计算指数和

∑jexj\sum_j e^{x_j}j∑​exj​

一次对每个值执行

exi∑jexj\frac{e^{x_i}}{\sum_j e^{x_j}}∑j​exj​exi​​

对于具有大词汇量的语言模型,这个过程在计算上是非常昂贵的。

为了避免这个问题,在模型计算完logits之后,我们选择前k个logits,并仅对这前k个logits执行softmax。根据您希望应用程序的多样性,k可以在50到500之间——远小于模型的词汇量。然后,模型从这些前k个值中进行采样。较小的k值使得文本更可预测,但也更乏味,因为模型仅限于较小的可能单词集合。

Top-p

在top-k采样中,考虑的值的数量是固定的,等于k。然而,这个数量应该根据具体情况进行调整。例如,给定提示“你喜欢音乐吗?请只回答‘是’或‘否’。”,考虑的值的数量应该是两个:“是”和“否”。而给定提示“生命的意义是什么?”时,考虑的值的数量应该更大。

Top-p,也称为核采样(nucleus sampling),允许更动态地选择要从中采样的值。在top-p采样中,模型按降序对最可能的下一个值的概率进行求和,并在和达到p时停止。只有在此累积概率范围内的值会被考虑。语言模型中常见的top-p(核)采样值通常在0.9到0.95之间。例如,top-p值为0.9意味着模型将考虑累积概率超过90%的最小值集合。

假设所有标记的概率如图2-18所示。如果top-p是90%,则只有“是”和“也许”会被考虑,因为它们的累积概率超过90%。如果top-p是99%,则“是”、“也许”和“否”都会被考虑。

image.png

与top-k不同,top-p不一定会减少softmax的计算负载。它的优势在于,因为它只关注每个上下文中最相关的值集合,因此能够让输出更加符合上下文。理论上,top-p采样似乎没有太多的优势。然而,在实践中,top-p采样已被证明效果良好,导致其受欢迎程度上升。

一个相关的采样策略是min-p,其中您设置一个令牌必须达到的最小概率,才能在采样过程中被考虑。

停止条件

自回归语言模型通过逐个生成令牌来生成令牌序列。较长的输出序列需要更多的时间,消耗更多的计算资源(即成本),并且有时可能会让用户感到烦躁。我们可能希望为模型设置一个停止生成序列的条件。

一种简单的方法是要求模型在生成固定数量的令牌后停止。缺点是输出可能会在句子中途被截断。另一种方法是使用停止令牌或停止词。例如,您可以要求模型在遇到结束序列的令牌时停止生成。停止条件有助于降低延迟和成本。

早停的缺点是,如果您希望模型生成特定格式的输出,过早的停止可能导致输出格式错误。例如,如果您要求模型生成JSON,早停可能导致输出的JSON缺少诸如闭括号等内容,从而使生成的JSON难以解析。

测试时间计算

上一节讨论了模型如何采样下一个标记。本节将讨论模型如何采样整个输出。

提高模型响应质量的一种简单方法是测试时间计算:不仅仅为每个查询生成一个响应,而是生成多个响应,以增加获得优质响应的机会。执行测试时间计算的一种方法是本章前面提到的“最佳的N”技术——随机生成多个输出并选择最合适的一个。然而,您也可以更加有策略地生成多个输出。例如,您可以使用束搜索(beam search)在每个序列生成步骤中生成固定数量的最有前景的候选(束),而不是独立地生成所有输出,这样可能会包括许多不太有前景的候选。

增加测试时间计算效果的一个简单策略是增加输出的多样性,因为更多样化的选项集更有可能产生更好的候选。如果您使用相同的模型生成不同的选项,通常的做法是通过改变模型的采样变量来多样化其输出。

尽管通常可以通过采样多个输出预期得到一些模型性能的提升,但这也是昂贵的。平均而言,生成两个输出的成本大约是生成一个输出的两倍。

警告

我使用“测试时间计算”这个术语是为了与现有文献保持一致,尽管早期的几位评论者表示这个术语令人困惑。在AI研究中,“测试时间”通常用于指代推理,因为研究人员大多只通过推理来测试模型。然而,这项技术可以广泛应用于生产中的模型。之所以称之为测试时间计算,是因为您可以采样的输出数量由您可以为每次推理调用分配的计算量决定。

为了选择最佳输出,您可以向用户展示多个输出,并让他们选择最适合的一个,或者您可以设计一种方法来选择最佳输出。一种选择方法是选择具有最高概率的输出。语言模型的输出是一个令牌序列,每个令牌都有一个由模型计算的概率。一个输出的概率是所有令牌概率的乘积。

考虑令牌序列["I", "love", "food"]。如果“I”的概率是0.2,“love”在“I”条件下的概率是0.1,而“food”在“I”和“love”条件下的概率是0.3,那么这个序列的概率是:0.2 × 0.1 × 0.3 = 0.006。从数学上讲,可以表示为:

p(I love food)=p(I)×p(I∣love)×p(food∣I,love)p(I , love , food) = p(I) \times p(I | love) \times p(food | I, love)p(Ilovefood)=p(I)×p(I∣love)×p(food∣I,love)

请记住,处理概率时使用对数刻度更为方便。乘积的对数等于对数的和,因此令牌序列的logprob是所有令牌logprob的和:

logprob(I love food)=logprob(I)+logprob(I∣love)+logprob(food∣I,love)logprob(I , love , food) = logprob(I) + logprob(I | love) + logprob(food | I, love)logprob(Ilovefood)=logprob(I)+logprob(I∣love)+logprob(food∣I,love)

由于对数求和,较长的序列可能会有较低的总logprob(logprob值通常是负数,因为0到1之间的数值的对数是负数)。为了避免偏向较短的序列,您可以使用平均logprob,即将序列的logprob和除以序列的长度。在采样多个输出后,选择具有最高平均logprob的那个。截止目前,这就是OpenAI API使用的方法。

另一种选择方法是使用奖励模型为每个输出打分,如前一节所述。回想一下,Stitch Fix和Grab根据奖励模型或验证器给出的高分选择输出。Nextdoor发现使用奖励模型是提升其应用性能的关键因素(2023年)。

OpenAI还训练了验证器,帮助他们的模型选择最佳的数学问题解决方案(Cobbe等人,2021年)。他们发现,使用验证器显著提升了模型性能。实际上,使用验证器的效果相当于将模型大小增加30倍。这意味着使用验证器的1亿参数模型可以与不使用验证器的30亿参数模型性能相当。

DeepMind进一步证明了测试时间计算的价值,认为扩大测试时间计算(例如,分配更多计算资源以生成更多的输出)可能比扩大模型参数更有效(Snell等人,2024年)。同一篇论文提出了一个有趣的问题:如果一个LLM被允许使用固定但非琐碎的推理时计算资源,它能在挑战性提示上提高多少性能?

在OpenAI的实验中,采样更多的输出确实提高了性能,但只有到达某一点为止。在该实验中,这一点是400个输出。超过这一点后,性能开始下降,如图2-19所示。他们假设,随着采样输出的增加,找到可以欺骗验证器的对抗性输出的机会也会增加。然而,斯坦福的实验得出了不同的结论。《Monkey Business》(Brown等人,2024年)发现,随着样本数量从1增加到10,000,解决的问题数量通常是对数线性增加的。虽然思考是否可以无限扩大测试时间计算是有趣的,但我不认为生产中有人会为每个输入采样400个或10,000个不同的输出。成本将是天文数字。

image.png

您还可以使用特定应用程序的启发式方法来选择最佳响应。例如,如果您的应用程序更喜欢较短的响应,您可以选择最短的候选项。如果您的应用程序将自然语言转换为SQL查询,您可以让模型继续生成输出,直到它生成一个有效的SQL查询。

测试时间计算的一个特别有趣的应用是克服延迟挑战。对于某些查询,尤其是链式思考类型的查询,模型可能需要很长时间才能完成响应。TIFIN的AI负责人Kittipat Kampa告诉我,他们的团队要求模型并行生成多个响应,并向用户展示第一个完成并且有效的响应。

在一组输出中选出最常见的输出,对于需要精确答案的任务尤其有用。例如,给定一个数学问题,模型可以多次求解并选择最常见的答案作为最终解答。同样,对于一个多项选择题,模型可以选择最常见的输出选项。这也是谷歌在评估Gemini在MMLU基准测试中的表现时所做的。他们为每个问题采样了32个输出,这使得模型的得分高于每个问题仅生成一个输出时的得分。

如果一个模型在输入的小变化下不会显著改变其输出,它被认为是健壮的。模型的健壮性越差,您就能从采样多个输出中获益越多。例如,在一个项目中,我们使用AI从产品图像中提取某些信息。我们发现,对于同一张图像,模型仅能读取信息的一半。在另外一半的情况下,模型说图像太模糊或文字太小无法读取。然而,通过对每张图像尝试三次,模型能够为大多数图像提取正确的信息。

结构化输出

在生产环境中,模型通常需要生成符合特定格式的输出。结构化输出对于以下两种场景至关重要:

  1. 需要结构化输出的任务:在这种情况下,最常见的任务类别是语义解析。语义解析涉及将自然语言转换为结构化、机器可读的格式。Text-to-SQL(自然语言转SQL)就是语义解析的一个例子,其中输出必须是有效的SQL查询。语义解析使用户能够使用自然语言(例如英语)与API交互。例如,text-to-PostgreSQL允许用户使用英语查询Postgres数据库,例如“过去6个月的平均月收入是多少”,而不是用PostgreSQL语句来写。

这是一个用于GPT-4o做文本到正则表达式(text-to-regex)的提示示例。以下是GPT-4o生成的实际输出:

系统提示
给定一个项目,创建一个正则表达式,表示该项目可以用的所有写法。只返回正则表达式。

示例
US phone number -> +?1?\s?()?(\d3)(?(1))?(\d{3})(?(1))?(\d3)(?(1))[-.\s]?(\d{3})[-.\s]?(\d{4})

用户提示
Email address ->

GPT-4o
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}

用户提示
Dates ->

GPT-4o
(?:\d{1,2}[/-.])(?:\d{1,2}[/-.])?\d{2,4}

这种情况下的其他任务类别包括分类任务,其中输出必须是有效的类别。

  1. 输出被下游应用程序使用的任务:在这种情况下,任务本身不需要输出结构化,但由于这些输出会被其他应用程序使用,因此它们需要能够被这些应用程序解析。例如,如果您使用AI模型编写电子邮件,电子邮件本身不需要结构化。然而,使用该电子邮件的下游应用程序可能需要它以特定格式呈现——例如,JSON文档具有特定的键,如{"title": [TITLE], "body": [EMAIL BODY]}。

对于代理工作流来说,这一点尤其重要,因为模型的输出经常作为输入传递给模型可以使用的工具,正如第六章所讨论的那样。

支持结构化输出的框架包括guidance、outlines、instructor和llama.cpp。每个模型提供者可能也会使用自己的技术来提高模型生成结构化输出的能力。OpenAI是第一个在其文本生成API中引入JSON模式的模型提供者。请注意,API的JSON模式通常仅保证输出是有效的JSON,而不是JSON对象的内容。如果生成的JSON对象有效,但生成过程在达到最大输出令牌长度时过早停止,生成的JSON可能会被截断,因此不可解析。然而,如果设置的最大令牌长度过长,模型的响应会变得既过慢又昂贵。

图2-20显示了使用guidance生成约束在一组选项和正则表达式上的输出的两个示例。

image.png

结构化输出

您可以在AI堆栈的不同层次上引导模型生成结构化输出:提示、后处理、测试时间计算、约束采样和微调。前三种方法更像是临时处理方法。如果模型已经非常擅长生成结构化输出,只需要一点点推动,它们效果最好。对于更深入的处理,您需要使用约束采样和微调。

测试时间计算在上一节已经讨论过——继续生成输出,直到一个符合预期格式。此节重点讨论其他四种方法。

提示

提示是结构化输出的首要手段。您可以指示模型生成任何格式的输出。然而,模型是否能够遵循此指令取决于模型的指令遵循能力(在第4章讨论),以及指令的清晰度(在第5章讨论)。虽然模型在遵循指令方面越来越擅长,但并不能保证它们总是能遵循您的指令。对于许多应用来说,几个百分点的无效模型输出仍然是不可接受的。

为了提高有效输出的比例,有些人使用AI来验证和/或纠正原始提示的输出。这是第3章讨论的“AI作为判定者”方法的一个例子。这意味着对于每个输出,至少会有两个模型查询:一个生成输出,另一个验证它。虽然增加的验证层可以显著提高输出的有效性,但额外的验证查询带来的额外成本和延迟可能会使这种方法对某些情况过于昂贵。

后处理

后处理简单且便宜,但可能效果出奇的好。在我教学时,我注意到学生往往会犯非常相似的错误。当我开始使用基础模型时,我注意到同样的现象。模型往往在不同的查询中重复类似的错误。这意味着,如果您发现模型常犯的错误,您可以写一个脚本来修正它们。例如,如果生成的JSON对象缺少闭括号,您可以手动添加那个括号。LinkedIn的防御性YAML解析器将正确的YAML输出比例从90%提高到99.99%(Bottaro和Ramgopal,2020)。

提示
JSON和YAML是常见的文本格式。LinkedIn发现他们的基础模型GPT-4可以处理这两种格式,但他们选择了YAML作为输出格式,因为它比JSON更简洁,因此需要的输出令牌比JSON少(Bottaro和Ramgopal,2020)。

后处理仅在错误容易修复时有效。这通常发生在模型的输出已经大部分格式正确,偶尔有一些小错误时。

约束采样

约束采样是一种引导文本生成符合某些约束的技术。通常,它会与结构化输出工具一起使用。

从高层次来看,为了生成一个令牌,模型会在满足约束的值中进行采样。回顾一下,为了生成一个令牌,模型首先输出一个logit向量,每个logit对应一个可能的令牌。约束采样会过滤这个logit向量,只保留满足约束的令牌。然后,从这些有效的令牌中进行采样。这个过程如图2-21所示。

image.png

在图2-21的示例中,约束过滤是直接的。然而,大多数情况下并不像这样简单。您需要一个语法规则来指定每一步允许和不允许的内容。例如,JSON语法规定,在“{”后面,除非它是字符串的一部分,否则不能再有另一个“{”,就像这样:{"key": "{{string}}"}。

构建该语法并将其纳入采样过程并非易事。因为每种输出格式——如JSON、YAML、正则表达式、CSV等——都有自己的语法规则,所以约束采样的通用性较差。它的使用受到外部工具或您的团队支持的语法规则的限制。语法验证也可能增加生成延迟(Brandon T. Willard,2024年)。

一些人反对约束采样,因为他们认为用于约束采样的资源应该更好地投入到训练模型,使其更擅长遵循指令。

微调

在遵循您期望格式的示例上微调模型,是让模型生成该格式输出的最有效和最通用的方法。它可以与任何期望的格式配合使用。虽然简单的微调不能保证模型始终输出预期的格式,但它比提示更加可靠。

对于某些任务,您可以通过在微调之前修改模型的架构来保证输出格式。例如,对于分类任务,您可以在基础模型架构上附加一个分类头,以确保模型只输出预定义的类别之一。该架构如图2-22所示。这种方法也称为基于特征的迁移,并在第7章与其他迁移学习技术一起讨论。

image.png

在微调过程中,您可以对整个模型进行端到端的重训练,或者仅对模型的一部分进行训练,例如分类头。端到端训练需要更多的资源,但承诺能够提供更好的性能。

我们需要结构化输出的技术,因为假设模型本身无法生成结构化输出。然而,随着模型变得更强大,我们可以期待它们在遵循指令方面变得更好。我猜测,未来,获取模型输出我们需要的内容会变得更加容易,且仅需要最小的提示,而这些技术将变得不那么重要。

AI的概率性

AI模型生成响应的方式使其具有概率性。让我们通过一个例子来了解什么是概率性。假设你想知道世界上最好的菜系是什么。如果你向你的朋友提问两次,间隔一分钟,他的回答应该是相同的。但是,如果你向AI模型问同样的问题两次,它的回答可能会不同。如果AI模型认为越南菜有70%的可能性是世界上最好的菜系,而意大利菜有30%的可能性是最好的,它就会70%的概率回答“越南菜”,30%的概率回答“意大利菜”。概率性的反面是确定性的,即结果可以在没有任何随机变化的情况下确定。

这种概率性质可能会导致不一致性和幻觉。不一致性指的是模型为相同或略有不同的提示生成非常不同的响应。幻觉则指的是模型给出的回答不基于事实。想象一下,如果互联网上有人写了一篇关于所有美国总统都是外星人的文章,并且这篇文章被包含在训练数据中。模型之后可能会以概率方式输出当前的美国总统是外星人。对于不相信美国总统是外星人的人来说,模型是在胡编乱造。

基础模型通常使用大量数据进行训练。它们是大众意见的汇聚,字面上包含了一个可能性世界。任何具有非零概率的事物,无论多么离奇或错误,都可以由AI生成。这一特点使得构建AI应用既充满了兴奋,又充满了挑战。正如我们在本书中将看到的,许多AI工程努力旨在驾驭并减轻这种概率性特性。

这种概率性质使得AI非常适合创造性任务。创造力不就是探索常规路径之外的能力吗——跳出框框思考?AI是创意专业人士的得力助手。它可以进行无穷的头脑风暴,生成前所未见的设计。然而,这种相同的概率特性对于其他所有任务来说可能就是一种痛苦。

不一致性

模型不一致性表现为两种情况:

  1. 相同输入,不同输出:给模型相同的提示两次,得到两个非常不同的响应。
  2. 稍有不同的输入,截然不同的输出:给模型稍微不同的提示,比如不小心大写了一个字母,可能会导致非常不同的输出。

图2-23展示了我尝试使用ChatGPT给文章打分的例子。当我运行两次相同的提示时,得到了两个不同的分数:3/5和5/5。

image.png

不一致性可能会造成令人不悦的用户体验。在人与人之间的交流中,我们期望一定程度的一致性。试想一下,如果一个人每次见到你时都给你不同的名字,会是什么样的情况。类似地,用户在与AI沟通时也期望一定程度的一致性。

对于相同输入,不同输出的情况,有多种方法可以减轻不一致性。你可以缓存答案,这样下次问同样的问题时,会返回相同的答案。你可以固定模型的采样变量,比如温度、top-p和top-k值,如前面所讨论的。你还可以固定种子变量,可以把它理解为用于采样下一个令牌的随机数生成器的起始点。

然而,即使你固定了所有这些变量,也不能保证模型在100%的时间里都会保持一致。模型运行输出生成的硬件也可能影响输出,因为不同的机器有不同的执行相同指令的方式,并且能够处理不同范围的数字。如果你自己托管模型,你可以控制使用的硬件。然而,如果你使用像OpenAI或Google这样的模型API提供商,那么是否能控制这些变量就取决于这些提供商。

固定输出生成设置是一个好的做法,但它并不能激发对系统的信任。想象一下,如果一个老师只在特定的房间里给你一致的分数,而如果老师坐在另一个房间里,给你的分数就会大不相同,这种情况能给人信任吗?

第二种情况——稍有不同的输入,截然不同的输出——则更具挑战性。虽然固定模型的输出生成变量仍然是一个好的做法,但它并不能强制模型在面对不同输入时生成相同的输出。然而,通过精心设计的提示(第5章讨论)和记忆系统(第6章讨论),我们有可能让模型生成更接近我们想要的响应。

幻觉

幻觉对于依赖事实性的任务来说是致命的。如果你让AI帮你解释疫苗的优缺点,你肯定不希望AI提供伪科学的信息。2023年6月,一家律师事务所因向法院提交虚假的法律研究而被罚款。他们在准备案件时使用了ChatGPT,却未意识到ChatGPT有时会产生幻觉。

虽然幻觉随着大语言模型(LLMs)的崛起成为了一个显著的问题,但在“基础模型”和“变换器架构”这些术语被引入之前,生成模型中就已经存在幻觉现象。早在2016年,关于文本生成中的幻觉就有提到(Goyal等,2016)。自那时以来,检测和衡量幻觉已经成为自然语言生成(NLG)中的一个重要课题(参见Lee等,2018;Nie等,2019;Zhou等,2020)。本节重点解释为什么会发生幻觉。如何检测和衡量评估将在第4章讨论。

如果不一致性源自采样过程中的随机性,幻觉的原因则更为复杂。仅仅依靠采样过程并不能充分解释幻觉的产生。模型从所有可能的选项中采样输出。但为什么一些从未见过的内容会成为可能选项?模型可以输出一些被认为从未在训练数据中出现过的内容。我们无法确定这一点,因为无法逐一检查训练数据以验证是否包含某个特定的概念。我们构造出如此复杂的东西,以至于我们再也无法理解它,这既是祝福也是诅咒。

在没有理解幻觉为何发生的前提下,很难找到一种方法来消除幻觉。目前有两种关于语言模型为何会产生幻觉的假设。

第一种假设最早由DeepMind的Ortega等人于2021年提出,认为语言模型会产生幻觉,因为它无法区分它所接收到的数据与它生成的数据。让我们通过一个例子来说明这一点。

假设你给模型一个提示:“Who’s Chip Huyen?”(Chip Huyen是谁?),模型生成的第一句话是:“Chip Huyen is an architect.”(Chip Huyen是一个建筑师)。模型生成的下一个令牌将基于这个序列:“Who’s Chip Huyen? Chip Huyen is an architect.”(Chip Huyen是谁?Chip Huyen是一个建筑师)。模型把“Chip Huyen is an architect.”(Chip Huyen是建筑师)视为与它生成的其他数据一样的事实。通过这种方式,模型从一个稍有不同的生成序列开始,便可以扩展它并生成完全错误的事实。Ortega和其他作者将幻觉称为一种自我错觉。

图2-24展示了模型LLaVA-v1.5-7B的自我错觉示例。我让模型识别图片中产品标签上的成分,图片是一瓶洗发水。在它的回答中,模型说服自己图片中的产品是一瓶牛奶,然后继续将牛奶列入从产品标签提取的成分列表中。

image.png

Zhang等人(2023)称这种现象为滚雪球效应的幻觉。在做出错误假设后,模型会继续产生幻觉,以证明最初错误的假设。有趣的是,作者展示了最初的错误假设可能导致模型在本应能够正确回答的问题上犯错,如图2-25所示。

image.png

DeepMind的论文显示,幻觉可以通过两种技术来缓解。第一种技术来自强化学习,其中模型被要求区分用户提供的提示(在强化学习中称为关于世界的观察)和模型生成的令牌(称为模型的行为)。第二种技术依赖于监督学习,其中事实性和反事实信号被纳入训练数据。

第二种假设认为,幻觉是由模型的内部知识与标注者的内部知识之间的不匹配引起的。这个观点最早由OpenAI的研究员Leo Gao提出。在SFT(监督微调)过程中,模型被训练模仿标注者写的回答。如果这些回答使用了标注者拥有但模型没有的知识,我们实际上是在教模型产生幻觉。理论上,如果标注者能够在他们写的每个回答中包含他们使用的知识,以便模型知道这些回答不是凭空捏造的,我们或许可以教模型只使用它所知道的内容。然而,在实践中这是不可能的。

2023年4月,OpenAI的联合创始人John Schulman在他的加利福尼亚大学伯克利分校演讲中表达了相同的观点。Schulman也认为,LLM知道自己是否知道某些事情,这本身就是一个大声明。如果这一信念是真的,那么通过强制模型仅基于它所知道的信息给出答案,可以解决幻觉问题。他提出了两种解决方案。一种是验证:对于每个回答,要求模型检索它基于哪些来源作出的回答。另一种是使用强化学习。记住,奖励模型仅通过比较进行训练——回答A优于回答B——没有解释为什么A更好。Schulman认为,更好的奖励函数,可以通过让模型为捏造内容付出更大的代价,帮助缓解幻觉。

在同一次演讲中,Schulman提到OpenAI发现RLHF有助于减少幻觉。然而,《InstructGPT》论文显示,RLHF使幻觉问题变得更糟,如图2-26所示。尽管RLHF似乎加重了InstructGPT的幻觉问题,但它改善了其他方面,总体上,人类标注者更喜欢RLHF模型而不是仅使用SFT模型。

image.png

基于假设基础模型知道自己知道什么,有些人尝试通过提示来减少幻觉,例如加入“尽可能真实地回答,如果不确定答案,请说‘抱歉,我不知道’”这样的提示。要求模型提供简洁的回答似乎也有助于减少幻觉——模型生成的令牌越少,它编造内容的机会就越小。第5章和第6章中讨论的提示和上下文构建技巧也有助于缓解幻觉问题。

这两种假设是相辅相成的。自我错觉假设关注的是自我监督如何导致幻觉,而不匹配的内部知识假设则关注监督如何导致幻觉。

如果我们不能完全消除幻觉,至少能否检测到模型何时产生幻觉,这样我们就不会将这些幻觉的回答提供给用户呢?嗯,检测幻觉也并不那么简单——想想我们在人类之间检测谎言或捏造内容有多困难。但人们确实尝试过。我们将在第4章讨论如何检测和衡量幻觉。

总结

本章讨论了构建基础模型时的核心设计决策。由于大多数人将使用现成的基础模型,而不是从头开始训练一个,因此我跳过了细节繁琐的训练部分,重点讨论了帮助您决定使用哪些模型以及如何使用它们的建模因素。

影响模型性能的一个关键因素是其训练数据。大型模型需要大量的训练数据,而这些数据的获取可能既昂贵又耗时。因此,模型提供者通常利用现有的任何可用数据。这导致模型能够在训练数据中包含的许多任务上表现良好,但这些任务可能并不包括您所需要的特定任务。本章探讨了为什么通常需要精心策划训练数据,以开发针对特定语言(特别是低资源语言)和特定领域的模型。

在获取数据之后,模型开发就可以开始了。虽然模型训练常常占据头条,但在此之前一个重要的步骤是设计模型架构。本章研究了建模选择,如模型架构和模型大小。语言基础模型的主导架构是变换器(transformer)。本章探讨了变换器架构旨在解决的问题以及它的局限性。

模型的规模可以通过三个关键数字来衡量:参数数量、训练令牌数量和训练所需的FLOP数。影响训练模型所需计算量的两个方面是模型大小和数据大小。扩展法则有助于在计算预算给定的情况下,确定最佳的参数数量和令牌数量。本章还讨论了扩展瓶颈。目前,扩大模型通常能提高其性能。但这种情况能持续多久呢?

由于训练数据质量较低和预训练过程中的自我监督,生成的模型可能会产生与用户期望不符的输出。通过后训练来解决这个问题,后训练包括两个步骤:监督微调和偏好微调。人类偏好是多样的,且无法通过单一的数学公式来捕捉,因此现有的解决方案远非万无一失。

本章还讨论了我最喜欢的话题之一:采样,模型生成输出令牌的过程。采样使得AI模型具有概率性。这种概率性是像ChatGPT和Gemini这样的模型非常适合创意任务并且令人愉快的原因。然而,这种概率性质也会导致不一致性和幻觉。

与AI模型合作需要围绕其概率性特性建立工作流程。本书的其余部分将探讨如何使AI工程,尽管不能是确定性的,至少能变得系统化。朝着系统化AI工程迈出的第一步是建立一个坚实的评估管道,帮助检测失败和意外变化。基础模型的评估至关重要,以至于我为此专门分配了两章内容,从下一章开始。