LLM · TRANSFORMER · 编译图谱

LLM 到底是怎么工作

你每天都在跟它说话,但它拿到你那句话之后到底发生了什么? 这篇从分词一路讲到吐出下一个字,给写代码、但一直没空啃 Transformer 的你。

编译自 0xkato 《How LLMs Actually Work》(2026-06) ·中文重述 + 配图 by iostiny ·约 25 分钟

这篇是编译,不是逐句翻译。原文是 0xkato 写的《How LLMs Actually Work》,英文原文写得很顺,技术点给得很实。我按原文的叙事线索用中文重新讲了一遍,所有技术细节、数字、例子都保留,行文是我自己的。想看原汁原味的,点这里读原文

适合谁:会写代码,知道矩阵乘法是怎么回事,但从来没认真读过《Attention Is All You Need》,看到论文里的 RoPE、GQA、SwiGLU 这些缩写就头大的人。读完这篇,你再去翻模型卡(model card)或者新模型的技术报告,应该能知道每一节在说架构的哪个零件。

一句话先把全文剧透了:现代 LLM = 把文本切成整数 → 查表变成向量 → 几十层"交流 + 各自思考" → 猜下一个 token → 循环。下面把每一步拆开讲。

一句话在 LLM 内部走完的全程(本文目录就是这条流水线) "今天天气真" raw text [1271, 88, 9042, …] token ids 查表 → 向量 4096 dims each Transformer 层 × N Attention FFN 残差流串起来 · Norm 稳住数值 logits → softmax "好" 拼回输入,再来一轮 整段回答 = 这个循环跑几百次,一次一个 token

FIG 0 · 全景:text → token → 向量 → N 层 → logits → 采样 → 循环

01 · TOKENIZATION

分词:模型从来没"看见"过文字

先把一个最常见的误会摆平:LLM 不读文字。你打进去的那句话,第一站就被分词器(tokenizer)切碎,换成一串整数。每个整数是一个编号,指向一张固定的词表里的某一项。现代模型的词表大概在几万到几十万这个量级。从这一刻起,模型的世界里只有整数序列,没有字符串。

关键的设计选择是:token 通常不是完整的词,而是子词(subword)。比如 "tokenization" 会被切成 token + ization,"running" 可能切成 run + ning。为什么不直接一词一个编号?因为全词词表会大到离谱,而且碰到没见过的新词直接抓瞎;反过来按单个字符切,词表又太小,每个 token 承载的信息太稀。子词是两头折中:常见词独占一个 token,生僻词用几个零件拼。

顺带解了一个经典谜题 为什么 LLM 一度数不清 "strawberry" 里有几个 r?因为它根本没见过 s-t-r-a-w-b-e-r-r-y 这十个字母——它见到的是一两个 token 编号。让你看着一个哈希值数原文里有几个 r,你也数不出来。

具体切法各家不同:GPT 系用 BPE(Byte Pair Encoding)的变体,LLaMA 一系用 SentencePiece。所以同一句话,不同模型切出来的 token 数可以不一样——这也是为什么"按 token 计费"时同样的 prompt 在不同 API 上价格有差异。

同一个词被切成子词零件,每个零件换成一个编号 tokenization token id = 5239 + ization id = 2167 · 常见词:独占一个 token · 生僻词:几个子词零件拼起来 · 词表量级:几万 ~ 几十万项 GPT 系 → BPE 变体 · LLaMA 系 → SentencePiece

FIG 1 · subword 切分:词表大小和泛化能力的折中

02 · EMBEDDINGS

Embedding:一张巨大的查询表,给编号赋予含义

编号本身没有任何含义——5239 和 5240 之间不存在"语义相邻"。含义是embedding 矩阵给的。你可以把它想成一张巨大的查询表:词表里每一项对应一行,每行是一个很长的浮点数向量。token 编号进来,查表,出去的就是这个 token 的向量表示。

这个向量有多长?就是模型的"隐藏层宽度"。7B 量级的模型一般是每个 token 4096 个数字,更大的模型用更宽的向量。从这往后,整个模型内部流动的都是这种向量。

