NLP 技术专栏 · 第五篇(收官)
前四篇我们逐层拆解了 Transformer 的架构、三种分支、注意力优化和对齐技术。这一篇把所有碎片拼在一起,以 LLaMa 为锚点,完整走一遍从原始 Transformer 到现代大模型的每一个关键改进。


一、Transformer vs LLaMa:改了什么?

先来一张总览图,标注出 LLaMa 相对原始 Transformer 的每一处改动:

原始 Transformer (2017)                    LLaMa (2023+)
──────────────────────────────────────────────────────────────────

Token Embedding                           Token Embedding (共享权重)
     │                                         │
Positional Encoding (Sin/Cos)             RoPE 旋转位置编码         ← 改动①
     │                                         │
     ▼                                         ▼
┌──────────────────────┐              ┌──────────────────────┐
│ Multi-Head Attention │              │ Grouped-Query Attn   │  ← 改动②
│ (MHA)                │              │ (GQA)                │
│                      │              │ + KV Cache           │
├──────────────────────┤              ├──────────────────────┤
│ Add & LayerNorm      │              │ RMSNorm              │  ← 改动③
│ (Post-Norm)          │              │ (Pre-Norm)           │  ← 改动④
├──────────────────────┤              ├──────────────────────┤
│ Feed-Forward Network │              │ SwiGLU FFN           │  ← 改动⑤
│ (ReLU 激活)          │              │                      │
├──────────────────────┤              ├──────────────────────┤
│ Add & LayerNorm      │              │ RMSNorm              │
│ (Post-Norm)          │              │ (Pre-Norm)           │
└──────────────────────┘              └──────────────────────┘
     × 6 层                                × 32/64/80 层       ← 改动⑥
     │                                         │
  Linear + Softmax                          Linear + Softmax
  (权重独立)                                (与 Embedding 共享)   ← 改动⑦

预训练: Next Token                        预训练: Next Token (1.4T tokens)
对齐: 无                                  对齐: SFT + RLHF/DPO   ← 改动⑧

接下来逐一拆解每一处改动。


二、改动①:RoPE 旋转位置编码

2.1 回顾:原始 Transformer 的位置编码

第一篇讲过,原始 Transformer 使用 sin/cos 函数生成固定的位置编码,直接加到词嵌入上:

x_final = TokenEmbed(x) + PosEnc(position)

问题:sin/cos 位置编码是加法形式,模型需要额外学习如何从"嵌入+位置"的混合向量中分离出位置信息。而且外推到训练时没见过的长度时效果差。

2.2 RoPE 的核心思想

RoPE = Rotary Position Embedding(旋转位置编码)

核心想法:不用加法注入位置信息,而是通过旋转 Q 和 K 向量,让点积自然地包含相对位置信息。

直觉:把向量看作复平面上的一个点

  位置 0 的向量: (x₁, x₂, x₃, x₄, x₅, x₆, ...)
  位置 m 的向量: 原始向量旋转 mθ 角度

  两个向量的点积 = cos((m-n)θ) × |向量₁| × |向量₂|

  → 点积只和相对位置差 (m-n) 有关,和绝对位置无关!

2.3 数学表达

对于 Q 和 K 向量的每一对相邻维度 (x_{2i}, x_{2i+1}):

旋转后:
  ┌ x'_{2i}   ┐   ┌ cos(mθ_i)  -sin(mθ_i) ┐ ┌ x_{2i}   ┐
  │           │ = │                         │ │          │
  └ x'_{2i+1} ┘   └ sin(mθ_i)   cos(mθ_i) ┘ └ x_{2i+1} ┘

其中:
  θ_i = 10000^(-2i/d)  (和原始 Transformer 的频率公式一样)
  m: 位置索引

关键: 这个旋转只作用于 Q 和 K,不作用于 V

