一、一秒之内发生了什么
你在输入框里敲下一行字,按下回车。一秒钟后,屏幕上出现了答案。
这一秒里,模型内部经历了什么?
前几篇文章讲的是"身体结构"——Token 怎么切、Embedding 怎么表示、Attention 怎么工作、FFN 怎么消化、残差和 LayerNorm 各自负责什么。但这些都是静态的零件图。现在把它们组装起来,让它动起来。
以一个问题为例:
从按下回车,到"巴"字出现,所有计算步骤完整走一遍。
[外链图片转存中…(img-5IygWBmK-1779287429159)]
二、把你的话切成"词块"
模型只认数字,不认文字。第一步是把句子切成模型认识的词块——分词(Tokenization),工具叫词元化器(Tokenizer),本质是一个查找表。
"法国的首都是什么?"↓[1374,11223,1585,3425,30,40674]每个数字代表一个 Token。Token 不等于汉字——它是模型在训练时自己学出来的最小语义单元。
几个常见切分结果:
"巴黎"→[1585]一个 Token"首都"→[3425]一个 Token"人工智"→[24597,5765]被切成两块,训练时没见过这个词"ChatGPT"→[203,1372,1273,164,58]五个 Token,英文切得更碎Token 越少,计算越快,内存占用越低。这也是 GPT-4 Turbo 把上下文窗口从 32K 扩展到 128K Token 的原因——不只是多装文字,更是为了让代码、数学这类 Token 密集的内容更高效地处理。
"法国的首都是什么?"切成 9 个 Token(标点也占一个)
三、把词块变成数字
每个 Token 要变成一个向量,这一步叫Embedding(嵌入),把离散的符号映射到连续的向量空间。
Token ID:[1374,11223,1585,3425,30,40674]↓ Embedding 查表 向量序列:[v₁, v₂, v₃, v₄, v₅, v₆]每个v是768维浮点数向量(GPT-2)Embedding 表是训练时学出来的。每个 Token 在训练数据里反复出现,模型逐渐学到"最适合它表达语义"的向量。
但有个问题:Token Embedding 本身不包含位置信息。"人咬狗"和"狗咬人"Embedding 之后完全一样——对 Attention 来说是两条一样的数据。所以需要额外加上位置编码(Position Embedding):
最终输入向量=Token Embedding + Position Embedding给每个位置分配一个专属向量,加到 Token 向量上,模型这才知道"谁在谁前面"。
四、多层 Attention/FFN,依次"消化"
经过 Embedding 后的向量进入 Attention/FFN 层。多层结构完全相同,但参数不同,每一层都在做两件事:
Layer N:LayerNorm → Attention → 残差连接 LayerNorm → FFN → 残差连接来看"法"这个 Token 的向量在这一秒里经历了什么。
Attention 层:每个 Token 只能向自己及之前的 Token 提问。GPT 类模型叫这个因果掩码(Causal Mask),只能"看见过去",不能"偷看未来"。
注意力矩阵:
法 国 的 首 都 是 什 么 ?"法"能看见: ✓ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗"国"能看见: ✓ ✓ ✗ ✗ ✗ ✗ ✗ ✗ ✗"?"能看见: ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓"国"问"法"和自己:训练数据里"法"和"国"高频共现,所以跟"法"相关性高。
"?“问之前所有 8 个 Token:跟"首”"都"相关性高("首都"是固定搭配),跟"法"相关性也高("法国首都是什么"这个句式见过无数次)。
Attention 计算之后,每个 Token 的向量都被更新了,它"看见"了自己之前所有上下文。
FFN 层:每个 Token 单独经过自己的前馈网络(GPT-2 是 768→3072→768)“法"在这个向量附近学会了"法"常与"国”“欧洲”"首都"等词共现,但第一层上下文还很少,无法确定是哪个欧洲国家。
LayerNorm 把向量拉回标准范围,残差连接叠加原始信息,信息不丢失。
多层叠加的效果:虽然"法"永远不能直接"看见"后面的词,但"首都"等后续 Token 的向量在每一层都被精炼。第 多层的"首都"向量比第 1 层丰富得多,经过 多 次精炼,最终汇聚出完整理解。
[外链图片转存中…(img-Tmt1TK4Z-1779287429161)]
五、把向量翻译回词
经过 多层后,对最后一个 Token(“?”)的输出向量进行解码,叫LM Head(语言模型头),一个从隐藏维度映射回词表大小的线性层。
v₁₂("?"经过 多层后的输出向量):768 维 ↓ LM Head(W^T)50257维向量(词表中每个词的概率) ↓ Softmax[P("法"), P("国"),..., P("巴")=0.042, P("北")=0.018,...]↑ 最高50257 个数字,每个代表模型认为下一个词应该是什么的概率。"巴"的概率最高,因为训练语料里"法国的首都是……"后面接"巴黎"的频率远高于其他词。
六、从概率到文字
拿到概率分布后,下一步是从概率分布里抽取一个词——采样(Sampling)。
Greedy(贪心):直接选概率最高的词。结果确定,但容易陷入重复循环。
Temperature Sampling(温度采样):在 Softmax 前对 logits 除以一个温度参数 T。T > 1 时分布变平坦,高概率词优势减小;T < 1 时分布变尖锐,更倾向于高概率词;T = 1 是标准 Softmax。对话场景通常 T=0.7~1.0,创意写作可以更高。
Top-K Sampling:只从概率最高的 K 个词里采样,避免从 5 万个词里选到荒谬的词。
Top-P(Nucleus Sampling):从概率最高的词开始累加,达到阈值 P 为止。Token 概率分布窄时少选几个,宽时多选几个,比 Top-K 更灵活。GPT 系列默认用 Top-P + Temperature 组合。
七、循环:把输出的词再加回去
选出"巴"之后,故事还没结束。模型不能只输出一个字,它要生成一整句话。
"巴"要加回到输入序列,从头再跑一遍 多层 Attention/FFN,预测下一个词。这个过程叫自回归(Autoregressive)生成。
第1轮:[法, 国, 的, 首, 都, 是, 什, 么, ?]→"巴"第2轮:[法, 国, 的, 首, 都, 是, 什, 么, ?, 巴]→"黎"第3轮:[法, 国, 的, 首, 都, 是, 什, 么, ?, 巴, 黎]→"。"第4轮:[法, 国, 的, 首, 都, 是, 什, 么, ?, 巴, 黎, 。]→[EOS]每生成一个新 Token,都要重新跑一遍 多层 Attention/FFN。生成 50 个 Token,要跑 50 次完整前向——不是"多算一点",而是线性叠加。推理贵的根本原因就在这里。
八、成本拆解:这一次推理花了多少算力
用 GPT-2(多层,768 维,12 头,约 1.2 亿参数)来感受一下计算量。
输入 9 个 Token,输出一段话,大约经历:
- • Embedding 查表:9 次
- • 多层 Attention/FFN,每层 2 次 LayerNorm + 1 次 Attention + 1 次 FFN
- • LM Head:1 次(768→50257)
- • Softmax + 采样:1 次
- • 自回归:上述过程重复 N 次(N = 输出 Token 数)
粗略估算:
一次前向传播 ≈ 参数量 ×3(经验值)≈1.2亿 ×3≈3.6亿次浮点运算 生成50个 Token ≈50×3.6亿 ≈180亿次浮点运算这只是 GPT-2 的量级。LLaMA 7B 一次前向是 GPT-2 的 56 倍,难怪 ChatGPT 要收费。
推理优化的三个核心方向:
- •KV Cache:把已经算好的 Key、Value 存起来,不用每次重新算。
- •量化(Quantization):把 FP32 参数量化成 INT8、INT4,大幅降低内存和计算量,精度损失小。
- •投机解码(Speculative Decoding):用小模型猜几个词,大模型验证,并行加速。
九、结语
按下回车后的这一秒,大模型内部经历了:
输入 → Token 化 → Embedding → 多层 Attention/FFN → LM Head → Softmax → Top-P 采样 → 输出词 → 加回输入 → 重复 多层 … → 出现[EOS],停止输入 9 个 Token、输出 50 个 Token,一次推理约 180 亿次浮点运算,换来 50 个词。
Attention 让模型看见上下文,FFN 调用知识,残差连接保留信息,LayerNorm 稳定数值。这些机制在推理的每一毫秒里同时工作。
下篇文章要说的是:这一切是怎么来的?几十亿个随机参数,是怎么变成能精准预测下一个词的大脑的?
—
文章首发于 「小小寰宇」