GPT 技术架构与源码分析
2026/9/3 15:28:35 网站建设 项目流程

GPT 技术架构与源码分析

一句话概括:GPT 不是 Transformer 架构的简单复用,而是一场以“Decoder-Only + 因果语言建模”为核心的生成式 AI 范式革命——它舍弃了 Transformer 的编码器-解码器对称结构,仅保留解码器部分,用“预测下一个词”这一极其简洁的训练目标,通过海量无标注文本的预训练+少量有标注数据的微调,回答了深度学习领域一个根本性的问题:如果模型能够通过阅读互联网上的所有文本学会“理解”语言,那我们还需要为每个任务单独标注数据吗?****

一、引言

如果你用过 Hugging Face 的 Transformers 库,你一定写过类似这样的代码:

fromtransformersimportGPT2LMHeadModel,GPT2Tokenizer model=GPT2LMHeadModel.from_pretrained("gpt2")tokenizer=GPT2Tokenizer.from_pretrained("gpt2")inputs=tokenizer("The future of AI is",return_tensors="pt")outputs=model.generate(**inputs,max_length=50)print(tokenizer.decode(outputs[0]))

几行代码,一个能生成连贯文本的语言模型就跑起来了。看起来很轻松,对吧?

但在 2018 年之前,事情远没有这么简单。如果你想做一个文本分类、机器翻译或问答系统,你几乎绕不开有监督学习——你需要为每个任务收集大量标注数据,然后训练一个专用于该任务的模型。你做一个情感分析模型,需要上万条标注了“正面/负面”的影评;你做一台机器翻译系统,需要百万级对齐的双语语料。每个任务都是独立的,每个任务都需要重新标注数据、重新训练模型。

你可能会问:为什么不能让模型先“读懂”语言,再针对具体任务做少量微调?

这正是 GPT(Generative Pre-trained Transformer)回答的问题。

2018 年,OpenAI 的 Alec Radford、Karthik Narasimhan、Tim Salimans 和 Ilya Sutskever 发表了论文《Improving Language Understanding by Generative Pre-Training》。论文的核心思想极其简洁:在大规模无标注文本上预训练一个语言模型(预测下一个词),然后在具体任务上用少量有标注数据进行微调

这个“预训练 + 微调”的范式,彻底改变了 NLP 的研究范式。GPT 的原始版本只有1.17 亿参数——在今天看来微不足道——但它证明了“无标注预训练”的有效性。

2019 年,GPT-2 将参数规模扩大到15 亿,展示了零样本迁移的惊人能力。2020 年,GPT-3 将规模推至1750 亿参数,展示了少样本学习(Few-shot Learning)的能力——你只需要在 Prompt 中给几个例子,模型就能学会执行新任务。2023 年,GPT-4 据估计达到1.8 万亿参数,采用MoE(混合专家)架构,并具备了多模态能力。

那么,这个“Decoder-Only + 因果语言建模”的架构到底长什么样?为什么只用“预测下一个词”就能让模型学会理解语言?GPT-2 和 GPT-3 的源码是如何实现的?我们从论文、开源实现和 Hugging Face Transformers 库出发,一步步拆解。

二、整体架构与设计哲学

2.1 架构总览:Decoder-Only Transformer

GPT 系列模型的核心架构是Decoder-Only Transformer——它只使用了原始 Transformer 架构中的解码器(Decoder)部分,并舍弃了编码器(Encoder)和交叉注意力(Cross-Attention)机制。

┌─────────────────────────────────────────────────────────────────────┐ │ GPT 模型架构(Decoder-Only) │ ├─────────────────────────────────────────────────────────────────────┤ │ 输入文本 → Tokenizer → Token IDs │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 嵌入层(Token Embedding + Positional Embedding) │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ Transformer Decoder 层(×N) │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ │ │ Masked Multi-Head Self-Attention(因果掩码) │ │ │ │ │ │ · 每个 token 只能看到它之前的 token │ │ │ │ │ │ · 不能“偷看”未来位置 │ │ │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ │ ↓ │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ │ │ Layer Normalization + Residual Connection │ │ │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ │ ↓ │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ │ │ Feed-Forward Network(位置独立的前馈网络) │ │ │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ │ ↓ │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ │ │ Layer Normalization + Residual Connection │ │ │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ LM Head → Softmax → 下一个 Token 的概率分布 │ │ │ └──────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

