🚀 大模型核心揭秘:从输入到输出,LLM 如何精准预测下一个词?
从 Token 到 Attention,一文读懂 Transformer 架构下的“词语接龙”游戏
📝 导语:LLM 的“唯一任务”
如果你问一个 LLM(大语言模型):“你今天主要做什么工作?”
它的回答会是——“预测下一个词。” 🤖
没错,无论我们看到的 ChatGPT 多么“智能”,能写诗、能编程、能看病历……
其背后最核心、最本质的操作,就是在一个巨大的数学空间里,玩一场高维度的“词语接龙”。
这篇文章,我们将抛开复杂的数学公式,用最直观的比喻和语言,带你一步步走进 Transformer 的内部,看清从你输入文字到模型输出回答的完整路径。
下面这张图,就是这场旅程的“全貌地图” 🗺️:
输入文本 → [分词] → tokenId → [Embedding + 位置编码]
→ [Multi-Head Self-Attention → FFN] × N 层
→ 投影到词表 → softmax → 下一个词的概率 → 采样 → 输出词
准备好了吗?让我们从“货币”开始,一步步揭开大模型的神秘面纱。👇
💰 一. Token 词元:LLM 世界的“流通货币”
🔍 什么是词元?
用户输入的 Prompt(自然语言),计算机是看不懂的。
所以第一步,我们得把人类语言“翻译”成模型能处理的数字。
这个翻译官就是 分词器(Tokenizer),它负责将自然语言切分为一个个 Token(词元),并转换成对应的 tokenId。
自然语言 → [Tokenizer] → tokenId 序列 → LLM → tokenId 序列 → [DeTokenizer] → 自然语言
值得注意的是,大模型处理的最小单元不一定是完整的“词”,可能是“子词”、“字符”,甚至是“标点符号”。
用“词元”这个概念,能更精准地表达它是模型计算和计费的通用最小处理单位,而非语言学意义上的词。
❓ 为什么不直接用完整的词?
如果只认完整的词,模型需要记住几十万个英文单词和几百万个中文词汇,那计算量将是天文数字 💥。
把词切成子词,模型只需要掌握几万个基础积木(词元),token 查找表 size 就不会那么大,运算效率直线飙升 📈。
🔤 英语示例:
unhappiness 是个词 "不开心",拆开三个部分:
un(否定) + happi/happy(开心) + ness(状态)
llm 通常不会把它当成一个完整的词。
tokenization 拆开:
token + ization("……化的过程")
同理:modern + ization, visual + ization, global + ization
用少量积木块覆盖大量单词,而且模型学会了 un=否定、ness=名词化之后,遇到没见过的组合也能推断含义——这是子词切分最重要的泛化能力。
🇨🇳 中文示例:
"我爱人工智能,自然语言处理很有趣"
→ "我"、"爱"、"人工智能"、"自然语言"、"处理"、"很"、"有趣"
高频词汇保持完整不拆分,常用虚词各成一个 token,标点也独立成 token。
⚠️ 一条重要认知:词元拆分没有标准答案!
不同模型、不同词表大小,切出来的结果天差地别:
GPT-4 (cl100k_base, 10万词表): "tokenization" → ["token", "ization"] 2个 token
GPT-2 (r50k_base, 5万词表): "tokenization" → ["token", "iz", "ation"] 3个 token
词表越大,更多常见词能保持完整,序列更短,效率更高。但词表也不能无限大——Embedding 矩阵 vocab_size × d_model 会占大量显存。10 万左右是工程上的甜蜜点。 🍬
💸 Token 是 LLM 的“货币”
把词元理解为 LLM 的货币——
输入按 token 计费 💳,输出也按 token 计费 💳,
context 窗口的大小也是以 token 数量来衡量的。
🔮 Token → 预测下一个词
发一段文字给 LLM,比如:"你"
LLM 只会做一件事,预测下一个词:
你 -> tokenId -> llm(....) -> tokenId -> 好
再看一个更复杂的例子:
"中国的首都是"
中国的首都 -> llm(....) -> 北京(高概率),北平(4%),长安(2%)
具体要看上下文
tokenIds(词元变成数字,没有意义) -> embeddings(拿到语义向量)
LLM 内部除了 token 查找表,还通过预训练,embedding 存储了词元的语义向量。
📖 一本字典的比喻:
一本字典 tokenId——索引,某个词在第几页
这个词元的语义向量——在某一页有密密麻麻的各个维度的语义特征,存在神经网络中
基于"中国的首都是",前面的输入,给出后面这些词汇的词的概率,"北京" 就生成了。接下来生成","或者。"...这就是自回归生成——预测一个词、下一个词、下下一个词...LLM 只会做这个事情,做这个事情的整体架构统称 Transformer 架构。
🧬 二. Embedding 词嵌入:构建语义空间的“坐标”
语义向量 = 预训练得到的神经元权重。
第一步:tokenId → Embedding
tokenId(数字表达) ——> Embedding(语义向量坐标)
"你" ——> tokenId(57668)
这个编号本身没有任何含义,
不能通过这个编号直接计算得到下一个词——"好"——的编号。
📏 第二步:语义 + 距离计算
"你" → "好" ,在高维向量空间中,这两个词的向量距离比较近。
向量是多维空间里的一个坐标点,是有方向的,可以计算距离。语义相近的词,它们的向量距离就比较近。
🗂️ 第三步:查找 Embedding 矩阵
LLM 把编号查表转成一个高维的坐标向量,这个过程就叫 embedding。
LLM 内部有个巨大的向量查找表——Embedding Matrix。
模型拿到了 tokenId 57668("你"),就直接去 57668 号柜子里,把对应的向量"抽"出来。
➕ 语义空间的算术
"国王"和"王后"
这两个"点",在高维空间里距离接近。
国王 - 男性的向量 + 女性的向量 ≈ 王后
→ 向量的计算 = 语义的迁移
"国王"和"苹果",距离很远——语义无关的词在空间中自然分开。
模型的训练,就是在海量语料上不断调整这些向量,构建出这样一套语义空间坐标系。
📍 三. PE 位置编码:打破“词袋”魔咒
❓ 为什么需要位置编码
语义特征有一个盲区——Embedding 不携带位置信息!
"我咬了狗"
"狗咬了我"
光有语义的理解还不够,相同的四个字,顺序不一样,表达的意思完全相反。两个句子的 embedding 是一样的(词袋相同),只是顺序不同。但顺序在当前上下文中非常重要。
🛠️ 位置编码的做法
Embedding 不携带位置信息,我们就给每个向量加上一个位置编码 PE(Positional Encoding),告诉 LLM,这个词属于句子的第几个。
最终输入 = Embedding(是什么) + PE(在哪里)
(768维) (768维)
两个向量直接按位相加,结果仍是 768 维。
每个 token 携带两类信息:
- 语义信息:这个词是什么意思(来自 Embedding)
- 位置信息:这个词在句子中的第几个位置(来自 PE)
📐 PE 是怎么生成的?
位置编码本质上就是给每个位置分配一个独特的数值指纹。原始 Transformer 使用 sin/cos 函数来生成:
位置 0 → PE = [sin(0), cos(0), sin(0/10000²), cos(0/10000²), ...]
位置 1 → PE = [sin(1), cos(1), sin(1/10000²), cos(1/10000²), ...]
位置 2 → PE = [sin(2), cos(2), sin(2/10000²), cos(2/10000²), ...]
...
每个位置生成一个独一无二的 768 维向量,
而且相邻位置的 PE 向量比较接近(因为 sin/cos 是连续函数),
这天然表达了"位置越近,编码越像"。
💡 现代 LLM(如 GPT)也常用可学习的位置编码——不是用公式算,而是像 Embedding 一样,让模型在训练中自己学出每个位置的最佳编码。
加了 PE 之后,"我咬狗"三个词和"狗咬我"三个词的 Embedding 虽然一样,但每个位置上加的 PE 不同,最终进入 Transformer 的向量完全不同——模型因此能区分语序。 ✅
至此,带着语义 + 位置双重信息的向量,正式进入 Transformer 的第一层。
🧠 四. Self-Attention 自注意力机制:让词语“互联互通”
❓ 模型怎么理解上下文?
不只靠一个词元自身的向量。模型需要看整个句子来判断每个词的真实含义。
the animal didn't cross the street, because it was too tired
it 指的是谁?人读起来就知道是 animal。it 指代 animal,还是 street?
LLM 用来做这个判断的机制叫 Self-Attention(自注意力机制)。
🎯 Q、K、V 是什么?
Self-Attention 的核心思想是:让句子中的每个词,都去和其他所有词"对望一眼",看看谁跟自己有关。 👀
为了实现这个"对望",每个词的 embedding 会分别乘以三个矩阵(W_Q、W_K、W_V),生成三个不同的向量:
原始词向量 × W_Q → Q(Query,查询)
原始词向量 × W_K → K(Key,钥匙)
原始词向量 × W_V → V(Value,内容)
🎭 打个比方——把每个词想象成一个人,在参加一场配对游戏:
Q(查询)= "我想找谁?" —— 每个人手里举着一个牌子,写着自己在找什么
K(钥匙)= "我是谁?" —— 每个人胸前挂着一个标签,写着"我能被找到"
V(内容)= "我身上带了什么?" —— 每个人口袋里装着实际有用的信息
游戏中是这样运作的: 你拿着自己的 Q(牌子),去和全场每个人的 K(标签)做匹配。标签跟牌子对上了的那个人,你就从他口袋里拿走 V(信息)。
🔄 用 "it" 走一遍完整流程
回到刚才的句子,it 需要找出自己指谁。整个过程分三步:
第一步:生成 Q、K、V
animal → 各自乘以 W_Q、W_K、W_V → Q1、K1、V1
it → 各自乘以 W_Q、W_K、W_V → Q2、K2、V2
street → 各自乘以 W_Q、W_K、W_V → Q3、K3、V3
...
第二步:it 拿着自己的 Q,去"敲门" 🚪
it 的 Q2 去和每个词的 K 做点积(一种衡量两个向量有多"合拍"的计算):
Q2 × K1(animal) → 0.92 ← 分数最高!合拍!
Q2 × K2(it) → 0.08
Q2 × K3(street) → 0.11
Q2 × K4(cross) → 0.05
...
分数越高 = it 越应该关注那个词。animal 分数最高,说明 it 找到了——"我就是指 animal。"
第三步:按分数去取 V 🎁
把分数做 softmax(变成加总为 1 的权重):
animal: 0.89
it: 0.03
street: 0.04
其他词: 0.04
用这些权重去加权拿 V:
it 的新向量 = 0.89 × V1(animal) + 0.03 × V2(it) + 0.04 × V3(street) + ...
≈ 几乎全部来自 animal 的语义
之前: "it" 的向量——空洞的代词,不知道指谁
之后: "it" 的向量 ≈ 90% animal → 模型现在知道 it = animal 了
🌐 同一个词在不同语境下
Self-Attention 不只是代词需要,每个词都在同时做同样的事——找跟自己最相关的上下文。这个过程是并行的、对称的:你也在看我,我也在看你,每个词都和其他所有词互相"对望"。
以"苹果"为例:
"苹果手机"
"苹果"的 Q 去匹配,发现"手机"的 K 得分最高
→ "苹果"大量取走"手机"的 V
→ 最终表示偏向"手机品牌",不是"水果"
"我吃了苹果"
"苹果"的 Q 去匹配,发现"吃"的 K 得分最高
→ "苹果"大量取走"吃"的 V(和食物相关)
→ 最终表示偏向"可食用的苹果"
同一个词"苹果",不同的上下文 → 不同的 Q·K 匹配结果 → 融合了不同的 V → 最终得到了不同的向量表示。
这就是 Self-Attention 实现让一个词在不同语境下拥有不同的含义的方式。🌟
🤔 为什么多一个 V 出来?只用 Q 和 K 不行吗?
Q × K → 知道"应该关注谁"(相关性)
× V → 知道"从被关注者那里拿走什么内容"(实际信息)
关注谁 ≠ 拿走什么。
V 让"被关注者实际携带的语义"可以不同于"自己被关注时的标识"。
两者解耦,模型更灵活。
📊 完整公式
Attention(Q, K, V) = softmax( Q × Kᵀ / √dₖ ) × V
Q × Kᵀ → 当前词和所有词的匹配分数
÷ √dₖ → 缩放一下。向量维度越大,Q×K 的结果就越大,
直接 softmax 会导致极端化(接近 0 或 1),
除以 √dₖ 让结果平缓,各词都有机会
softmax → 变成百分比权重
× V → 按权重把各词的 V 聚合在一起
👥 . Multi-Head Attention:同时关注多种关系
上面讲的是一组 Q、K、V,也就是一个"注意力头"。但现实中,句子里的语义关系不止一种。看这个例子:
"小明昨天在公园里给了小红一朵花"
这句话里同时存在多种关系:
- 主谓关系:"小明" ←→ "给"
- 时间关系:"昨天" → 什么时候
- 地点关系:"公园里" → 在哪里
- 对象关系:"小红" ←→ "给"
- 修饰关系:"一朵" ←→ "花"
一个 Attention Head 只能学一种关系。所以 Transformer 用了 Multi-Head(多头)——并排跑多组独立的 Q、K、V,每组一个"头",每个头关注不同类型的语义:
输入向量 (768维)
│
├─→ Head 1: Q₁, K₁, V₁ → 可能学会关注"主谓关系"
├─→ Head 2: Q₂, K₂, V₂ → 可能学会关注"修饰关系"
├─→ Head 3: Q₃, K₃, V₃ → 可能学会关注"指代关系"
├─→ ...
└─→ Head 12: Q₁₂, K₁₂, V₁₂ → 可能学会关注"位置关系"
然后把所有 Head 的输出拼起来,再投影回 768 维。
Multi-Head 的直观理解:
单头 = 一个人盯着句子,只能从一个角度看
多头 = 12 个人同时盯着句子,每人关注不同的角度
最后把 12 个人的观察拼成一张完整的"理解"
实践中,每个 Head 的维度会缩小(比如 768 / 12 = 每个 Head 64 维),所以总的计算量和单头大维度差不多,但表达能力大大增强。
GPT-3 有 96 个注意力头,GPT-4 据说更多。 头越多,模型能同时捕捉的语义关系种类就越多。
🏁 总结:从“孤立词汇”到“上下文理解”
经过 Multi-Head Self-Attention 这一层后,每个词的向量都不再是自己孤立的词向量,而是从 12 个角度揉进了整个句子的上下文信息——
刚才 it 从"空洞代词"变成"≈animal",苹果从"模糊词汇"变成"手机品牌"或"水果"。🍎📱
后面还会接 FFN(前馈网络)、残差连接、层归一化,再堆叠多层……最终从最后一个词拿到的向量,已经吸收了整句话的全部上下文,投影到词表上,softmax 出每个词的概率——这就是预测下一个词的全部秘密。 🔑
💬 写在最后
大模型看似神秘,拆解开来看,核心思想其实非常优雅:
用向量表示语义,用位置编码表示顺序,用注意力机制融合上下文,用多层网络不断抽象。
而所有这一切努力,最终都指向那个最简单的任务——
根据前文,猜出下一个最合适的词。 🎯
希望这篇文章能帮你建立对 LLM 内部机制的直观认知!