
简介《ChatGPT大模型技术发展与应用》是一份面向自然语言处理学习者、算法入门者及大模型研究者的综述型PDF可用于梳理ChatGPT的技术脉络与关键概念。全文沿深度学习、语言模型、语义表示和预训练技术展开串联N-gram到神经网络语言模型、Transformer自注意力、Word2Vec与ELMo/BERT/GPT-2的演进并讨论GPT-3的幻觉问题及ChatGPT通过指令学习、监督微调、人类反馈强化学习实现对齐的思路兼及问答、文本生成、翻译等应用。压缩包仅含1个PDF文件约2.15MB轻量易读。已有526人学习适合作为课程报告、技术综述或面试复习的参考。1. 幻觉不是 bugChatGPT 的能力其实来自「对齐」这一层外挂很多人读完 ChatGPT 的技术脉络会得出一个顺理成章的结论它强是因为参数多。把时间线摊开看这个结论站不住。GPT-3 已经是千亿级参数能写通顺长文却经常答非所问从 GPT-3 到 ChatGPT参数量并没有数量级变化真正被改掉的是训练目标的最后一段——先在指令数据上做监督微调再用人类偏好训练奖励模型最后用强化学习把输出往人想要的分布上拉。对话能力的跃迁发生在「对齐」这一层不在「规模」这一层。这个判断值得搞懂因为它同时解释了两件事为什么模型能听懂「帮我改写成正式语气」这种在预训练语料里几乎不以指令形式出现的句子以及为什么幻觉到今天仍压不干净——预训练目标就是「让下一个词的概率最大」它对「真」没有任何偏好对齐只是在外层加约束不是换引擎。理解了这条分界线再回看自然语言处理几十年的语言模型、语义表示与预训练技术演进很多设计选择就不像玄学了。这份材料把这条线从 N-gram 一路铺到对齐学习可以当成一张地图来读。2. 语言模型从 N-gram 的马尔可夫假设到自注意力的全局依赖语言模型这件事剥到最里层只有一句话给定一段文本算出它出现的概率或者等价地算出下一个词的概率分布。所有后续的复杂结构都是在回答同一个问题的不同侧面——怎么在算得动的前提下让这个概率估计尽量贴近真实语言。2.1 链式法则与马尔可夫假设N-gram 把概率算成了查表一句话的概率按链式法则展开就是每个词在它前面所有词条件下的条件概率连乘。这个式子在数学上没问题在工程上没法用要估第 k 个词的条件概率需要看过前面 k−1 个词的全部组合参数空间随句子长度指数膨胀语料再大也覆盖不了。N-gram 的做法是加一个马尔可夫假设——当前词只和前 n−1 个词有关更早的历史一律砍掉。于是整个模型退化成一堆「连续 n 个词出现多少次」的计数比值用极大似然估计直接除出来。n3 时就是三元语法参数规模从「句子长度指数」降到「词表大小的三次方」终于能存进内存了。代价有两个都很硬。其一是稀疏词表几万量级三元组合就是万亿级别绝大多数组合在语料里一次都没出现分子为零条件概率为零连乘之后整句概率归零——模型会对一个完全正常的句子给出「不可能」的判断。其二是泛化N-gram 把词当成离散符号「汽车」和「轿车」在模型眼里是两个毫无关系的 ID学到的知识没法互相迁移。工程上靠平滑缓解第一个问题——拉普拉斯平滑给所有计数加一Good-Turing 把高频计数匀一点给未登录组合Kneser-Ney 用接续计数修正低频项的偏差插值平滑则把不同阶的模型加权混合。这些手段有效但只是止血只要表示还是离散的语义相似性就永远进不了模型。2.2 神经网络语言模型把离散词表压进连续空间2003 年出现的一个思路转换把上面两个死穴一起绕开了别去数词去学词的向量。具体流程是把前 n−1 个词的 one-hot 表示分别乘一个投影矩阵得到低维稠密向量拼接后送进 tanh 激活的隐藏层再接线性层输出词表维度上的得分softmax 归一化成概率。那个投影矩阵的每一行就是这个词的向量表示而且是跟着语言模型目标一起训出来的。这一步的意义在于参数结构变了。N-gram 的参数量随 n 指数增长神经网络语言模型的参数量大致是「词表大小 × 向量维度 隐藏层尺寸」与窗口长度只有线性关系窗口开得大一点也不会爆炸。更重要的是语义相近的词在训练中被推到一起因为它们在不同的上下文里承担相似的预测角色。于是「汽车」上学到的规律可以顺带迁移给「轿车」稀疏性问题从「没见过的组合概率为零」变成「没见过的组合可以由相似词插值出来」。局限同样明显窗口是固定的模型只看前 n−1 个词更远的信息一律看不见。而语言里真正难的依赖——代词指代、跨句逻辑、长距离的因果——恰恰落在窗口之外。2.3 LSTM 与 GRU门控解决的到底是哪一段梯度为了突破固定窗口循环神经网络把「记住历史」做成了一个状态变量每一时刻读入当前词和上一时刻的隐藏状态算出新的隐藏状态往下传。理论上第一时刻的信息可以一路传到第一千时刻历史长度不再受窗口限制。实际训练时这套机制会翻车。反向传播要沿时间轴展开梯度是每一步雅可比矩阵的连乘。连乘项里如果特征值普遍小于 1梯度随步数指数衰减到接近零远距离的信息拿不到有效梯度等于白记如果普遍大于 1梯度指数爆炸一次更新就把参数推到数值发散。前者叫梯度消失后者叫梯度爆炸是循环结构绕不开的血泪经验。梯度爆炸好办梯度裁剪就够设一个阈值范数超了就按比例缩回去保证单步更新不发散。梯度消失没法靠裁剪解决因为问题不在幅度而在结构——信息必须经过太多次乘法。真正的解法是改结构让网络自己决定「什么该留、什么该丢」。LSTM 引入了一条独立的细胞状态通道用输入门控制新信息写入多少、遗忘门控制旧信息保留多少、输出门控制当前暴露多少三个门都是 sigmoid 输出的 0 到 1 之间的系数。梯度沿着细胞状态这条近似线性的路径回流乘法次数大幅减少远距离依赖才学得动。GRU 是它的简化版把三个门合并成更新门和重置门两个参数更少在很多任务上效果相当。但循环结构留下了一个无法回避的工程问题它是顺序计算的。第 t 步必须等第 t−1 步算完一个长度为 L 的序列要串行 L 次GPU 的并行能力用不上。模型越大这个串行瓶颈越致命——你想堆参数先得训得动。2.4 Seq2Seq 与 Attention压缩瓶颈与动态对齐循环网络在机器翻译上催生了 Encoder-Decoder 框架编码器把源语言句子读成一个语义向量解码器从这个向量出发逐词生成目标语言。早期版本还依赖规则和统计组件真正端到端的做法是直接用一个神经网络对完成源到目标的转换不需要显式的词对齐。这个框架有一个结构性缺陷不管源句多长编码阶段的信息最终都要压进最后一个隐藏状态这一个向量里。句子一长前面的信息被反复覆盖解码器拿到的只是一个有损摘要。翻长句时开头部分经常被整段漏掉这不是调参能解决的。Attention 机制改的就是这一点。解码每一步不再只看那一个向量而是回看编码器的所有时刻用当前解码状态和每个编码位置的匹配度算出一组权重再对编码器各时刻的表示加权求和。权重高的位置就是当前要「看」的位置对齐关系不用人工标注从数据里自己学出来。这一步的意义超出翻译本身它第一次把「模型可以按需检索输入序列的不同部分」变成了可微、可训练的操作。后来的自注意力本质上就是把这个操作从「解码器对编码器」搬到了「序列对自己」。同一时期还有一个信号值得注意用卷积结构堆叠的 Seq2Seq 在翻译任务上也能取得好效果说明序列建模不必依赖循环。既然不用循环也能建长依赖那就可以彻底并行——Transformer 沿着这条路把循环整个拆掉了。2.5 Self-attention并行化如何反过来成就了大模型Transformer 保留 Encoder-Decoder 骨架但把循环换成了自注意力。编码器由自注意力层和前馈网络层堆叠而成解码器在自注意力之外再加一层掩码自注意力保证生成第 t 个词时只能看到前 t−1 个词。自注意力的计算很朴素把序列每个位置的表示投影成查询、键、值三组向量用查询和所有位置的键做点积得到相关性分数softmax 归一化成权重再对值向量加权求和。关键在于每个位置的计算只依赖其他位置的表示位置之间没有任何先后依赖整个序列可以一次性并行算完。位置信息靠位置编码注入用一组与位置相关的向量叠加到词向量上把顺序信息从结构里挪到了输入里。import numpy as np def scaled_dot_product_attention(Q, K, V, maskNone): # Q/K/V 形状均为 (batch, heads, seq_len, d_k) d_k Q.shape[-1] # 除以 sqrt(d_k)点积的方差随维度线性增长不缩放会让 softmax 进入饱和区梯度趋近 0 scores np.matmul(Q, K.swapaxes(-1, -2)) / np.sqrt(d_k) if mask is not None: # mask 为 True 的位置保留False 的位置填极大负数softmax 后权重归零 scores np.where(mask, scores, -1e9) # 减去行最大值再取指数避免 exp 溢出数学上等价于原 softmax scores scores - scores.max(axis-1, keepdimsTrue) weights np.exp(scores) / np.exp(scores).sum(axis-1, keepdimsTrue) return np.matmul(weights, V), weights这段实现的参数含义需要说清楚d_k是每个头的维度缩放因子随它变化mask是一个布尔张量编码器里用来屏蔽填充位解码器里用来屏蔽未来位置这是同一套代码能同时服务两种模式的根本原因返回的weights形状是(batch, heads, seq_len, seq_len)它本身就是一张对齐图调试「模型到底在看哪里」时直接可视化它比看 loss 曲线有用得多。多头注意力是同一机制的横向扩展把 Q、K、V 投影到多组不同的子空间各自算一遍注意力再拼接。不同的头可以关注不同类型的关系有的盯相邻词有的盯句法结构有的盯远距离指代。代价也很清楚。自注意力的计算量随序列长度平方增长因为每个位置都要和所有位置算一次分数相比之下循环结构是线性的。但循环的串行无法利用硬件并行自注意力的平方复杂度换来了全序列并行在当时的硬件条件下是净赚。真正被彻底解决的是路径长度任意两个位置之间的信息传递只需要一步不再随距离增长而衰减长依赖建模从此不再靠门控硬撑。这条路一旦走通堆参数就变成了工程问题而不是理论问题。后续的 GPT 系列、BERT 系列都是在这块地基上做规模和数据的选择题。3. 语义表示与预训练从词袋统计到上下文相关的三段跳语言模型解决的是「怎么算一句话的概率」语义表示解决的是另一个问题怎么把一段文本变成向量让向量之间的距离和方向能承载含义。这两条线在预训练范式出现之后合流成了大模型的技术底座。3.1 TF-IDF、pLSA、LDA统计语义的天花板在哪最早的文本表示靠统计。TF-IDF 的思路直白一个词在本篇出现得越多、在整个语料库里出现得越少它对这个文档的区分度就越高两者相乘作为权重。计算极快稀疏性也极强——词表几万维每篇文档只有几十个非零项。它的问题在于完全没有语义多义词拿同一个维度表示同义词拿不同维度表示「苹果」在水果和公司两个语境下算出来的向量一模一样。为了挖出词背后的主题出现了潜在语义分析把文档-词频矩阵做奇异值分解投影到低维空间让共现模式相近的词在低维里靠近。这一步确实缓解了同义问题但分解出来的维度没有可解释的物理含义而且本质仍是线性代数处理不了复杂的语义层次。pLSA 往前推了一步引入潜在主题作为中间变量文档以一定概率选择主题主题再以一定概率生成词。这样文档、主题、词三者被一个概率图连起来主题的含义比 SVD 的隐维度清晰得多。它的硬伤出在生成新文档上——模型把文档的主题分布当成待估参数训练时见过多少文档就有多少组参数来一篇新文档没有对应的那组参数只能靠间接手段凑效果不稳定。参数随文档数线性增长过拟合几乎是必然。LDA 用贝叶斯的方式补上了这个洞。它给文档的主题分布加一个 Dirichlet 先验给主题的词分布也加一个先验超参数 α 控制文档倾向于集中到少数主题还是均匀铺开β 控制主题倾向于集中在少数词还是覆盖整个词表。加了先验之后文档不再持有私有参数主题分布变成可以从先验加数据推断出来的量新文档来了直接采样推断就行。这套生成过程让 LDA 成了概率主题模型的代表作在文本主题分析、信息检索、推荐系统里用了很多年。但这三种方法的共同上限很明显它们都是词袋模型词序被彻底丢弃「狗咬人」和「人咬狗」在表示上完全一样。而语义里相当一部分信息恰恰编码在顺序和结构里。这条路的尽头需要换一种表示。3.2 Word2Vec一次无监督训练换来的语义几何2013 年出现的词向量方法把词表示从「几万维稀疏计数」变成了「几百维稠密实数」而且这些实数是从大规模无标注语料里自己学出来的。核心思路是分布式假设一个词的含义由它经常出现的上下文决定。于是把「预测上下文」做成训练任务词的向量就是训练过程的副产品。两种结构互为镜像。CBOW 用上下文词预测中心词把周围几个词的向量平均后去预测目标Skip-Gram 反过来用中心词预测周围的词。后者在语料规模大、低频词多的时候表现更好因为每个词能贡献的的训练样本数更多。工程上还要处理 softmax 的分母要遍历整个词表这件事通常用负采样把多分类降成二分类或者用层次 softmax 把复杂度从词表大小降到对数级。真正让人信服的是学出来的向量空间有几何结构语义相近的词距离近而且方向能承载类比关系经典的例子是「国王 − 男人 女人 ≈ 女王」。这意味着语义相似性第一次变成了可以计算的数值而不是靠人工维护的同义词表。局限也在这里埋下。每个词只有一个向量多义词被强行压成一个平均意义上的点「苹果」的向量既不像水果也不像公司。词表外的词没有向量低频词向量质量差。训练完之后向量是冻结的换个下游任务也改不了。最根本的是它只建模词级别的共现建模不了短语和句子层面的语义组合。3.3 ELMo、BERT、GPT-2单向、双向与上下文相关把「用语言模型做预训练」这套思路正式立起来的是先在一个单向 LSTM 上做无监督预训练、再把预训练好的模型当作特征提取器接到下游任务上、只微调输出层的做法。它验证了一件事从无标注语料里学到的先验语言知识是可以迁移的。ELMo 在这个基础上做了两处改进输入用字符级嵌入缓解未登录词问题用双向 LSTM 分别训练前向和后向语言模型再把两层模型的各层输出加权融合。关键是它的词向量是上下文相关的——同一个词在不同句子里得到不同的向量多义词问题从「一个词一个点」变成了「一个词一族点」。但要注意它的「双向」是有水分的前向和后向两个 LSTM 是分开训练的每一侧都看不到另一侧的完整上下文融合发生在输出层。GPT 换掉了 LSTM用 Transformer 的解码器结构做单向语言模型预训练然后在下游任务上微调。自注意力的并行优势让它能堆到比 LSTM 大得多的参数规模文本生成质量显著提升。单向设计降低了预训练难度——每个位置只预测下一个词目标干净——但人类理解语言是双向的读到后半句常常要回头修正前半句的理解。BERT 选择了另一条路用 Transformer 编码器做双向预训练训练任务是掩码语言建模加上句对关系判断。掩码语言建模按比例遮住输入中的词让模型还原句对关系判断让模型学句子之间的蕴含关系。双向带来的上下文表示确实更丰富代价是训练更复杂、对数据规模和训练技巧更敏感。规模上Base 版本 12 层、约 1.1 亿参数Large 版本 24 层、约 3.4 亿参数预训练语料是约 8 亿词的书籍语料加约 25 亿词的百科语料。GPT-2 沿着「更大」这条路继续走最大版本约 15 亿参数预训练语料换成了从互联网抓取清洗后的高质量文本规模约 40 GB。规模的提升带来一个意外收获不做任何微调仅靠预训练参数加一段提示模型就能完成不少下游任务也就是 zero-shot 能力。这在方法论上是个信号——当预训练足够充分任务适配也许可以不靠改参数而靠改输入。3.4 GPT-3 的规模红利与幻觉账单GPT-3 把这个信号放大到了极致参数量进入千亿级别之后few-shot 甚至 in-context learning 成为可用能力给几个示例放在提示里模型就能照着格式完成新任务一次梯度更新都不需要。这直接改变了 NLP 的工程形态从「每个任务训一个模型」变成「一个模型加不同的提示」。但这份材料很清醒地列出了三类问题而且它们都不是调参能解决的。第一类是生成不可控模型不知道自己该在哪停也不知道哪些内容不该说输出长度和话题漂移全靠提示硬约束。第二类是知识谬误模型会以非常流畅的语气陈述错误事实因为流畅度和正确性在训练目标里根本不是一回事。第三类是逻辑推理薄弱多步推理时中间步骤容易断链。根因要回到预训练目标上。语言模型的损失函数是最大化训练语料的似然它奖励的是「像人写的文本」不是「说得对」。语料里本来就混杂着错误、过时、互相矛盾的内容模型忠实学到了这个分布。它没有事实核查模块也没有「不知道就说不知道」的机制因为这两件事在「预测下一个词」的框架里没有任何位置。要压住这些问题只调模型规模没用得给它一个新的训练信号——一个能表达「人类更想要哪种回答」的信号。这就是下一层要解决的问题。4. 对齐工程SFT、奖励模型与 PPO 怎么把续写模型调成对话体预训练模型本质上是个续写器。你给它「法国的首都是」它接「巴黎」你给它「请解释一下什么是梯度消失」它可能接着编几个类似的问题因为在语料里这种句式后面跟的往往是更多问题。要把续写器变成对话体需要三步每一步解决的问题都不一样。4.1 指令学习把「续写」重写成「回答」第一步是指令学习加监督微调。做法是人工写出大量「指令-回答」对覆盖问答、改写、摘要、翻译、代码、拒答等各种形态然后用标准的 token 级交叉熵在这些数据上微调预训练模型。损失函数没变变的只是数据分布——从「互联网文本」换成了「人类希望模型学会的应答方式」。这一步的效果被严重低估。它教会模型的是格式和角色什么时候该直接给答案什么时候该分点什么时候该说「这个问题我无法回答」。这些不是知识是行为模式而在预训练语料里它们从没以指令的形式集中出现过。微调数据量通常不大几万条量级就足以让模型的行为发生肉眼可见的变化因为它只是把预训练阶段已经具备的能力重新组织了一遍不需要注入新知识。但监督微调的天花板也很清楚模型学到的是「模仿标注员写的答案」而标注员写不出所有情况下的最优回答。更麻烦的是很多质量维度没法用「标准答案」表达——两个回答都正确但一个更简洁、更符合提问者的意图这种偏好用交叉熵损失根本表达不出来。4.2 奖励模型把人类偏好压成一个标量分数第二步是训练奖励模型思路是把「哪个回答更好」变成可优化的目标。具体做法是对同一个提示让模型生成多个不同的回答人工对这些回答做排序然后训一个模型去拟合这个排序。训练目标通常基于成对比较给定提示和两个回答奖励模型分别打出分数用两者的差值过一个 sigmoid 得到「A 比 B 好」的概率再用交叉熵去拟合人工标注的偏好。这样做的原因是绝对分数难以标定——不同标注员对「8 分」的理解不一样但「A 比 B 好」这种相对判断的一致性要高得多。奖励模型的输出是一个标量它不需要生成任何东西结构上通常就是把语言模型的最后一层换成一个回归头。这一步的价值在于它把模糊的人类偏好压缩成了一个可微、可批量计算的函数。有了它就可以对模型生成的任意回答自动打分不再需要人工逐条看。它也带来一个新的风险奖励模型只是人类偏好的近似凡是近似就有漏洞而后续的强化学习会拼命去找这些漏洞。4.3 PPO 与 KL 约束优化分数时怎么不把模型带崩第三步是用强化学习去优化策略。这里有个容易被忽略的细节整个流程里同时存在四个模型——正在训练的策略模型、一个冻结的参考模型通常是监督微调后的版本、奖励模型、以及一个价值模型用来估计基线、计算优势。四个模型同时驻留显存这是 RLHF 训练成本远高于普通微调的直接原因。for step in range(total_steps): prompt sample_prompts(batch_size) # 1) 当前策略采样回答同时记录每个 token 的 log 概率 resp, logp_old policy.generate(prompt, temperature1.0, return_logprobTrue) # 2) 奖励模型只给整条回答一个标量不区分 token reward reward_model.score(prompt, resp) # 3) 参考模型冻结的 SFT 模型算同一批 token 的 log 概率用于估 KL logp_ref ref_model.log_prob(prompt, resp) kl logp_old - logp_ref # 4) KL 惩罚折进逐 token 奖励beta 越大越保守防止策略偏离 SFT 分布太远 token_reward -beta * kl token_reward[:, -1] reward # 整条回答的奖励只挂在最后一个 token 上 # 5) 用价值模型估基线算优势再做 PPO 的裁剪更新 adv gae(token_reward, value_model(prompt, resp), gamma1.0, lam0.95) policy.update(prompt, resp, logp_old, adv, clip_ratio0.2)这段伪代码里的几个参数决定了训练稳不稳。beta是 KL 惩罚系数它约束新策略不要离监督微调后的模型太远——这是整个流程的安全绳。没有它策略会迅速学会刷奖励模型的分数输出一堆奖励模型喜欢但人类看了莫名其妙的文本这就是常说的 reward hacking。clip_ratio是 PPO 的裁剪范围限制单次更新的策略变化幅度避免一步走太远把之前学到的东西全毁掉。gamma设成 1.0 是因为这里的回报不打折一条回答的整体质量就该由整条回答的奖励决定。奖励只挂在最后一个 token 上是因为奖励模型打的是句级分前面的 token 通过优势函数的反向传播间接获得信用。这套流程也不是没有代价业界管它叫对齐税强化学习阶段优化的是奖励模型的打分而奖励模型和真实人类偏好之间有偏差于是模型在通用能力上可能出现轻微退化在某些基准测试上反而不如监督微调版本。工程上的应对通常是控制训练步数、用 KL 约束限幅、在奖励里混入一部分预训练损失或者在偏好数据里刻意覆盖多样化的任务类型避免模型在少数几个维度上过拟合。回过头看ChatGPT 的能力来源可以拆得很清楚预训练给了它语言知识和世界知识的底座指令微调给了它对话的形态奖励模型和强化学习给了它「往人希望的方向说话」的倾向。三层叠起来才有那种「像在跟人交流」的观感。而幻觉之所以还在是因为底座那一层的目标函数从没变过。5. 排查与避坑预训练到微调链路上最容易踩的五个坑理论和落地之间隔着一堆具体的翻车现场。下面这五条是在大模型链路上反复出现的典型问题每一条都给出从现象到根因再到处置的完整路径。5.1 微调之后通用能力掉得厉害现象在自己的任务数据上微调几轮之后目标任务指标上去了但拿去做别的任务明显变笨以前能答对的常识问题开始出错多轮对话的连贯性也变差。原因全参数微调在小数据集上等价于用几百条样本去覆盖几十亿参数的先验学习率稍大就会把预训练学到的表示冲掉这种现象叫灾难性遗忘。数据越单一、训练轮数越多退化越严重。解决优先用参数高效微调只训练低秩旁路或者适配层主干参数冻结遗忘风险会小一个量级。如果必须全参微调把学习率降到预训练阶段的十分之一以下训练轮数控制在一到两轮并在微调数据里按比例混入通用指令数据让模型在学新任务的同时不断被提醒旧能力。每次训练都留一个固定的小型通用评测集跑一遍把「掉点」当成硬指标盯着不要只看目标任务分数。5.2 loss 在降生成却开始复读现象训练损失曲线很漂亮一路下降但推理时模型生成的文本开始出现整句重复、绕圈子、停不下来温度调低之后更严重。原因先检查解码策略。贪心解码每一步都取概率最高的词一旦进入某个循环模式后面的高概率路径会把它锁死越走越出不来。再检查训练侧如果标注数据里的回答普遍偏长、结尾模式单一模型会学到「继续写下去」的先验对结束符的预测概率偏低于是不会主动停。还有一种情况是标签平滑或者损失掩码配错把不该算损失的位置算进去了。解决先换解码策略验证——加重复惩罚、用 top-p 采样替代贪心、把温度调到 0.7 左右如果复读消失问题就在解码而不在模型。如果换了策略还在复读就要检查训练数据里结束符的分布确认每个样本的损失掩码正确覆盖了回答部分、正确排除了提示部分。必要时在训练时对结束符位置加权提高模型主动停止的倾向。5.3 训练指标漂亮评测纹丝不动现象训练集损失降得很低验证集损失也在降但把模型接到实际业务评测上指标几乎没变化甚至比基线还差一点。原因最常见的是训练和推理不一致。训练时用了某种对话模板推理时换了一种模型看到的输入分布变了表现自然崩。其次是填充策略问题训练时用左侧填充还是右侧填充、注意力掩码有没有正确屏蔽填充位、位置编码在填充之后有没有错位任何一处不对模型学到的都是被污染的上下文。第三种可能是评测本身的问题——评测集的答案格式和模型输出格式对不上自动打分脚本把正确答案判成了错。解决把「训练用的模板」和「推理用的模板」写成同一个函数两边调用同一份代码从根上杜绝不一致。构造一条固定的样本分别走训练前向和推理 generate 两条路径打印出模型实际看到的 token id 序列逐位比对这一步能抓出绝大多数掩码和填充问题。评测侧则要人工看二十条错例确认是真错还是判分脚本错。5.4 长序列一来就爆显存现象短样本训练一切正常把最大长度从 1024 提到 4096 立刻 OOM调小 batch size 能跑但吞吐低得没法用。原因注意力机制的计算和显存开销随序列长度平方增长这是结构性的。此外激活值才是显存大头——为了反向传播前向过程中每一层的中间结果都要留着长度翻四倍激活值也大致翻四倍。再加上优化器状态全参训练时每个参数要额外存两到三份。解决按成本从低到高排——先用梯度累积把等效 batch size 凑够单卡放小 microbatch再开混合精度激活值显存直接减半还不行就上梯度检查点牺牲约三成计算时间换大幅激活值下降再往上才是序列并行或者更省的注意力实现。另外检查一下数据侧如果大部分样本远短于最大长度做长度分桶和序列打包能显著减少填充浪费这一条经常被忽略但收益很大。5.5 模型一本正经地胡说现象问它一个具体的事实性问题它给出结构完整、语气笃定的回答但内容完全是编的而且换一种问法再问答案还不一样。原因这是预训练目标自带的行为。模型优化的是「下一个词的概率」语料里大量存在「句式完整但内容错误」的文本模型无从区分。它也没有「知识边界」的概念不知道什么该说自己不知道因为在训练数据里「我不知道」这种回答的占比极低。解决不要指望靠提示词根治。工程上通常几条一起上——接检索把相关文档片段塞进上下文让模型基于给定材料回答并要求标注引用来源降低温度减少随机性在指令微调数据里专门加入「材料中没有相关信息时明确说明」的样本把拒答变成一种学过的行为最后配一套事实性评测集按领域抽样定期跑把幻觉率当成可观测指标而不是凭感觉判断。6. 规模、方向与对齐税三个绕不开的设计取舍把技术线拉直之后会发现大模型的每一次跃迁都不是单纯的「更强」而是在几个相互冲突的目标之间重新选边。理解这些取舍比记住某个模型的参数规模有用得多。取舍点一侧的收益另一侧的代价典型选择单向 vs 双向单向预训练目标干净、天然适合生成双向上下文表示更丰富但训练目标需人造掩码生成任务偏单向理解任务偏双向规模 vs 数据质量规模带来 zero-shot 与上下文学习能力低质语料被忠实放大幻觉与偏见同步增长后期普遍转向数据清洗与配比优化对齐强度更强对齐带来更好的指令遵循与安全性对齐税导致通用能力轻微退化、输出趋于保守用 KL 约束和混合损失限幅先看单向与双向。这个选择在 BERT 和 GPT 分道扬镳的时候就定型了。双向编码器能拿到完整上下文在分类、抽取、匹配类任务上优势明显但它的训练目标是人造的掩码还原和自回归生成不是一回事直接拿来做开放生成很别扭。单向解码器牺牲了右侧上下文换来的是训练目标和推理过程完全一致——训练时预测下一个词推理时也是逐个预测下一个词没有训练和推理之间的鸿沟。生成式应用成为主战场之后这个一致性比双向表示更有价值。再看规模与数据质量。早期的主流判断是「参数越多越好」GPT-3 的千亿参数确实换来了上下文学习能力。但规模的红利有边际递减而且它会忠实放大语料里的问题错误知识、过时信息、偏见表述参数量越大记得越牢。后期的普遍转向是把算力从「堆参数」挪到「洗数据」和「调配比」上同样的参数规模数据质量提升带来的效果往往比继续加参数更明显。这也解释了一个反直觉现象某些参数更小的模型在具体任务上能打赢更大的模型差距不在规模在数据。第三个取舍最微妙就是对齐强度。对齐做得越足模型越听话、越安全但输出的多样性会下降遇到边界问题时倾向于保守回避某些需要创造性或者需要踩线的任务反而做不好。这就是对齐税的另一种表现。工程上的分寸感在于用 KL 约束限制策略偏移在偏好数据里保留一定比例的多样性样本并且分场景部署不同对齐强度的版本而不是用一个模型打天下。还有一个容易被忽略的取舍是开源与闭源。开放的权重让研究可以复现、可以魔改、可以在本地做隐私敏感的场景但同时也意味着安全约束可以被绕过闭源接口便于统一管控和迭代但用户没法知道模型到底在自己的数据上做了什么。这份材料在讨论这个问题时保持了克制没有给出非此即彼的结论这个态度本身是合理的。我自己的教训来自一次微调实验当时只盯着目标任务指标训了五轮指标涨了两个点兴冲冲上线结果用户反馈「这模型怎么变笨了」。回头补跑通用评测才发现常识问答掉了将近十个百分点。从那以后我每次开训之前都强制走一遍「留存通用评测集 固定模板比对 长短序列显存压测」这三件事宁可多花半天也不要在上线后靠用户帮你发现问题。希望帮到你。本文还有配套的精品资源点击获取