图:GPT 的 Decoder-Only 架构。与原始 Transformer 不同,GPT 只保留了解码器部分,并去掉了编码器-解码器交叉注意力。每个 Token 通过因果掩码(Causal Masking)只能看到自己和前面的 Token,确保了自回归生成的因果性。

与原始 Transformer 的关键区别

维度原始 TransformerGPT(Decoder-Only)
架构Encoder + Decoder仅 Decoder
注意力双向自注意力(Encoder)+ 掩码自注意力(Decoder)仅掩码自注意力
交叉注意力有(Decoder 关注 Encoder 输出)
训练目标Seq2Seq(翻译等)因果语言建模(预测下一个词)
适用任务序列到序列文本生成、理解、对话

为什么舍弃 Encoder?因为 GPT 的目标不是“理解输入序列并生成输出序列”(如翻译),而是“根据已有文本预测下一个词”——这是一个纯粹的自回归生成任务,不需要双向编码上下文。

2.2 设计哲学:预训练 + 微调

GPT 的设计围绕一个核心判断展开:与其为每个 NLP 任务单独训练模型,不如先让模型在大规模无标注文本上学会“理解”语言,再针对具体任务做少量微调

这个“预训练 + 微调”范式包含两个阶段:

阶段一:无监督预训练(Unsupervised Pre-training)

在大规模无标注文本语料上,训练模型预测下一个词。训练目标是最小化负对数似然:

L1(U)=∑ilog⁡P(ui∣ui−k,...,ui−1;Θ)L_1(U) = \sum_i \log P(u_i | u_{i-k}, ..., u_{i-1}; \Theta)L1(U)=ilogP(uiuik,...,ui1;Θ)

其中kkk是上下文窗口大小,Θ\ThetaΘ是模型参数。模型通过这个任务学习语言的统计规律——词与词之间的共现关系、语法结构、语义关联,甚至一定程度上的世界知识。

阶段二:有监督微调(Supervised Fine-tuning)

在预训练完成后,将模型参数作为初始值,在具体任务(如文本分类、自然语言推理、问答)的有标注数据上进行微调。微调时,模型的输出层会根据任务进行调整,但主体参数只做小幅更新。

这种设计的核心洞察是:预训练阶段让模型获得了通用的语言理解能力,微调阶段只需要教会模型“如何把这种理解应用到具体任务上”。因此,微调所需的有标注数据远少于从头训练一个模型。

2.3 模型规模演进

GPT 系列模型的参数规模经历了指数级增长:

模型发布时间参数量层数隐藏维度注意力头数上下文长度
GPT-12018 年 6 月1.17 亿1276812512
GPT-22019 年 2 月15 亿4816001024
GPT-32020 年 5 月1750 亿9612288962048
GPT-42023 年 3 月~1.8 万亿12032K+

GPT-2 相比 GPT-1 的规模提升主要体现在层数和隐藏维度上——从 12 层 768 维扩展到 48 层 1600 维。GPT-3 则进一步扩大到 96 层、12288 维隐藏层。

GPT-4 的参数量据估计在1.8 万亿左右,分布在120 层中。值得注意的是,GPT-4 的架构从稠密 Transformer 转向了MoE(Mixture of Experts,混合专家)架构——包含16 个专家(Experts),每个专家约1110 亿参数。在推理时,每个 Token 只会被路由到部分专家,而非激活全部参数——这大幅降低了推理成本。

三、核心抽象与源码解析

3.1 Token Embedding + Positional Embedding——把文本变成数字

GPT 处理文本的第一步是将原始文本转换为数值表示,包含两个层次:

