大模型为什么能“读懂”你的话
很多人第一次使用大语言模型(简称 LLM)时都会有直觉上的困惑:它只是一个数学函数,输入文字、输出文字,为什么能回答得像是“理解了”你?回答这个问题最有效的路径,不是看铺天盖地的产品新闻,而是把它拆成三件事:文字怎么变成数字、数字怎么被处理、能力怎么被训练出来。
一句话概括:大模型本质是一个基于海量文本训练出来的“下一个词预测器”。它读入上下文,为词表中每个候选词打出概率分数,输出概率最高的那一个;把结果接到上下文后面再预测下一个,如此循环就得到流畅的段落。所谓“理解”,是这种预测能力在足够大的参数量和足够多的数据上涌现出来的副产品。
大模型不是数据库检索,也不是规则引擎;它是一台在数十亿参数的高维空间里做概率推断的机器。理解这一点,你就知道为什么它既会“胡说”,又确实有用。
- Token模型处理的最小文字单位,中文一个字通常对应 0.6 到 1 个 Token。
- 注意力让每个位置都能“看到”其他位置并对它们分配权重,是长距离依赖的关键。
- 预训练在海量通用文本上做自监督学习,得到基础模型。
- 微调与对齐用指令数据和人类偏好数据,把基础模型训练成听指挥的助手。
Token:模型眼中的文字单位
模型不认识“字”,它只认识整数 ID。把自然语言切成离散单元的过程叫分词(Tokenization)。早期做法是按词切,但词表会爆炸;现代方案普遍采用子词切分(如 BPE、WordPiece、Unigram),把高频词整块保留、低频词拆成更小的片段,从而在词表规模和表达力之间取得平衡。
“今天天气不错”可能被切成 4 到 6 个子词,而 “Artificial Intelligence” 则可能被切得更细。不同模型的分词器不同,同一个句子在不同模型里 Token 数量可能差 30% 以上,这就是某些模型处理中文更“费” Token 的原因。
Token 数量直接决定三件事:计费成本、上下文能装多少、推理速度。粗略换算:英文约 4 个字符 1 个 Token,中文约 1 个汉字 0.6 到 1 个 Token。做成本预估时把输入输出算清楚再乘单价,比拍脑袋靠谱。
- 输入 Token:系统提示词 + 历史对话 + 用户本轮提问,全部计入。
- 输出 Token:模型生成的每一个 Token 都要计费,通常单价高于输入。
- 缓存命中:如果服务商支持前缀缓存(Prompt Caching),重复的长前缀可以按更低价格计费。
注意力机制:Transformer 的核心
2017 年的论文《Attention Is All You Need》提出了 Transformer,用自注意力取代循环神经网络,成为今天所有主流大模型的骨架。思想很朴素:处理某个位置的词时,允许它按相关度去“看”序列里所有其他位置的词。
具体做法是给每个 Token 生成查询(Query)、键(Key)、值(Value)三个向量:用当前 Token 的 Query 和所有 Token 的 Key 做点积得到相似度分数,除以维度的平方根做缩放,经 Softmax 归一化得到权重,再用权重对所有 Value 加权求和。整个过程可以写成一行矩阵公式,也天然适合 GPU 并行。
为了让模型同时关注不同角度的关系,Transformer 使用多头注意力:把向量切分成若干份,每份独立做注意力再拼接。有的头学会语法依赖,有的头关注指代关系。这也是大模型可被理解为“多视角相关性聚合器”的原因。
位置信息同样重要——注意力本身不区分顺序,所以需要位置编码(如旋转位置编码 RoPE)。上下文能否从 4K 扩展到 128K,很大程度取决于位置编码的外推能力和注意力实现(如 FlashAttention、GQA)的效率。
预训练与微调:能力是怎么长出来的
预训练(Pre-training)是“读书”阶段。把网页、书籍、代码、论文等海量文本拼成长序列,让模型不断做“遮住一部分、猜被遮住的内容”或“预测下一个词”的练习。这个阶段不需要人工打标签,所以叫自监督学习。训练完成后得到的模型叫基础模型,它知道很多事实和语言规律,但还不会好好回答问题——你问它“北京在哪”,它可能回你“上海在哪?广州在哪?”,因为它只是在续写文本。
微调(Fine-tuning)是“学规矩”阶段。用人工构造的指令-回答对继续训练,让模型学会“看到问题就给出答案”的格式。再加上基于人类反馈的强化学习(RLHF)或者直接偏好优化(DPO),模型就变成了会拒绝不当请求、语气友好、愿意分步骤解释的对话助手。
检索增强生成(RAG)是另一条常被混为一谈的路线:它不改动模型参数,而是在提问时把检索到的资料塞进上下文。适合知识更新频繁、需要引用来源的场景;而微调适合改变风格、格式与领域术语。工程选型时,先问自己“是缺知识还是缺行为”,答案往往就清晰了。
从 Transformer 到 ChatGPT:对齐训练
ChatGPT 的突破不在网络结构——它和 GPT-3 的骨架几乎一样——而在于把预测机器训练成了遵循意图的助手。典型流程分三步:用高质量示范数据做监督微调(SFT);训练奖励模型(Reward Model),让人类对多个回答排序、模型学着打分;再用强化学习(如 PPO)依据奖励信号优化生成策略。
代价是对齐会牺牲一部分“纯粹的知识表达能力”,换来更好的可用性,也带来谄媚与幻觉等新问题。工程上常见的做法是给模型更多“可核查的锚点”:要求它引用来源、允许它说“不确定”、把关键计算交给工具。
另一个重要方向是推理时计算:让模型先展开长链条思考再作答,用更多算力换更高的正确率——这解释了同一模型在不同“思考预算”下表现差异明显的原因。
推理参数与上下文窗口
调用模型 API 时,除了提示词本身,还有几个参数直接影响输出质量:
| 参数 | 作用 | 推荐起点 |
|---|---|---|
| temperature | 采样随机性,越高越发散 | 事实问答 0~0.3,创意写作 0.7~1.0 |
| top_p | 核采样,只从累计概率前 p 的候选里挑 | 0.9(与 temperature 二选一调节) |
| max_tokens | 限制输出长度,防止跑偏与超支 | 按任务最少需要 +20% 余量 |
| stop | 命中即停止生成 | 结构化输出时指定结束标记 |
上下文窗口是模型一次能“看见”的 Token 总量。窗口大不意味着可以无脑堆资料:中间位置的信息容易被忽略(lost in the middle),长上下文也会推高延迟与成本。合理做法是分层:稳定规则放系统提示词,检索片段重排序后放最后,最关键的约束用编号列表强调。
temperature 只是把 logits 除以温度再做 Softmax:温度越低分布越尖,模型越倾向选最高分的词;温度越高分布越平,长尾候选也有机会被抽中。下面这段纯 NumPy 代码可以直接运行,观察不同温度下的概率分布:
import numpy as np
def softmax(x):
e = np.exp(x - x.max())
return e / e.sum()
logits = np.array([4.0, 2.5, 1.0, 0.2]) # 四个候选词的原始分数
for t in (0.2, 1.0, 2.0):
p = softmax(logits / t)
print("temperature=%.1f -> %s" % (t, np.round(p, 3)))
# temperature=0.2 -> [0.998 0.002 0. 0. ] 几乎必然选第一个词
# temperature=2.0 -> [0.453 0.256 0.122 0.073] 长尾候选也有机会被抽中
跑一遍再看文档里的 temperature 说明,它就不再是玄学旋钮了。
动手实现一个迷你注意力
理解注意力最快的方式是自己写一遍。下面用 NumPy 实现单头自注意力,包含缩放点积、Softmax 和因果掩码(让每个位置只能看到自己及之前的位置,这是自回归生成的前提)。
import numpy as np
def softmax(x):
x = x - x.max(axis=-1, keepdims=True)
e = np.exp(x)
return e / e.sum(axis=-1, keepdims=True)
def self_attention(X, Wq, Wk, Wv, causal=True):
# X: (seq_len, d_model);W*: (d_model, d_k)
Q, K, V = X @ Wq, X @ Wk, X @ Wv
d_k = Q.shape[-1]
scores = Q @ K.T / np.sqrt(d_k) # (seq_len, seq_len)
if causal:
mask = np.triu(np.ones_like(scores), k=1).astype(bool)
scores = np.where(mask, -1e9, scores) # 未来位置权重置为极小
weights = softmax(scores)
return weights @ V, weights
rng = np.random.default_rng(42)
seq_len, d_model, d_k = 4, 8, 8
X = rng.normal(size=(seq_len, d_model))
Wq, Wk, Wv = (rng.normal(size=(d_model, d_k)) for _ in range(3))
out, attn = self_attention(X, Wq, Wk, Wv)
print("输出形状:", out.shape) # (4, 8)
print("注意力权重行和:", attn.sum(axis=-1)) # 每行应为 1.0
print("第一行(只看自己):", np.round(attn[0], 3))
运行后你会看到注意力权重每一行加起来都是 1,第一行的权重 100% 落在第一个位置——因果掩码禁止它看到未来。把 causal 改成 False,第一行就会分散到全部四个位置。这个几十行的实现,和一个千亿参数模型里的注意力模块在数学上是同一件事。
学习路径与常见误区
从工程岗位转向 AI 应用开发,建议的学习顺序是:先掌握 Python 与 NumPy 的数组运算,再用 PyTorch 手写一遍注意力与一个小型 Transformer,然后跑通一次小规模预训练,最后才去调 API 做应用。亲手训练过一次小模型,你对采样参数、损失曲线和过拟合的理解会完全不同。
常见的三个误区值得提前避开。第一,把大模型当数据库,指望它准确记住私有数据——正确做法是 RAG 加工具调用。第二,迷信提示词的“玄学”,忽视评测集建设——没有离线评测,任何提示词改动都无法证明变好了。第三,忽略成本与延迟,把大模型塞进所有链路——很多场景用规则、小模型或缓存就能解决。
把大模型当作一位知识面极广但偶尔会自信地记错的同事:让它干活、给它核查手段、关键结论人工复核。这样用它,收益远大于风险。
下一篇我们会从提示词的工程化写法入手,讨论如何用结构化提示、角色设定与少样本示例,让同一个模型的输出稳定性上一个台阶。