04

Transformer 与注意力机制入门

⏱️ 30分钟

Transformer 与注意力机制入门

你有没有在直播课上盯着 "Self-Attention"、"Q/K/V"、"Multi-Head" 这几个词,点头如捣蒜,回去自己一想——其实一个字没懂

说实话,我第一次看 Transformer 那张经典架构图的时候也是这样。图上密密麻麻十几个框,箭头绕来绕去,配一堆矩阵公式,劝退感拉满。后来我发现:做 AI 工程根本不需要会推导那些公式,但你需要一个扎实到能撑住后面 RAG、Agent、微调的直觉——知道模型"读一句话"时脑子里到底发生了什么。这一篇就把这台发动机拆开给你看,带数字、带代码,但不带你去啃论文。


为什么要懂它?(不懂会怎样)

你完全可以不懂 Transformer 也调得通 OpenAI 的 API。但一旦往深走,这些问题会追上你:

  • 为什么有 context window 限制?为什么 token 一多,又慢又贵?→ 答案在注意力的计算量上。
  • 为什么模型会"中间遗忘"(lost in the middle),把长文档中段的信息漏掉?→ 跟注意力权重分配 + 位置编码有关。
  • temperaturetop_p 这些 API 参数到底在调哪一步?→ 调的是最后的采样层,不懂架构就只能背名词。
  • 微调、KV Cache、Flash Attention、量化……这些优化在优化哪个环节?→ 懂了架构,它们各归各位。

懂了这一层,后面很多"魔法"会变成"哦原来是这样"。


先破一个误解:LLM 不是"数据库"

术语:Transformer

  • 一句话解释:一种靠"注意力"让每个词去看句子里其他词的神经网络结构。
  • 形象比喻:开小组会。每个人(词)发言前,先扫一眼全桌其他人说了啥,再决定自己怎么说。
  • 工作中怎么用:GPT、Claude、Llama、几乎所有主流 LLM 的底座都是它(准确说是它的 decoder 部分)。
  • 最常踩的坑:以为它像数据库一样"存"了答案。它存的是词与词之间的关系权重,答案是现算出来的——这也是它会一本正经胡说(幻觉)的根源。

2017 年之前,处理文本的主力是 RNN/LSTM,它像排队念课文:一个字读完才能读下一个,前面的字读到后面就快忘光了。Transformer 那篇论文的名字很嚣张——《Attention Is All You Need》,意思是:排队那套不要了,让所有词一次性互相看就够了。

这一下解决了两件大事:①能并行(GPU 吃得饱,训练快);②再远的词也能直接"对上眼",不会读到后面忘了前面。


注意力到底在"看"什么

来看这句话:

那只没跳上桌子,因为太累了。

"它"指谁?人一眼知道是"猫"。模型靠什么知道?靠注意力:处理"它"这个词时,模型会给句子里每个词打一个"我该多关注你"的分数,"猫"的分数最高,于是"它"的含义就被"猫"带跑了。

这就是 self-attention 的全部直觉:每个词,根据当前语境,动态决定该从其他哪些词身上吸收信息。

Q / K / V:别被吓到,就是"找资料"

模型给每个词算三样东西,用找资料来类比最好懂:

术语:Query / Key / Value (Q/K/V)

  • 一句话解释:Query=我想问的问题,Key=每个词的"标签",Value=每个词真正的内容。
  • 形象比喻:去图书馆。你的问题(Q)拿去跟每本书的书脊标签(K)比对,匹配上的书,就把它的正文(V)读进来。
  • 工作中怎么用:注意力权重 = Q 和 K 的匹配程度;最终输出 = 按权重把各个 V 加权求和。
  • 最常踩的坑:以为 Q/K/V 是三种不同的词。不是——它们是同一个词乘上三个不同权重矩阵后的三个"视角"。

一句话公式(看看就好,不用背):