Token Embedding(词元嵌入):将每个 Token(词或子词)映射为一个固定维度的向量。GPT 使用BPE(Byte Pair Encoding)分词器——将罕见词拆分为更常见的子词单元,既控制了词表大小,又能处理未登录词。

Positional Embedding(位置嵌入):由于 Transformer 本身不包含顺序信息,需要显式注入位置编码。GPT-1/2 使用可学习的位置嵌入(Learned Positional Embedding),而非原始 Transformer 的正弦编码。

# 文件路径:mingpt/model.py(minGPT 实现,结构示意)# 来源:github.com/karpathy/minGPTclassGPT(nn.Module):def__init__(self,config):super().__init__()# Token Embedding:将 token id 映射为向量self.tok_emb=nn.Embedding(config.vocab_size,config.n_embd)# Position Embedding:可学习的位置编码self.pos_emb=nn.Parameter(torch.zeros(1,config.block_size,config.n_embd))# Dropoutself.drop=nn.Dropout(config.embd_pdrop)# Transformer Decoder 层堆叠self.blocks=nn.Sequential(*[Block(config)for_inrange(config.n_layer)])# Layer Normalization(GPT-2 采用 Pre-LN 结构)self.ln_f=nn.LayerNorm(config.n_embd)# LM Head:将隐藏状态映射回词表概率分布self.lm_head=nn.Linear(config.n_embd,config.vocab_size,bias=False)

这段代码实现了什么?输入是一串 Token ID(整数序列),经过tok_emb变成向量序列,加上pos_emb注入位置信息,然后送入 Transformer 层堆叠处理。

设计模式解读:这是工厂模式(Factory Pattern)的体现——GPT类像一个工厂,将 Token Embedding、Position Embedding、Transformer Blocks、Layer Norm 和 LM Head 组装成一个完整的语言模型。

3.2 Causal Self-Attention——因果掩码的核心

因果自注意力(Causal Self-Attention)是 GPT 与原始 Transformer 自注意力的本质区别——它通过一个上三角掩码矩阵确保每个 Token 只能看到自己和之前的位置,而不能“偷看”未来。

# 文件路径:mingpt/model.py(minGPT 实现,结构示意)classCausalSelfAttention(nn.Module):def__init__(self,config):super().__init__()# 将 Q、K、V 放在一个线性层中self.c_attn=nn.Linear(config.n_embd,3*config.n_embd)# 输出投影self.c_proj=nn.Linear(config.n_embd,config.n_embd)# 因果掩码(上三角矩阵)self.register_buffer("bias",torch.tril(torch.ones(config.block_size,config.block_size)).view(1,1,config.block_size,config.block_size))defforward(self,x):B,T,C=x.size()# batch, sequence length, embedding dimension# 1. 计算 Q、K、Vqkv=self.c_attn(x)# (B, T, 3 * C)q,k,v=qkv.split(self.n_embd,dim=2)# 2. 计算注意力分数att=(q @ k.transpose(-2,-1))*(1.0/math.sqrt(k.size(-1)))# 3. ★ 应用因果掩码——将未来位置的分数设为 -infatt=att.masked_fill(self.bias[:,:,:T,:T]==0,float('-inf'))# 4. Softmax 得到注意力权重att=F.softmax(att,dim=-1)# 5. 加权求和y=att @ vreturny

这段代码实现了什么?自注意力机制的核心是让序列中的每个位置“关注”其他位置。在 GPT 中,通过masked_fill将上三角(未来位置)的注意力分数设为-inf,使得每个 Token 在计算注意力时只能看到自己和之前的 Token。

设计模式解读:这是模板方法模式(Template Method Pattern)的体现——自注意力的计算流程(QKV 投影 → 注意力分数 → 掩码 → Softmax → 加权求和)是固定的,但掩码策略(因果 vs 双向)可以替换。

