How LLMs Actually Work:零基础读懂 Transformer
2026.06.12 08:00How LLMs Actually Work:零基础读懂 Transformer
原文:How LLMs Actually Work by 0xkato
前言:为什么要读这篇文章?
我对 LLM 完全零基础,但一直好奇 ChatGPT、Claude、Gemini 这些模型”里面到底发生了什么”。它们不是魔法,但也不是简单的”查表”。这篇文章从最基础的 Tokenization 开始,一路讲到 Next-Token Prediction,把现代 Transformer 的骨架讲得很清楚。
我采用的学习方式是不让 AI 直接给答案,而是让它一步步引导我,每个模块都要我用自己的话复述并回答验证问题。这篇文章就是我学习过程的整理。
一、先见森林:LLM 生成一句话的完整流程
在深入每个零件之前,先看看整台机器是怎么运转的。假设你输入了”今天天气”,模型要生成下一个词:
输入文本:"今天天气"
↓
[1] Tokenizer:把汉字切成 token,变成数字 ID
↓
[2] Embedding:查表把数字变成向量(一串小数)
↓
[3] 位置编码:给向量加上"第几个字"的信息
↓
[4] Transformer 层 × N 层(核心计算,后面详细讲)
↓
[5] 取最后一个词的向量
↓
[6] Unembedding:投影到词汇表,得到每个候选词的分数
↓
[7] Softmax:分数变成概率(和为 1)
↓
[8] 采样:根据概率选下一个词(比如"很好")
↓
把"很好"拼回输入,变成"今天天气很好",重复步骤 1-8这就是 LLM 工作的全貌。接下来我们逐个拆解这 8 个步骤。
二、Tokenizer:文本怎么变成数字?
为什么需要这一步?
计算机只认识数字,不认识汉字。所以第一步必须把”今天天气”变成模型能处理的数字序列。
三种切分方式
| 粒度 | 例子 | 问题 |
|---|---|---|
| 整词 | “tokenization” 是一个词 | 词汇表太大,新词无法处理 |
| 字符 | t-o-k-e-n-i-z-a-t-i-o-n | 序列太长,模型要从头学简单模式 |
| 子词(subword) | “token” + “ization” | 平衡,能组合出新词 |
现代 LLM 都用子词(subword)。比如 “unhappiness” 可能被切成 “un” + “happiness” 或 “un” + “happy” + “ness”。
著名的 “strawberry” 问题
问 LLM “strawberry” 里有几个 R,它以前经常答错。这不是模型笨,而是模型不直接操作字母,它操作的是 token。如果 “strawberry” 被切成 “straw” + “berry”,模型看不到字母级别的信息。
三、Embedding:给数字赋予意义
Token ID 只是行号
Tokenizer 输出的数字只是”第几个 token”,没有任何语义。比如:
- “猫” → ID 1234
- “狗” → ID 5678
1234 和 5678 之间没有任何数学关系,模型无法理解它们都是动物。
Embedding 矩阵:巨大的查表
Embedding 就是一个巨大的表格,每行对应一个 token,每行是一个向量(比如 4096 个小数):
Token ID → 查表 → 向量 [0.23, -0.45, 0.89, ..., 0.12](4096 维)为什么向量能表示语义?
训练过程中,模型会自动调整这些向量,让语义相近的词在向量空间中靠得更近。著名的例子:
king - man + woman ≈ queen这说明 embedding 空间的几何结构携带了语义关系。
还缺什么?
Embedding 本身不包含位置信息。“今” 在第 1 位和第 5 位是同一个向量。模型不知道”今天天气”和”天气今天”的区别。所以需要位置编码。
四、位置编码:模型怎么知道顺序?
核心问题
模型处理的是向量,而向量本身没有”位置”概念。
"今天天气很好" → 5个向量
"天气今天很好" → 5个向量
如果不加位置信息,这两句话对模型来说完全一样!因为同一个词的向量在任何位置都相同。模型需要额外信息来区分”第1个字”和”第3个字”。
方案一:直接告诉它位置数字(最简单但不好用)
给每个向量附加一个位置编号:
"今" → [向量内容, 位置=1]
"天" → [向量内容, 位置=2]
"气" → [向量内容, 位置=3]问题:位置数字太大(比如第1000个字),模型学起来困难。而且数字之间是线性关系,模型难以捕捉周期性模式(比如”每两个字一组”)。
方案二:正弦/余弦编码(原始Transformer用的)
不用原始数字,而是用正弦和余弦函数把位置转换成一种”波浪”模式。
直观理解:想象一个时钟
位置1:指针指向1点钟方向
位置2:指针指向2点钟方向
位置3:指针指向3点钟方向
...每个位置对应一个独特的角度,而且这个角度是周期性的(转一圈回到原点)。
具体做法:
对于维度i,使用不同频率的正弦波:
- 维度0:sin(位置 × 1) ← 慢波,周期长
- 维度1:sin(位置 × 2) ← 稍快
- 维度2:sin(位置 × 4) ← 更快
- …
- 维度d:sin(位置 × 很大) ← 快波,周期短
效果:
- 每个位置得到独特的”指纹”(不同频率波的叠加)
- 相邻位置相似(慢波变化小),远距离位置差异大(快波变化大)
- 可以外推到训练时没见过的长度
问题:这些位置编码是固定死的,不能学习调整。而且embedding要同时装”词义”和”位置”,有点挤。
方案三:RoPE(旋转位置编码,现代模型都用)
RoPE说:别直接加位置信息了,旋转向量本身!
直观理解:想象每个向量是一个二维平面上的箭头
原始向量:→
位置1:旋转1° →↗
位置2:旋转2° →↗↗
位置3:旋转3° →↗↗↗关键洞察:
- 位置越远,旋转角度差越大
- 两个向量的点积(相似度)只取决于它们的相对角度差
- 所以模型自然学到”距离近的词关系更紧密”
为什么比正弦编码好?
| 正弦编码 | RoPE | |
|---|---|---|
| 怎么加位置 | 直接加到向量上 | 旋转向量本身 |
| 能否学习 | 固定死的 | 融入注意力计算,可学习 |
| 相对位置 | 需要模型自己学 | 天然体现在点积中 |
| 长文本外推 | 一般 | 更好 |
具体怎么旋转?
对于二维向量 (x, y),旋转θ角度后:
x' = x·cosθ - y·sinθ
y' = x·sinθ + y·cosθ高维向量就是每两个维度组成一对,分别旋转。
相对位置怎么体现?
假设Query在位置m,Key在位置n:
- Query旋转了 mθ
- Key旋转了 nθ
- 它们的相对角度是 (m-n)θ
所以点积结果只取决于距离差(m-n),而不是绝对位置。这意味着”相邻词的关系”和”远距离词的关系”有固定的数学模式,模型更容易学习。
为什么旋转能保持语义?
核心洞察:旋转是一种”刚性变换”
想象你拿着一张地图:
- 拉伸/压缩:地图变形了,距离关系改变(会破坏语义)
- 旋转:地图只是转了个方向,所有相对位置不变(保持语义)
数学上,旋转矩阵是正交矩阵,满足:
R^T · R = I(单位矩阵)这意味着:
- 向量长度不变:旋转后向量的”大小”不变,不会放大或缩小某些维度
- 角度关系不变:向量之间的相对角度保持,语义关系不被扭曲
对比:直接加位置编码的问题
原始向量:[0.5, 0.3] 表示"猫"
加位置1:[0.5+0.1, 0.3+0.2] = [0.6, 0.5] ← 方向和长度都变了
加位置2:[0.5+0.2, 0.3+0.4] = [0.7, 0.7] ← 变得更多
问题:位置数字"污染"了语义信息,而且位置越大污染越严重RoPE的旋转操作
原始向量:[0.5, 0.3] 长度=√(0.5²+0.3²)=0.58
旋转30°后:[0.5·cos30°-0.3·sin30°, 0.5·sin30°+0.3·cos30°]
= [0.43-0.15, 0.25+0.26]
= [0.28, 0.51]
验证长度:√(0.28²+0.51²)=0.58 ✓ 长度不变!关键:旋转只是改变了向量的”朝向”,没有拉伸或压缩。就像你把椅子转了个方向,它还是那把椅子。
为什么长度很重要?
Embedding空间的几何结构携带语义:
- 向量长度代表”概念的强度”或”确定性”
- 方向代表”概念的类型”
如果操作改变长度,就等于改变了”猫有多猫”或”猫有多确定”。旋转只改变方向(加了位置信息),不改变长度(保留语义强度)。
RoPE和正弦编码的数学联系
惊人的事实:RoPE是正弦编码的”进化版”
正弦编码:
PE(pos, 2i) = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))RoPE的旋转:
[x, y] 旋转 θ 后:
x' = x·cosθ - y·sinθ
y' = x·sinθ + y·cosθ其中 θ = pos × base^(-2i/d)
联系在哪里?
把正弦编码的公式重排:
sin(pos / 10000^(2i/d)) = sin(pos × 10000^(-2i/d))令 θ = pos × 10000^(-2i/d),这就是RoPE的旋转角度!
本质区别:
- 正弦编码:位置信息是外部添加剂,加到向量上
- RoPE:位置信息是内部旋转,融入向量本身
为什么RoPE更好?
| 正弦编码 | RoPE | |
|---|---|---|
| 位置信息在哪 | 额外维度 | 融入现有维度 |
| 和attention的关系 | 独立计算 | 相对位置天然体现在点积中 |
| 可学习性 | 固定死的 | 旋转角度可微调 |
| 长文本外推 | 一般 | 更好(旋转周期天然存在) |
Lost in the Middle
即使有了RoPE,LLM对长文本中间部分的信息利用仍然较差。这不是位置编码的锅,而是attention机制的固有特性:
- 两端的词参与的attention计算更少(前面只有少量词,后面也只有少量词)
- 中间的词要和所有词计算,信息容易被稀释
- 训练数据中,关键信息通常在开头或结尾(摘要、结论)
所以提示工程建议:重要信息放开头,关键信息在结尾重复。
五、Transformer 层:核心计算
这是 LLM 的心脏。每一层做两件事:
- Attention:词与词互相交流(收集信息)
- FFN:每个词独立思考(深度加工)
5.1 Attention:词与词如何交流?
Q、K、V 的直觉
我用一个房间里的场景来理解:
| 角色 | 类比 | 作用 |
|---|---|---|
| Query(查询) | 你要找的人的特征描述 | “我在找什么” |
| Key(键) | 每个人的名片 | “我提供什么” |
| Value(值) | 你实际想得到的信息 | “匹配成功后传递什么” |
完整过程
- “was” 发出 Query:“我要找主语”
- 每个词亮出 Key
- “cat” 的 Key 最匹配(分数高)
- 拿取 “cat” 的 Value
- “was” 更新自己的理解:主语是 “cat”
点积 + Softmax
Query · Key_cat = 0.74 ← 高
Query · Key_yesterday = -0.05 ← 低Softmax 把这些分数变成概率(和为 1),然后加权平均 Value。
为什么比 RNN 好?
**RNN(循环神经网络)**像传纸条游戏:
第1个词 → 第2个词 → 第3个词 → ... → 第1000个词每个词只能看到前面传过来的压缩信息。传到第 1000 个词时,最早的信息已经被稀释得差不多了。这就是长程依赖问题。
Attention让每个词直接看所有其他词,像电话会议而不是传纸条。长距离关系不会稀释,而且可以并行计算。
| RNN | Transformer | |
|---|---|---|
| 信息传递 | 逐个传,像接力赛 | 任意两点直接连接,像电话会议 |
| 长距离关系 | 很难 | 容易 |
| 并行计算 | 不能 | 可以 |
Multi-Head Attention:多个侦探并行
语言中同时存在多种关系:主谓关系、指代关系、语义关系、位置关系、修饰关系。一个头只能学一种模式。
所以用多个头,每个头有独立的投影矩阵,把完整的向量映射到更小的空间,专注于一种关系:
| Head | 专长 |
|---|---|
| Head 1 | 语法:动词找主语 |
| Head 2 | 指代:it 指谁 |
| Head 3 | 语义:相关概念 |
| Head 4 | 位置:时间词配对 |
最后把所有头的输出拼接起来,再通过一个矩阵学习如何组合。
KV Cache:加速生成
生成文本时,模型一个词一个词地输出。如果没有缓存,每生成一个新词都要重新计算前面所有词的 K 和 V。
有了 KV Cache:只计算新词的 Q,K 和 V 从缓存里取。计算量从 O(n²) 降到 O(n)。
GQA(Grouped-Query Attention)
KV Cache 内存开销大。GQA 让多个 Query Head 共享同一组 K/V Head:
传统:64 Query Heads + 64 K/V Heads
GQA: 64 Query Heads + 8 K/V Heads内存减少,精度几乎不变。
5.2 FFN(Feed-Forward Network):独立思考时间
Attention vs FFN 的分工
| Attention | FFN | |
|---|---|---|
| 角色 | 开会议,收集信息 | 回办公室,深度思考 |
| 数学 | 加权平均(线性) | 非线性变换 |
| 跨 token | 是 | 否,每个 token 独立 |
为什么需要非线性?
没有非线性,多层线性层叠加等价于一层线性层。非线性让网络能表达复杂函数。
简单理解:线性变换只能拉伸和旋转,非线性变换可以弯曲和折叠,创造出更复杂的决策边界。
FFN 是模型的”知识库”
研究发现,FFN 中的某些神经元会对特定概念强烈激活:某个神经元 → 埃菲尔铁塔,某个神经元 → Python,某个神经元 → 过去时动词。
ROME 方法甚至可以直接编辑 FFN 权重,改变模型”知道”的事实。
MoE(Mixture of Experts)
传统 FFN:每个 token 都经过同一个大网络。MoE:有多个专家网络,但每个 token 只激活其中几个。
Mixtral 8x7B:
- 总参数 46.7B
- 每 token 激活 12.9B
- 效果接近 70B Dense 模型好处:参数多(知道得多),计算少(跑得快)。
5.3 残差连接与 LayerNorm:让 100 层稳定训练
深层网络的问题
信号经过 100 层:前向传播数字越乘越小(消失)或越大(爆炸),反向传播梯度消失或爆炸。
残差连接:抄近路
新向量 = 旧向量 + 层的输出这样原始信息可以直接传到深层,梯度也能直接传回浅层。即使中间某层学坏了,信息也能通过”近路”绕过它。
LayerNorm:自动音量控制
每层之间把向量缩放回稳定范围,防止数字爆炸。就像音响的自动增益控制,声音太大就调小,太小就调大。
Pre-norm vs Post-norm
- 原始 Transformer:Attention → Add → Norm
- 现代模型:Norm → Attention → Add
Pre-norm 训练更稳定。
RMSNorm
LayerNorm 做两件事:减均值 + 除标准差。RMSNorm 只做除法,更便宜,效果一样好。
六、从向量到词:Next-Token Prediction
完整过程
- 取最后一个 token 的向量(它包含了前面所有词的信息)
- 通过 Unembedding 矩阵 → 100000 个 logits(每个候选词的分数)
- Softmax → 概率分布(分数变成 0-1 之间的概率,和为 1)
- 根据 temperature / top-k / top-p 采样
- 得到下一个 token
- 解码成文字,拼回输入,重复
Temperature:控制随机性
| 温度 | 效果 |
|---|---|
| 低(0.1) | 保守,几乎总是选最高概率 |
| 中(1.0) | 自然 |
| 高(1.5+) | 随机,更有创意,可能胡说 |
Temperature 就是给概率分布”加热”或”冷却”。温度高,概率分布变平坦,小概率词也有机会被选中;温度低,概率分布变尖锐,总是选最可能的词。
Top-k / Top-p
- Top-k:只考虑概率最高的 k 个候选词
- Top-p(nucleus sampling):考虑概率累积到 p 的最小集合
过滤掉离谱的候选词,只在合理范围内采样。
Speculative Decoding
小模型快速草稿,大模型并行验证。速度提升 2-3 倍,输出质量不变。
七、神经网络基础:从”写规则”到”学规则”
传统编程 vs 神经网络
| 方式 | 怎么做 | 缺点 |
|---|---|---|
| 传统编程 | 人类写规则,机器执行 | 规则太多,无法穷举 |
| 神经网络 | 给数据+目标,机器自己找规律 | 需要大量数据和算力 |
神经网络的核心是权重(weights)。训练过程就是不断调整这些权重,让模型的输出越来越接近真实答案。
梯度下降:蒙眼下山
想象你蒙着眼睛在山上,目标是走到山谷最低点。你只能感觉到脚下的坡度:往坡度最陡的反方向走一小步,停下来再感受坡度,重复。
这就是梯度下降。步长叫学习率(learning rate),太大容易跨过谷底,太小则收敛太慢。
八、Architecture vs Trained Weights:模型之间到底哪里不同?
共享的骨架
GPT、Claude、Gemini、LLaMA 等现代 LLM 都共享:Tokenization、Embeddings、RoPE、Stacked Transformer layers、Multi-head attention、FFN、Residual stream、LayerNorm、Next-token prediction。
差异点
- 训练数据:学什么
- 配置:层数、维度、头数、词汇表大小
- 权重:具体训练出来的数字
- Post-training:指令微调、RLHF、安全对齐
现代 Transformer 栈的收敛
2017-2025 年间,业界独立地收敛到相似选择:
| 组件 | 现代选择 |
|---|---|
| 位置编码 | RoPE |
| 归一化 | Pre-norm + RMSNorm |
| 激活函数 | SwiGLU |
| Attention | GQA |
| 超大模型 | MoE |
九、我的学习感悟
不要追求一次性理解全部。这篇文章我分了十几个模块,每个模块都停下来复述、回答问题,才真正内化了。
类比很重要。把 Attention 想象成”房间里的人互相看”,把 FFN 想象成”会议后的独立思考”,这些类比比公式更容易记住。
Why 比 What 更重要。知道”Transformer 用 Attention”没用,知道”为什么 RNN 不行、Attention 为什么能解决”才有用。
边缘情况不能忽略。比如 “strawberry” 问题、“lost in the middle”、KV Cache 内存压力——这些才是理解模型限制的关键。
参考
- How LLMs Actually Work — 0xkato
- Attention Is All You Need — Vaswani et al., 2017
- RoPE: Rotary Position Embedding — Su et al., 2021
- Induction Heads — Anthropic, 2022
痕迹
没有过去,就没法认定现在的自己