注意力输出 = softmax( Q · Kᵀ / √d ) · V
             └── 每个词该被关注多少 ──┘  └按权重取内容┘
  • Q · Kᵀ:算"问题"和每个"标签"的匹配分。
  • / √d:除一个数防止分值过大(否则 softmax 会变得非黑即白)。
  • softmax:把一堆分数压成加起来等于 1 的权重。
  • · V:按权重把内容混合出来。

上手算一遍:三个词的注意力(带数字)

光看公式没感觉,我们用"猫/累/它"三个词手算一次"它"该关注谁。假设经过一层网络后,算出"它"的 Query 和三个词的 Key 的匹配分是这样(数字我编的,只为演示):

"它" 对 "猫" 的原始分:  8.0
"它" 对 "累" 的原始分:  2.0
"它" 对 "它" 的原始分:  3.0

第一步 /√d 缩放(假设 d=64,√d=8):1.0 / 0.25 / 0.375。 第二步 softmax(把它们压成加起来=1 的权重),大致得到:

关注 "猫":  0.60   ← 最高,"它" 主要从 "猫" 吸收含义
关注 "累":  0.16
关注 "它":  0.24

第三步:最终"它"这个位置的新表示 = 0.60×V猫 + 0.16×V累 + 0.24×V它"它"就这样被"猫"带跑了 60%,指代消解在数学上就是这么发生的。这一整套,GPT 每一层、每个词、每次生成都在做。

不信手算?20 行 numpy 自己跑一遍

上面的数字是我给的,你可以用 numpy 把整个流程复现出来——不需要 GPU,不需要装深度学习框架,纯矩阵乘法:

# pip install numpy
import numpy as np

def softmax(x):
    e = np.exp(x - x.max())
    return e / e.sum()

# 3 个词:"猫" "累" "它",用 d=4 的迷你向量演示(数字是编的,逻辑是真的)
q_it = np.array([1.0, 0.5, 0.2, 0.8])   # "它" 的 Query
K = np.array([
    [1.1, 0.4, 0.3, 0.9],   # "猫" 的 Key —— 故意设计得跟 q_it 很像
    [0.1, 0.9, 0.1, 0.0],   # "累" 的 Key
    [0.3, 0.2, 0.6, 0.3],   # "它" 的 Key
])
V = np.array([
    [10.0, 0.0, 0.0, 0.0],  # "猫" 的 Value(用好认的整数)
    [0.0, 10.0, 0.0, 0.0],  # "累" 的 Value
    [0.0, 0.0, 10.0, 0.0],  # "它" 的 Value
])

scores = K @ q_it / np.sqrt(4)   # Q·Kᵀ / √d
weights = softmax(scores)
output = weights @ V             # 按权重混合 Value
print("注意力权重:", weights.round(3))   # ≈ [0.503 0.237 0.260]
print("『它』的新表示:", output.round(2)) # ≈ [5.03 2.37 2.6  0.  ]

跑出来你会看到"猫"拿走了约 0.5 的权重,"它"的新表示里第一个维度("猫"的成分)也明显最大。整个 self-attention 的核心,就是这三行矩阵运算——scoressoftmax、加权求和。真实模型只是把 d=4 换成 d=上万、3 个词换成几万 token、单头换成几十个头、再叠几十层而已。就这些。跑通这个,你就懂了注意力的 80%。

Multi-Head:同一句话,派好几组人各看各的

Multi-Head Attention(多头注意力):与其派一个人看整句,不如派 8 组、16 组人同时看,每组盯不同的关系——一组盯语法(主谓宾),一组盯指代(它=猫),一组盯时态或情绪……最后把各组结论拼起来再过一个线性层融合。这样一层就能同时抓住多种关系,信息远比单头丰富。GPT-3 有 96 个头,不是拍脑袋,是"分工看"的并行度。