计算 Q·K.T 时:
  Q_m 旋转了 mθ, K_n 旋转了 nθ
  Q_m · K_n = R(mθ)q · R(nθ)k = R((m-n)θ)q · k
  
  → 点积自动包含相对位置 (m-n) 的信息!

2.4 代码实现

def apply_rotary_embeddings(x, freqs_cos, freqs_sin):
    """
    x: (batch, heads, seq_len, d_k)
    freqs_cos, freqs_sin: (seq_len, d_k // 2)
    """
    # 将 x 拆分为两两一组
    x_r = x.float().reshape(*x.shape[:-1], -1, 2)  # (..., d_k/2, 2)
    x1, x2 = x_r[..., 0], x_r[..., 1]

    # 旋转
    out1 = x1 * freqs_cos - x2 * freqs_sin
    out2 = x1 * freqs_sin + x2 * freqs_cos

    # 拼回
    output = torch.stack([out1, out2], dim=-1).reshape(x.shape)
    return output.type_as(x)


def precompute_rope_frequencies(d_k, max_seq_len, base=10000.0):
    """预计算旋转角度的 cos 和 sin"""
    # θ_i = base^(-2i/d)
    freqs = 1.0 / (base ** (torch.arange(0, d_k, 2).float() / d_k))
    # 每个位置的角度
    positions = torch.arange(max_seq_len).float()
    angles = torch.outer(positions, freqs)  # (max_seq_len, d_k/2)

    return torch.cos(angles), torch.sin(angles)


# 在注意力计算中的使用
class AttentionWithRoPE(nn.Module):
    def forward(self, x, freqs_cos, freqs_sin):
        Q = self.W_Q(x)
        K = self.W_K(x)
        V = self.W_V(x)

        # 在计算注意力之前,对 Q 和 K 应用旋转
        Q = apply_rotary_embeddings(Q, freqs_cos, freqs_sin)
        K = apply_rotary_embeddings(K, freqs_cos, freqs_sin)

        # 正常的注意力计算
        scores = Q @ K.transpose(-2, -1) / math.sqrt(self.d_k)
        # ...

2.5 RoPE 的优势

对比          Sin/Cos 位置编码           RoPE
─────────────────────────────────────────────────────────
注入方式       加法                       乘法(旋转)
作用位置       加到嵌入上                 作用于 Q, K
相对位置       模型需要学习如何提取       点积天然包含相对位置
外推能力       差(超过训练长度效果骤降)  较好(可配合 NTK-aware 缩放)
实现位置       输入层                     每层注意力中

RoPE 的外推改进:
  原始 RoPE: 超出训练长度后效果下降
  NTK-aware Scaling: 调整 base 值,支持更长上下文
  YaRN: 进一步改进外推,支持 128K+ 上下文
  LLaMa 3.1: 使用调整后的 RoPE,支持 128K 上下文

三、改动②:Grouped-Query Attention (GQA)

第三篇详细讲过,这里简要回顾在 LLaMa 中的配置:

LLaMa-2 70B 的 GQA 配置:
  总 Q 头数: 64
  总 KV 头数: 8
  每组: 8 个 Q 头共享 1 组 KV
  KV Cache 节省: 8× (对比 MHA)

LLaMa-3 70B:
  同样使用 GQA (8 组)

为什么 LLaMa 选择 GQA 而非 MQA?
  GQA 是效果和效率的最佳平衡点
  MQA 信息损失较大,在 LLaMa 的规模下不划算

四、改动四、改动③④:RMSNorm + Pre-Norm

4.1 回顾:LayerNorm

原始 Transformer 使用 Layer Normalization:

LayerNorm(x) = (x - μ) / σ × γ + β

μ = mean(x),  σ = std(x)

需要计算均值和标准差两个统计量
有可学习的缩放 γ 和偏移 β

4.2 RMSNorm:更简单的归一化

RMSNorm = Root Mean Square Layer Normalization

RMSNorm(x) = x / RMS(x) × γ