设计权衡分析

  • 收益:① 因果掩码保证了自回归生成的因果性——生成第 t 个 Token 时只能依赖前 t-1 个 Token;② 在训练时可以进行 Teacher Forcing——所有位置的预测可以并行计算,大幅提升训练效率。
  • 代价:① 因果掩码意味着每个 Token 的视野受限,无法利用未来的上下文信息;② 对超长序列(如 10K+ tokens),O(n²) 的注意力计算仍然是瓶颈。
  • 适用场景:因此,Decoder-Only + Causal Attention 是自回归文本生成的标准范式——GPT、GPT-2、GPT-3、GPT-4 以及所有主流大语言模型(LLaMA、Claude、DeepSeek 等)都采用这一设计。

3.3 Transformer Block——堆叠出深度理解

GPT 的每一层 Transformer Block 包含两个子层:掩码多头自注意力前馈网络(FFN),每个子层都配有残差连接和层归一化。

GPT-2 相比 GPT-1 的一个关键架构变化是Layer Norm 前置(Pre-LN)

# 文件路径:mingpt/model.py(minGPT 实现,结构示意)classBlock(nn.Module):def__init__(self,config):super().__init__()# Pre-LN:Layer Norm 放在 Attention 和 FFN 之前self.ln1=nn.LayerNorm(config.n_embd)self.attn=CausalSelfAttention(config)self.ln2=nn.LayerNorm(config.n_embd)self.mlp=MLP(config)defforward(self,x):# Pre-LN + 残差连接x=x+self.attn(self.ln1(x))x=x+self.mlp(self.ln2(x))returnx

Pre-LN vs Post-LN:原始 Transformer 采用 Post-LN(Layer Norm 在子层之后),而 GPT-2 开始采用 Pre-LN(Layer Norm 在子层之前)。Pre-LN 的优势在于训练更稳定——梯度可以直接通过残差连接传播,避免了深层网络中梯度消失的问题。

3.4 minGPT:300 行的 GPT 教学实现

minGPT 是 Andrej Karpathy 开发的最小化 GPT 实现,旨在用最简洁的代码展示 GPT 的核心机制。

整个库只有三个核心文件:

mingpt/ ├── model.py # ★ Transformer 模型定义(~300 行) ├── bpe.py # BPE 分词器实现 └── trainer.py # 训练循环(PyTorch 模板代码)

model.py的核心结构:

classGPT(nn.Module):"""300 行代码实现的 GPT 语言模型"""# 包含:Token Embedding、Position Embedding、# Transformer Block 堆叠、Layer Norm、LM Head

设计模式解读:minGPT 是教学型实现(Educational Implementation)的典范——它的目标不是性能最优,而是可读性最优。300 行代码覆盖了 GPT 的所有核心组件,让学习者能够快速理解“一个语言模型到底是怎么工作的”。

3.5 nanoGPT:生产级的 GPT 实现

nanoGPT 是 Karpathy 对 minGPT 的重写版本,定位从“教学”转向“实用”。

核心特征:

  • model.py300 行train.py300 行
  • 8×A100 40GB节点上约4 天可复现 GPT-2 (124M)
  • 可选的GPT-2 权重加载,支持从 OpenAI 的预训练权重继续微调
  • 支持混合精度训练分布式训练等生产级特性

nanoGPT 的设计哲学是“简洁但实用”——代码足够简单,任何人都可以按需修改;同时足够强大,可以在真实硬件上训练出可用的模型。

3.6 MiniGPT:从第一性原理重建 GPT

2026 年 5 月,一篇题为《MiniGPT: Rebuilding GPT from First Principles》的论文正式发表。MiniGPT 是一个从零开始、在单个 Notebook 中实现的 GPT,旨在从第一性原理重建 GPT 的核心 pipeline。

MiniGPT 实现的完整组件包括:

  • Token 嵌入和位置嵌入
  • 因果多头自注意力
  • Pre-LayerNorm Transformer Block
  • 残差连接
  • 前馈 MLP 层
  • 下一个 Token 的交叉熵训练(Teacher Forcing)
  • 验证跟踪和检查点选择
  • 自回归文本生成