有意思的是这张表学出来的性质:语义相近的 token,向量也相近。"king" 离 "queen" 近,"Paris" 离 "France" 近。更夸张的是向量还能做算术,那个最出名的例子是:

向量空间里的方向是有含义的:“性别”这个方向是模型自己从数据里学出来的 king man + woman queen 没人写过一行代码定义“性别方向”——纯粹是预测下一个 token 的副产品

FIG 2 · 著名的 king − man + woman ≈ queen

重点在最后一句:这些语义结构没有任何人去设计。训练目标只有一个——预测下一个 token——而这些关系是为了把这件事做好而自然涌现出来的。这是全文反复出现的主题:看起来很"智能"的结构,都是从一个很笨的目标里长出来的。

03 · POSITIONAL ENCODING

位置编码:attention 天生不知道词序

这里有个反直觉的事实:后面要讲的 attention 机制,本身完全不知道顺序。对它来说一句话就是一袋子 token——"狗咬人"和"人咬狗"在它眼里是同一袋东西。"dog" 出现在第 1 个位置和第 5 个位置,查出来的 embedding 一模一样。顺序信息必须从外面注入。

2017 年那篇原始 Transformer 论文的做法是:用一组不同频率的正弦、余弦波,给每个位置生成一个独特的"波形指纹",直接到 token 的 embedding 上。好处是对没见过的更长序列也能外推;坏处是同一个向量既要装含义又要装位置,而且绝对位置的泛化效果不好。

现在的主流是 RoPE(Rotary Position Embeddings,Su et al. 2021),LLaMA、Mistral、Gemma、Qwen 全在用。思路换了一个维度:不往 embedding 里加东西,而是在做 attention 之前,把 Query 和 Key 向量按位置旋转一个角度——位置 1 转一点点,位置 100 转得多。这样两个 token 做匹配时,起作用的是它们之间的相对旋转差,也就是相对距离。

RoPE:按位置旋转 Q/K 向量,attention 里只剩下“相对角度差”= 相对距离 pos = 1 · 转 15° pos = 10 · 转 58° pos = 100 · 转得更多

FIG 3 · RoPE:位置 = 旋转角度,相对位置 = 角度差

RoPE 的三个实际好处:编码的是相对位置(attention 真正需要的就是这个);对更长的上下文泛化更好;而且不增加任何参数。

这解释了一条你可能听过的 prompt 玄学 Liu et al. 2023 发现了 "lost in the middle" 现象:长 prompt 里,开头和结尾的信息模型用得好,中间的信息利用率明显下降。所以"重要内容放前面"、"关键指令在结尾再重复一遍"这类提示词技巧不是迷信,是有论文背书的。

04 · ATTENTION

Attention:每个 token 环顾四周,决定该听谁的

到了整个架构的心脏。attention 干的事一句话能说完:每个 token 看一圈它被允许看的其他 token,决定谁重要,然后按重要程度把别人的信息加权揉进自己的表示里。难的是记住三个角色,每个 token 同时扮演这三个角色(三套变换矩阵都是训练学出来的):

流程是:拿自己的 Q 去跟所有可见 token 的 K 算匹配分(用缩放点积),分数过一遍 softmax 变成总和为 1 的权重,再用这组权重对所有 V 做加权平均——结果就是这个 token 的新表示。

抽象的话看个具体例子。处理 The cat that I saw yesterday was sleeping 里的 "was" 时:模型训练里学到了"动词得找主语",所以 "was" 的 Q 跟 "cat" 的 K 点积很高,跟 "yesterday" 的 K 点积很低。softmax 之后 "cat" 拿到大头权重,"was" 的新表示就主要由 "cat" 的 Value 构成——动词成功认领了自己的主语,隔着一个定语从句。

“was” 的 Query 在全句的 Key 里找匹配 · 线越粗 = softmax 权重越大 The cat that I saw yesterday was sleeping 0.62 · 主语在这 0.11 0.04 虚线框 = 未来的 token,被因果掩码挡住,看不到

