Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 人工智能 / Artificial Intelligence

大语言模型 / Large Language Models

1. LLM 前置知识学习路线 / A Prerequisite Learning Path for Large Language Models

2. 神经网络基础 - 从零理解 AI 的"计算单元" / Neural Network Fundamentals from Artificial Neurons

3. Token 与上下文窗口 - LLM 的计费与记忆单位 / Tokens and Context Windows as the Units of LLM Cost and Memory

4. 解码策略 - 控制 LLM 输出的艺术 / Decoding Strategies for Controlling LLM Output

5. 消息角色 - 构建 Agent 对话的基础 / Message Roles as the Foundation of Agent Conversations

6. 流式输出 - 实时交互的体验优化 / Streaming Output for Responsive Interaction

7. Prompt 工程基础 - 与 LLM 高效对话的技巧 / Prompt Engineering Fundamentals for Effective LLM Interaction

8. LLM 进化史 - 从词向量到 Transformer / The Evolution of LLMs from Word Embeddings to Transformers

9. Transformer 手动计算:从 Attention 到 Encoder-Decoder 完整数据流

10. Transformer 核心原理 - 现代 LLM 的基石 / Transformer Fundamentals Behind Modern LLMs

11. Decoder-Only LLM 深度解析:为什么扔掉 Encoder,以及 KV Cache 如何工作

12. 训练 vs 推理:同一个 Transformer,两条完全不同的执行路径

13. Transformer 训练阶段计算详解 - 手算每一行矩阵 / Transformer Training Computation Matrix by Matrix

14. Transformer 推理阶段详解 — 模型如何"思考"并生成回答 / Transformer Inference and Autoregressive Generation

15. 训练基础扫盲 - 理解 Fine-tune 在做什么 / A Training Primer for Understanding Fine-Tuning

16. LLM 预训练全景:数据管道、Scaling Laws 与训练稳定性

17. 训练基础设施 - 从单卡到千卡集群 / Training Infrastructure from One GPU to Thousand-GPU Clusters

18. Post-Training Pipeline - 从 Base Model 到可用助手 / The Post-Training Pipeline from Base Model to Assistant

19. SFT 深度解析:从 Base Model 到指令跟随——后训练第一步 / SFT Deep Dive: Teaching Base Models to Follow Instructions

20. RLHF 深度解析:从 Reward Model 到 PPO 的完整对齐流程

21. DPO 与对齐方法:从 RLHF 复杂度到直接偏好优化

22. 研究视角:DL/RL 理论到 LLM 训练的完整映射

本页目录

Transformer 推理阶段详解 — 模型如何"思考"并生成回答 / Transformer Inference and Autoregressive Generation ​

📅 创建时间:2026-04-29 🏷️ 标签:#Transformer #推理 #自回归 #KV-Cache #生成模型 📚 前置知识:[[09 - Transformer训练阶段计算详解]] [[08 - Transformer核心原理]] 🎯 文档类型:推理机制 · 端到端流程解析


📋 文档目标 ​

阅读完本文档后,你将能够:

  • [ ] 理解训练阶段与推理阶段的本质区别
  • [ ] 完整描述自回归生成(Autoregressive Generation)的工作流程
  • [ ] 解释解码器中 Masked Attention 的作用(为什么不能"看到未来")
  • [ ] 理解 KV Cache 机制如何将推理速度提升数十倍
  • [ ] 掌握 Prompt 模板与对话格式对推理的影响
  • [ ] 理解上下文窗口(Context Window)对推理的限制
  • [ ] 区分并选择合适的采样策略组合

第1章:从训练到推理 — 两种截然不同的工作模式 ​

1.1 核心区别一览 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        训练 vs 推理:本质差异                                 │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【训练阶段】                                                                │
│                                                                             │
│  输入:   "猫 追 老鼠 <EOS>"  (整个序列一次性输入)                          │
│           ↓                                                                  │
│  过程:   所有 Token 同时并行计算前向传播                                      │
│           ↓                                                                  │
│  目标:   让每个位置的预测概率分布尽可能接近"正确答案"                        │
│           ↓                                                                  │
│  输出:   Cross-Entropy Loss → 反向传播 → 更新权重                             │
│                                                                             │
│  关键:✓ 并行计算  ✓ 一次处理整个序列  ✓ 需要正确答案(标签)                 │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【推理阶段】                                                                │
│                                                                             │
│  输入:   "请帮我写一首诗:"  (用户 Prompt)                                  │
│           ↓                                                                  │
│  过程:   逐 Token 生成,每生成一个都要重新计算整个序列                        │
│           ↓                                                                  │
│  目标:   根据已生成的内容,预测下一个最可能的 Token                             │
│           ↓                                                                  │
│  输出:   "春风吹" → 加入序列 → 继续预测 → 直到遇见 <EOS>                      │
│                                                                             │
│  关键:✗ 串行生成  ✗ 无法并行  ✗ 没有正确答案,只能采样                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

1.2 训练阶段的工作方式 ​

训练的本质是教会模型"完形填空":

输入序列:"我喜欢学习机器学习"
                   ↓
位置 0 "我":已知 → 预测下一个 "喜欢"
位置 1 "喜欢":已知 → 预测下一个 "学习"
位置 2 "学习":已知 → 预测下一个 "机器"
位置 3 "机器":已知 → 预测下一个 "学习"
位置 4 "学习":已知 → 预测下一个 <EOS>

