← 进阶 vibe coding生成回答是在逐步选择下一个 token

免费文章 · 02 理解模型怎样生成回答

生成回答是在逐步选择下一个 token


  同一个问题,让 AI 回答两次,措辞可能就不一样;补充一些要求,回答又会跟着改变。有时候,它写到一半就停了下来;有时候,回答看起来很流畅,却没有真正完成任务。这些现象究竟是怎么产生的?

  上一节我们看到,文本进入模型后会形成向量表示。接下来要了解的是,这些计算怎样变成我们看到的文字。常见的自回归文本模型,会根据已有内容,计算下一个 token 的候选得分,按一定方式选出一个,再继续预测下一个。一段回答就是这样逐步生成的。

  理解这个过程,我们才能进一步弄清:为什么相同的问题可能得到不同回答,怎样调整生成方式,为什么回答会提前停止,以及给模型补充信息和重新训练模型有什么区别。

  这一节,我们就从一次简单的生成过程开始,看看模型怎样选择下一个 token,又是怎样决定何时结束的。

先计算下一枚 token 的得分

  上一节我们看到,token 经过模型计算,会形成结合上下文的隐藏状态。那么,模型究竟怎样从词表中选出下一枚 token?

  模型会利用这些计算结果,为词表中的候选 token 分别打分,这些得分称为 logits。分数可以为负,也不需要加起来等于 1。如果要把它们转换成便于比较和抽样的概率,就可以使用 softmax,得到一组总和为 1 的概率。

  我们用一个简单的例子看看这个过程。假设前文是“早餐喝”,接下来只有“豆浆”“咖啡”“茶”三个候选 token,模型给出的得分分别是 2、1、0。这里的候选和分数都是人为设置的,只用于演示计算,并不代表真实模型的输出或实际切分结果。

候选 token

得分

softmax 后的概率

豆浆

2

66.52%

咖啡

1

24.47%

茶

0

9.00%

  这些概率是怎么算出来的呢?softmax 会先对每个得分取指数,再除以所有指数的总和。例如,“豆浆”的概率就是 e² / (e² + e¹ + e⁰),约为 66.52%。表中的百分比经过四舍五入,因此相加可能略有偏差,实际计算仍使用未舍入的数值。

  到这里,我们就得到了在“早餐喝”这个前文下,下一枚 token 的概率分布。不过,模型还没有真正选出下一枚 token,只是算出了各个候选的概率。

  这里还要注意一个区别:“豆浆”的概率是 66.52%,并不意味着现实中有 66.52% 的人早餐喝豆浆。它描述的是模型在当前前文下对下一枚 token 的预测,而不是现实世界的统计概率,更不能直接代表答案的正确率。

选中的 token 会成为下一步的前文

  有了概率分布,模型接下来就要真正选出一枚 token。贪心解码总是选择概率最高的候选;采样则按照概率抽取,因此概率较低的候选也有机会被选中。这就解释了为什么相同的输入,有时也会得到不同的回答。至于温度、top-p 等参数怎样影响选择,我们会在后面的课程中展开。

  假设第一步选中了“豆浆”,前文就从“早餐喝”变成了“早餐喝豆浆”。接下来,模型会根据新的前文重新计算下一枚 token 的得分和概率,而不是继续沿用刚才“豆浆、咖啡、茶”的分布。每生成一枚 token,后续预测的依据也会随之改变。

  为了看清这个过程,我们在人工实验中,为两种不同的选择分别设置了下一步的概率分布:

已有前文

接逗号“,”

接句号“。”

早餐喝豆浆

26.89%

73.11%

早餐喝咖啡

73.11%

26.89%

  可以看到,同样是选择逗号或句号,前文不同,下一枚 token 的概率也随之改变。模型每走一步,都会根据新的前文继续预测。

  真实模型会通过已训练的网络计算这些得分,而这里我们提前设置了两组数值,只是为了观察生成过程。两个分支也是人为指定的,并不代表模型实际采样的结果。

  从图中可以看到,每选出一枚 token,它就会被接到前文后面,成为下一步预测的依据。这个过程会不断向后推进,但不会回头修改已经生成的 token。如果前面出现错误,只能在后续内容中纠正,或者由应用另行修改。

  另外,即使每一步都选择当前概率最高的 token,也不意味着最终得到的整段回答就是最合适的。