这个"图书馆/分工"比喻帮你理解检索这层,但和真实系统有一处不同:图书馆的书是固定的,而这里的 Q/K/V 每过一层都会被重新计算、重新混合,越往上越抽象。


一个完整的 Transformer Block 里发生了什么

注意力只是一层里的一半。真实的一层(block)是这样,从下往上:

        输入向量(每个 token 一串数字)
              │
   ┌──────────▼───────────┐
   │  Multi-Head Attention │  ← 词互相看,吸收上下文
   └──────────┬───────────┘
              │  + 残差(把输入原样加回来) → LayerNorm
   ┌──────────▼───────────┐
   │  Feed-Forward (FFN)   │  ← 每个词各自过一个小型两层网络,加工信息
   └──────────┬───────────┘
              │  + 残差 → LayerNorm
              ▼
        输出向量 → 喂给上面一层,重复 N 次

三个你一定会听到的名词,一次说清:

  • FFN(前馈网络):注意力负责"词之间互相看",FFN 负责"每个词自己再想想"。它是一个先放大(如 4 倍维度)再压回来的两层网络,模型很大一部分"知识"其实存在这里。
  • 残差连接(Residual):把这一层的输入原封不动加到输出上。为什么?网络堆到几十上百层,梯度会消失、信息会走丢;残差留了一条"高速公路",让信息和梯度能直通到底。没有它,深层网络根本训不动。
  • LayerNorm(层归一化):把每层数值拉回一个稳定范围,防止越算越离谱。可以理解成每层之间的"稳压器"。

GPT-3 就是把这样的 block 叠了 96 层。"大模型"的"大",一大半是层数 × 每层宽度堆出来的。

顺手记一组数,讲课或面试都用得上:GPT-3(175B 参数)= 96 层 × 96 头 × 12288 维隐藏层。而微调里常听到的 LoRA/PEFT,动的主要就是注意力那几个投影矩阵——为什么"只训 1% 参数也有效",等你学到微调那一章会回来感谢这张架构图。


位置编码:模型本来分不清词序

注意力有个尴尬的先天缺陷:它是"一次性看全部"的,天生没有顺序概念。对纯注意力来说,"猫追狗"和"狗追猫"里的词集合一模一样,它分不清谁先谁后。

术语:位置编码 (Positional Encoding)

  • 一句话解释:给每个位置加一个独特的"数字指纹",让模型知道谁在第几位。
  • 形象比喻:剧院座位号。同样一批观众,有了排号座号,才知道谁挨着谁、谁在前排。
  • 工作中怎么用:早期(原版 Transformer)用固定的正弦/余弦波形当指纹;现在主流(如 RoPE 旋转位置编码)把位置信息直接编进 Q/K 里,长文本外推更好。
  • 最常踩的坑:以为 context window 想开多大开多大。位置编码的设计决定了模型能可靠处理多长,超出训练长度太多,效果会掉——这也是"长 context 模型"们真正在卷的技术点之一。

一句话:词序信息全靠位置编码补进去。 去掉它,GPT 会变成一个不懂语序的词袋子。


从文本到"下一个词":完整流水线

拿 "猫太累了" 喂进 GPT,大致流程:

文本
  │  ① 分词 Tokenize:切成 token(不完全等于"字")
  ▼
[那只][猫][太][累][了]
  │  ② Embedding:每个 token 变成一串数字(向量),含"语义坐标"
  │  ③ 位置编码:告诉模型谁在前谁在后
  ▼
  │  ④ 堆叠 N 层 Block(Attention+FFN,各带残差/LayerNorm)
  ▼
  │  ⑤ 输出层:把最后一层向量投影成"每个候选 token 的分数(logits)"
  │  ⑥ 采样:按分数挑下一个 token
  ▼
下一个词 → 接回输入末尾 → 再跑一遍 → 循环,逐字吐出来