FIG 4 · "was" 隔着定语从句认领主语 "cat"(权重为示意值)

两个重要补充。第一,因果掩码(causal masking):GPT 这类模型从左往右生成,第 5 个位置的 token 只能看位置 1–5,不许偷看未来。实现上很糙——把未来 token 的匹配分直接设成一个极小的数,softmax 之后权重自然趋近于零。

第二,attention 不只是"语法工具"。Anthropic 在 2022 年找到一类叫 induction heads(诱导头)的注意力头,专门干一件事:发现序列里出现过 A B … A 模式时,预测下一个是 B。这是目前关于 in-context learning(你在 prompt 里给几个例子,模型当场学会照做)最清楚的机制解释之一。

代价也写在脸上 完全 attention 是每个 token 跟所有可见 token 两两比较——序列长度翻倍,计算量大约翻四倍。这就是长 prompt 贵的根本原因,也是 FlashAttention、稀疏 attention、线性 attention 这一整条研究线存在的理由。
为什么点积要除以 √d("缩放"点积的缩放)

Q 和 K 的点积是 d 个乘积加起来(d 是每个头的维度,常见 128)。维度越高,点积的方差越大,数值动不动就跑到很大或很小。而 softmax 对大数值非常敏感——输入一大,输出就变成几乎 one-hot,梯度趋近于零,训练学不动。

score = (Q · K) / √d

除以 √d 把方差拉回 1 的量级,让 softmax 工作在它的"灵敏区间"。一个纯粹为了数值健康的工程补丁,但没有它训练真的会崩。

05 · MULTI-HEAD ATTENTION

多头:同一句话,三十二副眼镜同时看

一个 attention 头一次只能表达一种关系视角。但语言里的关系是叠着来的:语法关系、指代关系、位置模式、语义关联,全在同一句话里同时存在。解法简单粗暴:多个头并行跑,各看各的

这里有个容易想歪的细节:每个头拿到的不是token 向量切出来的一段,而是整个向量经过这个头自己的投影矩阵变换后的结果。4096 维的向量、32 个头,每个头确实只在 128 维里工作,但那 128 维是对全向量的一次学习出来的投影——是同一个 token 的 32 种"视角",不是 32 块"切片"。各头独立做完 attention,输出拼接起来,再过一个线性层揉回完整宽度。

每个头 = 一套自己的投影矩阵 · 并行跑 attention · 拼接后揉回原宽度 token 向量 4096 维 head 1 · 语法头 动词 ←→ 主语 / 宾语 head 2 · 指代头 it / 它 → 指的是谁 head 3 · induction head A B … A → 下一个是 B … × 32 个头,每头 128 维投影 concat 32 × 128 线性层揉合 → 4096 维 分工没人安排, 是训练中自己长出来的

FIG 5 · 多头 = 学出来的投影 × N,不是向量切片 × N

这些头各自管什么,没有任何人去分配。训练完了之后研究者去解剖,发现有的头专盯语法(动宾搭配、冠词找名词),有的头专做代词消解,有的头盯位置规律,还有上一节说的 induction heads。一层通常 32 个头,现代前沿模型几十层起步——加起来是几千个注意力头在同时工作。

工程侧还有两个高频词值得在这儿一并拿下:

06 · FEED-FORWARD NETWORK

FFN:开完会,回工位各自干活

一个 Transformer 层里有两个主角。attention 是开会——token 之间交换信息;FFN(前馈网络)是回工位干活——每个 token 独立处理自己手头的信息,互相不说话。结构简单到有点失望:

中间那一步看着不起眼,其实是命门:没有非线性,两个线性层在数学上等价于一个线性层,叠一百层也还是一次矩阵乘法。激活函数的选型这些年也换了几代:原始 Transformer 用 ReLU,GPT/BERT 时代换 GELU,现在 LLaMA、Mistral、PaLM 用 SwiGLU。

真正让人意外的是另一件事:稠密模型的参数大头不在 attention,在 FFN。而解释性研究发现,模型记住的事实和语义结构,很大程度上就存在这些 FFN 权重里。有的神经元专门在出现"埃菲尔铁塔"相关文本时激活,有的对编程语言敏感,有的盯过去式动词。"巴黎有埃菲尔铁塔"这条知识,就分布式地写在某几层 FFN 的权重里。