生成停下来,不代表回答已经写完

  模型不会一直生成下去。有时,它会选出表示结束的特殊 token,比如 EOS(end of sequence);聊天模型也可能使用相应的消息结束标记。这些标记通常不会显示在正文中。不过,生成也可能因为达到输出长度上限而停止。因此,文字不再增加,并不意味着回答一定已经完整结束。

  在实验中,连续点击“选最高概率”,会依次生成“豆浆 → 。 → <EOS>”,最后一枚就是结束标记。而重新开始后,手动选择“咖啡 → , → 配面包 → , → 配包子 → ,”,则会在第六枚 token 达到长度上限时停止,句子还停在逗号后面。

  两种情况都让生成停了下来,但前者是模型生成了结束标记,后者则是受到长度限制而截断。

  在实验中,句号后只剩下 EOS 这一个候选,是为了方便区分不同的停止原因。真实模型即使生成了句号,也可能继续写下一句话。

  而且,生成结束并不等于任务完成。即使模型选出了结束标记,也只能说明这次生成已经结束。回答是否覆盖了问题、文章是否完整,仍然需要我们对照任务要求来判断。

运行逐步生成实验

沿用已准备的课程实验仓库,打开逐步生成实验。

  1. 连续点击“选最高概率”,检查记录经过豆浆、句号和 EOS,停止原因是结束标记。
  2. 点击“重来”,按正文的六枚token手动选择,检查最后一枚为逗号,停止原因是达到上限。
  3. 再次重来,第一步选“咖啡”,观察前文色块及后续候选;展开第一条“逐步记录”,比较当时的前文、概率和选择方式。

词表、得分与转移规则由人设定,概率由程序计算;本地机制实验不调用语言模型。

训练改变参数,推理使用参数

  前面我们看到,模型会为候选 token 计算得分。那么,这些得分是从哪里来的?它们来自模型的计算,而计算所用的参数,是在训练过程中逐步形成的。

  还是用“早餐喝”这个例子。假设训练文本是“早餐喝咖啡”,当模型看到“早餐喝”时,需要预测的下一枚 token 就是“咖啡”。训练时,我们已经知道正确目标,因此可以比较模型的预测与目标之间有多大差距。

  按照前面的人为设定,“咖啡”只有 24.47% 的概率。如果用常见的交叉熵损失来衡量,目标概率越低,损失就越大,这里约为 1.408。假设调整参数后,模型给“咖啡”的概率提高到 60%,损失就会降到约 0.511。

  训练就是通过这样的反馈不断调整参数,逐步降低大量样本上的预测损失。不过,这里的数值只是为了演示计算,并没有真正训练模型;单次预测的损失降低,也不意味着整个模型一定变好了。

预测损失与奖励信号

  在没有额外类别权重的单目标例子中,交叉熵损失是 −ln p(目标 token)。因此 −ln(0.244728…) ≈ 1.408,−ln(0.6) ≈ 0.511。损失用于指导参数调整,不能读成答案错误的百分比。

  奖励是另一种评价信号:它可以衡量人更喜欢哪一个回答,也可以来自规则或程序检查,用来鼓励某些输出行为。奖励是否反映真正想完成的任务,取决于评价规则;它不是模型每次说“我完成了”就自动获得的证明。

  前面这种从大量文本中学习预测下一个 token 的方式,是预训练的一种常见做法。预训练之后,我们还可以通过大量示范,让模型进一步学习怎样按照要求完成任务,这通常称为指令微调(SFT)。例如,给模型提供不同的问题和回答示例,让它学习怎样把问题回答得更准确、更有条理。

  不过,除了模仿示范,模型还可以根据反馈继续改进。比如让人评价哪些回答更好,再利用这些反馈进行强化学习,这类方法称为 RLHF(人类反馈强化学习)。反馈也可以来自规则或程序验证,而不一定由人提供。Qwen3 的公开训练方案就结合了长推理示范微调和规则奖励强化学习。

  这些方法可以组合使用,也不一定按照固定顺序进行。它们的共同点是通过训练调整模型参数,让模型逐渐形成我们希望它具备的能力和行为。

  那么,我们平时给 AI 补充资料、纠正回答,也是在训练它吗?通常不是。日常使用模型进行的是推理(inference):模型利用已经训练好的参数,根据当前输入生成回答。比如我们告诉它“试用账号不可导出”,它随后按这条规则回答,是因为现在的上下文包含了这条信息,并不代表模型重新接受了训练。

  上传文件、增加示例或继续聊天,通常也是在补充当前上下文。有些产品还会保存记忆,在后续对话中重新提供。让模型记住或用上某些信息,不等于改变了模型参数。 只有实际进行了参数优化,才属于训练。

