39-ChatGPT核心技术栈-Transformer到RLHF全流程
文章目录
【36.Python+AI】ChatGPT背后的核心技术栈:从Transformer到RLHF全流程拆解
📖 文章简介: 本文用一张图+逐层拆解的方式,讲清楚ChatGPT背后的完整技术栈。从最底层的Transformer自注意力机制讲起,串联Tokenization分词原理、预训练(Pre-training)的海量数据学习过程、监督微调(SFT)的指令跟随训练、再到RLHF(基于人类反馈的强化学习)如何让模型"对齐"人类偏好。文中配以Mermaid架构图贯穿全篇,每个阶段都附Python伪代码帮助建立直觉。适合刚接触大模型、想知道ChatGPT到底"怎么训练出来"的开发者。

🎬 个人主页: 源码骑士
❄ 专栏传送门: 《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"
导入语
上一篇文章你成功调用了GPT的API。模型聪明得不可思议,但脑子里肯定会冒出一个问题:这东西到底怎么训练出来的?
如果你去看原始的Transformer论文(Attention Is All You Need),九页纸的公式和架构图足够劝退大部分人。但一个残酷的事实是——面试官问你"ChatGPT的技术原理",你不能只说"它是一个大语言模型"。
这篇文章的目标:用一张Mermaid架构图串起ChatGPT从零到成品的三阶段训练流程,每个阶段都用Python伪代码帮你建立直觉。 不需要读论文,看完你就能跟面试官聊清楚:预训练学了什么、SFT做了什么、RLHF为什么是点睛之笔。
1 ~> 全景架构:一张图看透ChatGPT的训练管线
1.1 三阶段训练全景
1.2 三个阶段的类比
用教小孩写作文来类比:
阶段一(预训练):
├─ 让小孩读几亿本书(互联网文本)
├─ 不教他怎么写,就是让他"浸泡"在语言里
└─ 结果:他会续写句子,但你问他问题他不懂
阶段二(监督微调):
├─ 给他看几千篇"问题→标准答案"的范文
├─ 手把手教他"别人问这个,你要这样答"
└─ 结果:他会对话了,但回答有时不靠谱
阶段三(RLHF):
├─ 让小孩写了回答,找老师打分
├─ 分高的回答→奖励,分低的→惩罚
└─ 结果:他学会了"什么样的回答是人类喜欢的"
2 ~> 地基:Transformer的自注意力机制
2.1 为什么需要自注意力
传统的RNN处理句子是"一个词一个词地读",读到第100个词时,第1个词已经忘得差不多了。
Transformer的自注意力(Self-Attention)不一样——它让每个词都能"看到"句子里的所有其他词,并决定该关注谁。
句子:"昨天在图书馆看的那本书很有意思"
传统RNN:
├─ 读到"书"时,对"昨天"的记忆已经模糊了
Transformer自注意力:
├─ "书"和"图书馆"之间建立强关联(书在图书馆)
├─ "书"和"看"之间建立强关联(看书)
├─ "书"和"有意思"之间建立强关联(评价书)
└─ 每个词都和其他所有词计算"相关度分数"
2.2 自注意力的核心公式(用代码理解)
不用管数学符号,用Python伪代码来理解:
# 假设我们有一个句子,已经转成了向量
# sentence_vectors: shape = (seq_len=5, d_model=512)
# 5个词,每个词用512维向量表示
def self_attention(query, key, value):
"""
自注意力的本质:每个词去问其他所有词"你跟我有关吗?"
有关 → 权重高 → 你的信息我会更多吸收
无关 → 权重低 → 你的信息我忽略
"""
# Step 1: 计算"相关性分数"(点积)
# Q @ K^T: 每个词问其他所有词"我们有多相关?"
scores = query @ key.transpose() # (5, 5) — 5个词两两之间的分数
# Step 2: 缩放(防止分数太大导致梯度消失)
d_k = query.shape[-1]
scores = scores / (d_k ** 0.5)
# Step 3: Softmax → 把分数变成概率(权重),加起来=1
attention_weights = softmax(scores) # (5, 5)
# Step 4: 加权求和 → "按权重吸收其他词的信息"
output = attention_weights @ value # (5, 512)
return output
2.3 多头注意力
一个"头"只能从一个角度关注。多头注意力(Multi-Head Attention)= 多个自注意力并行,每个头关注不同的语言特征:
头1:关注"主语-谓语"关系
头2:关注"修饰语-被修饰语"关系
头3:关注"代词-指代对象"关系
...
头8:关注位置关系(前一个词/后一个词)
3 ~> Tokenization:把文字变成模型能吃的数字
3.1 为什么需要分词
模型不吃文字,只吃数字。Tokenization就是把"今天天气很好"变成一个数字列表[123, 456, 789, …]。
3.2 BPE分词算法(ChatGPT用的方案)
# 伪代码:BPE的核心思想
def bpe_tokenize(text):
"""
BPE (Byte Pair Encoding) 的核心:
1. 从字符级开始
2. 统计最常一起出现的字符对
3. 把它们合并成一个新token
4. 重复直到达到目标词汇量
"""
# 初始:每个字符是一个token
# "low" → ["l", "o", "w"]
# 发现"lo"经常一起出现 → 合并
# "low" → ["lo", "w"]
# 发现"low"经常一起出现 → 合并
# "low" → ["low"]
# 最终词汇表包含:单字符 + 常见组合 + 常见词
一个中文的例子:
原文:"人工智能改变了世界"
Token化后:["人工", "智能", "改变", "了", "世界"]
└─ 注意:"人工智能"被拆成了两个Token!中文的一个词经常对应多个Token
4 ~> 预训练:让模型"读遍天下书"
4.1 预训练的目标
预训练的目标简单到"无聊"——给定前面N个词,预测第N+1个词是什么。
# 预训练的伪代码逻辑
model = GPTModel(vocab_size=50257, n_layers=12, n_heads=12)
# 训练数据:从互联网上爬的海量文本
for text in internet_texts: # 几TB的数据
# "今天天气很好,我去了公园"
# 训练目标:给定"今天天气很好,我去了",预测"公园"
input_ids = tokenize(text[:-1]) # 前面的词
target_id = tokenize(text[-1:]) # 最后一个词
prediction = model(input_ids)
loss = cross_entropy(prediction, target_id)
loss.backward()
optimizer.step()
4.2 预训练学了什么
预训练后的Base Model拥有的能力:
├─ 语言能力:知道中文的语法、常用搭配
├─ 知识储备:记住了大量事实(北京是中国的首都、水在100度沸腾...)
├─ 推理雏形:给定足够长的上下文,能做简单的逻辑推理
└─ 不具备的能力:
├─ 不会按指令办事(你跟它说"写首诗",它可能给你续写一段散文)
├─ 不知道什么是"好的回答"
└─ 可能会输出不当内容(互联网上有什么它就学了什么)
5 ~> 监督微调SFT:教模型"听人话"
5.1 SFT做了什么
预训练模型只会"续写",不会"对话"。SFT就是收集几千条高质量的 “指令→理想回答” 对,让模型学会:当用户给出这样的指令时,你应该给出那样的回答。
# SFT的伪代码逻辑
# 人工标注的问答对
sft_data = [
{
"instruction": "用简单的语言解释什么是黑洞",
"response": "黑洞是宇宙中一个引力极强的区域..."
},
{
"instruction": "用Python写一个冒泡排序",
"response": "def bubble_sort(arr):\n ..."
},
# ... 几千到几万条
]
for sample in sft_data:
# 输入:"用简单的语言解释什么是黑洞\n回答:"
# 目标:模型输出 = 人工标注的高质量回答
input_text = f"{sample['instruction']}\n回答:"
target_text = sample['response']
loss = model.train_on_batch(input_text, target_text)
5.2 SFT的局限
SFT之后模型会对话了,但还有两个问题:
├─ 问题一:回答"正确"但"不讨喜"
│ └─ 比如问"我该辞职吗?",它可能给一个冷冰冰的"应该"或"不应该"
│ 但人类更希望听到"这取决于你的具体情况,建议你先考虑..."
└─ 问题二:不知道拒绝不当请求
└─ 问"怎么制作炸弹",SFT模型可能真的回答
6 ~> RLHF:让模型学会"讨人喜欢"
6.1 RLHF的三步走
RLHF(Reinforcement Learning from Human Feedback)是ChatGPT成功的关键。它分三步:
6.2 奖励模型(Reward Model)是什么
奖励模型就是一个"AI评分员",输入(问题 + 回答),输出一个分数。这个分数代表了"人类有多喜欢这个回答"。
# 奖励模型的伪代码
reward_model = GPTModel() # 也是基于GPT架构
def get_reward(prompt: str, response: str) -> float:
"""
输入:用户问题 + AI的回答
输出:一个分数(越高=人类越喜欢)
"""
input_text = f"问题:{prompt}\n回答:{response}"
score = reward_model(input_text)
return score
# 训练数据来自人类标注:
# "帮我写一封辞职信" + "亲爱的老板,我决定辞职..." → 分数 4.2/5
# "帮我写一封辞职信" + "辞职。明天不来了。" → 分数 1.0/5
6.3 PPO:用奖励分数优化模型
PPO(Proximal Policy Optimization) 是RLHF的核心算法。它的逻辑很简单:
# PPO伪代码(极度简化)
for epoch in range(n_epochs):
# 1. SFT模型生成一个回答
prompt = "给我讲个笑话"
response = sft_model.generate(prompt)
# 2. 奖励模型给这个回答打分
reward = reward_model.get_reward(prompt, response)
# 3. 如果分高 → 鼓励模型"以后多生成这种风格"
# 如果分低 → 惩罚模型"以后少生成这种风格"
# 但有一个限制:本次更新不能偏离SFT模型太远(防止"学歪")
loss = -reward * log_prob(response) + kl_penalty # KL散度约束
loss.backward()
optimizer.step()
思考 && 总结
本文用一张架构图贯穿全程,拆解了ChatGPT从零到成品的完整技术栈:
- Transformer自注意力是地基: 它让每个词都能看到其他所有词,解决了长距离依赖问题。多头注意力则让模型同时从多个角度理解语言关系。
- Tokenization是翻译官: BPE分词算法把文字变成数字序列。中文一个汉字经常对应1.5~3个Token,这就是为什么ChatGPT处理中文比英文"费Token"。
- 预训练是"读万卷书": 目标就是一个——给定上文预测下文。这个过程极其烧钱(训练一次几百万美元),但它赋予了模型语言能力和海量知识。
- SFT是"学对话礼仪": 用几千条人工标注的高质量问答对,让模型从"续写机器"变成"对话助手"。SFT的量不在多,在精。
- RLHF是"学讨人喜欢": 先让人来给回答排序,再训练一个"AI评分员",最后用PPO算法让模型朝着"人类更喜欢"的方向进化。这是ChatGPT比GPT-3好用100倍的根本原因。
- 三个阶段缺一不可: 只预训练=吟游诗人(会写不会聊);只预训练+SFT=听话但不讨喜;预训练+SFT+RLHF=我们每天用的ChatGPT。
理解这个三阶段训练流程,你就比"只会调API"的开发者高了一个段位。面试时被问到"ChatGPT怎么训练的",你可以从自注意力讲到RLHF,至少多聊十分钟。
结尾
各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!
源码骑士 — Android Framework & 全栈开发
👀 关注:跟博主一起从源码视角深耕底层原理,见证每一次成长
❤️ 点赞:让优质内容被更多人看见,让知识传递更有力量
⭐ 收藏:三阶段训练架构图存好,面试前看一遍就够了
💬 评论:你对哪个阶段最感兴趣?预训练、SFT还是RLHF?评论区聊聊
🔄 一键四连:不要忘记给博主"一键四连"哦!今日技术深潜达成!
🗡️ 寄语:读理论不是为了炫耀,是为了在调API出错时知道问题出在哪一层。
结语:技术原理这种东西,第一次看觉得难,第二遍就顺了,第三遍你就能给别人讲。把这篇文章的架构图和三个阶段记住,你就掌握了ChatGPT 80%的核心知识。不要忘记给博主"一键四连"哦!
更多推荐



所有评论(0)