性能数据

  • 0.83M 参数的基线模型在 Tiny Shakespeare 数据集上训练 3000 步后,验证损失达到1.7236
  • 10.77M 参数的更强配置,验证损失达到1.4780,能够生成可识别的莎士比亚风格对话

MiniGPT 的意义在于:它证明了 GPT 的核心思想可以用极少的代码、在单个 Notebook 中完整复现。这对于教育者和研究者理解 GPT 的内部机制具有重要价值。

四、推理过程:从概率分布到文本

4.1 生成策略——解码的艺术

模型前向传播输出的只是概率分布(Logits),如何将这些概率转化为流畅的文本,是解码策略的核心。

Hugging Face Transformers 库的model.generate()方法封装了完整的解码流程:

输入 Prompt → Tokenizer → input_ids ↓ model.generate() 循环: ├── 前向传播 → Logits ├── 应用解码策略(Greedy / Beam Search / Sampling / Top-k / Top-p) ├── 选择下一个 Token ├── 将 Token 追加到序列 └── 判断是否满足停止条件(达到 max_length / 遇到 EOS) ↓ 输出 Token IDs → Tokenizer.decode() → 文本

常见解码策略

策略原理特点
Greedy Decoding每步选择概率最高的 Token最快,但容易陷入重复
Beam Search维护 K 条候选序列质量更高,但计算量大
Top-k Sampling从概率最高的 k 个 Token 中采样平衡多样性和质量
Top-p (Nucleus) Sampling从累积概率达到 p 的最小集合中采样动态调整候选集大小
Temperature Scaling调整概率分布的“尖锐度”控制生成的随机性

在 Transformers 库中,通过model.generate()的参数控制解码策略:

