Skip to content

自回归生成与推理基础

输入如何构造 → 回答如何生成 → 下一个 Token 如何选择 → 推理如何执行 → 长度、随机性与成本

一、从对话输入到生成回答:整体流程

一次语言模型调用,可以理解为:把本次需要的指令和对话内容转换成 Token 序列,再让模型根据这个序列逐步生成新的 Token,最后转换成文本。

1.1 输入:系统指令、多轮历史与当前用户消息

大模型的推理接口是无状态的(stateless):每次调用都是一次独立的计算,模型不会自动“记得”上一轮聊过什么。因此,多轮历史必须由调用方(应用程序或服务端会话机制)显式地拼进本次请求中。

模型接收的输入由三部分组成,首先,它们被拼接成一个完整的消息列表

输入部分作用举例
系统指令(System Prompt)设定模型的角色、回答方式和总体要求数学助教、用中文解释
多轮历史(Conversation History)之前所有轮次的对话,包括用户的提问和模型的回复已经讨论过最大似然估计
当前用户消息(Current User Message)本轮用户最新说的话比较最大似然估计与最大后验估计
python
messages = [
    {"role": "system",    "content": "你是一名数学助教,请用中文解释概念。"},
    {"role": "user",      "content": "什么是最大似然估计?"},
    {"role": "assistant", "content": "最大似然估计是选择使观测数据出现的似然最大的参数……"},
    {"role": "user",      "content": "那它与最大后验估计有什么区别?"}
]

对于通常的文本模型调用,模型不会自动读取此前所有聊天内容。 应用需要把相关历史放入本次上下文,或者由服务端的会话机制将其组织进去。

记:第 t 轮的用户输入记为 ut ,助手回复记为 at ,则本轮输入整体为 ct

ct=(St,Ht,ut),Ht=(u1,a1,,ut1,at1)

其中 St 是系统指令。本次任务就是根据 (c_t) 生成助手回答 (a_t):

atπθ(|ct)=πθ(|St,Ht,ut)

1.2 一次回答的完整流程

t 轮回答的完整过程可以写成:

ct=(St,Ht,ut)模板与分词xt反复预测与选择yt转换为文本at.

第一步:使用 Chat Template 组织对话格式,如 1.1所示

第二步:使用 Tokenizer 转换为整数序列

分词器将格式化后的内容转换为 Token ID。记第 t 轮的模型输入为:

ct=(St,Ht,ut)应用层:结构化对话xt=(xt,1,,xt,nt)模型层:Token 序列xt=Tokenizer(Template(ct))=(xt,1,xt,2,,xt,nt),

第三步:自回归生成 :从下一 Token 的概率分布 + 解码策略

xtyt 是一次完整的 Decoder-Only 架构的推理过程:

xtEmbeddingH(0)L 个 Decoder blocksH(L)NormZWvocablogits(下一个token的概率分布)logits解码策略yt

整个生成过程在逻辑上表现为:

xtyt,1,(xt,yt,1)yt,2,(xt,yt,1,yt,2)yt,3, (xt,yt,1,,yt,Lt1)yt,Lt.

第四步:将生成的 Token 序列转换为回答文本

生成结束后,我们得到的是一串 Token ID:

yt=(yt,1,yt,2,,yt,Lt).

分词器将它们解码为文本,并根据规则处理不需要展示的特殊标记:

at=TextDecode(yt).

1.3 进入下一轮对话

t 轮回答的完整过程可以写成:

ct=(St,Ht,ut)模板与分词xt反复预测与选择yt转换为文本at.

从执行顺序来看:

  1. 应用组织系统指令、历史消息和当前用户消息。
  2. 使用 Chat Template 和 Tokenizer 构造输入 Token 序列。
  3. 模型计算下一 Token 的分布。
  4. 解码策略选出一个 Token,将其追加到生成序列。
  5. 若未满足停止条件,则继续预测下一个 Token。
  6. 将生成的 Token 转换为文本,得到本轮助手回复。

回答结束后,应用将本轮的用户消息和助手回复加入历史:

Ht+1=Ht(ut,at),

其中 表示按顺序追加。

当下一轮用户消息 ut+1 到来时,新的输入为:

ct+1=(St+1,Ht+1,ut+1).

这样,**上一轮生成的输出,就成为了下一轮输入的一部分。**因此,改变一个回复会改变后续对话分布。


二. 对话如何进入模型:Chat Template 与多轮历史

上一节把本轮对话输入记为:

ct=(St,Ht,ut),

其中 St 是系统指令,Ht 是历史对话,ut 是当前用户消息。

这一节要进一步解释:这些带有角色和轮次的信息,如何被编码进一个连续的 Token 序列,以及模型如何知道应该从哪里开始回复。

2.1 消息列表与角色

  • systemuserassistant 的作用。
  • 消息角色与消息正文的区别。

2.2 Chat Template:将结构化消息转换为序列

  • 角色标记、消息边界与特殊 Token。
  • 不同模型可能使用不同模板。
  • 模板与模型训练格式保持一致的意义。

2.3 多轮历史的拼接

  • 按时间顺序排列历史消息。
  • 先前的 Assistant 回答如何成为新的输入。
  • 当前用户消息与待生成回答的位置。

2.4 Assistant 生成前缀

  • 如何提示模型开始生成 Assistant 回答。
  • add_generation_prompt 的含义。
  • 开始一条新回复与续写已有回复的区别。

2.5 模型的“记忆”来自哪里

  • 单次模型调用与应用保存的对话状态。
  • 历史未进入输入时,模型通常无法直接访问它。
  • 历史截断、摘要与选择性保留的基本概念。