生成概率不能替代事实与任务检查

  前面我们看到,模型是一枚一枚 token 地生成回答,但这并不意味着它只是在机械地拼接常见词语。每一步生成背后,模型都可能结合大量上下文进行复杂计算,因此也能完成分析问题、制定计划和编写代码等任务。逐 token 生成描述的是输出方式,而不是模型能力的上限。

  不过,某个 token 的生成概率高,并不意味着它组成的内容就一定正确。比如询问某个接口是否支持退款,即使 AI 给出了一段完整、流畅的解释,我们仍然需要对照接口文档或实际行为确认。让模型继续解释为什么它是对的,也只是生成了更多内容,并不会自动增加事实依据。

  后面的课程中,我们还会通过小说创作练习与 AI 协作。比如让 AI 完成一章故事,情节可以自由发挥,但已经确定的人物设定和章节要求仍然需要遵守。如果生成因为长度限制停在半句话,我们就要检查停止原因,再决定怎样继续;即使模型正常结束,也要看看章节是否完整、有没有违背设定。

  所以,理解生成机制能帮助我们知道 AI 为什么这样回答、为什么会停止;至于回答是否正确、任务是否完成,还需要回到具体要求和实际结果中判断。

聊天为什么仍然是 token 序列

  聊天接口中的消息角色与内容,会按模型所用的格式转换为 token 序列。角色、消息边界和回答起点帮助模型区分“用户在说什么”与“接下来应由助手回答”。对话训练让模型学会在这种格式中回答;它并没有绕过逐 token 生成。消息格式与 API 的对应关系会在接口专题展开。

答案变了,任务就完成了吗?

  设想我们请 AI 写一章故事,过程中遇到了三个情况:

  1. 告诉 AI“主角不会游泳”后,它把原本游泳过河的情节改成了寻找渡船。
  2. 保持输入不变,使用采样重新生成一次,发现故事的措辞有所不同。
  3. 故事写到一半突然停止,查看记录发现已经达到输出长度上限。

  想一想:前两种变化分别是什么原因?它们能说明模型接受了新的训练吗?第三种情况,如果模型不是达到长度上限,而是生成了结束标记,就能说明这一章已经写完了吗?

查看答案与解析

  第一种情况是上下文发生了变化。我们补充了人物设定,模型便根据新的信息调整情节。第二种情况则是采样带来了不同的选择,即使输入相同,也可能生成不同的内容。两种情况都不能说明模型参数被重新训练过。

  第三种情况是长度截断,故事停在半句话,显然还需要继续生成。如果模型选出了结束标记,只能说明这次生成已经结束,并不代表故事一定写完了。

  真正判断这一章是否完成,还要回到故事本身:情节是否完整、人物行为有没有违背设定、本章要求是否得到满足。

  生成机制告诉我们回答为什么变化、为什么停止;任务是否完成,还要由实际结果来判断。

  到这里,我们已经知道模型怎样一步步生成 token。不过,这里还留下一个问题:模型在预测下一枚 token 时,究竟怎样从已有的前文中找到相关信息? 下一节,我们就从注意力机制开始,继续了解模型内部的计算过程。

讨论

登录后参与讨论