简介:大语言模型看似“理解”语言,本质却在做一件朴素的事:根据上文预测下一个 token。本文从分词与词向量讲起,逐步拆解注意力机制、Transformer 架构与训练流程,解释规模化训练为何能催生推理、翻译、代码生成等涌现能力,并附工程实践建议,帮你一次性建立对 LLM 的系统认知。
初次使用大语言模型(LLM)的人,往往会被它翻译、总结、写代码、多轮对话甚至一步步推理的表现震撼,进而产生一个疑问:它是不是真的“懂”我在说什么?
从机制层面看,答案出人意料地朴素:LLM 并不先“理解”语义再组织语言,而是把语言这件事压缩成一个可优化的数学任务——给定前文所有 token,预测下一个 token 的概率分布。它做的本质上是概率意义上的“完形填空”,而且每次只填一个空。
这个任务看似简单到有些笨拙,但当它在数万亿 token 的语料上被推到极致时,翻译、摘要、代码生成、推理、对话等能力会自然“长”出来。研究者把这种现象称为涌现:当参数规模、数据规模与算力投入跨过某个阈值后,模型出现小模型所不具备的综合能力,且能力曲线呈非线性跃迁。
可以把一次完整的文本生成拆成五个环节:
下面依次拆解。
计算机不认识汉字,也不认识英文单词,它只认数字。因此文本进入模型前,第一道工序是分词:把连续文本切成一串离散单元,每个单元称为一个 token。token 的粒度介于“字”和“词”之间,可能是单个汉字、完整的词、子词片段,也可能是标点或特殊符号。
以中文为例(概念示意):
"我 喜欢 大 语言 模型" → [314, 52, 88, 120, 455]
工程上普遍采用“子词”方案(典型做法是基于高频字节对逐步合并的统计方法),原因有二:
分词质量直接影响三件事:词表大小、单条文本的 token 数量(直接关系到上下文长度预算与推理成本),以及模型对代码、公式等非自然语言文本的表达精度。
每个 token 编号随后会被映射成一个可训练的高维向量,维度从几百到上万不等。可以把它理解为:每个词在模型“脑内”都拥有一组坐标,语义接近的词,坐标也彼此接近。比如“猫”与“狗”在向量空间中距离较近,而“猫”与“显卡”则相距甚远。
更关键的是,向量间的方向与差值还能承载细粒度的语义关系。一个经典的语言学观察是:“男人”与“女人”的差向量,近似平行于“国王”与“女王”的差向量——“男性→女性”这一关系在几何空间中表现为一段相对固定的位移。这说明 embedding 不是随机编码,而是一张可以被几何运算操纵的“语义地图”。
这张地图并非人工标注,而是在训练中自动学得:模型为了更准地预测下一个词,必须把“用法相近的词”放到相近的位置。高质量的语义表示,是整个体系的训练副产品。
读这句话:“小明把报告交给小红,因为她明天要出差。”当你读到“她”时,会不自觉地回看前文,判断“她”指的是小红还是别人。注意力机制做的正是这件事,并把它写成了可训练的矩阵运算。
对当前位置的每个 token,注意力会:
相关性高的词被多看一眼,相关性低的词被当作背景噪声弱化——这正是人类阅读时注意力分配的计算化版本。
工程实现上,注意力被组织成一场“查询—检索”,可以理解为一个句子内部的小型搜索引擎:
当前 token 拿着自己的 query 去和每个 key 做相似度匹配:匹配度越高,就把对应的 value 取出越多。最终输出是所有 value 的加权求和。
注意力的经典公式:
Attention(Q, K, V) = softmax(QKᵀ / √d_k) · V
分母中的 √d_k 是缩放因子:当向量维度较大时,点积数值会随之膨胀,导致 softmax 后的分布过于尖锐、梯度趋近于零,训练难以推进;除以 √d_k 把分数拉回合理区间。
用简化伪代码表达核心计算:
def attention(Q, K, V):# Q, K: 序列长度 × d_k 的矩阵;V: 序列长度 × d_v 的矩阵scores = matmul(Q, K.T) / sqrt(d_k) # 1. 打分:当前词与每个历史词算相似度weights = softmax(scores, axis=-1) # 2. 归一化:分数变成权重,总和为 1output = matmul(weights, V) # 3. 汇总:按权重混合历史信息return output
三行代码对应上文的三步直觉:打分、归一化、加权汇总。
两个关键工程细节值得单独说明:
注意力只负责在 token 之间搬运和混合信息,每个位置还需要独立深加工。这个职责由前馈网络(FFN)承担:它对每个位置的向量做非线性变换,参数量通常占模型的很大比重,被认为承载了大量事实与知识的存储。
现代解码器结构由几十个这样的层堆叠而成,每层遵循“多头注意力 + 前馈网络”的组合,并配合两项稳定设计:
数据在层间流动时,语义表示逐层精炼:底层捕捉局部的语法搭配,中层组合出短语与实体关系,高层浮现篇章主题与任务意图,最终在顶层输出对下一个 token 的预测。
三步走完,一个可对外服务的模型才算真正成型。
推理阶段是一个自回归循环:输入前文 → 模型输出整个词表上的概率分布 → 按策略选出一个 token → 拼接回输入 → 继续预测下一个,直到触发停止条件。
def generate(model, prompt_ids, max_new_tokens):ids = list(prompt_ids)for _ in range(max_new_tokens):logits = model(ids) # 预测下一个 token 的概率分布next_id = sample(logits, temperature=0.7, top_p=0.9)ids.append(next_id) # 拼回输入,进入下一轮return decode(ids)
采样策略决定模型的“性格”:
工程上还普遍配合键值缓存:缓存已计算过的注意力中间结果,避免每生成一个词都重算全部前文,把生成成本从平方级增长降到接近线性增量。
这可能是最反直觉的一环:任务如此简单,复杂能力从何而来?
第一,语料本身是“任务的海洋”。互联网文本天然包含翻译对照、问答、代码、数学推导、论证与反驳。模型为了把下一词预测准,被迫隐式学习这些任务的模式——把一段代码的下一行预测得足够准,本质上就是在“写代码”。
第二,统一的任务形式逼出通用能力。所有任务被压平成同一格式后,模型无法针对某个单一任务过拟合,只能发展出可迁移的语言规律与推理路径。
第三,规模跨过阈值后的非线性跃迁。参数量、数据量与训练算力共同作用,当规模跨过临界点,多步推理、上下文学习(仅在提示中给出少量示例即可执行新任务)等能力以远超线性外推的速度出现。
理解原理的另一半是理解边界:
对应的工程建议:
LLM 的震撼之处,恰恰在于它把“智能”这个最复杂的问题,简化成了一件最朴素的事:看前文、猜下一词,并在全网语料上把这件事做到极致。分词与词向量解决“语言如何进入数学世界”,注意力解决“上下文里该重视谁”,层叠结构与预训练解决“知识与能力从哪里来”,采样与对齐解决“如何输出得像样”。
理解了这条主线,再去看待 LLM 的强与弱便不再神秘:它的强大来自规模与任务的统一,它的局限也来自同一处——它毕竟只是在概率意义上,把“下一个字”猜得足够好。