RMS(x) = √(mean(x²))

和 LayerNorm 的区别:
  1. 不减均值: 没有 (x - μ) 这一步
  2. 不用标准差: 用 RMS(均方根)代替
  3. 可选去掉偏移 β: LLaMa 中没有 β

为什么有效?
  研究表明: 归一化的"缩放"效果比"平移"效果更重要
  减均值这一步对最终效果影响不大
  去掉后计算更快,尤其是在推理时
class RMSNorm(nn.Module):
    def __init__(self, dim, eps=1e-6):
        super().__init__()
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))  # γ

    def forward(self, x):
        # 计算 RMS
        rms = torch.sqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
        # 归一化 + 缩放
        return x / rms * self.weight

4.3 Pre-Norm vs Post-Norm

原始 Transformer (Post-Norm):          LLaMa (Pre-Norm):

  x → Attention → +x → LayerNorm      x → LayerNorm → Attention → +x
                  ↑                                               ↑
               残差连接                                         残差连接

  Post-Norm 的问题:
    残差连接的输出 = x + SubLayer(x)
    在深层网络中,x 和 SubLayer(x) 的量级可能差距很大
    导致训练不稳定

  Pre-Norm 的优势:
    SubLayer 的输入先归一化,输出量级可控
    残差连接更稳定
    支持更深的网络(LLaMa 有 32-80 层)

五、改动⑤:SwiGLU 前馈网络

5.1 回顾:原始 FFN

原始 Transformer:
  FFN(x) = ReLU(x·W₁ + b₁)·W₂ + b₂

  d_model = 512, d_ff = 2048 (4×)

5.2 SwiGLU 激活函数

SwiGLU = Swish + GLU(Gated Linear Unit)

GLU (门控线性单元):
  GLU(x, W, V, W₂) = (x·W ⊙ σ(x·V))·W₂
  
  其中 σ 是激活函数, ⊙ 是逐元素乘法

SwiGLU:
  SwiGLU(x) = (Swish(x·W₁) ⊙ x·W_gate)·W₂
  
  Swish(x) = x · sigmoid(x) = x / (1 + e^(-x))

展开:
  FFN_SwiGLU(x) = (x·W₁ ⊙ Swish(x·W_gate))·W₂

和原始 FFN 的区别:
  ┌─────────────────────────────────────────────────────┐
  │ 原始:  x → W₁ → ReLU → W₂ → 输出                     │
  │ SwiGLU: x → W₁ → Swish → ⊙ → W₂ → 输出              │
  │        x → W_gate ↗                                 │
  └─────────────────────────────────────────────────────┘

  SwiGLU 有两个矩阵 W₁ 和 W_gate
  通过门控机制,模型可以动态决定每个神经元的"开/关"

5.3 代码实现

class SwiGLU_FFN(nn.Module):
    def __init__(self, d_model, d_ff):
        super().__init__()
        self.w1 = nn.Linear(d_model, d_ff, bias=False)      # 主变换
        self.w_gate = nn.Linear(d_model, d_ff, bias=False)  # 门控
        self.w2 = nn.Linear(d_ff, d_model, bias=False)      # 输出

    def forward(self, x):
        return self.w2(
            F.silu(self.w1(x)) * self.w_gate(x)
            #   ↑ Swish 激活  逐元素相乘(门控)
        )

# F.silu 就是 Swish: x * sigmoid(x)

5.4 为什么 SwiGLU 效果更好?

参数效率的调整:

  原始 FFN:  d_ff = 4 × d_model   (两个矩阵: d→4d, 4d→d)
  SwiGLU:    d_ff = 8/3 × d_model (三个矩阵: d→8d/3, d→8d/3, 8d/3→d)
  
  参数量:
    原始: 2 × d × 4d = 8d²
    SwiGLU: d × 8d/3 + d × 8d/3 + 8d/3 × d = 8d²
  
  总参数量相同,但 SwiGLU 有更好的表达能力

  为什么更好:
  1. 门控机制让网络可以"选择性地"激活信息
  2. Swish 比 ReLU 更平滑(在 0 点可导),梯度更好
  3. 实验表明 SwiGLU 在各种规模上都优于 ReLU FFN