图解说明(对着流程图看):

  1. 这张图在讲什么:一句话从文本到"预测下一个词"要过的完整工序,以及为什么它是"逐字接龙"。
  2. 先看哪里:先看①②③理解"文字先变数字+补位置";再看④,那是重复几十次的核心;最后⑤⑥解释它为什么会"编"。
  3. 工作中的关键判断:第⑤⑥步只是"挑下一个词",所以 LLM 本质是超强的文字接龙,不是查答案——这解释了它为什么流畅但会幻觉。

第⑥步就是 temperature / top_p 在管的地方

输出层给出的是一串候选词的分数,怎么从里面挑一个,就是采样策略——这正是你天天调的 API 参数

参数在干什么调高会怎样一句话记忆
temperature把分数分布"抹平"或"拉尖"越高越随机、越有创意也越容易胡说;=0 近似永远挑最高分创意/确定性的旋钮
top_p (核采样)只在"累计概率前 p"的候选里挑p 越小越保守,只从最可能的几个里选砍掉长尾垃圾选项
top_k只在分数最高的 k 个里挑同上,按个数截断另一种截断方式

所以"要稳定输出就 temperature=0"这句经验,在架构上就是"每步都选分数最高的词"。

顺带说清:token ≠ 字

第①步补一个最常踩的坑:token 不是字也不是单词。"ChatGPT" 可能被切成 2 个 token,一个中文字常占 1–2 个 token。你按 token 付费、context window 也按 token 算,所以"字数"和"token 数"永远对不上,别用字数估成本

第②步的主角:Embedding

术语:Embedding(词嵌入)

  • 一句话解释:把每个 token 变成一串数字(向量),意思相近的词,数字也相近。
  • 形象比喻:给每个词发一张"语义坐标"的地图定位——"猫"和"狗"住得近,"猫"和"发票"隔着十条街。
  • 工作中怎么用:LLM 输入的第一步;RAG 里的向量检索、语义搜索、推荐系统,用的全是这套"距离=语义相似度"的思路。
  • 最常踩的坑:以为 embedding 是固定查表就完事。查表只是起点——过完注意力层之后,同一个词在不同句子里的向量是不一样的("苹果发布会"和"苹果真甜"里的"苹果"),这正是 Transformer 比老式词向量强的地方。

上手代码:亲眼看看分词和注意力

# pip install transformers torch
from transformers import AutoTokenizer, AutoModel
import torch

tok = AutoTokenizer.from_pretrained("bert-base-chinese")
model = AutoModel.from_pretrained("bert-base-chinese", output_attentions=True)

text = "那只猫没跳上桌子因为它太累了"
enc = tok(text, return_tensors="pt")
print("token 切分:", tok.convert_ids_to_tokens(enc["input_ids"][0]))
# ['[CLS]','那','只','猫','没','跳',... ,'它','太','累','了','[SEP]']  ← 每个字≈1个token

with torch.no_grad():
    out = model(**enc)

# out.attentions: (层数) 个张量,每个 shape = [batch, 头数, seq, seq]
att = out.attentions[-1][0]          # 最后一层,去掉 batch 维 → [头数, seq, seq]
att = att.mean(0)                    # 对所有头取平均 → [seq, seq]
tokens = tok.convert_ids_to_tokens(enc["input_ids"][0])
it_idx = tokens.index("它")
scores = att[it_idx]                 # "它" 这一行 = 它对每个词的注意力权重
top = torch.topk(scores, 3)
print("『它』最关注:", [(tokens[i], round(float(scores[i]),3)) for i in top.indices])
# 通常你会看到 "猫" 排在前面 —— 亲眼验证指代

图解说明:

  1. 这段在干嘛:加载一个真实模型,把注意力权重掏出来,看"它"到底关注了谁。
  2. 先看哪里:先看 att.shape 的四个维度(层、头、词×词),这就是前面讲的多头注意力矩阵;再看最后打印的"它最关注"。
  3. 关键判断:不同的头会关注不同东西,所以我们 mean(0) 取平均看整体倾向;想研究"哪个头管指代",就别取平均,逐头看。