所有位置的损失可以一次性并行计算(Teacher Forcing)
1
2
3
4
5
6
7
8
9
┌─────────────────────────────────────────────────────────────────────────────┐
│                         Teacher Forcing 机制                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  "猫 追 老鼠" 的训练过程:                                                   │
│                                                                             │
│  Step 0: 输入 <BOS>,期望输出 "猫"                                           │
│  Step 1: 输入 <BOS> 猫,期望输出 "追"                                        │
│  Step 2: 输入 <BOS> 猫 追,期望输出 "老鼠"                                    │
│  Step 3: 输入 <BOS> 猫 追 老鼠,期望输出 <EOS>                                │
│                                                                             │
│  每次预测时,"正确答案"已经在输入序列中(Teacher Forcing 的含义)              │
│  模型不需要自己生成之前的内容,只需要预测下一个词                                │
│                                                                             │
│  ✓ 训练效率高:可以批量并行                                                    │
│  ✓ 梯度稳定:因为输入是"标准答案"                                             │
│  ✓ 收敛快:每个位置都有明确的优化目标                                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

1.3 推理阶段的工作方式 ​

推理的本质是模型根据已有内容"自己续写":

用户输入:"请写一首诗:"

推理过程(自回归生成):
┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│  Step 1: 输入 "请写一首诗:"                                                │
│  → 模型预测:"春风"                                                          │
│                                                                             │
│  Step 2: 输入 "请写一首诗:春风"                                            │
│  → 模型预测:"吹"                                                            │
│                                                                             │
│  Step 3: 输入 "请写一首诗:春风吹"                                           │
│  → 模型预测:"绿"                                                            │
│                                                                             │
│  Step 4: 输入 "请写一首诗:春风吹绿"                                          │
│  → 模型预测:"草"                                                            │
│                                                                             │
│  ... 持续直到模型输出 <EOS>                                                   │
│                                                                             │
│  最终输出:"请写一首诗:春风吹绿草,花开满庭芳"                                │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

1.4 训练与推理的关键差异总结 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        训练 vs 推理 详细对比                                  │
├─────────────────────┬──────────────────────┬───────────────────────────────┤
│ 维度                │ 训练                │ 推理                            │
├─────────────────────┼──────────────────────┼───────────────────────────────┤
│ 数据输入            │ 完整序列             │ 从 Prompt 开始逐个生成            │
│ 计算方式            │ 全序列并行           │ 逐 Token 串行                   │
│ 目标                │ 最小化 Loss          │ 最大化生成质量                  │
│ 损失计算            │ Cross-Entropy         │ 无(无标签)                    │
│ 解码策略            │ 无                   │ Temperature/TopP/TopK           │
│ 计算量               │ 固定(序列长度)       │ 随输出长度线性增长              │
│ 显存占用            │ 大(存中间激活值)     │ 小(可逐层释放)               │
│ 生成确定性          │ N/A                  │ 随机(除非 T=0)               │
│ 优化目标            │ 预测准确              │ 文本流畅、符合指令              │
└─────────────────────┴──────────────────────┴───────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

第2章:自回归生成 — 逐 Token 的思考过程 ​

2.1 一个完整的推理示例 ​

让我们用具体例子追踪推理全过程:

场景:用户输入 "中国最高的山是什么?"

预期输出:"中国最高的山是珠穆朗玛峰。"
1
2
3

2.2 解码器的特殊设计:Masked Attention ​

在推理阶段,解码器使用 Masked Self-Attention(因果注意力),这是推理能工作的关键。

问题:解码器在预测第 N 个词时,不应该"看到"第 N+1、N+2... 个词。

┌─────────────────────────────────────────────────────────────────────────────┐
│                    Masked Self-Attention 原理                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  原始 Attention(可以看到所有位置):                                          │
│                                                                             │
│         位置0  位置1  位置2  位置3                                          │
│  位置0   ✓      ✓      ✓      ✓                                            │
│  位置1   ✓      ✓      ✓      ✓                                            │
│  位置2   ✓      ✓      ✓      ✓                                            │
│  位置3   ✓      ✓      ✓      ✓                                            │
│                                                                             │
│  Masked Attention(只能看到自己和之前的位置):                                 │
│                                                                             │
│         位置0  位置1  位置2  位置3                                          │
│  位置0   ✓      ✗      ✗      ✗                                            │
│  位置1   ✓      ✓      ✗      ✗                                            │
│  位置2   ✓      ✓      ✓      ✗                                            │
│  位置3   ✓      ✓      ✓      ✓                                            │
│                                                                             │
│  实现方式:将"未来"位置的注意力分数设为 -∞                                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Mask 的具体数值实现:

假设某位置的原始注意力分数:
score = [0.5, 0.3, 0.1, 0.1]  # 对位置0,1,2,3的注意力

要 Mask 位置1,2,3(只能看位置0):
masked_score = [0.5, -∞, -∞, -∞]

exp(0.5) = 1.65
exp(-∞) = 0

softmax 后:
attention = [1.0, 0, 0, 0]  ← 100% 关注自己
1
2
3
4
5
6
7
8
9
10
11

2.3 Step-by-Step 生成过程 ​

我们用更具体的数字来追踪推理的每一步:

设定:

  • 输入序列:"中国最高的山是"(已分词为5个Token)
  • 词表大小:d_vocab = 6
  • 输出要预测下一个词

Step 0:输入处理

用户输入 → Token化 → Embedding + 位置编码

"中国" → 索引 2 → Embedding [0.5, 0.3, 0.8, 0.2]
"最高" → 索引 1 → Embedding [0.2, 0.7, 0.4, 0.9]
"的"  → 索引 3 → Embedding [0.6, 0.1, 0.3, 0.5]
"山"  → 索引 4 → Embedding [0.3, 0.8, 0.7, 0.1]
"是"  → 索引 5 → Embedding [0.1, 0.4, 0.9, 0.6]