六、改动⑥⑦:架构比例与权重共享

6.1 更深更窄的架构

原始 Transformer Base:
  d_model = 512, num_layers = 6, num_heads = 8
  参数量: ~65M

LLaMa-7B:
  d_model = 4096, num_layers = 32, num_heads = 32
  参数量: ~7B

LLaMa-70B:
  d_model = 8192, num_layers = 80, num_heads = 64
  参数量: ~70B

趋势: 层数大幅增加 (6 → 32/80)
      维度适中增加 (512 → 4096/8192)
      更深比更宽更有效

6.2 Embedding 与输出层权重共享

LLaMa 中:
  输入 Embedding 矩阵: (vocab_size, d_model)
  输出 Linear 层:      (d_model, vocab_size)
  
  两者共享同一组权重!
  输出 Linear 的权重 = Embedding 矩阵的转置

  好处:
  1. 减少参数量 (vocab_size × d_model 个参数)
  2. 输入和输出的表示空间一致
  3. 尤其在大词表时效果明显

  LLaMa-2 词表大小: 32000, d_model = 4096
  节省参数: 32000 × 4096 = 131M 参数

七、LLaMa 1/2/3 的演进

7.1 LLaMa-1 (2023.02)

Meta 的第一代开源大模型,"改变了一切":

  规模: 7B / 13B / 33B / 65B
  训练数据: 1.4T tokens (公开数据集)
  架构: Pre-Norm + RoPE + SwiGLU + 标准 MHA (7B/13B)
  
  影响:
  - 证明了开源模型可以接近 ChatGPT 水平
  - 1.4T tokens 的训练量远超当时的共识(之前认为 Chinchilla 最优量是 20× 参数量)
  - 引爆了开源社区的 LLM 浪潮

7.2 LLaMa-2 (2023.07)

关键升级:

  架构变化:
  ├── 7B/13B: 标准 MHA → 和 LLaMa-1 相同
  ├── 34B/70B: 引入 GQA (8 组)
  └── 上下文长度: 2048 → 4096

  训练数据: 2T tokens (比 v1 多 40%)
  
  最大变化: 基座模型 + Chat 模型同时开源
  ├── 基座模型: 预训练权重
  └── Chat 模型: 经过 SFT + RLHF 对齐

  对齐流程:
  SFT: ~27,540 条高质量标注数据
  RLHF: ~1,000,000 条人类比较数据
  
  安全措施: 拒绝训练(教模型拒绝有害请求)

7.3 LLaMa-3 / 3.1 (2024)

再一次大幅提升:

  架构:
  ├── 所有规模都使用 GQA
  ├── 词表: 32K → 128K (更高效的分词)
  ├── 上下文: 4096 → 8192 (3), 128K (3.1)
  └── 规模: 8B / 70B / 405B

  训练数据: 15T+ tokens (LLaMa-2 的 7.5 倍!)
  
  Scaling Law 的实践:
  ├── 数据量: 大幅增加 (1.4T → 2T → 15T+)
  ├── 计算量: 按 Chinchilla 最优比例扩展
  └── 效果: 8B 的 LLaMa-3 ≈ 70B 的 LLaMa-2

  关键改进:
  ├── 更高效的分词器 (128K 词表,多语言更好)
  ├── 改进的 RoPE (支持 128K 外推)
  └── 更好的对齐数据和流程

7.4 演进数据一览