KV Cache:为什么第一个 token 慢,后面的快

生产环境有个现象你迟早会撞上:调 API 时,第一个 token 等得最久,后面哗哗地吐。我第一次给客户查"响应慢"的工单时就栽在这——盯着日志看了半天总耗时,后来才发现该拆开看两个指标:首 token 延迟(time to first token)和吐字速度(tokens/s)。这俩背后是两个完全不同的阶段:

  • Prefill(预填充):把你的整个 prompt 一次性过完所有层,算出每个 token 的 K 和 V。prompt 越长这步越慢——这就是首 token 延迟的大头。
  • Decode(逐字生成):之后每生成一个新 token,理论上要重新算前面所有 token 的 K/V——但它们根本没变过!所以推理框架把算好的 K/V 缓存起来,每步只算新 token 自己的 Q/K/V,再去查缓存。这就是 KV Cache

没有 KV Cache 会怎样?算笔账:1000 token 的 prompt 生成 500 token 回复,第 500 步要重算 1500 个 token 的 K/V,整个生成过程的重复计算量是缓存方案的几百倍。KV Cache 是空间换时间——代价是显存:以 7B 模型(fp16)为例,每个 token 的 K/V 缓存约占 0.5 MB,一条 4096 token 的对话就是约 2 GB 显存。为什么长对话的 API 又慢又贵、为什么本地部署跑长 context 显存爆炸,账就在这里。

一句话记住:Prefill 决定首 token 快不快,KV Cache 决定后面吐字快不快,显存决定你能缓存多长。 这三个词以后在部署与成本优化里还会反复出现。


为什么这架构又贵又有 context 限制

注意力要让每个词看所有词,n 个词就是 n×n 次比对。文本翻倍,计算量翻四倍(O(n²))。这个平方有多凶?代进数字看:

1,000 token   →  100 万次比对
10,000 token  →  1 亿次比对      (文本 ×10,计算 ×100)
100,000 token →  100 亿次比对    (文本 ×100,计算 ×10000)

这就是为什么:

现象根因一句话记忆
context window 有上限n 越大,注意力矩阵 n² 吃爆显存不是不想给你长,是平方级烧钱
token 多就慢就贵计算量按平方涨长 prompt 是真金白银
长文档"中间遗忘"注意力被稀释 + 位置外推变弱重点别塞文档正中间

后来的 Flash Attention(把注意力算得更省显存)、稀疏/滑窗注意力(不让每个词看全部)、KV Cache(生成时缓存已算过的 K/V,不重算)全是在跟这个 O(n²) 死磕。你现在不用会,但知道"瓶颈在注意力"就够了。

这也是做 RAG 的第一性原理:与其把 10 万 token 全塞进 context 让注意力稀释,不如先检索出最相关的 2000 token 再喂进去——又准又便宜。等你到 RAG 那一章,会发现整套方案就是在绕这个 n² 走。


这些权重是从哪来的?训练一分钟版

看到这你可能会问:Q/K/V 的那些投影矩阵、FFN 里的参数,数值是谁定的?答案简单到让人意外——全是"猜下一个词"猜出来的

1. 拿一大段真实文本,如 "那只猫没跳上桌子因为它太累了"
2. 遮住后半截,让模型预测下一个 token:"那只猫没跳上桌子因为它太___"
3. 模型输出每个候选 token 的概率,跟正确答案 "累" 对比,算出差距(loss)
4. 反向传播:把所有权重朝 "下次更可能猜对" 的方向微调一点点
5. 换下一段文本,回到第 2 步 —— 重复几万亿个 token

