GPT 转 Llama从教学版 GPT 走向现代 LLM 架构这个模块教你把 GPT 骨架逐步改造成 LlamaRMSNorm、RoPE、SwiGLU、GQA、现代 tokenizer、权重加载。1. GPT 和 Llama 的关系GPT 和 Llama 都是 decoder-only Transformer。它们的主干非常像token embedding - 多层 Transformer block - final norm - output head差异主要在 block 内部细节GPT: LayerNorm learned positional embedding GELU FFN MHA Llama: RMSNorm RoPE SwiGLU FFN GQA这些差异就是现代 LLM 架构演化的重点。2. 第一个变化LayerNorm - RMSNormGPT 主线里用的是 LayerNorm。Llama 用的是 RMSNorm。LayerNorm 会使用均值和方差(x - mean) / sqrt(var eps)RMSNorm 只用均方根x / sqrt(mean(x^2) eps)公式可以理解成RMSNorm 不减均值只按整体大小缩放。好处是计算更简单 训练效果通常也很好 现代 LLM 大量使用3. 第二个变化GELU FFN - SwiGLU FFNGPT 的 feed forward 通常是Linear - GELU - LinearLlama 使用 SwiGLUclassFeedForward(nn.Module):def__init__(self,cfg):super().__init__()self.fc1nn.Linear(cfg[emb_dim],cfg[hidden_dim],biasFalse)self.fc2nn.Linear(cfg[emb_dim],cfg[hidden_dim],biasFalse)self.fc3nn.Linear(cfg[hidden_dim],cfg[emb_dim],biasFalse)defforward(self,x):x_fc1self.fc1(x)x_fc2self.fc2(x)xnn.functional.silu(x_fc1)*x_fc2returnself.fc3(x)关键是这行nn.functional.silu(x_fc1)*x_fc2它是门控结构一路生成内容 一路控制哪些内容通过SwiGLU 是现代 LLM feed forward 的常见标配。4. 第三个变化绝对位置 embedding - RoPEGPT 主线里用了 learned positional embeddingtoken embedding position embeddingLlama 使用 RoPERotary Position Embedding。RoPE 不再把位置向量直接加到 token embedding 上而是在 attention 里旋转 query 和 key。代码路线是cos,sincompute_rope_params(...)queriesapply_rope(queries,cos,sin)keysapply_rope(keys,cos,sin)直觉理解RoPE 把位置信息编码进 Q/K 的角度关系里。这样 attention score 里天然带有相对位置信息。5. RoPE 的核心代码先预计算 cos/sindefcompute_rope_params(head_dim,theta_base10_000,context_length4096,freq_configNone):inv_freq1.0/(theta_base**(torch.arange(0,head_dim,2).float()/head_dim))positionstorch.arange(context_length)anglespositions.unsqueeze(1)*inv_freq.unsqueeze(0)anglestorch.cat([angles,angles],dim1)costorch.cos(angles)sintorch.sin(angles)returncos,sin再应用到 Q/Kdefapply_rope(x,cos,sin):x1x[...,:head_dim//2]x2x[...,head_dim//2:]rotatedtorch.cat((-x2,x1),dim-1)x_rotated(x*cos)(rotated*sin)returnx_rotated.to(dtypex.dtype)你不用一开始完全推导数学先记住RoPE 只作用在 attention 的 Q/K 上不作用在 V 上。6. 第四个变化MHA - GQALlama 3 开始更典型地使用 GQA。GQA 的核心是query heads 多 key/value groups 少 多个 query heads 共享 K/V在GroupedQueryAttention里self.W_querynn.Linear(d_in,d_out,biasFalse)self.W_keynn.Linear(d_in,num_kv_groups*head_dim,biasFalse)self.W_valuenn.Linear(d_in,num_kv_groups*head_dim,biasFalse)然后keyskeys.repeat_interleave(self.group_size,dim1)valuesvalues.repeat_interleave(self.group_size,dim1)这让 Llama 更省 KV cache 显存更适合长上下文推理。7. Llama TransformerBlock 的结构Llama block 仍然是norm - attention - residual norm - feed forward - residual示意shortcutx xself.norm1(x)xself.att(x,mask,cos,sin)xxshortcut shortcutx xself.norm2(x)xself.ff(x)xxshortcut这叫 pre-norm 结构。和 GPT 主线相比整体骨架没变变的是 norm、attention、FFN 的内部实现。8. Llama3Model 主体standalone-llama32.ipynb里的模型大致是classLlama3Model(nn.Module):def__init__(self,cfg):self.tok_embnn.Embedding(cfg[vocab_size],cfg[emb_dim])self.trf_blocksnn.ModuleList([TransformerBlock(cfg)for_inrange(cfg[n_layers])])self.final_normnn.RMSNorm(cfg[emb_dim])self.out_headnn.Linear(cfg[emb_dim],cfg[vocab_size],biasFalse)forward 里动态创建 causal maskmasktorch.triu(torch.ones(num_tokens,num_tokens,devicex.device,dtypetorch.bool),diagonal1)然后把x, mask, cos, sin传进每个 block。9. 为什么不预存巨大 maskLlama 3.1 / 3.2 支持很长上下文。如果预先创建128k x 128k causal mask内存会非常夸张。所以 notebook 里强调mask 可以 forward 时按实际num_tokens动态创建。这是从教学模型走向真实长上下文模型时非常重要的工程意识。10. Llama 2 - Llama 3 / 3.1 / 3.2这个目录里不是只讲 Llama 2。推荐路线是GPT - Llama 2 Llama 2 - Llama 3 Llama 3 - Llama 3.1 / 3.2变化主要包括tokenizer 改变。词表大小改变。上下文长度改变。RoPE 频率缩放策略改变。使用 GQA。模型配置不同。你可以把它看成“现代开源模型结构演进”的压缩课。11. 权重加载为什么重要主线章节训练的是小模型。这个 bonus 会加载 Meta / Hugging Face 上的预训练权重。这一步能帮助你理解从零实现模型结构 然后把官方权重映射到自己的 PyTorch 类里这是学习开源模型实现非常重要的能力。权重加载函数常见逻辑检查 shape 是否匹配 把外部权重复制到自己模型的参数里 处理命名差异12. 建议Llama 不是推翻 GPT而是在 GPT decoder-only 骨架上换成更现代的 norm、位置编码、FFN 和 attention 设计。