这事已经能动手术了 ROME(Rank-One Model Editing)这类方法可以不重新训练,直接对特定 FFN 权重矩阵做一次低秩修改,把"埃菲尔铁塔在巴黎"改成"在罗马"——之后模型生成的相关文本会真的跟着改口。事实不是存在某个数据库里,就是存在权重里,而且能被定点编辑。

FFN 还是当下最重要的扩容手段的发生地——MoE(Mixture of Experts,专家混合)。把一个稠密 FFN 换成多个并行的 FFN("专家"),外加一个路由网络,给每个 token 现场挑选用哪几个专家。Mixtral 8x7B 每层 8 个专家、每个 token 只激活 2 个:总参数 46.7B,每个 token 实际只用约 12.9B。参数规模上去了,推理成本几乎没涨——这就是前沿模型纷纷转 MoE 的原因。

稠密 FFN:扩展 → 掰弯 → 压回 × 4 宽 ReLU → GELU → SwiGLU 中间过非线性 MoE:路由器给每个 token 挑 2 个专家 token Router 挑 2 / 8 E1 ✓ E2 E3 E4 E6 ✓ E5 E7 E8 Mixtral 8x7B:总参数 46.7B · 每 token 只跑 ~12.9B

FIG 6 · 左:稠密 FFN 的"领结"结构 · 右:MoE 路由选择性激活

07 · RESIDUAL STREAM & NORM

残差流:每层都在"追加批注",没人能整页重写

前面说了 attention 和 FFN 各干各的,那几十层是怎么串起来的?关键在一个不起眼的加号:每个子块(attention 或 FFN)的输出不会替换原来的 token 向量,而是回去——新向量 = 旧向量 + 子块输出。

把这条贯穿全部层的向量想成一条传送带(残差流,residual stream):每一层只能往传送带上"追加批注",不能把前面的内容撕掉重写。三五十层甚至上百层走下来,每层的贡献是累积的,而且最初的 embedding 始终有一条加法直通道连到最后。

残差流 = 一条贯穿所有层的传送带,每个子块只能往上加,不能覆盖 embedding → 输出 Attention + FFN + N N N N = Norm,进子块前先把数值拉回可控范围(pre-norm) … 这个 "Norm → 子块 → 加回" 的小模式,重复几十次直到最后一层

FIG 7 · 残差流 + pre-norm:加法直通道贯穿全部层

这招不是 Transformer 发明的,是从 ResNet(He et al. 2015,图像识别)抄来的。当年的问题是深网络根本训不动:训练信号穿过太多层之后不是弱到没了就是炸了,模型没法从错误里学习。残差捷径让信号能从输出直接流回输入,一下子让几百层的网络变得可训练。Transformer 全盘继承。如今做模型解释的研究里,残差流干脆成了核心研究对象——每个组件(每个头、每个 FFN,连最后的输出投影)都被看作"从传送带读、往传送带写"。

但全是加法也有麻烦:加了几十轮之后数值会失控,要么爆炸要么塌缩,训练直接失败。所以每个子块旁边都配一个归一化(normalization),把向量重新缩放回可控范围。这里有两代演进:

08 · NEXT-TOKEN PREDICTION

下一个 token:模型唯一会做的事

几十层走完,序列里每个 token 都有了一个最终向量。生成的时候只用最后一个 token 的那一条:把它投影成"词表里每一项一个分数"——词表 10 万项就是 10 万个数。这些数叫 logits,不是概率(可正可负、想多大多大),过一遍 softmax 才变成总和为 1 的概率分布。

然后是很多人不知道的一点:模型通常不会直接挑概率最高的那个。解码参数控制确定性和多样性的平衡——temperature 调低模型保守,调高就放飞;top-k / top-p 先把候选裁剪到最靠谱的一小撮再抽签。与其干讲,不如直接玩:

🌡 动手实验 · TEMPERATURE 如何改写概率分布