所谓"预训练"(pretraining)就是这个循环跑上几个月。没有人给模型标注"它=猫"这种规则——指代、语法、常识,全是为了把下一个词猜得更准而"顺便"学会的。这也解释了两件事:

  • 为什么微调有效:预训练已经把语言规律压进了那些矩阵,微调只是在现成基础上小幅调向。LoRA 敢只训 1% 参数,赌的就是"底子不用动"。
  • 为什么幻觉治不断根:训练目标从头到尾是"猜得像",不是"说得对"。像与对高度相关,但不是一回事。

就这些。训练的数学细节(梯度下降、优化器)留给机器学习基础那章,这里你只需要这个直觉。


三种 Transformer:GPT 只是其中一款

《Attention Is All You Need》原版有 encoder 和 decoder 两半,后来分化成三种用法:

类型代表怎么看词擅长一句话记忆
Encoder-onlyBERT双向,能看前后文理解类:分类、检索、抽取做阅读理解的
Decoder-onlyGPT / Llama / Claude单向,只能看左边(前文)生成类:对话、写作、代码做文字接龙的,你天天用的这种
Encoder-DecoderT5 / 原版翻译模型先读懂再生成翻译、摘要等"输入→输出"任务先读后写的

为什么 GPT 只能看左边?因为它的任务是"预测下一个词",训练和推理时不能偷看答案(右边),所以用了带掩码的注意力(masked attention)把右边挡住。这也是为什么它天然是"从左往右逐字生成"。

顺便一提:RAG 里管检索的 embedding 模型,多数是 encoder 系的后代;你天天聊天用的是 decoder 系。同一套注意力机制,两种吃法——一个用来"读懂",一个用来"接龙"。


⚠️ 常见陷阱

陷阱实际情况一句话记忆
"参数越多越聪明"大致相关但不绝对。数据质量、训练方法、对齐同样关键,调好的 7B 能吊打没调好的更大模型参数是身材,训练是本事
"Transformer = ChatGPT"Transformer 是架构,GPT 是基于它的 decoder-only 模型;BERT 也是 Transformer,干的却是理解类的活架构是发动机,产品是整车
"context window 越大越好、随便塞"受位置编码和 O(n²) 成本双重制约,塞满长 context 既贵又可能触发"中间遗忘"塞得进 ≠ 记得住
"位置编码可有可无"去掉它,"猫追狗"和"狗追猫"在模型眼里一模一样没座位号,全场大乱
"LLM 会查答案,错了就是没查到"它从头到尾只做"预测下一个 token",没有查询这个动作,幻觉是机制自带的接龙选手,不是图书管理员
"temperature=0 就绝对可复现"只是每步近似挑最高分,浮点并行计算、服务端批处理仍可能带来细微差异=0 是很稳,不是公证处
"Q/K/V 是三种不同的输入"同一个词向量乘三个不同矩阵得到的三个"视角",源头是同一个 token一人分饰三角
"多头 = 多算几遍一样的注意力"每个头有独立的投影矩阵,学到的关系各不相同(语法/指代/位置……)分工不同,不是复读机

🔧 动手练习

练习 1:亲手复现"它 → 猫"的注意力(约 20 分钟)

  1. 把上面那段 numpy 代码原样跑通(本地 pip install numpy 或直接开一个 Colab)。
  2. K 矩阵第二行("累"的 Key),把它改成跟 q_it 很像的向量(比如 [1.0, 0.5, 0.2, 0.8]),重跑——看权重怎么从"猫"倒向"累"。
  3. scores 那行的 / np.sqrt(4) 删掉,再把 K 的数值全体 ×10 重跑——观察 softmax 输出变得多"非黑即白",这就是公式里 /√d 存在的理由。
  4. 进阶:跑 transformers 那段 BERT 代码,把句子换成"律师把文件交给助理因为他快迟到了",看"他"的注意力落在"律师"还是"助理"——模型的判断跟你的直觉一致吗?