┌──────────┬───────┬──────────┬───────────┬────────┬─────────────┐
│ 模型     │ 参数量 │ 训练数据  │ 上下文长度 │ 词表    │ 注意力        │
├──────────┼───────┼──────────┼───────────┼────────┼─────────────┤
│ LLaMa-1  │ 7-65B │ 1.4T     │ 2048      │ 32K    │ MHA         │
│ LLaMa-2  │ 7-70B │ 2T       │ 4096      │ 32K    │ MHA/GQA     │
│ LLaMa-3  │ 8-70B │ 15T+     │ 8192      │ 128K   │ GQA         │
│ LLaMa-3.1│ 8-405B│ 15T+     │ 128K      │ 128K   │ GQA         │
└──────────┴───────┴──────────┴───────────┴────────┴─────────────┘

趋势: 数据量 >> 一切。LLaMa 系列的秘诀就是"用远超最优量的数据训练"

八、LLaMa 的完整配置代码

把所有改动整合起来:

import torch
import torch.nn as nn
import torch.nn.functional as F
import math
from dataclasses import dataclass


@dataclass
class LLaMaConfig:
    """LLaMa 模型配置"""
    vocab_size: int = 32000
    d_model: int = 4096        # hidden_size
    num_layers: int = 32
    num_heads: int = 32        # Q 的头数
    num_kv_heads: int = 32     # KV 的头数 (等于 num_heads 时为 MHA, 小于时为 GQA)
    d_ff: int = 11008          # SwiGLU 的中间维度 (~8/3 × d_model)
    max_seq_len: int = 4096
    rope_base: float = 10000.0
    rms_eps: float = 1e-6


class RMSNorm(nn.Module):
    def __init__(self, dim, eps=1e-6):
        super().__init__()
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))

    def forward(self, x):
        rms = torch.sqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
        return x / rms * self.weight


class RotaryEmbedding(nn.Module):
    def __init__(self, d_k, max_seq_len, base=10000.0):
        super().__init__()
        freqs = 1.0 / (base ** (torch.arange(0, d_k, 2).float() / d_k))
        positions = torch.arange(max_seq_len).float()
        angles = torch.outer(positions, freqs)

        self.register_buffer('cos_cached', torch.cos(angles))
        self.register_buffer('sin_cached', torch.sin(angles))

    def forward(self, seq_len):
        return self.cos_cached[:seq_len], self.sin_cached[:seq_len]