上文:今天天气真 → 下一个 token 抽中了:?

1.00

logits 是固定的(假装模型已经算完了),变的只是 softmax(logit / T)。拖到 0.1 看它变成"几乎必选『好』",拖到 2.0 看『香蕉』也开始有戏。

抽中一个 token 之后呢?拼回输入末尾,整个流程再来一遍(靠 KV cache 不必重算前缀),新一轮 attention、FFN、新的 logits、再抽下一个。你看到的整段回答,就是这个循环跑了几百上千次的产物,一次一个 token。生成到出现"序列结束"标记或者撞到长度上限为止。

最值得记住的一句 基座模型的训练目标只有"在海量文本上预测下一个 token"。它没有被直接训练去"讲事实"、"会聊天"、"会推理"、"会写代码"——这些要么是从预测任务里顺带涌现的,要么是后训练(指令微调、人类反馈、安全对齐)追加上去的。理解了这一点,模型一本正经胡说八道(hallucination)就不那么神秘了:它在补全一段"看起来像真的"的文本,这正是它唯一被教过的事。
推理加速的当红技巧:speculative decoding(投机解码)

一次只生成一个 token 太慢了。投机解码的玩法:让一个小而快的模型先往前猜好几个 token,再让大模型并行地一次性验证这一串。猜对的全部收下,猜错的从错处由大模型接管。

妙处在于:实现正确的话,最终输出的分布跟大模型单独慢慢生成完全一致——纯赚速度,不赔质量。你在各家 API 上感受到的"今年明显变快了",有它一份功劳。

09 · ARCHITECTURE VS WEIGHTS

架构 vs 权重:GPT、Claude、LLaMA 到底差在哪

读到这里你可能想问:既然 GPT、Claude、Gemini、LLaMA 都是上面这套零件,那它们差在哪?答案分两层。架构层面,在本文的颗粒度上,它们基本是同一套设计:分词 → embedding → 位置编码 → 一摞 Transformer 层(多头 attention + FFN)→ 残差流 → 归一化 → 下一个 token 预测。

真正的差异在三处:

还有个挺有意思的现象:2023–2025 年间,各家团队独立地收敛到了几乎同一组选择——pre-norm、RMSNorm、RoPE、SwiGLU、GQA,最大的那批再加 MoE。没有哪一年出现过一次性的大发明,这是 2017 年那个设计被反复打磨五年的累积结果。所谓"现代 Transformer",指的就是这套公认配置。

零件2017 原版2025 共识
归一化位置post-norm(子块后)pre-norm(子块前),深层好训
归一化算法LayerNorm(平移+缩放)RMSNorm(只缩放,更便宜)
位置编码正弦/余弦相加RoPE(旋转 Q/K,编码相对位置)
FFN 激活ReLUSwiGLU
attention 形态每头独立 K/VGQA(多 Q 头共享少量 K/V)
FFN 形态稠密大模型多用 MoE 稀疏激活

10 · WHERE THIS IS GOING

往后看:架构会换,问题不变

Transformer 这种"一个架构吃遍所有领域"的局面,在机器学习历史上其实很反常。以前是图像一套网络、语言一套、音频又一套,做视觉的和做 NLP 的几乎不看对方的论文。现在语言、视觉、音频、多模态全是 Transformer 一家——这种大一统以前没出现过。

会不会被取代?候选者一直有:Mamba 和其他 state-space 模型在长序列上很有竞争力,各种混合架构也在试。而且"架构"这个词本身的含义也在漂移——五年前 MoE 还算异域风情,现在已经是前沿标配。

但这篇讲的东西不会过时,原因很简单:token 化、给离散符号赋予含义、注入顺序、token 间通信、token 内处理、深度网络的信号稳定、预测下一个符号——这些是任何序列模型都绕不开的问题。架构换代,换的是解法;问题本身会一直在。学会了问题和现在的解法,下一代架构出来时你看到的就不是天书,而是"哦,他们换了个方式解决位置编码"。

REFERENCES

原文与延伸阅读

📚 一手来源