LLM 是怎么工作的

创建于2023.12.29预计阅读13 分钟

用过 ChatGPT 就会觉得它像在聊天、会写代码。大语言模型(LLM)内部其实一直在做同一件事:根据已经出现的上文,预测下一个词。训练时在大量文本上学这个动作,生成时按概率挑一个接到后面,再预测下一个。

本文从这句话往下拆:模型看到的单位是什么,怎么变成向量,注意力和 Transformer 怎么工作,以及它是怎么训练、怎么对齐的。

预测下一个词

给模型一句话的开头:

「我早上起来喝了一杯……」

它对词表里每个候选算出「它是下一个的可能性」,得到一张概率表:咖啡 32% / 水 25% / 牛奶 11% / …。然后按这张表挑一个(比如「咖啡」),把「我早上起来喝了一杯咖啡」当成新的输入,再算下一张表。这样一路续下去,直到生成一个表示结束的特殊标记。这种「用自己的输出当下一步输入」的方式叫自回归。

我早上起来喝了一杯…已有的词(上文)模型算全词表的概率咖啡 32%水 25%牛奶 11% …
上文 → 一张覆盖整个词表的概率分布 → 采样一个 → 接回输入 → 再来一遍。

写成公式,就是一个条件概率:已知前 t1t-1 个 token,给出第 tt 个的分布。

Pθ(wtw1,w2,,wt1)P_\theta\left(w_t \mid w_1, w_2, \dots, w_{t-1}\right)
  • wtw_t:第 tt 个位置的 token。
  • w1wt1w_1 \dots w_{t-1}:它前面的所有 token,也就是上文。
  • θ\theta:模型的全部参数。

整段文本的联合概率,是把每个位置的条件概率连乘起来。这是概率的链式法则,也是语言模型的定义:

Pθ(w1,,wn)=t=1nPθ(wtw<t)P_\theta(w_1,\dots,w_n) = \prod_{t=1}^{n} P_\theta\left(w_t \mid w_{<t}\right)

具体到一步:模型先对词表里每个词输出一个未归一化的分数,叫 logits,再用 softmax 压成一个和为 1 的概率分布。上面那张「咖啡 32% / 水 25%」就是这样来的。

softmax(z)i=ezijezj\text{softmax}(z)_i = \frac{e^{z_i}}{\displaystyle\sum_{j} e^{z_j}}

Token

上面一直说「词」,模型实际处理和预测的单位叫 token。

我们读「苹果」是两个字。模型不按字、也不按词处理,而是按一种折中的单位:子词(subword)。常用词整块保留,生僻词拆成更小的片段,标点、空格也各占一块。切完,每一块映射到词表里的一个固定编号。

这一块就是 token(词元)。这套切分叫 tokenization,常见算法是 BPE,GPT-2 之后很多模型用的是按字节做的 BPE。按字的话序列太长、计算太贵;按整词的话词表会很大,也总会遇到没见过的新词。

我啃了一口苹果一口苹果每块 token → 词表里的一个整数编号:[2769] [22651] [6693] [8080] [99164]
文本先被切成 token,再变成整数编号。模型全程只跟这些编号打交道。图里的编号是示意。

上下文长度(比如 8K、128K)指的是一次能处理多少个 token。API 计费、速度、能塞多少资料,也都按 token 算。

嵌入

编号本身没有意义。99164 和 99165 相邻,代表的内容可能毫不相关。所以每个编号会经过一张查找表,映射成一个几百到几千维的实数向量。

这个映射叫 embedding,中文是嵌入:把离散的 token 嵌进连续向量空间。查出来的那个向量叫嵌入向量。Word2Vec 那会儿大家常说词向量,指的也是这种向量,不过那时的单位是词。现在切出来的是子词,叫嵌入更准确。

查找表给每个 token 的是一个固定的初始向量,和上下文无关。语义相近的 token,向量往往也比较近,但同一个写法仍可能对应不同意思。

向量空间(真实有几百到几千维,这里投影到 2 维示意)苹果(水果)香蕉水果簇苹果(公司)谷歌微软科技公司簇
「苹果」有两个可能的语义落点。查找表只能给一个初始向量,偏向哪个含义,要靠后面的注意力结合上下文来定。

Word2Vec 里有个常被拿来举例的运算:向量(国王) − 向量(男人) + 向量(女人) 会靠近 向量(女王)。那是静态词向量上的观察。GPT 这类模型的查找表不一定能干净地做出这种算术,消歧主要靠下一节的注意力。

注意力

查找表给「苹果」的初始向量是静态的。同一个词的意思常常取决于旁边的词:

  • 「我啃了一口苹果」:水果。
  • 「我在发布会上买的苹果」:公司。

处理「苹果」这个位置时,模型会回看序列里的每一个 token,按相关度分配权重,再按权重把信息加权汇总,得到一个掺入了上下文的新向量。看到「啃」「一口」权重高,就往水果偏;看到「发布会」「买」权重高,就往公司偏。

这个机制叫注意力(attention)。每个位置都在看同一段里的其它位置,所以也叫自注意力(self-attention)。

啃了一口苹果「啃」「一口」权重高 → 偏向水果义线越粗 = 注意力权重越大换成「发布会上买的苹果」,粗线改连到「发布会」「买」,语义随之翻成公司。
注意力按「上下文里谁相关」更新当前位置的表示。静态嵌入因此变成上下文相关的表示。

实现上,每个位置的向量会乘上三个可学习的矩阵 WQ,WK,WVW_Q, W_K, W_V,投影成三个角色:

  • Query(Q):当前位置要找什么。
  • Key(K):每个位置用来被检索的标签。
  • Value(V):每个位置实际携带的内容。