+ 位置编码(略)
→ X_input (5 × 4)
1
2
3
4
5
6
7
8
9
10

Step 1:第一次前向传播

X_input → Multi-Head Self-Attention → Add&Norm
→ FFN → Add&Norm
→ Linear → Logits

Logits (5 × 6):
       <PAD>   珠峰   喜马拉雅  泰山  华山   什么
位置0: [-0.2,   0.1,   0.3,    0.2,  0.1,  -0.5]
位置1: [ 0.1,   0.2,   0.4,    0.3,  0.2,  -0.3]
位置2: [-0.1,   0.3,   0.5,    0.2,  0.1,  -0.4]
位置3: [ 0.2,   0.4,   0.6,    0.1,  0.2,  -0.2]
位置4: [ 0.3,   0.8,   1.2,    0.5,  0.4,  -0.1]  ← 最后一个位置是预测位置

只看位置4(预测位置)的 Logits:[0.3, 0.8, 1.2, 0.5, 0.4, -0.1]

预测位置4的候选分布(Softmax):
Token:   <PAD>  珠峰  喜马拉雅  泰山  华山   什么
Logits:  0.3    0.8    1.2     0.5   0.4   -0.1
Prob:    8.2%  13.5%  20.1%   10.0%  9.3%  5.5%

→ 最高概率是 "喜马拉雅"(20.1%)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Step 2:采样下一个 Token

假设 Temperature = 0.7, TopP = 0.9

经过解码策略后,选中 "喜马拉雅"(Token 索引 = 3)

生成结果:"中国最高的山是喜马拉雅"
1
2
3
4
5

Step 3:将新 Token 加入序列

序列变为:"中国最高的山是喜马拉雅"

再次进入模型,重复 Step 1~3:
→ 预测 "峰"(下一个 Token)

序列变为:"中国最高的山是喜马拉雅峰"
→ 预测 "。"(下一个 Token)
→ 预测 <EOS>

生成结束!
1
2
3
4
5
6
7
8
9
10

2.4 自回归生成的计算成本 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        自回归生成的计算成本分析                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  生成 N 个 Token 的总计算量:                                                │
│                                                                             │
│  总计算量 = 1 + 2 + 3 + ... + N                                            │
│          = N × (N + 1) / 2                                                 │
│          ≈ O(N²)                                                            │
│                                                                             │
│  具体示例:                                                                  │
│  生成 100 个 Token:100 × 101 / 2 = 5,050 次注意力计算                       │
│  生成 1000 个 Token:1000 × 1001 / 2 = 500,500 次注意力计算                  │
│                                                                             │
│  线性近似(KV Cache 优化后):O(N)                                           │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────┐             │
│  │ 计算量增长对比:                                             │             │
│  │                                                              │             │
│  │ 无优化:    ████████████████████████████  O(N²)            │             │
│  │ 有KV Cache:███████████████  O(N)                            │             │
│  │                                                              │             │
│  │ KV Cache 让计算量从二次降为线性!                               │             │
│  └─────────────────────────────────────────────────────────────┘             │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

第3章:KV Cache — 推理加速的核心技术 ​

3.1 没有 KV Cache 的困境 ​

每次生成新 Token 时,传统方法需要重新计算整个序列的 Attention:

生成第1个Token:
"中国最高的山是" → 计算注意力 → 生成 "喜"

生成第2个Token:
"中国最高的山是喜" → 重新计算所有5+1=6个位置的注意力 → 生成 "马"

生成第3个Token:
"中国最高的山是喜马" → 重新计算所有6+1=7个位置的注意力 → 生成 "拉"
...
1
2
3
4
5
6
7
8
9

问题:每次生成都在重复计算之前已经算过的内容!

3.2 KV Cache 的核心思想 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         KV Cache 工作原理                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  观察:                                                                     │
│  - Q(Query)只关心当前位置                                                  │
│  - K(Key)和 V(Value)存储的是每个位置的"记忆"                              │
│                                                                             │
│  每次生成新 Token 时:                                                       │
│  - 不需要重新计算所有旧位置的 K 和 V                                          │
│  - 只需要计算新位置的 K 和 V                                                  │
│  - 将所有 K 和 V 缓存起来                                                    │
│                                                                             │
│  Attention 计算:                                                            │
│  - Q_新 只和所有 K(旧的+新的)做点积                                        │
│  - 结果用所有 V(旧的+新的)加权求和                                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

3.3 KV Cache 具体数值示例 ​

Step 1:输入 "中国最高的山是"(5个Token)

计算并缓存:
K_cache = [K_中国, K_最高, K_的, K_山, K_是]   # 形状 (5, d_k)
V_cache = [V_中国, V_最高, V_的, V_山, V_是]   # 形状 (5, d_v)

Step 2:预测 "喜马拉雅"(新Token)

只需要:
1. 计算新 Token 的 Q_new, K_new, V_new
2. Q_new 与 K_cache 做注意力计算(无需重新计算旧的)
3. 将 K_new, V_new 加入缓存

Q_new = "喜"的 Query
Q_new · K_cache^T → 注意力分数(关于所有旧位置)
Q_new · K_new^T   → 注意力分数(关于自己)
attention = softmax(上述分数) · [V_cache; V_new]  → 输出

更新缓存:
K_cache = [K_中国, K_最高, K_的, K_山, K_是, K_喜]   # +1
V_cache = [V_中国, V_最高, V_的, V_山, V_是, V_喜]   # +1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

