
如果只让我用一个词概括近十年自然语言处理领域最关键的进展我会毫不犹豫地选“GPT”。这三个字母背后是Generative Pre-Training——生成式预训练——这套如今几乎所有大语言模型都在沿用的底层范式。我第一次完整跑通一个预训练加微调的流程时最大的感受并不是效果有多惊艳而是一种“原来语言模型还可以这样训练”的恍然大悟。这篇文章不是把GPT系列逐一代罗列一遍就算完事而是想把它之所以成立的逻辑链完整讲透为什么模型要预测下一个词、为什么单靠这一个任务就能学到知识、微调和对齐到底改了什么、以及部署时你会撞上哪些书上不写的坑。适合所有被GPT系列绕晕的算法同学、想落地大语言模型的工程师以及对“预训练”只有模糊概念但想建立系统认知的产品同学。1. 先搞清楚一件事GPT到底是“怎么长出来”的1.1 名字里藏着全部设计思路“OpenAI-GPTGenerative Pre-Training”这个全称拆开了就是整套方案的设计蓝图。先说“Generative”。生成式意味着模型的根本任务是生成文本而不是给文本贴标签。早年的自然语言处理模型多数是为了某个具体任务训练的情感分类就输出正面或负面实体识别就在每个词上打标签。这类模型本质上是“判别器”它只会在给定输入时做判断却不知道如何自己写出一段通顺的话。而GPT选择了另一条路模型必须逐个词地把文本“接下去”它内部表征的每一寸都被迫服务于“怎么把下一段话说自然”这个目标。再说“Pre-Training”预训练。这是整套范式的灵魂先用海量无标注文本让模型自学语言的一般规律得到一组通用的初始参数之后再到具体任务上做微调。为什么要这么做因为标注数据太贵了。传统做法里做一个情感分类器就要标几万条评论做一个问答系统又要标几万组问答对任务之间完全没有复用每次都从零训练又慢又费钱。而预训练等于先让模型读几万本书把语法、事实、逻辑推理的常识都内化进参数里等到具体任务上只需要很少的标注样本就能让它学会“把学到的本领用在这个方向上”。最后那个“T”Transformer决定了GPT怎么读文本。这里因为篇幅原因我会在第三章重点展开但可以先记住一句话Transformer是个擅长根据上下文加权吸收信息的网络结构它给大脑搭好了骨架而预训练负责往骨架里填肌肉。1.2 预训练加微调的两段式逻辑这套逻辑可以打一个很朴素的比方预训练是一个人的通识教育微调是这个人的岗位培训。通识教育阶段学生读文学、学历史、接触数学所有知识都来者不拒。对应到GPT就是让它在大规模书籍和网页文本上做自监督学习——具体任务就是“遮住下一句话猜它是什么”。这个任务表面看很单调但语言本身就是浓缩的知识一句话里包含语法规则、常识关系、实体事实甚至隐含的推理步骤。模型为了把下一句猜得准就必须把这些规律都吸收到参数中去。更妙的是这个任务的训练信号不需要人工标注互联网上有取之不尽的自然文本所以可以把模型做得极大、数据喂得极多。微调阶段则是“岗位培训”。还是同一个模型只不过把输出层换成和执行目标匹配的结构再用少量高质量标注数据继续训练几步。比如要让模型做情感分类就给它“这句话是正面还是负面”这类样本让它在原有语言能力之上学会把内部知识引向分类这个具体用途。两个阶段的核心差异在于目标函数预训练是“在所有语言上最小化预测误差”微调是“在任务数据上优化任务指标”。但它们的参数是连续的——微调是在预训练得到的参数基础上继续走不是推倒重来。这也是GPT和其他早期迁移学习方案最本质的区别早期的词向量方案只是把预训练结果当作输入特征模型的主体结构仍然要为每个任务单独重新训练而GPT直接让整个模型带着通用知识迁移到新任务上效果自然不可同日而语。我在第一次实现这个流程时最解触动的地方在于预训练模型本身没有任何“想帮人干活”的意愿它只是续写文本的机器。你让它看到“中国的首都是”它能接出“北京”是因为语料里这句话陪着“北京”出现无数次但如果你让它“请回答中国的首都”它可能一头雾水因为“请回答”这个句式在普通语料里极少和地理知识共现。理解这一点是理解后面所有微调、对齐、提示词技巧的起点——我们做的一切本质上都是为了让“续写机器”学会按人类的对话形式来使用它学到的知识。2. 一路走来四代GPT各自解决了什么问题2.1 GPT-1把“预训练加微调”钉在自然语言处理的地图上2018年前后自然语言处理领域的主流仍然是各个任务各自为战一个任务一个模型、一份标注数据训一次。公开的预训练资源只有词向量它们只是查表得到词的静态表示不包含上下文信息“银行”在“河边银行”和“商业银行”里是同一个向量。GPT-1做的事情就是把整条链路重新设计了一遍。整个模型是一个12层的Transformer解码器参数量约1.17亿上下文窗口512个词元预训练数据用的是大约5GB的书籍语料。本质上就是让模型把这几千本书一页一页地“读”下去每读到一个词就预测下一个词是什么错了就更新参数。我后来回头看真正的创新点其实在微调那一步作者不是简单把分类标签接到模型末尾而是设计了一套“文本加分隔符再接标签”的输入格式让不同任务都能统一进同一个序列输入框架里。在预训练参数的基础上做微调模型在12个自然语言处理任务上大幅刷新了当时的结果有些任务甚至比专门设计的模型还要好。这个结果的意义远不止分数它用实验证明了一个很反直觉的猜想——一个在“猜下一词”任务上练出来的模型内部居然已经隐含着情感、语义相似度、文本蕴含等任务所需要的大量抽象能力微调只需要轻轻拨动几个方向就能把这些能力激发出来。2.2 GPT-2意外收获“不微调也能用”GPT-2把规模提升到了15亿参数预训练数据换成从互联网上抓取的约40GB网页文本上下文窗口也从512扩到1024。单看设计它和GPT-1的区别不大更大、更多数据、更长的上下文似乎是按同一配方做了一道加大号的菜。让行业内集体改观的是它展现出的零样本能力不经过任何微调直接给模型一段前文它就能自动续写出符合风格的新闻稿、把英文句子翻译成法语、甚至回答事实性问题。这在当时是颠覆性的。之前大家都默认预训练模型只是一个“底座”底座上面必须有任务层的精细打磨而GPT-2直接让人看到底座本身已经具备多任务能力只是被提示词“唤醒”而已。为什么会有这种能力我当时总结了一个比较朴素的解释预训练语料里天然包含各种任务模式。新闻稿开头后面总跟着正文英文段落后面偶尔跟着法文译文问题后面往往跟着答案。模型学的是这些模式的统计规律所以当提示词里出现类似任务的开头它就会沿着高概率的续写方向走下去。这其实是“拿来主义”并不神秘只是放大了规模之后效果超出了所有人的预期。2.3 GPT-3与InstructGPT少样本学习和人类对齐GPT-3的出现把参数量一下提到了1750亿上下文窗口2048训练数据覆盖网页、书籍、维基百科等混合来源。这个体量带来的最直观变化是少样本学习能力的跃升。少样本学习在GPT-3里的形态非常特别不需要更新任何参数只要在提示词里塞几个输入输出示例模型就能照着示例的格式去完成新输入。比如你想让模型做中文古诗翻译成现代文只需要在提示词里写“鹅鹅鹅曲项向天歌鹅啊鹅弯着脖子向天唱歌”几组示例它就能接着译下一首。这种能力的学名叫“上下文学习”现在被研究得非常多但当时大家最震撼的是一个只会预测下一词的模型居然能把提示词里的示例当作“模板”来类比推理。不过GPT-3也有一个致命问题它生成的内容经常在事实性上翻车且话术僵硬满嘴“作为一个语言模型”式的套话。它并不是为了让人类舒服地使用而被训练出来的。于是InstructGPT来了它给GPT-3加上了人类反馈强化学习RLHF用人类打分数据来修正模型的输出偏好。效果最直观的证据来自当时公开测试一个13亿参数的InstructGPT在人类偏好评估上比未对齐的1750亿参数GPT-3更受欢迎。这条路径后来直接发展成ChatGPT所依赖的技术底座也是“对齐”这个概念进入大众视野的起点。2.4 GPT-4参数量之外的新维度GPT-4在能力上又抬了一个台阶支持多模态输入、复杂推理显著增强、长上下文处理能力大幅提升。但在技术层面官方几乎不公开任何关键细节参数规模、训练数据、架构改动都被当作商业机密。这种情况在开源生态成熟之前是很难想象的也直接促成了行业后来“公开与闭源分叉”的格局。对我们做实际项目的开发者来说GPT-4带来的最大价值不是参数数字本身而是让大家意识到当规模跨过某个阈值能力会不再遵循“加数据涨几分”的线性规律而会冒出一些训练时没有明确设计过的能力点比如代码解释、数学推理、工具调用。这也是为什么后来很多团队开始研究“涌现能力”的边界并尝试用小模型加工程化手段去逼近这些能力。以下用一个简单表格把四代模型的公开信息做一个对照模型参数量上下文窗口核心贡献信息公开程度GPT-1约1.17亿512词元验证预训练加微调范式公开权重与细节GPT-2约15亿1024词元零样本能力的发现模型可本地部署部分细节公开GPT-3约1750亿2048词元少样本上下文学习仅API接入细节有限公开GPT-4未公开多档可选多模态与复杂推理仅API接入几乎不公开细节注意上面表格里的数字是沿着公开资料整理的GPT-4的参数规模和内部结构官方从未确认这篇文章里也不做任何猜测。3. 拆开看看生成式预训练的关键零件3.1 自回归语言建模一切能力的起点理解GPT必须理解那个最简单的训练目标给定前文所有词元预测下一个词是什么。形式上就是最大化整个序列的联合概率把它分解成每一步条件概率的乘积。在实现层面几乎没有门槛输入一段文本把模型在最后一个位置的输出向量过一个词表大小的线性层得到下一个词的预测分布再和真实下一个词计算交叉熵损失反向传播。一个极简的训练循环长这样import torch import torch.nn as nn from torch.utils.data import DataLoader def train_step(model, batch, optimizer, criterion): # batch: 已经按固定长度切好的token id序列形状 [batch, seq_len] x batch[:, :-1] # 输入不取最后一个位置 y batch[:, 1:] # 标签下一个词 logits model(x) # 输出 [batch, seq_len-1, vocab_size] loss criterion(logits.reshape(-1, logits.size(-1)), y.reshape(-1)) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item()这个训练目标有几个隐性好处。第一学习信号极其密集文本里的每一个词都是一个训练样本不像人工标注那样一条样本就要花成本。第二数据天然可得无论什么领域的文本都能直接用来训练这让模型可以无限扩大知识面。第三预测下一个词这个操作本身迫使模型同时掌握语法结构、实体知识、上下文一致性等多层次信息因为任何一个短板都会增大预测误差。从数学上把每一步预测概率乘起来再取负对数平均就得到了一个很常用的评价指标——困惑度。困惑度本质上是对“模型每一步预测的平均惊讶程度”做指数化数值越低说明模型对文本的拟合越好。不过要注意困惑度低不代表生成质量好这个坑我在后面的评测章节会再展开。3.2 掩码自注意力只看左边不看右边Transformer结构里最关键的自注意力机制可以理解成一个信息聚合过程序列里每个位置都会计算一个查询向量到所有其他位置去“查资料”把与自己相关的信息按权重加权汇总。具体感受一下这个流程每个词元都有三个角色查询角色负责提问键角色负责被检索值角色负责提供内容注意力分数由查询和键的相似度算出再在值上加权求和。这个机制让模型能轻松建立长距离依赖“小明走进房间他关上门”模型在“他”的位置可以远程吸取“小明”的信息。但GPT用的是Transformer解码器不是普通自注意力它的关键区别在于因果掩码计算注意力分数时当前词元不允许看序列中它右侧的那些词元。实现上很简单就是把右上三角的注意力分数全部设成负无穷经过softmax以后权重归零。这背后的逻辑非常直接推理时模型只能看到已经生成的左侧内容永远看不到右侧还没写的词所以训练时也必须模拟这种场景否则训练和推理行为就不一致模型会产生严重性能退步。如果把注意力机制写成一段示意代码思路大致是import torch import torch.nn.functional as F def causal_attention(q, k, v, mask): # q, k, v 形状都是 [batch, heads, seq_len, head_dim] scores q k.transpose(-2, -1) / (q.size(-1) ** 0.5) scores scores.masked_fill(mask 0, float(-inf)) weights F.softmax(scores, dim-1) return weights v这个掩码设计带来的综合效果是模型每一层的输出都只携带了“过去和现在的信息”这让它能被当成一个可迭代的生成器逐词往外蹦。GPT系列从始至终坚持这种纯解码器架构而不是使用“编码器加解码器”的布局正是因为它追求的是流畅生成而非双向理解。后来自编码器模型虽然也能做生成但在纯文本续写上的效率与一致性和解码器路径并不是同一种思路。3.3 从词到词元BPE分词是怎么回事模型读的不是“字面字符”而是经过分词后的词元。早期做法是直接按词切开但词表会非常庞大而且遇到生僻词、拼写变体就没办法。GPT系列用的是字节级别的BPE算法也就是字节对编码。BPE的基本流程是先把文本拆成一个个字节或单字符然后反复统计相邻符号对的出现频率把最高频的相邻对合并成新符号重复直到词表达到目标大小。这样做的效果是常见词会形成完整词元比如“language”可能直接占一个词元不常见的词会被拆成几个子词单位比如“tokenization”可能被拆成“token”“ization”完全没见过的字符则会被拆到底层字节。为什么这个设计重要因为它让模型在处理任意语言、任意领域、任意拼写时都能“兜底”。对于中文来说BPE通常会把常用的汉字或词汇聚成词元但中文的信息密度很高同样一段内容消耗的词元数往往比英文少这在按词元计费的部署场景里是一个实实在在的成本变量。我见过不少团队在做中文大模型应用时专门对比不同分词器的词元消耗它的影响面往往被低估。一个重要的实操认知是分词表本质上也是模型“世界观”的一部分。比如某个专业领域的术语如果能在分词阶段被压缩成完整词元模型对这个概念的建模粒度就更细后续生成质量通常也会更好。这也是很多垂直领域训练会自定义扩充词表的原因。3.4 生成时的采样温度、Top-p和重复惩罚预训练和微调解决了“模型会什么”而生成参数解决的是“模型以什么风格把会的说出来”。同一个模型用不同采样策略输出可能天差地别。最基础的生成方式是贪心解码每一步都选概率最大的那个词。但这么做很容易陷入重复循环因为语言里概率最大的路径往往是最俗套的路径。于是就有了采样从概率分布里随机抽一个词让输出变得多样。温度就是控制这个分布平滑度的旋钮。把原始分数除以温度再做softmax温度越高曲线越平低概率词也有机会被选到输出更跳跃温度越低曲线越尖模型越倾向于确定性输出。下面是一段调节温度后采样的简化实现import torch import torch.nn.functional as F def sample_with_temperature(logits, temperature0.8, top_p0.9): logits logits / temperature if top_p is not None: probs F.softmax(logits, dim-1) sorted_probs, sorted_indices torch.sort(probs, descendingTrue) cumulative torch.cumsum(sorted_probs, dim-1) # 保留累积概率超过top_p的最小集合 keep cumulative top_p keep[..., 1:] keep[..., :-1].clone() keep[..., 0] True logits logits.masked_fill(~keep, float(-inf)) probs F.softmax(logits, dim-1) return torch.multinomial(probs, num_samples1)Top-p核采样做的是另一件事只从累积概率达到阈值的那一小撮词里采样比如0.9的top-p意味着每次生成只考虑概率最高的那些“核心词”把拖后腿的长尾概率黑洞斩掉。还有重复惩罚会对已经出现的词的概率进行打折降低汉字或短语循环的概率。从实际经验看不同类型的任务适合不同的参数组合创意写作、头脑风暴温度可以放到0.8到0.9故意给它一点“疯”的空间知识问答、结构化输出温度压到0.1到0.3让它尽量稳定代码生成则经常直接用贪心或极低温度配合解析器校验因为代码容不下语法层面的随机性。4. 让模型干活微调、对齐与提示工程三板斧4.1 指令微调从“续写”到“听话”不带任何微调的预训练模型用起来非常别扭你输入一句问题它输出的可能是一长串维基百科式的说明而不是一句干净利落的回答。因为它学的是“续写”不是“服从指令”。指令微调要做的事情就是构造一批“指令到回答”的数据集继续训练模型让它把“收到指令后给出回答”这种互动模式固化下来。构造这批数据时最关键的一点是格式统一。常见的做法是把指令、上下文、回答拼成一个完整序列中间加特殊分隔符训练损失只计算在回答部分让模型不去花力气背指令文本。拿一套已经整理好的数据用常见微调框架里的LoRA方案来做参数高效微调是当前成本最低的入场方式。示意代码如下from transformers import AutoModelForCausalLM, AutoTokenizer model AutoModelForCausalLM.from_pretrained(base_model_path) tokenizer AutoTokenizer.from_pretrained(base_model_path) def format_sample(sample): # sample: {instruction: ..., input: ..., output: ...} parts [ |im_start|user\n, sample[instruction] \n sample[input], |im_end|\n, |im_start|assistant\n, sample[output], |im_end|, ] return .join(parts)关于数据量我的经验是质量远比数量重要。用上千条覆盖场景广、格式规范、没有错误的高质量指令数据效果通常好过几万条爬来的噪声数据。见过不少团队用开源指令数据集直接微调结果模型学会的是一堆重复套话这条弯路希望你能避开。4.2 RLHF人类反馈如何进入训练指令微调之后模型会“听指令”了但距离“让人舒服”还有很大距离。它可能答得很完整却满是错误或者拒绝问题的姿势特别生硬。为了把人类偏好真正写进模型就有了RLHF一种让模型对着人类打分结果做强化学习的方案。整个流程分为三步。第一步用人工书写的优质答案对模型做监督微调得到一个行为基线。第二步让模型对同一批问题生成多份候选回答由标注员按偏好排序然后拿这些排序结果训练一个奖励模型它学会的是“什么样的回答更被人类喜欢”。第三步用强化学习算法让主模型不断生成回答去争取奖励模型的高分同时引入一个重要约束模型不能偏离最初监督版的输出太远否则容易退化成一派胡言但分数很高的“刷分机器”。从工程实现上看RLHF的代码复杂度和资源需求比普通微调高一截。它需要同时维护策略模型、参考模型、奖励模型并在每一轮更新后做采样和奖励计算。很多团队在初期阶段其实不需要立刻上RLHF先把指令微调和提示词工程做扎实明显觉得“模型能力有但表达方式惹人生厌”时再考虑对齐环节。我的建议是从小模型上先跑通一套最小化的RLHF流程感受一下它对风格和稳定性的影响再决定是否投入大规模算力。4.3 提示工程不训练也能提升质量如果说微调是有监督地改变模型行为提示工程就是无监督地把模型已有的能力“拧”到正确方向。它的底层逻辑是预训练模型已经在无数种文本模式里浸泡过你给的提示词越能激发正确的模式输出就越接近你想要的效果。结构化的提示词一般分四块角色设定、任务描述、约束条件、示例。例如让模型做技术文章写作先告诉它“你是一位有十年经验的架构师”再给“请解释什么是预训练”再补上“不要使用套话不要超过五百字”最后扔两个风格示例进去。这个结构远比简单问一个问题要稳定。把约束条件写在任务之前是我在实践中觉得最有效的小技巧。模型在生成时会对位置靠前的指令权重更高把“不要编造事实”“不要输出无关内容”放在开头比放在最后管用。另外少样本示例比抽象描述更高效给模型一个“照着抄”的参照物往往比规则列表更能约束它的行为。思维链提示是另一个性价比极高的技术在提示词里引导模型“先列出推理步骤再给出最终答案”。比如数学题直接问答案可能出错但如果要求“先说明题目的关键条件再分三步计算”模型生成过程中的中间文本会迫使自己按步骤组织信息准确率大幅上升。说白了这利用了模型“续写中的中间文本会影响后续生成”的特点。5. 从模型到服务部署与效果评估的实战经验5.1 选型先算钱再选模型很多团队一上来就奔着最大的模型去结果在算力和延迟面前卡住。我习惯的决策路径是先列出任务的实际约束再反推需要多大规格的模型。第一条约束是任务难度。如果是开放域自由对话、复杂推理大概率需要较大的基座模型这条路省不了但如果你只是做分类、抽取、改写这类结构化任务一个几十亿参数的小模型经过微调配合良好的提示词完全可能达到可接受的效果。第二条约束是延迟和成本。大模型推理慢单次请求贵如果产品要求秒级响应就得考虑小模型加蒸馏或者把大模型能力封装成离线批处理任务。第三条约束是数据隐私。很多企业内部文档不能出域这时候本地部署小模型往往是唯一选项而不是调外部大模型。量化是一个见效最快的部署优化手段。把权重从FP16压到INT8内存占用几乎砍半推理速度明显提升大部分任务的质量损失肉眼几乎看不出再往下压到INT4质量开始出现可感知的下降但显存占用优势非常诱人。做一个粗略对照精度相对显存占用推理速度质量损失经验感受FP16基准基准无INT8约一半更快大多数场景几乎无感INT4约四分之一最快复杂推理与生成多样性会有下降这个表格是我的经验值不同模型、不同任务会有浮动实际部署前一定要拿自己的评测集跑一版量化前后的对比不要拿别人的结论当作自己的结论。5.2 评估别被指标骗了评估大语言模型最忌讳的是只看一个数字就下结论。自动评测指标各有各的盲区困惑度只能说明模型对文本的拟合程度反映不出生成内容是否忠于事实BLEU适合机器翻译这种参考答案确定的场景在开放生成里它经常判错一句话说得比参考答案更好反而会被扣分ROUGE评价摘要任务时偏向“字面重合”两个语义等价的句子如果措辞不同得分就上不去。所以在实际项目里我强烈建议走“自动指标粗筛加人工评估精判”的路线。先让自动指标把明显低质量的候选剔除再用人工评估对剩余结果做细粒度打分。人工评估一定要用成对比较而不是单个打分因为人对绝对分数的标准很不稳定但面对两个候选时大多能做出一致的选择。如果评估集规模大可以设计双盲的“左右随机交换”投票我记得有一次经验复盘发现这种设计能显著降低标注员对“后出现的答案更好”的惯性偏见。5.3 成本与性能调优模型部署上线后成本优化是长期工作。第一招是缓存对用户问题做语义去重高频问题直接返回缓存答案能省掉一大批重复计算。第二招是输入压缩把冗长的上下文先摘要再喂给模型输入token少了单次成本直接下降。第三招是结果复用如果一段长文本需要多次分析先把文本分词保存每次只在结果层做叠加而不是重新跑一遍整段。检索增强生成是另一个能真正改善质量与成本双指标的思路只把用户问题最相关的几段知识库内容拼进上下文而不是把所有文档都塞进模型。这减少了模型需要处理的内容量也让回答更聚焦降低了幻觉风险。我在做企业内部问答系统时深有体会同样是回答一个问题接检索前的回答经常模棱两可接检索后能明确到具体条款所以别急着让模型“背下”所有知识教会它“哪里查知识”往往更划算。6. 实践中的坑我从真实项目里总结的排查清单6.1 模型“一本正经地胡说八道”幻觉是大语言模型最让人头疼的问题。本质原因是生成模型优化的是“看起来自然”而不是“符合事实”它从海量语料里学到了很多模式的统计关联却没有可靠的事实校验通道。遇到不确定的问题它会用高概率的流畅表达“编”出一个答案来。我的排查思路有四个方向。第一检查提示词里是否明确给出了“如果不知道请直接说不知道”的约束这招能拦住一部分幻觉。第二给模型接检索工具让它生成答案前先查资料。第三在关键生成结果上增加一套独立校验流程比如数字、日期、引用用规则或另一个模型交叉验证。第四约束解码只让模型从给定的候选集合里选答案用在标签必须准确的场景里特别管用。6.2 上下文窗口超限遇到长文档场景最常见的报错是提示词长度超过模型上下文限制。大部分模型对超长输入不是优雅地“忽略中间内容”而是直接截断。结果往往是开头的背景还在结尾的关键诉求反而没了回答牛头不对马嘴。解决思路分两级轻量级的做法是滑动窗口摘要每隔一段就把之前的内容压缩成摘要用摘要代替原文继续向下读重量级的做法是做分层检索把长文档切成小块并建索引每次只把和问题相关的几块塞进上下文而不是把全文档灌进去。后者本质上就是RAG也是目前处理超长文档的主流路线。6.3 输出重复、车轱辘话来回绕这个问题在对话场景特别常见。最经典的原因是贪心解码配合低温度导致模型死磕概率最高的那几条路径绕进循环出不来。另一个贡献因素是重复惩罚参数设得太低模型意识不到自己在复读。我的排查顺序是先看看是不是解码参数太低把温度调到0.7以上再把重复惩罚调到1.1左右试一轮如果还不行检查训练数据里是不是有大量重复句式这一条经常被人忽视——模型把“复读”当成了语言风格的一部分。另外设置n-gram阻断直接禁止某个连续片段在输出里重复出现超过一次也能快速止血。6.4 评测分数高实际体验差最迷惑的坑离线评测集上跑出来的指标很漂亮一上线用户反馈却是各种难用。原因通常出在评测集和真实分布不一致。比如评测集里大部分问题都很短、很清晰而线上用户的问题夹杂口语、错别字、多轮上下文模型在“没见过的场景”上自然会露馅。我现在的做法是每次升级模型前除了维护核心评测集还会单独收集一批往期线上真实问题加上各种边界情况比如超长问题、带干扰信息的问题、明显诱导性的问题。评测时对这些类型分别统计通过率避免一个平均分掩盖住某一类场景的塌方。把上面这些常见问题汇总成一张速查表现象常见原因排查思路答非所问上下文被截断、提示词模糊检查实际送入模型的token序列确认真实输入长度编造事实模型缺乏事实校验通道加RAG、约束解码、提示词允许“不知道”复读循环温度过低、重复惩罚不足调高温、调高重复惩罚、加n-gram阻断评测分高但体验差评测集与线上分布不一致补充真实案例与边界案例分类统计指标微调后能力退化学习率过大、数据过少降低学习率、加回预训练数据混合我实际做过的几个项目里最深的感受是大语言模型项目的成功与否往往不取决于把模型做到了多大而取决于有没有把数据、评测、提示词这三件事扎实地打磨到位。模型的通用能力在同代产品里差距并没有想象中那么大真正拉开体验差距的是对场景的理解和围绕模型搭起来的工程骨架。如果你正准备入坑我的建议是别急着追新模型先用最小成本把一个开源的百亿级模型跑通一个完整的评估闭环再决定要不要往上堆算力。把“预测下一个词”这套朴素的逻辑吃透后面再多的技巧都只是它的延伸罢了。