Q 和所有 K 做点积得到相关度分数,缩放后再做 softmax,变成权重,再用权重对所有 V 加权求和。这就是缩放点积注意力:

Attention(Q,K,V)=softmax ⁣(QKdk)V\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V
  • QKQK^{\top}:每个 Query 和每个 Key 的点积,也就是「谁和谁相关」的分数。
  • dk\sqrt{d_k}dkd_k 是 Q/K 的维度。除以它做缩放,避免点积过大把 softmax 推到饱和区。
  • VV:按权重汇总上下文,得到该位置的新表示。

softmax(QKᵀ / √dₖ) 决定关注谁、关注多少,乘 V 是按这个比例把信息汇总过来。这里对整段两两算相关度,计算量随序列长度 nnO(n2)O(n^2),长上下文贵,主要就贵在这里。

实际会并行跑多组 Q/K/V,叫多头注意力(multi-head)。不同的头可以学到不同的关系,输出拼接后再做一次线性变换。

Transformer

单层注意力只汇总一轮信息。真正的模型把「多头自注意力 + 前馈网络(FFN)」打包成一个 block,再叠几十到上百层。每个子层通常还配残差连接和层归一化,让梯度能穿过很深的网络。这套架构是 2017 年论文提出的 Transformer。GPT 这类模型只用它的解码器部分,并且加了因果掩码:每个位置只能看它左边的 token,不能偷看后面的答案。

token → 嵌入 + 位置编码 → 逐层加工 → logits嵌入 + 位置编码多头自注意力按相关度回看上文前馈网络 FFN一个 block(含残差 + LayerNorm)× N 层(重复 N 次)logits → softmax → 概率表
block 一层层叠上去。低层往往更局部,高层往往更抽象,这是常见观察,不是每层都严格如此。

注意力本身分不清先后:把词序打乱,加权求和的结果可以不变。所以要另外注入位置信息。早期用正弦位置编码(positional encoding),现在常见的是 RoPE(旋转位置编码)这类相对位置方案。

预训练

GPT 这类模型的预训练任务不是随机遮住中间某个词(那是 BERT 的做法),而是给定前面的 token,预测下一个。一段文本里,每个位置都可以当训练样本。

预测得到的分布和真实那个 token 越接近越好,否则就调整参数。因为答案就在文本里,不需要人工标注,所以叫自监督。这个阶段叫预训练(pre-training)。

目标等价于最小化交叉熵(负对数似然):

L(θ)=1NtlogPθ(wtw<t)\mathcal{L}(\theta) = -\frac{1}{N}\sum_{t} \log P_\theta\left(w_t \mid w_{<t}\right)
  • L(θ)\mathcal{L}(\theta):平均到每个 token 的损失,越小表示预测越准。
  • Pθ(wtw<t)P_\theta(w_t \mid w_{<t}):模型给真实 token 的概率。
  • log\log:真实 token 的概率越接近 1,这项越接近 0;越接近 0,惩罚越重。

有了损失,就用反向传播求每个参数的梯度,再用 Adam 一类优化器更新 θ\theta。在大量 GPU 上对很多 token 重复这个过程,就是预训练。

衡量语言模型好坏的常用指标是困惑度(perplexity),等于 eLe^{\mathcal{L}},也就是平均交叉熵再取指数。可以粗略理解成:模型平均要在多少个词里犹豫。

为了把下一个词预测准,参数里会压进语法、事实、常识和一些代码结构。这些不是一条条写进去的,是这个训练目标的副产品。

对齐

刚预训练完的模型只会续写。你问「怎么煮咖啡」,它可能接「怎么煮咖啡才好喝?这是很多人的疑问」,像在补全网页。

后面还有第二阶段。先用「指令 / 优质回答」样本做监督微调(SFT),让它遇到提问就作答;再用人对多个回答的排序,让模型偏向人更满意的输出。经典方法是 RLHF(基于人类反馈的强化学习),也可以用更简单的 DPO。这个阶段统称对齐(alignment)。

预训练决定它从文本里学到了多少,对齐决定它会不会按问题来答。

生成时怎么挑词

有了概率分布,还要落到一个具体的 token。每次都挑概率最高的(greedy)容易呆板、重复,所以一般会随机采样,并用温度 TT 调节分布有多尖:

pi=ezi/Tjezj/Tp_i = \frac{e^{z_i / T}}{\displaystyle\sum_{j} e^{z_j / T}}
  • TT 接近 0:几乎总选最高分,更稳定,也可以复现。
  • T=1T = 1:就是原来的 softmax。
  • T>1T > 1:分布被抹平,低分词也有机会,更散,也更容易出错。

再配合截断:top-k 只在概率最高的 kk 个里采,top-p(核采样)只在累积概率达到 pp 的最小集合里采。

几个容易混的地方

它不是检索数据库。存的是参数,不是一篇篇原文,答案是现算的。同一问题多问几次,结果可能不同,因为采样带随机性。

「幻觉」是这套目标带来的副作用。它要接一个概率高的、读起来顺的 token,并不是要保证为真。手头没有确切事实时,流畅但错的下一词,往往比留白更像训练时见过的文本,于是它会编。

它没有跨轮的持久记忆。每次都是把当前这段上下文重新读一遍再预测,超出窗口的内容就看不见了。聊天产品看起来像有记忆,多半是系统把历史对话又塞回了上下文。

参数量大不一定更强。数据质量、训练时数据和参数的配比、对齐质量都有影响。Kaplan 等人总结过 scaling law:算力、数据、参数配比合适时,测试损失会比较平滑地下降。Chinchilla 后来指出,很多大模型其实数据不够,该把更多算力花在数据上。

延伸阅读

Yi Liu

© 2026 Yi Liu

GitHubRSS