def apply_rope(x, cos, sin):
    """对 (batch, heads, seq, d_k) 的张量应用旋转位置编码"""
    d = x.shape[-1]
    x_r = x.float().reshape(*x.shape[:-1], d // 2, 2)
    x1, x2 = x_r[..., 0], x_r[..., 1]

    cos = cos.unsqueeze(0).unsqueeze(0)  # (1, 1, seq, d_k/2)
    sin = sin.unsqueeze(0).unsqueeze(0)

    out1 = x1 * cos - x2 * sin
    out2 = x1 * sin + x2 * cos
    return torch.stack([out1, out2], dim=-1).reshape(x.shape).type_as(x)


class GroupedQueryAttention(nn.Module):
    """GQA 注意力层"""
    def __init__(self, config: LLaMaConfig):
        super().__init__()
        assert config.num_heads % config.num_kv_heads == 0

        self.num_heads = config.num_heads
        self.num_kv_heads = config.num_kv_heads
        self.num_groups = config.num_heads // config.num_kv_heads
        self.d_k = config.d_model // config.num_heads

        self.W_Q = nn.Linear(config.d_model, config.num_heads * self.d_k, bias=False)
        self.W_K = nn.Linear(config.d_model, config.num_kv_heads * self.d_k, bias=False)
        self.W_V = nn.Linear(config.d_model, config.num_kv_heads * self.d_k, bias=False)
        self.W_O = nn.Linear(config.num_heads * self.d_k, config.d_model, bias=False)

    def forward(self, x, cos, sin, mask=None):
        B, S, _ = x.shape

        Q = self.W_Q(x).view(B, S, self.num_heads, self.d_k).transpose(1, 2)
        K = self.W_K(x).view(B, S, self.num_kv_heads, self.d_k).transpose(1, 2)
        V = self.W_V(x).view(B, S, self.num_kv_heads, self.d_k).transpose(1, 2)

        # RoPE (只作用于 Q, K)
        Q = apply_rope(Q, cos, sin)
        K = apply_rope(K, cos, sin)

        # GQA: KV 头重复到 Q 头数
        if self.num_groups > 1:
            K = K.repeat_interleave(self.num_groups, dim=1)
            V = V.repeat_interleave(self.num_groups, dim=1)

        # Flash Attention (PyTorch 2.0+ 原生支持)
        output = F.scaled_dot_product_attention(Q, K, V, attn_mask=mask)

        output = output.transpose(1, 2).contiguous().view(B, S, -1)
        return self.W_O(output)


class SwiGLU_FFN(nn.Module):
    """SwiGLU 前馈网络"""
    def __init__(self, config: LLaMaConfig):
        super().__init__()
        self.w1 = nn.Linear(config.d_model, config.d_ff, bias=False)
        self.w_gate = nn.Linear(config.d_model, config.d_ff, bias=False)
        self.w2 = nn.Linear(config.d_ff, config.d_model, bias=False)

    def forward(self, x):
        return self.w2(F.silu(self.w1(x)) * self.w_gate(x))


class LLaMaBlock(nn.Module):
    """LLaMa 的一个 Transformer 层 (Pre-Norm + GQA + SwiGLU)"""
    def __init__(self, config: LLaMaConfig):
        super().__init__()
        self.attn_norm = RMSNorm(config.d_model, config.rms_eps)
        self.attn = GroupedQueryAttention(config)
        self.ffn_norm = RMSNorm(config.d_model, config.rms_eps)
        self.ffn = SwiGLU_FFN(config)

    def forward(self, x, cos, sin, mask=None):
        # Pre-Norm + 残差
        x = x + self.attn(self.attn_norm(x), cos, sin, mask)
        x = x + self.ffn(self.ffn_norm(x))
        return x


class LLaMa(nn.Module):
    """完整的 LLaMa 模型"""
    def __init__(self, config: LLaMaConfig):
        super().__init__()
        self.config = config

        # Embedding (输出层共享权重)
        self.embed = nn.Embedding(config.vocab_size, config.d_model)

        # RoPE (预计算,注册为 buffer)
        d_k = config.d_model // config.num_heads
        self.rope = RotaryEmbedding(d_k, config.max_seq_len, config.rope_base)

        # Transformer 层
        self.layers = nn.ModuleList([
            LLaMaBlock(config) for _ in range(config.num_layers)
        ])

        # 最终归一化
        self.norm = RMSNorm(config.d_model, config.rms_eps)

        # 输出层 (与 Embedding 共享权重)
        self.output = nn.Linear(config.d_model, config.vocab_size, bias=False)
        self.output.weight = self.embed.weight  # 权重共享

    def forward(self, token_ids, mask=None):
        B, S = token_ids.shape

        # Embedding
        x = self.embed(token_ids)

        # RoPE 频率
        cos, sin = self.rope(S)

        # 因果掩码 (如果没提供)
        if mask is None:
            mask = torch.tril(torch.ones(S, S, device=x.device))
            mask = mask.masked_fill(mask == 0, float('-inf'))
            mask = mask.unsqueeze(0).unsqueeze(0)

        # 逐层前向
        for layer in self.layers:
            x = layer(x, cos, sin, mask)

        x = self.norm(x)
        logits = self.output(x)
        return logits


# 快速测试
config = LLaMaConfig(
    vocab_size=32000,
    d_model=4096,
    num_layers=32,
    num_heads=32,
    num_kv_heads=8,    # GQA: 4 组
    d_ff=11008,
    max_seq_len=4096,
)
model = LLaMa(config)

# 统计参数量
total_params = sum(p.numel() for p in model.parameters())
print(f"总参数量: {total_params / 1e9:.1f}B")  # ~7B

# 前向传播
x = torch.randint(0, 32000, (2, 128))  # batch=2, seq=128
logits = model(x)
print(logits.shape)  # torch.Size([2, 128, 32000])

九、完整技术栈总结

9.1 五篇专栏的知识图谱

第一篇: Transformer 基础
  │ Self-Attention, Multi-Head, FFN, 位置编码
  │
  ├──→ 第二篇: 三种分支
  │     │ Encoder-Only (BERT), Decoder-Only (GPT), Encoder-Decoder (T5)
  │     │
  │     └──→ 第四篇: 对齐技术
  │           │ SFT, RLHF, DPO, RLAIF
  │           │ 为什么 Decoder-Only 赢了
  │
  └──→ 第三篇: 注意力优化
        │ MQA, GQA, Flash Attention
        │
        └──→ 第五篇: LLaMa (本文)
              │ 把所有技术组装到一起
              │ RoPE, RMSNorm, SwiGLU, GQA
              │ LLaMa 1/2/3 演进

9.2 现代大模型的"标准配方"

┌─────────────────────────────────────────────────────────────┐
│  现代 Decoder-Only 大模型的典型配置                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  架构: Decoder-Only Transformer                             │
│  归一化: RMSNorm (Pre-Norm)                                 │
│  位置编码: RoPE                                             │
│  注意力: GQA (8 组) + Flash Attention                       │
│  FFN: SwiGLU                                                │
│  Embedding: 与输出层共享权重                                 │
│  上下文长度: 8K - 128K+                                     │
│  训练数据: 2T - 15T+ tokens                                 │
│  对齐: SFT + DPO/RLHF                                       │
│                                                             │
│  符合这个配方的模型:                                         │
│  LLaMa 2/3, Mistral, Qwen-2, Gemma, DeepSeek-V2, ...      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

9.3 从 2017 到 2025:一张时间线

2017 ── Transformer (Attention Is All You Need)
  │    Encoder-Decoder, MHA, Sin/Cos 位置编码, ReLU FFN, Post-Norm
  │
2018 ── BERT / GPT-1
  │    预训练 + 微调范式确立
  │
2019 ── GPT-2 / T5 / RoBERTa
  │    MQA 提出, 更大的模型
  │
2020 ── GPT-3
  │    Few-shot, 涌现能力
  │
2021 ── Codex / 改进的预训练研究
  │    Chinchilla 最优缩放比例
  │
2022 ── ChatGPT / InstructGPT
  │    RLHF 对齐, Flash Attention v1
  │    Pre-Norm 成为标准
  │
2023 ── LLaMa 1/2 / GPT-4 / Mistral
  │    RoPE + SwiGLU + GQA 成为标准配方
  │    DPO 简化对齐, Flash Attention v2
  │    开源社区爆发
  │
2024 ── LLaMa 3 / Claude 3 / Gemini / DeepSeek-V2
  │    15T+ 训练数据, 128K 上下文
  │    MLA (低秩 KV), PagedAttention
  │    多模态融合
  │
2025 ── 持续演进...
         推理模型 (o1/o3), Agent 能力
         更长上下文, 更高效的架构

参考文献

  • Touvron, H., et al. (2023). LLaMA: Open and Efficient Foundation Language Models. Meta.
  • Touvron, H., et al. (2023). LLaMA 2: Open Foundation and Fine-Tuned Chat Models. Meta.
  • Grattafiori, A., et al. (2024). The Llama 3 Herd of Models. Meta.
  • Su, J., et al. (2024). RoFormer: Enhanced Transformer with Rotary Position Embedding.
  • Zhang, B. & Sennrich, R. (2019). Root Mean Square Layer Normalization.
  • Shazeer, N. (2020). GLU Variants Improve Transformer.
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