3.4 KV Cache 的收益 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         KV Cache 性能收益                                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  场景:生成 100 个 Token,序列长度从 1 增长到 100                              │
│                                                                             │
│  无 KV Cache:                                                              │
│  第1步: 1×注意力计算                                                        │
│  第2步: 2×注意力计算                                                        │
│  第3步: 3×注意力计算                                                        │
│  ...                                                                        │
│  第100步: 100×注意力计算                                                    │
│  总计: 1+2+3+...+100 = 5050 次                                             │
│                                                                             │
│  有 KV Cache:                                                              │
│  第1步: 计算 K,V_位置0,存入缓存 → 1次 K,V 计算                             │
│  第2步: Q_位置1 + K_cache → 输出,存入 K,V_位置1 → 1次 K,V 计算            │
│  第3步: Q_位置2 + K_cache → 输出,存入 K,V_位置2 → 1次 K,V 计算            │
│  ...                                                                        │
│  第100步: Q_位置99 + K_cache → 输出 → 1次 K,V 计算                          │
│  总计: 100 次 K,V 计算                                                      │
│                                                                             │
│  加速比:5050 / 100 = 50.5倍!                                              │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

3.5 KV Cache 的代价:显存 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        KV Cache 的显存开销                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  单层 Transformer 的 KV Cache 大小:                                          │
│                                                                             │
│  K_cache: 2 × seq_len × d_k × bytes_per_float                              │
│  V_cache: 2 × seq_len × d_v × bytes_per_float                              │
│                                                                             │
│  以 GPT-3 为例:                                                            │
│  - num_layers = 96                                                          │
│  - d_model = 12288                                                          │
│  - num_heads = 96                                                           │
│  - d_k = d_model / num_heads = 128                                          │
│  - seq_len = 2048                                                           │
│  - FP16 (2 bytes)                                                           │
│                                                                             │
│  每层 KV Cache = 2 × 2048 × 128 × 2 bytes = 1 MB                           │
│  总 KV Cache = 96 × 1 MB = 96 MB(仅 2048 tokens)                         │
│                                                                             │
│  如果 seq_len = 32768(长上下文):                                          │
│  每层 = 2 × 32768 × 128 × 2 = 16 MB                                        │
│  总 KV Cache = 96 × 16 MB = 1.5 GB                                         │
│                                                                             │
│  这就是为什么长上下文需要大量显存!                                            │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

3.6 多轮对话中的 KV Cache ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      多轮对话中的 KV Cache 管理                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  对话历史:                                                                  │
│  用户:"请介绍一下北京"                                                       │
│  助手:"北京是中国的首都..."                                                 │
│  用户:"那里有什么好吃的?"                                                   │
│                                                                             │
│  方式1:完整缓存(推荐)                                                      │
│  - 保留所有历史的 K,V 缓存                                                    │
│  - 新输入时,Q_new 与完整 K_cache 计算                                        │
│  - 优点:上下文连贯                                                          │
│  - 缺点:显存随对话长度线性增长                                               │
│                                                                             │
│  方式2:滑动窗口缓存                                                          │
│  - 只保留最近 N 个 Token 的 K,V                                               │
│  - 超过窗口的历史被丢弃                                                       │
│  - 优点:显存固定                                                            │
│  - 缺点:丢失早期上下文                                                       │
│                                                                             │
│  方式3:语义压缩缓存                                                          │
│  - 用摘要向量压缩历史信息                                                      │
│  - 还在研究中                                                                │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

第4章:完整推理流程 — 从用户输入到模型输出 ​

4.1 推理 Pipeline 总览 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      Transformer 推理完整 Pipeline                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段1:输入预处理                                                    │   │
│  │                                                                     │   │
│  │ 用户输入:"请用一句话介绍北京"                                        │   │
│  │     ↓                                                               │   │
│  │ Tokenizer:将文本切分为 Token 序列                                   │   │
│  │     ↓                                                               │   │
│  │ Token IDs: [100, 230, 582, 1205, 891]                               │   │
│  │     ↓                                                               │   │
│  │ Embedding + 位置编码                                                 │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    ↓                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段2:模型前向传播                                                  │   │
│  │                                                                     │   │
│  │ 输入向量 → [编码器层×N] → [解码器层×N] → Logits                      │   │
│  │                                                                     │   │
│  │ (推理时:解码器自回归运行,KV Cache 加速)                           │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    ↓                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段3:Token 选择(解码策略)                                        │   │
│  │                                                                     │   │
│  │ Logits → Temperature → Softmax → TopP → 采样 → Token               │   │
│  │                                                                     │   │
│  │ 例如:选中 Token ID = 2347                                          │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    ↓                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段4:输出后处理                                                    │   │
│  │                                                                     │   │
│  │ Token ID → Tokenizer.decode() → 文本 "北京是中国的首都。"             │   │
│  │     ↓                                                               │   │
│  │ 检查:是否 <EOS>?长度是否达到 max_tokens?                          │   │
│  │     ↓                                                               │   │
│  │ 是 → 结束,输出完整文本                                              │   │
│  │ 否 → 将新 Token 加入序列,回到阶段2                                  │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

4.2 各阶段详解 ​

阶段1:输入预处理 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         输入预处理详解                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  原始文本 → Token IDs → Embedding → 加入位置编码                              │
│                                                                             │
│  示例:                                                                      │
│  原始文本:"请介绍北京"                                                      │
│                                                                             │
│  Token 化后(假设 BPE 分词):                                               │
│  ["请", "介绍", "北京"]                                                     │
│                                                                             │
│  转换为 Token IDs:                                                         │
│  [1024, 3506, 8901]                                                        │
│                                                                             │
│  查 Embedding 表:                                                          │
│  [0.23, -0.45, 0.78, ...]  # "请" 的向量                                  │
│  [0.11, 0.56, -0.23, ...]  # "介绍" 的向量                                │
│  [-0.34, 0.12, 0.67, ...]  # "北京" 的向量                                │
│                                                                             │
│  加入位置编码(每个位置不同):                                               │
│  位置0: +[0.00, 1.00, 0.00, 1.00]                                          │
│  位置1: +[0.84, 0.54, 0.00, 1.00]                                          │
│  位置2: +[0.91, -0.42, 0.00, 1.00]                                         │
│                                                                             │
│  最终输入向量矩阵 X (3 × d_model)                                           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