outputs=model.generate(input_ids,max_length=100,do_sample=True,# 启用采样temperature=0.8,# 温度参数top_k=50,# Top-k 采样top_p=0.95,# Top-p (Nucleus) 采样)

4.2 Pipeline 的数据流

当你使用 Hugging Face 的 Pipeline 接口时,数据经历了完整的生命周期:

  1. Preprocess(预处理):文本被 Tokenizer 转换为input_idsattention_mask
  2. Forward(前向传播):模型执行generate()
  3. Postprocess(后处理):Token IDs 被解码为文本
fromtransformersimportpipeline generator=pipeline('text-generation',model='gpt2')result=generator("I like eating fried",max_length=20)

在这个 Pipeline 内部:

  • input_ids的形状是(1, 4),对应输入"I like eating fried"的 4 个 Token
  • 模型逐 Token 生成,每步将新 Token 追加到序列中
  • 最终输出被解码为完整文本

五、工程化实践

理论说完了,接下来聊聊实战——用 GPT 类模型搭建应用时,你最关心的几个问题。

5.1 快速接入

使用 Hugging Face Transformers

fromtransformersimportGPT2LMHeadModel,GPT2Tokenizer# 加载预训练模型和分词器model=GPT2LMHeadModel.from_pretrained("gpt2")tokenizer=GPT2Tokenizer.from_pretrained("gpt2")# 文本生成inputs=tokenizer("The future of AI is",return_tensors="pt")outputs=model.generate(**inputs,max_length=50,do_sample=True)print(tokenizer.decode(outputs[0]))

使用 minGPT 从零训练

frommingpt.modelimportGPTfrommingpt.trainerimportTrainer# 配置模型(GPT-2 124M 版本)config=GPT.get_default_config()config.model_type='gpt2'config.vocab_size=50257config.block_size=1024model=GPT(config)# 训练trainer=Trainer(train_config,model,train_dataset)trainer.run()

使用 nanoGPT 训练

# 准备数据(以莎士比亚字符级为例)python data/shakespeare_char/prepare.py# 训练python train.py config/train_shakespeare_char.py# 生成文本python sample.py--out_dir=out-shakespeare-char

在单张 A100 GPU 上,上述莎士比亚字符级训练约需3 分钟

5.2 常见工程陷阱与解决方案

陷阱 1:OOM(显存不足)

现象:加载大模型或处理长序列时显存溢出。

解决方案

  • 使用更小的模型(如gpt2而不是gpt2-xl
  • 减小max_lengthbatch_size
  • 启用梯度检查点(Gradient Checkpointing)
  • 使用混合精度训练(FP16/BF16)
陷阱 2:生成文本重复

现象:模型陷入重复循环,不断输出相同的词或短语。

解决方案

  • 使用Repetition Penaltymodel.generate(..., repetition_penalty=1.2)
  • 调整解码策略:从 Greedy 改为 Top-k/Top-p Sampling
  • 增加temperature值(如 0.8-1.0)
陷阱 3:Tokenizer 不匹配

现象:加载预训练模型时,Tokenizer 的词表与模型不匹配。

解决方案:始终使用与模型配套的 Tokenizer:

# 正确做法tokenizer=AutoTokenizer.from_pretrained("gpt2")model=AutoModelForCausalLM.from_pretrained("gpt2")# 错误做法:混用不同模型的 Tokenizer# tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")# model = AutoModelForCausalLM.from_pretrained("gpt2") # ❌

六、总结与展望

6.1 关键版本里程碑

版本/事件时间参数量核心创新
GPT-1 论文发表2018 年 6 月1.17 亿预训练 + 微调范式
GPT-2 发布2019 年 2 月15 亿零样本迁移、Pre-LN
GPT-3 发布2020 年 5 月1750 亿少样本学习(In-Context Learning)
GPT-4 发布2023 年 3 月~1.8 万亿MoE 架构、多模态
GPT-52024 年持续迭代

6.2 设计哲学提炼

GPT 的设计哲学可以提炼为三个关键词:

  1. 预训练即基础:在大规模无标注文本上预训练语言模型,让模型先“读懂”语言

  2. 微调即适应:在具体任务上用少量标注数据进行微调,将通用能力转化为专项能力

  3. 规模即能力:随着模型参数、训练数据和计算资源的增长,模型能力持续涌现

6.3 核心架构亮点

亮点说明
Decoder-Only 架构舍弃 Encoder,仅保留 Decoder,专注自回归生成
因果掩码(Causal Masking)确保每个 Token 只能看到过去,不能看到未来
Pre-LN(Layer Norm 前置)训练更稳定,支持更深层的网络
BPE 分词平衡词表大小和未登录词处理
可学习位置嵌入相比正弦编码,更具灵活性
预训练 + 微调范式开创了 NLP 的新范式

6.4 对开发者的启示与适用场景

GPT 的本质不是一种“模型架构”,而是一种“学习范式”——用“预测下一个词”这个极其简单的训练目标,让模型从海量文本中自动学习语言的统计规律、语法结构、语义关联,甚至世界知识。它回答了一个根本性的问题:如果模型能够通过阅读互联网上的所有文本学会“理解”语言,那我们还需要为每个任务单独标注数据吗?GPT 的答案是:不需要。

适用场景

  • 文本生成:故事写作、邮件撰写、代码生成
  • 对话系统:聊天机器人、客服助手
  • 内容理解:文本分类、情感分析、命名实体识别(通过微调)
  • 代码辅助:代码补全、代码解释、Bug 修复

不适用场景

  • 推理延迟极度敏感的场景(自回归生成是顺序的,无法完全并行)
  • 输出确定性有极致要求的场景(采样引入随机性)
  • 超长序列(>10K tokens)的处理(O(n²) 注意力计算是瓶颈)

本文数据来源:OpenAI GPT 系列论文(Radford et al., 2018, 2019; Brown et al., 2020)、GPT-4 Technical Report(OpenAI, 2023)、minGPT 与 nanoGPT 开源实现、Hugging Face Transformers 文档、第三方技术解析(截至 2026 年 8 月)

如您所在的企业正面临数字化难题,或有 AI 落地、系统集成相关需求,欢迎进一步沟通。我们可提供针对贵企业具体场景的定制化方案和现场调研服务。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询