我最初折腾大模型的时候,和大多数人一样,是从调API开始的。让模型续写一段新闻、翻译一句英文、补全一段代码,效果确实惊艳,但用久了心里总有一个疙瘩:它到底是怎么做到的?是真的“理解”了我在说什么,还是某种高级的文字接龙?后来我开始自己加载开源的权重跑推理,看论文、试微调、观察中间层的输出,才逐步把“文本生成大模型”这几个字背后的机制捋清楚。这篇文章就是把那些底层原理用最直白的方式讲一遍,不堆数学公式,不贴一堆看不懂的术语,只讲清楚“大模型生成一句话时,每一步到底发生了什么”。如果你懂一点Python,知道“概率”这个词,哪怕没碰过深度学习,也能跟上。读完你会发现,那些看起来聪明的回答背后,其实是一个非常简洁——甚至简单到有点朴素——的机制。搞清楚这个,你再去看各种大模型技巧、调参指南,会有一个完全不同的视角。1. 从“续写”开始:大模型的核心不是理解,而是猜下一个词很多刚接触的人会觉得,大模型像搜索引擎一样,在数据库里找出最匹配你问题的答案,然后返回给你。这个印象大错特错。大模型更像一个“续写狂魔”:你给它一段话,它接着这段话往下写,一次只写一个词,写完再看一眼,继续写下一个,直到写出一整段。这个过程的学名叫自回归生成。所谓自回归,简单说就是:新的输出依赖前面已经生成的所有内容。你在聊天框里输入“今天天气”,它内部做的事情不是“检索今天的天气”,而是计算“今天天气”后面最可能跟什么词——“很好”?“很热”?“怎么样?”——选一个出来,拼上去,变成“今天天气很好”,然后再继续计算“今天天气很好”后面跟什么。这个朴素到几乎像是骗人的机制,恰恰是所有文本生成大模型的底层逻辑,包括那些动辄几千亿参数的大模型,本质都逃不开“一次一个词地续写”。1.1 自回归机制:把整句话拆成无数次“答题”在模型眼里,任何文本都不是一连串连续的意义,而是一个token序列。token可以简单理解为“词元”——英文里接近一个单词或单词片段,中文里往往是词语或字。模型的工作,就是对序列中下一个token打分:给定前面所有的token,每一个候选token有多大概率出现在这里。如果写成数学形式,那就是一个条件概率链:P(整个句子) = P(token1) × P(token2 | token1) × P(token3 | token1, token2) × ...训练时,模型就是拿海量文本,反复练习这种“猜下一个词”的游戏。它有几千亿个参数,这些参数记下来的,就是不同上下文条件下,下一个词的概率分布。这句话很关键:模型记住的不是某个问题的“标准答案”,而是词与词之间的统计关联。你问它“中国的首都是哪里”,它能说出北京,并不是因为它在数据库里查到了北京这个答案,而是因为人类语料里,“中国的首都”后面跟“是北京”这个词序列出现的概率极高,它只是在完成概率最大的续写。我在跑模型的时候,第一次真正意识到这件事,是从一张“top 5候选词”的调试输出里看到:输入“今天天气”,模型给前五个候选词分别打了分,其中“很好”概率最高,但“不错”“一般”“怎么样”也有不小的概率。那一刻我突然明白,模型不是在回答你的问题,而是在和概率分布共舞。1.2 输出层:Softmax是怎么把“打分”变成“概率”的模型内部的计算过程,最终会得到一长串分数,每个分数对应词表里的一个token。这个分数叫logits,字面意思就是“未归一化的对数概率”。但光有分数还不够,我们需要的是“概率”——所有候选词的概率加起来必须等于1,这样才能从中采样。这一步靠的就是Softmax函数:p_i = exp(logits_i) / Σ exp(logits_j)通俗讲,就是把每个分数做指数运算后,再除以所有分数的总和。指数运算的作用是“拉开差距”:原本分数高一点的,经过指数放大后会更高;原本分数低一点的,会被压得更低。最终得到一组和为1的概率分布。所以说,模型每生成一个token,真正做的动作是:把当前已经生成的所有token喂进去,通过几十层神经网络算出每个候选词的概率,然后按照概率抽样。抽样的时候可以纯随机,也可以取概率最大的那个,这就是后面会说的解码策略问题了。这里有一个新手常踩的理解误区:以为模型是“想好了整句答案再说出来”。实际上模型只有“当前这一刻的概率”,并没有全局的规划能力。你让它写一篇五百字的文章,它不是先搭好框架再填内容,而是像人打字一样,打完第一个词,才知道第二个词往哪走。区别在于人靠的是语义理解,模型靠的是统计规律。这也是为什么长文本生成到后面容易逻辑混乱——它没有一开始就规划好结尾。2. 喂给模型的是数字,不是文字:Token化与Transformer架构如果说自回归是这套系统的“玩法”,那Transformer就是承载这个玩法的“物理实体”。它解决了一个更底层的问题:模型怎么把一个词变成它能计算的数字?怎么记住一句话里的先后顺序?怎么在几万个词的范围内捕捉“谁和谁有关系”?在Transformer出现之前,循环神经网络是处理序列的主流方案。RNN像人读句子一样,从左到右一个词一个词地读,把之前的信息存在“记忆单元”里。这个方案的痛点很明显:句子一旦太长,早先的信息经过层层传递会丢失,也就是大家常说的长距离依赖问题。而且RNN不能并行计算——第10个词必须等前9个算完才能算,训练效率很低。Transformer的诞生直接把这两个痛点同时解决掉了。它用自注意力机制替代了循环结构,让序列里任意两个位置的词可以“直接对话”,不管距离多远。这一步太关键了。2.1 Token化:中文和英文的“切分”方式完全不同在进入Transformer之前,文本必须先被切成token。这一步叫tokenization(分词)。英文世界里,像“unbelievable”这样的词,可能会被切成“un”、“believ”、“able”,而不是完整保留。原因是词表大小有限,把常见词根、前缀后缀拆开,可以用更小的词表覆盖更多的词,同时减少生僻词的困扰。中文的情况不太一样。中文字和词没有天然空格,分词器通常会把常见的双字词、三字词切成一个token,但也会在字级别切分。比如“北京”可能是一个token,但“北京市朝阳区”就会被切成一串token。这就是为什么同样长度的中文和英文,最终token数量差很多——中文的token信息密度通常更高。关于tokenization有两个实操中一定会踩到的点。第一,模型的处理上限基本都用token数衡量,不是字数。很多模型的上下文长度是4096、8192或更多token,一张A4纸的中文约1000字,大约1500到2000个token。你以为能塞进很长一段资料,一算token却发现早就超限了。调API时,计费也是按token算的,不是按字数。第二,特殊token的存在。除了文字token,词表里还塞了一堆控制用的特殊token,比如表示句子开始、结束、填充用的占位符,或者对话里区分“用户消息”和“模型回复”的分隔符。这些特殊token是预训练时就设定好的,微调时绝对不能乱动。之前有人做微调,不小心改了特殊token的ID,结果模型生成时不断吐无意义的乱码符号,排查了好久才发现是这里的问题。2.2 自注意力:让每个词都能“回头看”整句话自注意力机制这个名字听着唬人,拆开说其实不复杂。你可以把它想象成一场跨部门会议:句子里的第i个词,需要给其他所有词发一个问题:“我关心什么特征?”其他词收到后,根据自己手头的“身份信息”和“内容信息”,分别给出回答。第i个词汇总所有回答,知道自己在当前的上下文里,应该重点关注谁。在计算层面,这个过程通过三个矩阵实现:Q(查询)、K(键)、V(值)。每个位置的token,都通过乘以不同的权重矩阵,得到自己的Q、K、V三个向量。Q代表“我想从别人那里找什么”,K代表“我能提供什么信息”,V代表“我真正携带的内容”。注意力分数就是Q和K做点积,反映“你想找的东西,我这里有没有”。最后用这个分数对V加权求和,得到这个位置新的表示。用生活场景类比:想象你在读一篇报道,里面提到“苹果公司发布了新品”。句子里的“苹果”这个词,它需要决定自己的注意力偏向谁——是“公司”还是“水果”?通过自注意力机制,它会把大部分注意力权重分配给“公司”这个词,因为它发现“公司”提供的语境信息(K)和自己要找的信息(Q)匹配度最高。于是“苹果”在这句话里的语义表示,会更多地融入“公司”相关特征。这就是为什么模型能在不同语境里区分一词多义。但注意力本身不关心词序。把“苹果发布新品”倒过来变成“新品发布苹果”,注意力计算出来的结果可能一模一样。为了保留先后顺序,Transformer给每个位置的token注入一个位置编码——一组代表位置信息的向量,加在token向量上,让模型知道这个token在序列里的第几位。这一点非常重要,因为人类语言往往“先说的是主语,后说的是宾语”,词序本身就是信息的一部分。我在实操中有一个很深的体会:自注意力机制让模型拥有了“海里捞针”的能力——你可以在几万字的上下文里,让句子间的关联信息被捕捉到。但代价是计算量是平方级增长的。一句话有n个token,注意力要计算n×n两两之间的关系。这也是为什么长文本场景特别吃显存,也是后来各种稀疏注意力、线性注意力优化的出发点。3. 预训练三阶段:从“续写机器”到“对话助手”的关键流程现在很多人说“大模型”,实际上默认说的是一套完整的系统,而不只是一个基座模型。从原始模型到你我聊天框里的那个“聪明助手”,中间其实走过了三个阶段:无监督预训练、监督微调、人类反馈对齐。每个阶段解决的问题完全不同。市面上常见的开源基座模型,在第一个阶段完成后,具备的是“续写能力”——你给它一段话,它能顺着写得像模像样,但它不会“回答问题”,不知道什么叫“指令”,甚至不知道应该以什么样的格式回应你。你问“你是谁”,它可能一本正经地继续写“你是谁”相关的百科内容,而不是告诉你“我是一个AI助手”。之所以会出现这种情况,是因为预训练数据的形态就是“互联网上的海量文本”,其中绝大多数是叙述性文字,不是一问一答式对话。要让模型从“会续写”变成“会对话”,必须引入后续阶段。3.1 指令微调(SFT):教模型“听人话”第二阶段做的是监督微调,简称SFT。核心操作是收集大量“用户指令—人工编写的高质量回复”这样的配对数据,把模型的续写能力往“按指令行事”的方向校准。这个阶段的数据质量远比数量重要。我见过有人拿几百万条对话数据去做微调,结果模型越调越蠢,答非所问、车轱辘话、风格混乱;反而有人只用了几千条精心打磨的高质量指令数据,效果立竿见影。原因是SFT阶段的学习本质上是在“示范”:你给模型看什么样的输入应该对应什么样的输出,模型会快速模仿这种模式。如果示范本身乱七八糟,模型学到的就是“乱”。SFT阶段还有一个很容易忽略的细节:模型在这一阶段需要学会的不是“背答案”,而是“建立对话习惯”。比如知道用户的输入以特殊token包裹时,自己要开始生成回复;知道一条消息结束后,要等待下一条用户输入而不是自说自话。很多微调新手只关注内容对不对,忽略了对话格式的学习,结果模型生成时不知道停,一口气写出一整篇文章。3.2 人类反馈对齐(RLHF):把“答得上”变成“答得好”第三阶段是目前大模型能让人觉得“聪明”的关键,也是三阶段里最难复现的部分,叫基于人类反馈的强化学习(RLHF)。SFT之后,模型已经能对答如流了,但它的目标函数和人类偏好并不完全一致。预训练和SFT阶段,模型学的是“最大化下一个词的预测概率”;但人眼里的“好回答”,往往是“内容丰富”“语气自然”“有安全意识”,这些很难用概率衡量。于是就有了RLHF:先让人对模型的多个回复打分排序,用这些偏好数据训练一个“奖励模型”,再用强化学习算法让语言模型在生成过程中尽量获取高奖励。用一个粗浅但好懂的类比:第一阶段是让一个人看书自学写作,第二阶段是给他看范文让他模仿,第三阶段是找一位老师批改他的文章,告诉他“这样写加分”“那样写减分”,反复训练让他越写越符合老师的偏好。到了这一步,我才真正理解为什么那些大模型回答起来语气那么自然——它在第三阶段被专门训练过“人的偏好”。同样一道题,直愣愣给出答案和先解释再举例、最后给结论,后者获得的人类反馈分数明显更高。模型学到的是这种结构,而不是某个具体的答案。这也是为什么市面上很多“仿品”大模型效果差的根源:只做了前两个阶段,没有做RLHF,输出内容虽然正确,但总是透着一种干巴巴的机械感。这里补充一个训练细节:RLHF对算力的消耗极大,路线也比较繁琐。现在有不少开源项目用“直接偏好优化”这类简化方案替代,效果略逊,但胜在轻量。如果你自己动手做对齐,建议先在小模型上跑通流程再扩大规模,别一上来就砸大算力。3.3 Loss掩码与训练批次:模型在训练时到底“看”了什么很多人看完训练流程会问:模型训练时,一条样本是怎么送进去的?是不是把整段对话全部拿来学习?这里面有一个特别容易忽视的细节:不是所有token都在参与Loss计算。以一次对话训练为例,一条样本通常由“用户消息”和“助手回复”拼接而成。但训练时,模型只对“助手回复”部分计算预测损失,对“用户消息”部分做掩码处理——也就是说,用户部分只是被当作上下文喂给模型,模型不需要预测用户会说什么,只需要学会在正确的时机开始生成“助手回复”。这个设计的逻辑在于:我们需要模型学习的是回答的能力,而不是学习用户怎么说问题。如果对全部token计算损失,会让模型把精力分散在“预测用户下一句会问什么”上,显然跑偏了。实操中,这个掩码逻辑要在数据预处理阶段做到非常严谨。我见过有人做数据时漏掉掩码,或者掩码位置错位,导致同一个batch里模型既在学回答又在学提问,最后模型输出总是带出奇怪的“用户语录”。排查这种问题特别痛苦,因为从Loss曲线上看一切正常,只有生成结果不对劲,最后是逐条检查训练样本才定位到问题。4. 推理阶段:从概率分布到一句完整的话讲完训练,再来看推理。模型在训练阶段已经学完了所有的参数,推理时参数不再更新,它只做一件事:基于输入,逐步生成token。但“从概率分布里挑出哪个词”这个过程,策略有讲究。如果你直接让模型每次都选概率最大的那个token,得到的是贪心解码。这种策略生成的文本通常非常“平均”——每个位置都选最俗套的下一个词,结果往往是平淡无奇、甚至重复啰嗦。打个比方,让一个作家每次都写最保险的句子,写出来的东西一定无聊透顶。为了让生成更有变化,便有了各种采样策略。这些策略控制的核心,就是“在多大程度上保留概率分布中的意外性”。4.1 温度参数:给概率分布“加热”或“降温”**温度(temperature)**是最常用的控制手段,它直接作用于Softmax。p_i = exp(logits_i / T) / Σ exp(logits_j / T)当T小于1时,logits被“压缩”到更极端的区间,概率高的token会更高,输出会更确定、更保守,适合代码生成、事实问答这类需要准确率的场景。当T大于1时,logits之间的差距被抹平,原本概率低的token也有机会被选中,输出会更多样、更有创造力,但错误率也随之上升。我自己的经验是:写代码时温度调到0.2左右,模型基本就按照最常规的写法输出;做头脑风暴、文案创意时调到0.8到1.0,会蹦出很多平时想不到的表述;超过1.2基本就开始胡说八道了,除非你有意要特别“天马行空”的结果。这个“度”需要针对具体模型调试,不同模型在相同温度下的表现差异很大,没有绝对的标准值。4.2 Top-K 与 Top-P:只从“候选人”里挑词温度调节的是所有词的概率分布,而Top-K和Top-P是直接砍掉一批“不靠谱”的候选词。Top-K只保留概率最高的K个候选词,其余全部排除,再在这些候选词里重新归一化采样。比如K=40,表示每次只从概率最高的40个词里选。这样做的好处是防止模型在那些极端低概率的词上“抽风”。问题是K是固定值,不同上下文的概率分布形态差别很大,固定K有时候会错误地排除很多本应合理的词。Top-P(也叫核采样)是另一种思路:动态确定候选词的截断范围。把所有候选词按概率从高到低排序,累加概率直到超过P这个阈值,比如0.9,那么这组词就是本次采样的候选范围。概率分布越平滑,候选词就越多;概率分布越集中,候选词越少。相比之下,Top-P更贴合概率分布的实际情况,是目前实践中最常用的一套方案。在主流推理框架里,温度、Top-K、Top-P经常组合使用,比如把温度设为0.7、Top-P设为0.9,效果通常比单独使用某一个要好。实际操作时建议先固定Top-P,微调温度,最后再考虑Top-K。4.3 推理加速的真相:KV Cache与重复惩罚推理阶段还有个绕不开的话题:性能。同样是生成1000个字,为什么有的框架快得多?核心秘密在于KV Cache。之前讲了自注意力机制,每生成一个新token,都要对前面所有token重新计算一遍注意力。如果每次从头算起,生成后面词时前面积累的计算全部作废,效率极低。KV Cache的做法是:把前面已经算好的K和V向量缓存下来,新token只需要算自己的Q、K、V,然后去和缓存的KV做注意力,省掉重复计算。但KV Cache的代价是显存。它的大小跟“序列长度×层数×注意力头数×维度”成正比,这也是为什么长文本生成时显存消耗涨得飞快。我跑过一些长上下文实验,序列从2k涨到32k,KV Cache能把几十GB的显存吃光。理解了这一点,你就明白为什么很多框架不断优化KV Cache的量化、压缩和淘汰策略——这些都是在和显存极限做斗争。另外,长文本生成里还有一个很现实的问题:重复。模型到了中后段,很容易开始反复输出相同的词组或句子。原因还是那个核心——它只关注局部概率,一旦某段话在之前出现过,模型发现“顺着重复写下去”概率最高,就会陷入循环。解决办法一般是加一个重复惩罚项,把已经出现过token的分数压低;更精细的做法是用“无重复n-gram”约束,禁止模型连续输出相同短语。5. 那些“看似聪明”的能力,其实是统计规律的副产物聊到这里,一个更根本的问题浮现出来:模型的这些能力到底是怎么“长”出来的?它不是程序员手写规则编出来的,而是从海量文本中自己“长”出来的。这种长大过程,本质上是在学一个极其庞大的概率表。你可以把大模型的知识,理解成一种“压缩的互联网”——它没有把每一篇文章存成原文,而是把所有文本中的模式、关联、结构,压缩进了几千亿的参数里。这就是为什么大模型会给人一种“理解”的错觉。当你说“帮我写一封辞职信”,它给出的文本那么贴切,看起来像是真的理解了你的意图。但拆到底层,它只是学会了“辞职信”这种体裁的词语组合规律:开头要写称谓、中间要写感谢、结尾要写日期。它不需要“懂得”什么是辞职,它只需要知道这个上下文里最可能出现的词序列是什么样子。5.1 能力涌现:为什么大模型像个通才“涌现”是这几年的热词,意思是:当模型规模跨过某个阈值后,一些能力突然冒出来了——比如多步推理、代码生成、在没专门训练过的任务上也表现良好。这种现象和参数量的增长关系很大,但背后的机制至今没有完全定论,一种主流的解释是:足够多的参数、足够广的语料覆盖,让模型学会了大量子任务的基本技能,这些技能在推理时被组合运用,于是产生了“看起来像通才”的效果。你让一个7B参数的小模型做算术,它能做简单的加减法,但遇到三位数乘三位数就开始瞎编。让一个超过100B的模型做同样的问题,却经常能分步算出正确答案。不是大模型被人教了更好的算法,而是参数量变多之后,它内部的表示空间能够容纳更复杂的中间步骤,相当于“工作记忆”更宽了,可以边算边记住中间结果。我自己的感受是:把大模型理解成一个“超大规模的模式匹配器”并不为过。它的能力上限,很大程度上取决于训练语料里覆盖了多少种模式。语料里有大量“思考过程”格式的文本,它学会的就是分步推理;语料里代码占比高,它写代码就熟练。这也解释了为什么不同团队用不同配比的语料训练,最终模型擅长领域的差异会很大。5.2 幻觉的根源:模型并不拥有“事实错误”的概念大模型会一本正经地编造听起来合理但实际错误的内容,这个问题被称作“幻觉”。理解它的根源,要从训练目标说起。训练时,模型的目标只有一个:最大化下一个token的预测概率。这个目标里没有“事实性”这一项。它只知道语料里“某段话后面最常跟什么词”,不知道这段话在现实世界里是不是对的。所以当用户问一个语料里稀缺的问题,或者问题本身设置了一个不存在的假设时,模型并不会停下来说“我不知道”,它会强行续写出一段在语言上通顺、但内容上无中生有的回答。有个很常见的现象:你问模型“某市有一个叫XX的餐厅吗”,哪怕这个餐厅完全不存在,模型也可能编出一个地址、几道招牌菜,说得煞有其事。因为它见过大量“回答餐厅推荐”的文本模式,知道这种回答应该包括结构,但它没有足够的信息来判断这家餐厅是否真实存在。知道这一点后,你会明白为什么和模型对话时,“提示词里提供详细信息”特别重要——你给的信息越充分,模型需要瞎编的空间就越小。5.3 上下文窗口与知识时效:工程师必须知道的两个边界大模型还有一个经常被误解的特性:上下文窗口。上下文窗口决定了模型在生成当前token时,能“看到”最多多长的历史内容。但注意,窗口内的内容并非都被同等重视。自注意力是平方级计算,序列越长,注意力的分布往往越稀疏,靠中间的信息容易被“挤”到两头去。业界有个著名的“长海捞针”测试:在很长的上下文里埋一个关键信息,然后问模型,模型经常找不到那个信息。这就解释了为什么“把资料全塞进上下文里”并不是万能方案,尤其是关键信息埋在中段时,效果往往意外地差。另一个边界是知识时效。模型的知识“冻结”在训练数据收集时间点。训练完成后的模型,不会自动知道新发生的事情。模型发布时间之后的事件,它要么不知道,要么根据语言学到的规律瞎猜。这也是为什么现在主流大模型应用都会外挂检索环节:先从外部数据库里搜出最新资料,再塞进上下文让模型基于这些资料回答。理解了模型原理,你就知道这个“检索增强生成”的后端设计并不是一时兴起,而是针对模型固有缺陷的必然补丁。6. 从原理到动手:我建议你亲手做一次“概率观察实验”如果只看不练,上面这些内容很容易变成“好像懂了但用不起来”的知识。我最推荐初学者做的一件事,不是马上训练大模型——那个成本太高了——而是加载一个几百M参数的开源小模型,亲眼看一次“概率分布长什么样”。现在跑小模型的工具链已经很成熟了。如果你本地有支持CUDA的显卡,或者退而求其次用CPU跑,也完全没问题,只是慢一些。下面这段Python脚本,能让你直观看到“输入一段话后,模型预测下一个词的概率分布”:import torch from transformers import AutoTokenizer, AutoModelForCausalLM # 换成你手头任意一个开源基座模型的路径 MODEL_NAME = "your-model-path" tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) model = AutoModelForCausalLM.from_pretrained(MODEL_NAME) input_text = "今天天气" inputs = tokenizer(input_text, return_tensors="pt") with torch.no_grad(): outputs = model(**inputs) # 取最后一个位置的logits next_logits = outputs.logits[0, -1, :] probs = torch.softmax(next_logits, dim=-1) # 打印概率最高的前10个token top_probs, top_indices = torch.topk(probs, 10) for prob, idx in zip(top_probs, top_indices): token = tokenizer.decode(idx) print(f"{token}: {prob:.4f}")当你真的看到输出时,会发现一件很有意思的事:不仅是“很好”“不错”这些合理候选,连一些奇怪的词也在列表里,只是概率很低。这个“低概率尾巴”正是温度参数起作用的舞台,也是模型能产生创造性输出的来源。你可以再手动改一改温度参数,比如设成0.1、0.5、1.0、1.5,重新算softmax,你会看到同一句话、同一个模型,在不同温度下给出的排名产生很有启发性的变化——温度越低,概率越集中;温度越高,低概率词的排名会明显上浮。做这个实验的时候,有几个坑提前说一下。第一,模型下载的时候,注意先确认它是“基座模型”还是“对话模型”。对话模型在原始续写任务上表现会“怪怪的”,因为它的行为已经被SFT和RLHF阶段重新塑造了,直接续写时可能输出大量对话格式文本。这个现象本身也是很好的体验——你能直观感受到三个阶段对模型行为的改变有多大。第二,中文模型的分词结果可能和你的直觉不同。“今天天气”这几个字,不一定被切成整整四个字的token,可能是“今天”和“天气”两个词元。打印token_id和decoded结果时留意看一下,能加深你对tokenization连贯逻辑的理解。第三,如果模型比较大,记得加一行model.eval(),把模型切换到推理模式,关闭dropout之类的训练专用机制。不然同一个输入每次跑出来的结果可能有细微差异——注意,这里的差异来自随机性,不是模型学到了什么新东西。7. 最后分享一点自己踩出来的经验原理讲完了,最后聊点我在实际项目中反复被验证过的心得,也可能是你接下来最容易踩到的地方。第一,不要把温度参数当成万能旋钮。它只能改变生成时采样分布的形态,不能改变模型“会不会这件事”。一个模型本来就不懂某门语言,你把温度调到最高,它不会突然变懂,只会把各种乱码一样的词拼得更天马行空。所以先选对模型、选对数据,最后才轮到调温度。第二,微调之前一定要先跑通小规模的pipeline。我见过太多人一上来就集齐了几万条数据,准备微调一个大模型,结果因为tokenizer的特殊token处理不对、训练时的掩码没加对、或者是数据格式和预训练不一致,跑了一整天之后拿到的模型完全不可用。正确姿势是先拿几百条数据,在最小的基座模型上跑,从batch到loss全部检查一遍,确认无误再上规模。第三,了解原理之后,你会更懂提示词的价值。很多人觉得提示词工程是玄学,但拆开看,提示词的本质是在为模型构造一个更有利的概率环境。你把任务背景写清楚,相当于给模型提供了更长的上下文,它“续写时”的选择空间会被大幅约束到正确方向上。你要求模型“一步一步思考”,本质上是让它生成更多中间token,给概率链留出更充足的计算路径。这些都不是魔法,而是这套概率机制的自然推论。文本生成大模型的原理,远没有它看起来那么神秘。往上拆,是一个接一个的概率预测;往底层看,是海量参数对不同上下文的概率记忆。理解这个最朴素的内核之后,那些营销号吹得眼花缭乱的概念,什么“智能涌现”“对齐”“思考链”,都会回到一个平实的坐标系里,你会知道自己真正能控制的是什么、模型的边界在哪里、以及下一步该往哪个方向使劲。
我最初折腾大模型的时候,和大多数人一样,是从调API开始的。让模型续写一段新闻、翻译一句英文、补全一段代码,效果确实惊艳,但用久了心里总有一个疙瘩:它到底是怎么做到的?是真的“理解”了我在说什么,还是某种高级的文字接龙?后来我开始自己加载开源的权重跑推理,看论文、试微调、观察中间层的输出,才逐步把“文本生成大模型”这几个字背后的机制捋清楚。这篇文章就是把那些底层原理用最直白的方式讲一遍,不堆数学公式,不贴一堆看不懂的术语,只讲清楚“大模型生成一句话时,每一步到底发生了什么”。如果你懂一点Python,知道“概率”这个词,哪怕没碰过深度学习,也能跟上。读完你会发现,那些看起来聪明的回答背后,其实是一个非常简洁——甚至简单到有点朴素——的机制。搞清楚这个,你再去看各种大模型技巧、调参指南,会有一个完全不同的视角。1. 从“续写”开始:大模型的核心不是理解,而是猜下一个词很多刚接触的人会觉得,大模型像搜索引擎一样,在数据库里找出最匹配你问题的答案,然后返回给你。这个印象大错特错。大模型更像一个“续写狂魔”:你给它一段话,它接着这段话往下写,一次只写一个词,写完再看一眼,继续写下一个,直到写出一整段。这个过程的学名叫自回归生成。所谓自回归,简单说就是:新的输出依赖前面已经生成的所有内容。你在聊天框里输入“今天天气”,它内部做的事情不是“检索今天的天气”,而是计算“今天天气”后面最可能跟什么词——“很好”?“很热”?“怎么样?”——选一个出来,拼上去,变成“今天天气很好”,然后再继续计算“今天天气很好”后面跟什么。这个朴素到几乎像是骗人的机制,恰恰是所有文本生成大模型的底层逻辑,包括那些动辄几千亿参数的大模型,本质都逃不开“一次一个词地续写”。1.1 自回归机制:把整句话拆成无数次“答题”在模型眼里,任何文本都不是一连串连续的意义,而是一个token序列。token可以简单理解为“词元”——英文里接近一个单词或单词片段,中文里往往是词语或字。模型的工作,就是对序列中下一个token打分:给定前面所有的token,每一个候选token有多大概率出现在这里。如果写成数学形式,那就是一个条件概率链:P(整个句子) = P(token1) × P(token2 | token1) × P(token3 | token1, token2) × ...训练时,模型就是拿海量文本,反复练习这种“猜下一个词”的游戏。它有几千亿个参数,这些参数记下来的,就是不同上下文条件下,下一个词的概率分布。这句话很关键:模型记住的不是某个问题的“标准答案”,而是词与词之间的统计关联。你问它“中国的首都是哪里”,它能说出北京,并不是因为它在数据库里查到了北京这个答案,而是因为人类语料里,“中国的首都”后面跟“是北京”这个词序列出现的概率极高,它只是在完成概率最大的续写。我在跑模型的时候,第一次真正意识到这件事,是从一张“top 5候选词”的调试输出里看到:输入“今天天气”,模型给前五个候选词分别打了分,其中“很好”概率最高,但“不错”“一般”“怎么样”也有不小的概率。那一刻我突然明白,模型不是在回答你的问题,而是在和概率分布共舞。1.2 输出层:Softmax是怎么把“打分”变成“概率”的模型内部的计算过程,最终会得到一长串分数,每个分数对应词表里的一个token。这个分数叫logits,字面意思就是“未归一化的对数概率”。但光有分数还不够,我们需要的是“概率”——所有候选词的概率加起来必须等于1,这样才能从中采样。这一步靠的就是Softmax函数:p_i = exp(logits_i) / Σ exp(logits_j)通俗讲,就是把每个分数做指数运算后,再除以所有分数的总和。指数运算的作用是“拉开差距”:原本分数高一点的,经过指数放大后会更高;原本分数低一点的,会被压得更低。最终得到一组和为1的概率分布。所以说,模型每生成一个token,真正做的动作是:把当前已经生成的所有token喂进去,通过几十层神经网络算出每个候选词的概率,然后按照概率抽样。抽样的时候可以纯随机,也可以取概率最大的那个,这就是后面会说的解码策略问题了。这里有一个新手常踩的理解误区:以为模型是“想好了整句答案再说出来”。实际上模型只有“当前这一刻的概率”,并没有全局的规划能力。你让它写一篇五百字的文章,它不是先搭好框架再填内容,而是像人打字一样,打完第一个词,才知道第二个词往哪走。区别在于人靠的是语义理解,模型靠的是统计规律。这也是为什么长文本生成到后面容易逻辑混乱——它没有一开始就规划好结尾。2. 喂给模型的是数字,不是文字:Token化与Transformer架构如果说自回归是这套系统的“玩法”,那Transformer就是承载这个玩法的“物理实体”。它解决了一个更底层的问题:模型怎么把一个词变成它能计算的数字?怎么记住一句话里的先后顺序?怎么在几万个词的范围内捕捉“谁和谁有关系”?在Transformer出现之前,循环神经网络是处理序列的主流方案。RNN像人读句子一样,从左到右一个词一个词地读,把之前的信息存在“记忆单元”里。这个方案的痛点很明显:句子一旦太长,早先的信息经过层层传递会丢失,也就是大家常说的长距离依赖问题。而且RNN不能并行计算——第10个词必须等前9个算完才能算,训练效率很低。Transformer的诞生直接把这两个痛点同时解决掉了。它用自注意力机制替代了循环结构,让序列里任意两个位置的词可以“直接对话”,不管距离多远。这一步太关键了。2.1 Token化:中文和英文的“切分”方式完全不同在进入Transformer之前,文本必须先被切成token。这一步叫tokenization(分词)。英文世界里,像“unbelievable”这样的词,可能会被切成“un”、“believ”、“able”,而不是完整保留。原因是词表大小有限,把常见词根、前缀后缀拆开,可以用更小的词表覆盖更多的词,同时减少生僻词的困扰。中文的情况不太一样。中文字和词没有天然空格,分词器通常会把常见的双字词、三字词切成一个token,但也会在字级别切分。比如“北京”可能是一个token,但“北京市朝阳区”就会被切成一串token。这就是为什么同样长度的中文和英文,最终token数量差很多——中文的token信息密度通常更高。关于tokenization有两个实操中一定会踩到的点。第一,模型的处理上限基本都用token数衡量,不是字数。很多模型的上下文长度是4096、8192或更多token,一张A4纸的中文约1000字,大约1500到2000个token。你以为能塞进很长一段资料,一算token却发现早就超限了。调API时,计费也是按token算的,不是按字数。第二,特殊token的存在。除了文字token,词表里还塞了一堆控制用的特殊token,比如表示句子开始、结束、填充用的占位符,或者对话里区分“用户消息”和“模型回复”的分隔符。这些特殊token是预训练时就设定好的,微调时绝对不能乱动。之前有人做微调,不小心改了特殊token的ID,结果模型生成时不断吐无意义的乱码符号,排查了好久才发现是这里的问题。2.2 自注意力:让每个词都能“回头看”整句话自注意力机制这个名字听着唬人,拆开说其实不复杂。你可以把它想象成一场跨部门会议:句子里的第i个词,需要给其他所有词发一个问题:“我关心什么特征?”其他词收到后,根据自己手头的“身份信息”和“内容信息”,分别给出回答。第i个词汇总所有回答,知道自己在当前的上下文里,应该重点关注谁。在计算层面,这个过程通过三个矩阵实现:Q(查询)、K(键)、V(值)。每个位置的token,都通过乘以不同的权重矩阵,得到自己的Q、K、V三个向量。Q代表“我想从别人那里找什么”,K代表“我能提供什么信息”,V代表“我真正携带的内容”。注意力分数就是Q和K做点积,反映“你想找的东西,我这里有没有”。最后用这个分数对V加权求和,得到这个位置新的表示。用生活场景类比:想象你在读一篇报道,里面提到“苹果公司发布了新品”。句子里的“苹果”这个词,它需要决定自己的注意力偏向谁——是“公司”还是“水果”?通过自注意力机制,它会把大部分注意力权重分配给“公司”这个词,因为它发现“公司”提供的语境信息(K)和自己要找的信息(Q)匹配度最高。于是“苹果”在这句话里的语义表示,会更多地融入“公司”相关特征。这就是为什么模型能在不同语境里区分一词多义。但注意力本身不关心词序。把“苹果发布新品”倒过来变成“新品发布苹果”,注意力计算出来的结果可能一模一样。为了保留先后顺序,Transformer给每个位置的token注入一个位置编码——一组代表位置信息的向量,加在token向量上,让模型知道这个token在序列里的第几位。这一点非常重要,因为人类语言往往“先说的是主语,后说的是宾语”,词序本身就是信息的一部分。我在实操中有一个很深的体会:自注意力机制让模型拥有了“海里捞针”的能力——你可以在几万字的上下文里,让句子间的关联信息被捕捉到。但代价是计算量是平方级增长的。一句话有n个token,注意力要计算n×n两两之间的关系。这也是为什么长文本场景特别吃显存,也是后来各种稀疏注意力、线性注意力优化的出发点。3. 预训练三阶段:从“续写机器”到“对话助手”的关键流程现在很多人说“大模型”,实际上默认说的是一套完整的系统,而不只是一个基座模型。从原始模型到你我聊天框里的那个“聪明助手”,中间其实走过了三个阶段:无监督预训练、监督微调、人类反馈对齐。每个阶段解决的问题完全不同。市面上常见的开源基座模型,在第一个阶段完成后,具备的是“续写能力”——你给它一段话,它能顺着写得像模像样,但它不会“回答问题”,不知道什么叫“指令”,甚至不知道应该以什么样的格式回应你。你问“你是谁”,它可能一本正经地继续写“你是谁”相关的百科内容,而不是告诉你“我是一个AI助手”。之所以会出现这种情况,是因为预训练数据的形态就是“互联网上的海量文本”,其中绝大多数是叙述性文字,不是一问一答式对话。要让模型从“会续写”变成“会对话”,必须引入后续阶段。3.1 指令微调(SFT):教模型“听人话”第二阶段做的是监督微调,简称SFT。核心操作是收集大量“用户指令—人工编写的高质量回复”这样的配对数据,把模型的续写能力往“按指令行事”的方向校准。这个阶段的数据质量远比数量重要。我见过有人拿几百万条对话数据去做微调,结果模型越调越蠢,答非所问、车轱辘话、风格混乱;反而有人只用了几千条精心打磨的高质量指令数据,效果立竿见影。原因是SFT阶段的学习本质上是在“示范”:你给模型看什么样的输入应该对应什么样的输出,模型会快速模仿这种模式。如果示范本身乱七八糟,模型学到的就是“乱”。SFT阶段还有一个很容易忽略的细节:模型在这一阶段需要学会的不是“背答案”,而是“建立对话习惯”。比如知道用户的输入以特殊token包裹时,自己要开始生成回复;知道一条消息结束后,要等待下一条用户输入而不是自说自话。很多微调新手只关注内容对不对,忽略了对话格式的学习,结果模型生成时不知道停,一口气写出一整篇文章。3.2 人类反馈对齐(RLHF):把“答得上”变成“答得好”第三阶段是目前大模型能让人觉得“聪明”的关键,也是三阶段里最难复现的部分,叫基于人类反馈的强化学习(RLHF)。SFT之后,模型已经能对答如流了,但它的目标函数和人类偏好并不完全一致。预训练和SFT阶段,模型学的是“最大化下一个词的预测概率”;但人眼里的“好回答”,往往是“内容丰富”“语气自然”“有安全意识”,这些很难用概率衡量。于是就有了RLHF:先让人对模型的多个回复打分排序,用这些偏好数据训练一个“奖励模型”,再用强化学习算法让语言模型在生成过程中尽量获取高奖励。用一个粗浅但好懂的类比:第一阶段是让一个人看书自学写作,第二阶段是给他看范文让他模仿,第三阶段是找一位老师批改他的文章,告诉他“这样写加分”“那样写减分”,反复训练让他越写越符合老师的偏好。到了这一步,我才真正理解为什么那些大模型回答起来语气那么自然——它在第三阶段被专门训练过“人的偏好”。同样一道题,直愣愣给出答案和先解释再举例、最后给结论,后者获得的人类反馈分数明显更高。模型学到的是这种结构,而不是某个具体的答案。这也是为什么市面上很多“仿品”大模型效果差的根源:只做了前两个阶段,没有做RLHF,输出内容虽然正确,但总是透着一种干巴巴的机械感。这里补充一个训练细节:RLHF对算力的消耗极大,路线也比较繁琐。现在有不少开源项目用“直接偏好优化”这类简化方案替代,效果略逊,但胜在轻量。如果你自己动手做对齐,建议先在小模型上跑通流程再扩大规模,别一上来就砸大算力。3.3 Loss掩码与训练批次:模型在训练时到底“看”了什么很多人看完训练流程会问:模型训练时,一条样本是怎么送进去的?是不是把整段对话全部拿来学习?这里面有一个特别容易忽视的细节:不是所有token都在参与Loss计算。以一次对话训练为例,一条样本通常由“用户消息”和“助手回复”拼接而成。但训练时,模型只对“助手回复”部分计算预测损失,对“用户消息”部分做掩码处理——也就是说,用户部分只是被当作上下文喂给模型,模型不需要预测用户会说什么,只需要学会在正确的时机开始生成“助手回复”。这个设计的逻辑在于:我们需要模型学习的是回答的能力,而不是学习用户怎么说问题。如果对全部token计算损失,会让模型把精力分散在“预测用户下一句会问什么”上,显然跑偏了。实操中,这个掩码逻辑要在数据预处理阶段做到非常严谨。我见过有人做数据时漏掉掩码,或者掩码位置错位,导致同一个batch里模型既在学回答又在学提问,最后模型输出总是带出奇怪的“用户语录”。排查这种问题特别痛苦,因为从Loss曲线上看一切正常,只有生成结果不对劲,最后是逐条检查训练样本才定位到问题。4. 推理阶段:从概率分布到一句完整的话讲完训练,再来看推理。模型在训练阶段已经学完了所有的参数,推理时参数不再更新,它只做一件事:基于输入,逐步生成token。但“从概率分布里挑出哪个词”这个过程,策略有讲究。如果你直接让模型每次都选概率最大的那个token,得到的是贪心解码。这种策略生成的文本通常非常“平均”——每个位置都选最俗套的下一个词,结果往往是平淡无奇、甚至重复啰嗦。打个比方,让一个作家每次都写最保险的句子,写出来的东西一定无聊透顶。为了让生成更有变化,便有了各种采样策略。这些策略控制的核心,就是“在多大程度上保留概率分布中的意外性”。4.1 温度参数:给概率分布“加热”或“降温”**温度(temperature)**是最常用的控制手段,它直接作用于Softmax。p_i = exp(logits_i / T) / Σ exp(logits_j / T)当T小于1时,logits被“压缩”到更极端的区间,概率高的token会更高,输出会更确定、更保守,适合代码生成、事实问答这类需要准确率的场景。当T大于1时,logits之间的差距被抹平,原本概率低的token也有机会被选中,输出会更多样、更有创造力,但错误率也随之上升。我自己的经验是:写代码时温度调到0.2左右,模型基本就按照最常规的写法输出;做头脑风暴、文案创意时调到0.8到1.0,会蹦出很多平时想不到的表述;超过1.2基本就开始胡说八道了,除非你有意要特别“天马行空”的结果。这个“度”需要针对具体模型调试,不同模型在相同温度下的表现差异很大,没有绝对的标准值。4.2 Top-K 与 Top-P:只从“候选人”里挑词温度调节的是所有词的概率分布,而Top-K和Top-P是直接砍掉一批“不靠谱”的候选词。Top-K只保留概率最高的K个候选词,其余全部排除,再在这些候选词里重新归一化采样。比如K=40,表示每次只从概率最高的40个词里选。这样做的好处是防止模型在那些极端低概率的词上“抽风”。问题是K是固定值,不同上下文的概率分布形态差别很大,固定K有时候会错误地排除很多本应合理的词。Top-P(也叫核采样)是另一种思路:动态确定候选词的截断范围。把所有候选词按概率从高到低排序,累加概率直到超过P这个阈值,比如0.9,那么这组词就是本次采样的候选范围。概率分布越平滑,候选词就越多;概率分布越集中,候选词越少。相比之下,Top-P更贴合概率分布的实际情况,是目前实践中最常用的一套方案。在主流推理框架里,温度、Top-K、Top-P经常组合使用,比如把温度设为0.7、Top-P设为0.9,效果通常比单独使用某一个要好。实际操作时建议先固定Top-P,微调温度,最后再考虑Top-K。4.3 推理加速的真相:KV Cache与重复惩罚推理阶段还有个绕不开的话题:性能。同样是生成1000个字,为什么有的框架快得多?核心秘密在于KV Cache。之前讲了自注意力机制,每生成一个新token,都要对前面所有token重新计算一遍注意力。如果每次从头算起,生成后面词时前面积累的计算全部作废,效率极低。KV Cache的做法是:把前面已经算好的K和V向量缓存下来,新token只需要算自己的Q、K、V,然后去和缓存的KV做注意力,省掉重复计算。但KV Cache的代价是显存。它的大小跟“序列长度×层数×注意力头数×维度”成正比,这也是为什么长文本生成时显存消耗涨得飞快。我跑过一些长上下文实验,序列从2k涨到32k,KV Cache能把几十GB的显存吃光。理解了这一点,你就明白为什么很多框架不断优化KV Cache的量化、压缩和淘汰策略——这些都是在和显存极限做斗争。另外,长文本生成里还有一个很现实的问题:重复。模型到了中后段,很容易开始反复输出相同的词组或句子。原因还是那个核心——它只关注局部概率,一旦某段话在之前出现过,模型发现“顺着重复写下去”概率最高,就会陷入循环。解决办法一般是加一个重复惩罚项,把已经出现过token的分数压低;更精细的做法是用“无重复n-gram”约束,禁止模型连续输出相同短语。5. 那些“看似聪明”的能力,其实是统计规律的副产物聊到这里,一个更根本的问题浮现出来:模型的这些能力到底是怎么“长”出来的?它不是程序员手写规则编出来的,而是从海量文本中自己“长”出来的。这种长大过程,本质上是在学一个极其庞大的概率表。你可以把大模型的知识,理解成一种“压缩的互联网”——它没有把每一篇文章存成原文,而是把所有文本中的模式、关联、结构,压缩进了几千亿的参数里。这就是为什么大模型会给人一种“理解”的错觉。当你说“帮我写一封辞职信”,它给出的文本那么贴切,看起来像是真的理解了你的意图。但拆到底层,它只是学会了“辞职信”这种体裁的词语组合规律:开头要写称谓、中间要写感谢、结尾要写日期。它不需要“懂得”什么是辞职,它只需要知道这个上下文里最可能出现的词序列是什么样子。5.1 能力涌现:为什么大模型像个通才“涌现”是这几年的热词,意思是:当模型规模跨过某个阈值后,一些能力突然冒出来了——比如多步推理、代码生成、在没专门训练过的任务上也表现良好。这种现象和参数量的增长关系很大,但背后的机制至今没有完全定论,一种主流的解释是:足够多的参数、足够广的语料覆盖,让模型学会了大量子任务的基本技能,这些技能在推理时被组合运用,于是产生了“看起来像通才”的效果。你让一个7B参数的小模型做算术,它能做简单的加减法,但遇到三位数乘三位数就开始瞎编。让一个超过100B的模型做同样的问题,却经常能分步算出正确答案。不是大模型被人教了更好的算法,而是参数量变多之后,它内部的表示空间能够容纳更复杂的中间步骤,相当于“工作记忆”更宽了,可以边算边记住中间结果。我自己的感受是:把大模型理解成一个“超大规模的模式匹配器”并不为过。它的能力上限,很大程度上取决于训练语料里覆盖了多少种模式。语料里有大量“思考过程”格式的文本,它学会的就是分步推理;语料里代码占比高,它写代码就熟练。这也解释了为什么不同团队用不同配比的语料训练,最终模型擅长领域的差异会很大。5.2 幻觉的根源:模型并不拥有“事实错误”的概念大模型会一本正经地编造听起来合理但实际错误的内容,这个问题被称作“幻觉”。理解它的根源,要从训练目标说起。训练时,模型的目标只有一个:最大化下一个token的预测概率。这个目标里没有“事实性”这一项。它只知道语料里“某段话后面最常跟什么词”,不知道这段话在现实世界里是不是对的。所以当用户问一个语料里稀缺的问题,或者问题本身设置了一个不存在的假设时,模型并不会停下来说“我不知道”,它会强行续写出一段在语言上通顺、但内容上无中生有的回答。有个很常见的现象:你问模型“某市有一个叫XX的餐厅吗”,哪怕这个餐厅完全不存在,模型也可能编出一个地址、几道招牌菜,说得煞有其事。因为它见过大量“回答餐厅推荐”的文本模式,知道这种回答应该包括结构,但它没有足够的信息来判断这家餐厅是否真实存在。知道这一点后,你会明白为什么和模型对话时,“提示词里提供详细信息”特别重要——你给的信息越充分,模型需要瞎编的空间就越小。5.3 上下文窗口与知识时效:工程师必须知道的两个边界大模型还有一个经常被误解的特性:上下文窗口。上下文窗口决定了模型在生成当前token时,能“看到”最多多长的历史内容。但注意,窗口内的内容并非都被同等重视。自注意力是平方级计算,序列越长,注意力的分布往往越稀疏,靠中间的信息容易被“挤”到两头去。业界有个著名的“长海捞针”测试:在很长的上下文里埋一个关键信息,然后问模型,模型经常找不到那个信息。这就解释了为什么“把资料全塞进上下文里”并不是万能方案,尤其是关键信息埋在中段时,效果往往意外地差。另一个边界是知识时效。模型的知识“冻结”在训练数据收集时间点。训练完成后的模型,不会自动知道新发生的事情。模型发布时间之后的事件,它要么不知道,要么根据语言学到的规律瞎猜。这也是为什么现在主流大模型应用都会外挂检索环节:先从外部数据库里搜出最新资料,再塞进上下文让模型基于这些资料回答。理解了模型原理,你就知道这个“检索增强生成”的后端设计并不是一时兴起,而是针对模型固有缺陷的必然补丁。6. 从原理到动手:我建议你亲手做一次“概率观察实验”如果只看不练,上面这些内容很容易变成“好像懂了但用不起来”的知识。我最推荐初学者做的一件事,不是马上训练大模型——那个成本太高了——而是加载一个几百M参数的开源小模型,亲眼看一次“概率分布长什么样”。现在跑小模型的工具链已经很成熟了。如果你本地有支持CUDA的显卡,或者退而求其次用CPU跑,也完全没问题,只是慢一些。下面这段Python脚本,能让你直观看到“输入一段话后,模型预测下一个词的概率分布”:import torch from transformers import AutoTokenizer, AutoModelForCausalLM # 换成你手头任意一个开源基座模型的路径 MODEL_NAME = "your-model-path" tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) model = AutoModelForCausalLM.from_pretrained(MODEL_NAME) input_text = "今天天气" inputs = tokenizer(input_text, return_tensors="pt") with torch.no_grad(): outputs = model(**inputs) # 取最后一个位置的logits next_logits = outputs.logits[0, -1, :] probs = torch.softmax(next_logits, dim=-1) # 打印概率最高的前10个token top_probs, top_indices = torch.topk(probs, 10) for prob, idx in zip(top_probs, top_indices): token = tokenizer.decode(idx) print(f"{token}: {prob:.4f}")当你真的看到输出时,会发现一件很有意思的事:不仅是“很好”“不错”这些合理候选,连一些奇怪的词也在列表里,只是概率很低。这个“低概率尾巴”正是温度参数起作用的舞台,也是模型能产生创造性输出的来源。你可以再手动改一改温度参数,比如设成0.1、0.5、1.0、1.5,重新算softmax,你会看到同一句话、同一个模型,在不同温度下给出的排名产生很有启发性的变化——温度越低,概率越集中;温度越高,低概率词的排名会明显上浮。做这个实验的时候,有几个坑提前说一下。第一,模型下载的时候,注意先确认它是“基座模型”还是“对话模型”。对话模型在原始续写任务上表现会“怪怪的”,因为它的行为已经被SFT和RLHF阶段重新塑造了,直接续写时可能输出大量对话格式文本。这个现象本身也是很好的体验——你能直观感受到三个阶段对模型行为的改变有多大。第二,中文模型的分词结果可能和你的直觉不同。“今天天气”这几个字,不一定被切成整整四个字的token,可能是“今天”和“天气”两个词元。打印token_id和decoded结果时留意看一下,能加深你对tokenization连贯逻辑的理解。第三,如果模型比较大,记得加一行model.eval(),把模型切换到推理模式,关闭dropout之类的训练专用机制。不然同一个输入每次跑出来的结果可能有细微差异——注意,这里的差异来自随机性,不是模型学到了什么新东西。7. 最后分享一点自己踩出来的经验原理讲完了,最后聊点我在实际项目中反复被验证过的心得,也可能是你接下来最容易踩到的地方。第一,不要把温度参数当成万能旋钮。它只能改变生成时采样分布的形态,不能改变模型“会不会这件事”。一个模型本来就不懂某门语言,你把温度调到最高,它不会突然变懂,只会把各种乱码一样的词拼得更天马行空。所以先选对模型、选对数据,最后才轮到调温度。第二,微调之前一定要先跑通小规模的pipeline。我见过太多人一上来就集齐了几万条数据,准备微调一个大模型,结果因为tokenizer的特殊token处理不对、训练时的掩码没加对、或者是数据格式和预训练不一致,跑了一整天之后拿到的模型完全不可用。正确姿势是先拿几百条数据,在最小的基座模型上跑,从batch到loss全部检查一遍,确认无误再上规模。第三,了解原理之后,你会更懂提示词的价值。很多人觉得提示词工程是玄学,但拆开看,提示词的本质是在为模型构造一个更有利的概率环境。你把任务背景写清楚,相当于给模型提供了更长的上下文,它“续写时”的选择空间会被大幅约束到正确方向上。你要求模型“一步一步思考”,本质上是让它生成更多中间token,给概率链留出更充足的计算路径。这些都不是魔法,而是这套概率机制的自然推论。文本生成大模型的原理,远没有它看起来那么神秘。往上拆,是一个接一个的概率预测;往底层看,是海量参数对不同上下文的概率记忆。理解这个最朴素的内核之后,那些营销号吹得眼花缭乱的概念,什么“智能涌现”“对齐”“思考链”,都会回到一个平实的坐标系里,你会知道自己真正能控制的是什么、模型的边界在哪里、以及下一步该往哪个方向使劲。