练习 2:用 API 参数验证"采样层"(约 15 分钟)

  1. 打开 OpenAI Tokenizer,把 "人工智能" 和 "Artificial Intelligence" 分别粘进去,数各占几个 token,体会"中文更费 token"。
  2. 同一个 prompt(建议用"给这款耳机写一句广告语"这类开放题),分别用 temperature=0temperature=1.2 各生成 3 次,对比稳定性和"胡说"程度,把结果和本文"采样层"那段对上。
  3. 找一段 500 字资料,把一个关键结论分别放在正中间结尾,各问一次模型,观察哪次答得准——亲手复现"中间遗忘"。
  4. 记录每次调用返回的 token 用量(usage 字段),对照第 1 步的分词结果,验证"按 token 计费"到底怎么算的。

📚 小结

  1. Transformer 靠注意力让每个词一次性看全句,取代 RNN 的排队式处理——又快又不忘;Q/K/V = 拿问题比标签再按匹配度取内容,multi-head 是"派好几组人各看各的关系",核心就是 softmax(QKᵀ/√d)·V 三步矩阵运算,20 行 numpy 就能复现。
  2. 一个 block = 注意力 + FFN,各配残差 + LayerNorm;残差是深层网络能训起来的"高速公路",FFN 存了模型大半知识,大模型的"大"主要是层数×宽度(GPT-3 = 96 层 × 96 头)。
  3. 注意力天生没有词序,位置编码把顺序补进去,它的设计也决定了 context 能可靠多长。
  4. LLM 本质是逐字接龙(⑤输出 logits→⑥采样),temperature/top_p/top_k 调的就是采样这一步;token≠字,成本和 context 都按 token 算;生成分 Prefill(决定首 token 延迟)+ Decode(KV Cache 加速吐字) 两阶段,KV Cache 用显存换速度(7B 模型约 0.5 MB/token)。
  5. 注意力是 O(n²)(文本 ×100 = 计算 ×10000),这是 context 限制、长文本又慢又贵、"中间遗忘"的共同根源,也是 RAG"先检索再喂"的第一性原理;GPT 是 decoder-only(只看左边、逐字生成),和 BERT(encoder,理解)、T5(encoder-decoder)分工不同。

相关阅读

下一步机器学习 / 深度学习基础速通

📚 相关资源

❓ 常见问题

关于本章主题最常被搜索的问题,点击展开答案

为什么 LLM 有 context window 限制?

注意力要求每个 token 和所有 token 两两比对,n 个 token 就是 n² 次计算,文本翻倍计算量翻四倍,显存和成本按平方烧;同时位置编码只在训练长度附近可靠,超出太多效果会掉。两个因素叠加,context 就有了上限。

注意力的计算量为什么是 n² 的?

self-attention 让每个词对句子里所有词各打一次「该多关注你」的分数,n 个词就是 n×n 次比对。1,000 token 是 100 万次,100,000 token 就是 100 亿次——文本长 100 倍,计算量涨 1 万倍,这就是长 prompt 又慢又贵的根因。

「lost in the middle」(中间遗忘)是怎么回事?

长文档里塞在中段的信息最容易被模型漏掉:一方面 token 越多,注意力权重被稀释得越薄;另一方面位置编码对超长距离的外推变弱。实践对策是把关键结论放在开头或结尾,或者用 RAG 先检索出相关片段再喂给模型。

temperature 调的到底是哪一步?

模型每步先输出一串候选 token 的分数(logits),temperature 作用在最后的采样层:调高把分数分布抹平,更随机更有创意也更容易胡说;调低把分布拉尖,更确定。设为 0 近似每步都挑最高分,跟注意力、位置编码这些环节无关。

KV Cache 优化了什么?

逐字生成时前面所有 token 的 K/V 其实没变,KV Cache 把它们缓存起来,每步只算新 token 自己的 Q/K/V,省掉几百倍的重复计算——代价是显存,7B 模型约每 token 0.5 MB。它决定吐字速度,首 token 延迟则由 prefill 阶段决定。