阶段2:模型前向传播 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         模型前向传播详解                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  X → [编码器层 × 12] → 编码器输出(如果是 Encoder-Decoder 架构)            │
│       ↓                                                                    │
│  X → [解码器层 × 12] → 解码器输出                                           │
│       ↓                                                                    │
│  Linear(投影到词表)→ Logits                                               │
│                                                                             │
│  解码器层内部(自回归模式):                                                 │
│                                                                             │
│  ┌───────────────────────────────────────────────────────────────────┐   │
│  │ 输入向量                                                           │   │
│  │     ↓                                                              │   │
│  │ Masked Self-Attention(只看自己和之前的 Token)                      │   │
│  │     ↓                                                              │   │
│  │ Add & LayerNorm                                                   │   │
│  │     ↓                                                              │   │
│  │ Cross-Attention(如有,Q来自解码器,K/V来自编码器)                  │   │
│  │     ↓                                                              │   │
│  │ Add & LayerNorm                                                   │   │
│  │     ↓                                                              │   │
│  │ FFN                                                               │   │
│  │     ↓                                                              │   │
│  │ Add & LayerNorm                                                   │   │
│  │     ↓                                                              │   │
│  │ 输出向量                                                           │   │
│  └───────────────────────────────────────────────────────────────────┘   │
│                                                                             │
│  GPT 类模型(纯解码器):只有 Masked Self-Attention                           │
│  T5/BERT 类模型(Encoder-Decoder):有完整的编码器和解码器                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

阶段3:Token 选择 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                          Token 选择详解                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Logits (1 × d_vocab):                                                     │
│  [0.23, -0.45, 0.78, -0.12, 0.56, ..., 0.34]  # 数千个候选                 │
│                                                                             │
│  Step 1:应用 Temperature(可选)                                            │
│  Logits' = Logits / T                                                      │
│                                                                             │
│  Step 2:Softmax 得到概率分布                                                │
│  P = softmax(Logits')                                                      │
│                                                                             │
│  Step 3:应用 TopP(核采样)                                                 │
│  - 按概率排序                                                                │
│  - 从高到低累加,直到达到 TopP                                               │
│  - 只保留这个集合内的 Token                                                   │
│                                                                             │
│  Step 4:归一化 + 采样                                                       │
│  - 在候选集合内重新归一化概率                                                 │
│  - 按概率随机采样                                                            │
│                                                                             │
│  Step 5:输出 Token ID                                                      │
│  selected_token_id = 2347                                                  │
│                                                                             │
│  特殊情况:                                                                 │
│  - T=0:直接取 argmax(贪婪解码)                                            │
│  - TopK=1:也是贪婪解码                                                      │
│  - EOD 标记:停止生成                                                        │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

阶段4:输出后处理与循环 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                       输出后处理与循环控制                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  生成循环:                                                                  │
│                                                                             │
│  while True:                                                                │
│      # 1. 前向传播(KV Cache 加速)                                          │
│      output = model(input_ids)                                              │
│                                                                             │
│      # 2. 解码策略选择 Token                                                 │
│      next_token = sample(output.last_logits, T, top_p)                      │
│                                                                             │
│      # 3. 追加到序列                                                         │
│      input_ids = concat(input_ids, next_token)                              │
│                                                                             │
│      # 4. 停止条件检查                                                        │
│      if next_token == <EOS>:        break    # 遇到停止符                    │
│      if len(output) >= max_tokens:  break    # 达到最大长度                  │
│      if is_stuck_in_loop():        break    # 检测到重复                    │
│                                                                             │
│  最终输出 = decode(input_ids)                                                │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

第5章:Prompt 工程 — 引导模型行为的关键 ​

5.1 Prompt 在推理中的角色 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Prompt 的本质                                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  训练时:                                                                    │
│  - 模型学习的是"给定前文,预测下一个词"                                        │
│  - 学习了海量文本中的语言模式                                                 │
│                                                                             │
│  推理时:                                                                    │
│  - Prompt 充当"前文"的角色                                                   │
│  - 模型根据 Prompt 中的模式续写                                               │
│  - 通过精心设计 Prompt,可以激活模型的不同"技能"                               │
│                                                                             │
│  核心洞察:                                                                  │
│  好的 Prompt = 给模型一个清晰的"任务启动上下文"                                │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

5.2 Prompt 模板的组成 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      标准 Prompt 模板                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │ [System Prompt]                                                       │ │
│  │ 你是一个乐于助人的AI助手。请用简洁、专业的语言回答问题。                  │ │
│  │                                                                     │ │
│  │ [User Message]                                                       │ │
│  │ 请介绍一下人工智能的发展历史                                           │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  实际 Token 序列:                                                           │
│  [<BOS>, system, 助手, ..., user, 请, 介绍, ...]                            │
│                                                                             │
│  模型处理:                                                                  │
│  - <BOS> → 解码器开始生成                                                    │
│  - system 内容设定了"角色"                                                   │
│  - user 内容是实际任务                                                       │
│  - 模型在 system 的语境下回答 user 的问题                                    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

5.3 常见 Prompt 策略 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Prompt 工程策略                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【Zero-Shot】直接提问                                                       │
│  "把以下句子翻译成英文:我爱你"                                               │
│                                                                             │
│  【Few-Shot】提供示例                                                        │
│  "请完成类比:                                                               │
│   猫-狗 : 动物    苹果-? : 水果                                             │
│   红-蓝 : 颜色    高-? :矮"                                                 │
│                                                                             │
│  【Chain-of-Thought】引导思考步骤                                             │
│  "问题:一个商店有20个苹果,卖掉了8个,又进了15个。现在有几个苹果?            │
│   让我们一步步思考:                                                         │
│   1. 原来有20个苹果                                                          │
│   2. 卖掉8个,剩20-8=12个                                                   │
│   3. 又进了15个,12+15=27个                                                  │
│   所以答案是27个。"                                                          │
│                                                                             │
│  【结构化输出】指定格式                                                        │
│  "请用JSON格式回答:                                                         │
│   {\"城市\": \"北京\", \"人口\": 2154万, \"首都\": true}"                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

5.4 上下文窗口限制 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      上下文窗口(Context Window)                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  定义:模型一次能处理的最大 Token 数量                                        │
│                                                                             │
│  常见模型的上下文窗口:                                                       │
│  ┌────────────────┬──────────────────┐                                     │
│  │ 模型            │ 上下文窗口        │                                     │
│  ├────────────────┼──────────────────┤                                     │
│  │ GPT-3.5        │ 16K tokens       │                                     │
│  │ GPT-4          │ 128K tokens      │                                     │
│  │ Claude 3       │ 200K tokens      │                                     │
│  │ Gemini 1.5     │ 1M tokens        │                                     │
│  └────────────────┴──────────────────┘                                     │
│                                                                             │
│  超出上下文窗口会发生什么:                                                   │
│  - 早期内容被截断(Truncation)                                              │
│  - 模型"忘记"对话开头的内容                                                  │
│  - 丧失上下文连贯性                                                          │
│                                                                             │
│  解决方案:                                                                  │
│  1. 总结+压缩早期对话                                                        │
│  2. RAG(检索增强生成)                                                       │
│  3. 滑动窗口对话                                                            │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

第6章:推理优化技术 ​

6.1 常见推理优化方法 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      推理优化技术全景                                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 计算优化                                                            │   │
│  │                                                                     │   │
│  │ • KV Cache:避免重复计算(已详述)                                   │   │
│  │ • 批量推理(Batch):同时处理多个请求,提高GPU利用率                  │   │
│  │ • 混合精度推理:FP16/BF16 代替 FP32                                 │   │
│  │ • 算子融合:将多个操作合并为一个 kernel                              │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                              ↓                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 显存优化                                                            │   │
│  │                                                                     │   │
│  │ • PagedAttention:分页管理 KV Cache,减少碎片化                      │   │
│  │ • 量化推理:INT8/INT4 量化模型权重                                   │   │
│  │ • 梯度检查点:重计算激活值换显存                                      │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                              ↓                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ 生成优化                                                            │   │
│  │                                                                     │   │
│  │ • 投机解码(Speculative Decoding):小模型预测+大模型验证             │   │
│  │ • 早停(Early Stopping):检测到足够置信时停止                        │   │
│  │ • 重复惩罚:防止生成循环                                              │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

6.2 量化推理详解 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         量化推理(Quantization)                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  原始:FP32(32位浮点,4字节)                                               │
│  INT8:8位整数,1字节 → 体积缩小 4倍,显存减少 4倍                            │
│  INT4:4位整数,0.5字节 → 体积缩小 8倍,显存减少 8倍                          │
│                                                                             │
│  示例:                                                                      │
│  原始权重 [0.234, -0.891, 1.234, -0.567]                                    │
│  量化到 INT8:                                                               │
│  1. 找到最大值:max = 1.234                                                  │
│  2. 缩放因子 = 127 / 1.234 ≈ 103                                            │
│  3. 量化:int([23, -92, 127, -58])                                          │
│  4. 反量化:float([0.223, -0.893, 1.234, -0.563]) ← 有误差                  │
│                                                                             │
│  精度损失 vs 效率收益:                                                       │
│  FP32: 100% 精度,100% 显存,100% 计算量                                    │
│  FP16: ~100% 精度,50% 显存,50% 计算量                                      │
│  INT8: ~99% 精度,25% 显存,25% 计算量(推荐)                              │
│  INT4: ~97% 精度,12.5% 显存,12.5% 计算量(可接受)                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

6.3 投机解码(Speculative Decoding) ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      投机解码工作原理                                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  核心思想:用小模型快速预测多个 Token,大模型并行验证                          │
│                                                                             │
│  传统方式(自回归):                                                         │
│  大模型 → 预测1 → 预测2 → 预测3 → ...(慢)                                  │
│                                                                             │
│  投机解码:                                                                  │
│  小模型 → 快速预测 [T1, T2, T3, T4, T5]  → 大模型并行验证 → 接受/拒绝       │
│                                                                             │
│  具体步骤:                                                                  │
│  1. 小模型(7B)快速生成 5 个候选 Token                                       │
│  2. 大模型(70B)并行验证这 5 个 Token                                        │
│     - T1:接受(概率高)                                                    │
│     - T2:接受(概率高)                                                    │
│     - T3:拒绝 → 重新采样 T3'                                               │
│     - T4:拒绝 → 重新采样 T4'                                               │
│     - T5:拒绝 → 重新采样 T5'                                               │
│  3. 输出:[T1, T2, T3', T4', T5']                                          │
│                                                                             │
│  加速效果:通常 2~3 倍                                                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

第7章:采样策略实战 — 完整参数组合 ​

7.1 采样流程再梳理 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                     采样完整流程(带具体数值)                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Logits 向量(d_vocab = 6):                                               │
│  [0.3, 0.8, 1.2, 0.5, 0.4, -0.1]                                          │
│   <PAD>   珠峰  喜马拉雅   泰山  华山    什么                                │
│                                                                             │
│  Step 1:Temperature 调整                                                   │
│  T = 0.7 → Logits' = [0.43, 1.14, 1.71, 0.71, 0.57, -0.14]                │
│                                                                             │
│  Step 2:Softmax → 概率分布                                                 │
│  [8.2%, 15.7%, 27.8%, 10.2%, 8.8%, 4.4%]                                  │
│  喜马拉雅 27.8%(最高)                                                     │
│                                                                             │
│  Step 3:TopP 截断                                                           │
│  排序后:[喜马拉雅(27.8%), 珠峰(15.7%), 泰山(10.2%), 华山(8.8%),             │
│          <PAD>(8.2%), 什么(4.4%)]                                          │
│  累积:27.8% → 43.5% → 53.7% → 62.5% → 70.7% → 75.1%                      │
│  TopP = 0.9 → 截断到累积超过 90%,即保留所有                                  │
│  候选集 = {喜马拉雅, 珠峰, 泰山, 华山, <PAD>, 什么}                          │
│                                                                             │
│  Step 4:重新归一化 + 采样                                                   │
│  归一化:[31.1%, 17.6%, 11.4%, 9.9%, 9.2%, 4.9%]                          │
│  按概率采样 → 选中 "喜马拉雅"                                                 │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

7.2 不同场景的完整参数示例 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                      场景化采样参数组合                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【场景1:精确问答(需要确定性)】                                              │
│                                                                             │
│  response = client.chat.completions.create(                                 │
│      model="gpt-4",                                                        │
│      messages=[{"role": "user", "content": "1+1等于几?"}],                │
│      temperature=0.0,   # 最高确定性                                          │
│      top_p=1.0,        # 不截断                                               │
│      max_tokens=10,    # 简短回答                                             │
│      stop=["。", "?"], # 遇到标点停止                                        │
│  )                                                                          │
│                                                                             │
│  输出特点:每次几乎相同,稳定可靠                                              │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【场景2:代码生成(语法正确优先)】                                            │
│                                                                             │
│  response = client.chat.completions.create(                                 │
│      model="gpt-4",                                                        │
│      messages=[{"role": "user", "content": "写一个Python快排"}],            │
│      temperature=0.1,   # 极低随机性                                          │
│      top_p=0.95,       # 允许小范围变化                                       │
│      max_tokens=500,   # 足够长度                                            │
│      presence_penalty=0.0,  # 不强制新话题                                   │
│      frequency_penalty=0.0, # 不惩罚重复词                                   │
│  )                                                                          │
│                                                                             │
│  输出特点:代码标准、语法正确、风格一致                                        │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【场景3:创意写作(高多样性)】                                               │
│                                                                             │
│  response = client.chat.completions.create(                                 │
│      model="gpt-4",                                                        │
│      messages=[{"role": "user", "content": "写一个科幻故事开头"}],           │
│      temperature=1.0,   # 最大随机性                                          │
│      top_p=0.95,        # 考虑更多Token                                       │
│      max_tokens=1000,   # 足够长度                                           │
│      presence_penalty=0.3,   # 鼓励新话题                                    │
│      frequency_penalty=0.5,   # 轻微惩罚重复                                  │
│  )                                                                          │
│                                                                             │
│  输出特点:每次不同,有创意惊喜                                                │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  【场景4:角色扮演(平衡)】                                                    │
│                                                                             │
│  response = client.chat.completions.create(                                 │
│      model="gpt-4",                                                        │
│      messages=[                                                            │
│          {"role": "system", "content": "你是一个古风诗人,说话文雅"}],       │
│          {"role": "user", "content": "请作一首诗"}],                        │
│      temperature=0.8,   # 有个性但不极端                                      │
│      top_p=0.9,        # 标准核采样                                          │
│      max_tokens=300,                                                   │
│      repetition_penalty=1.1,  # 防止诗句重复                                 │
│  )                                                                          │
│                                                                             │
│  输出特点:符合角色、风格统一、有适度变化                                      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

第8章:推理中的常见问题与解决 ​

8.1 重复生成(Repetition Loop) ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         重复生成问题                                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  问题现象:                                                                  │
│  "人工智能是...人工智能是...人工智能是..."                                    │
│  "猫和狗的关系...猫和狗的关系...猫和狗的关系..."                              │
│                                                                             │
│  根本原因:                                                                  │
│  - 模型在某个概率分布上"卡住"                                                │
│  - 高概率词被反复选中                                                        │
│                                                                             │
│  解决方案:                                                                  │
│                                                                             │
│  1. Repetition Penalty                                                      │
│     对已出现的 Token 降低其概率                                               │
│     P'(x) = P(x) / penalty  (penalty > 1)                                │
│                                                                             │
│  2. Presence Penalty                                                         │
│     出现过的 Token 统一降低固定值                                             │
│     P'(x) = P(x) - α  if x appeared before                                │
│                                                                             │
│  3. Frequency Penalty                                                       │
│     出现次数越多,惩罚越重                                                   │
│     P'(x) = P(x) / (penalty ^ count(x))                                    │
│                                                                             │
│  4. Early Stopping + 检测循环                                                │
│     检测到连续 N 个相同 Token 时停止                                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

8.2 截断与长度控制 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         长度控制策略                                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  方案1:Max Tokens(硬限制)                                                  │
│  - 设置 max_tokens = 500                                                     │
│  - 无论内容是否完整,达到上限就停止                                           │
│  - 简单但可能截断完整回答                                                    │
│                                                                             │
│  方案2:Stop Sequences(软限制)                                              │
│  - 设置 stop = ["\n\n", "## 参考", "如有疑问请追问"]                         │
│  - 遇到指定序列立即停止                                                      │
│  - 更精确的长度控制                                                         │
│                                                                             │
│  方案3:EOS 检测 + 特殊 Prompt                                               │
│  - Prompt 中要求"用三句话回答"                                               │
│  - 模型自发生成 <EOS>                                                       │
│  - 更自然,但不可靠                                                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

8.3 上下文溢出 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                         上下文溢出处理                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  问题:Prompt + 对话历史 + 生成的 Token > 上下文窗口                           │
│                                                                             │
│  解决方案:                                                                  │
│                                                                             │
│  1. 截断早期对话(简单但丢失信息)                                            │
│     - 保留最近 N 个 Token                                                     │
│     - 早期上下文被遗忘                                                       │
│                                                                             │
│  2. 摘要压缩(平衡)                                                         │
│     - 定期将早期对话摘要成一段话                                              │
│     - 用摘要替代原始历史                                                     │
│                                                                             │
│  3. RAG(检索增强)                                                          │
│     - 将外部知识存入向量数据库                                                │
│     - 按需检索相关内容注入 Prompt                                             │
│     - 不依赖模型记忆                                                         │
│                                                                             │
│  4. 调整 Prompt 设计(根本)                                                 │
│     - 精简 System Prompt                                                    │
│     - 移除冗余的对话历史                                                      │
│     - 减少 Token 开销                                                        │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

核心总结 ​

总结1:推理的本质 ​

推理 = 自回归生成 = "给定前文,预测下一个词" 的循环

训练教会模型如何预测
推理让模型实际执行预测
1
2
3
4

总结2:关键机制 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        推理关键机制速查                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Masked Attention → 防止"看到未来",保证自回归的正确性                       │
│  KV Cache          → 避免重复计算,将 O(N²) 降为 O(N)                       │
│  解码策略          → 控制输出的确定性/多样性                                  │
│  位置编码          → 保持词序信息(Attention 本身无序)                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10

总结3:训练 vs 推理对比 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                     训练 vs 推理 终极对比                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│                        训练                    推理                           │
│  ─────────────────────────────────────────────────────────────────────────  │
│  目标:              学习权重                应用模型生成                     │
│  方式:              并行(Teacher Forcing) 自回归(逐Token)                │
│  优化:              Cross-Entropy Loss      无优化(直接采样)              │
│  计算量:            固定(序列长度)         线性增长(输出长度)             │
│  核心机制:          梯度下降                解码策略                        │
│  硬件需求:          GPU显存(存激活值)      GPU显存(存KV Cache)           │
│  确定性:            N/A                     可控(由T/p/k决定)             │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

章节测试 ​

测试1:自回归生成 ​

为什么推理阶段不能像训练阶段一样并行计算所有 Token?

测试2:KV Cache ​

KV Cache 主要缓存什么?它如何加速推理?

测试3:Masked Attention ​

Masked Attention 在推理中的作用是什么?如果不 Mask 会发生什么?

测试4:采样策略 ​

temperature=0, top_p=0.9 这个组合是否合理?为什么?

测试5:Prompt 角色 ​

System Prompt 在推理中是如何影响模型输出的?


参考答案 ​

测试1答案 ​

因为推理时下一个 Token 还不存在,必须先生成它才能预测下下个 Token。这是因果依赖关系,无法并行。但训练时"正确答案"已经在输入序列中了,所以可以并行处理。

测试2答案 ​

KV Cache 缓存所有历史 Token 的 Key 和 Value 向量。每次生成新 Token 时,只需计算新 Token 的 Q/K/V,然后与缓存的 K/V 做 Attention,避免重复计算旧位置的 K/V。

测试3答案 ​

Masked Attention 确保预测第 N 个词时只能看到位置 0~N-1,无法偷看位置 N 及之后的词。如果不 Mask,模型在训练时会"作弊"(直接看到答案),推理时虽然无法偷看(因为还没生成),但会导致训练-推理不一致(Train-Test Mismatch),严重影响模型质量。

测试4答案 ​

不合理。T=0 时 Softmax 的输出会变成 one-hot(只保留最高概率的词),此时 TopP 截断毫无意义,因为只剩一个候选。建议 T=0 时设 top_p=1.0,或 T=0.7 时设 top_p=0.9。

测试5答案 ​

System Prompt 作为对话序列的一部分,模型在预训练阶段就学习了"给定前文模式,续写符合语境的内容"。System Prompt 设定了角色、格式、风格等约束,模型在生成时会遵循这些隐式约束,因为它们是前文上下文的一部分。


相关笔记 ​

  • [[09 - Transformer训练阶段计算详解]] — 训练时的端到端计算过程
  • [[08 - Transformer核心原理]] — 架构层面的组件理解
  • [[03 - 解码策略]] — 从应用角度的参数调优
  • [[04 - 消息角色]] — Prompt 中的角色设计

学习状态:🟡 新建

最后更新于:

Pager
上一篇13. Transformer 训练阶段计算详解 - 手算每一行矩阵 / Transformer Training Computation Matrix by Matrix
下一篇15. 训练基础扫盲 - 理解 Fine-tune 在做什么 / A Training Primer for Understanding Fine-Tuning

持续记录,持续成长

Copyright © Tidenflow