大语言模型基础
大语言模型(LLM)是从大量文本中学习语言规律和知识关联的模型。本文讨论的是根据已有文本逐个预测下一个 Token 的自回归模型。Token 是模型处理文本的基本单位,可以是单词或更小的片段。“自回归”指每次生成的新 Token 都参与后续预测。
本文面向应用开发和面试准备。调用模型时,开发者需要理解并解释以下四个问题:
- 文本怎样变成 Token?
- 上下文窗口限制了什么?
- 输出为什么每次会不同?
- 用量和费用怎样计算?
本文将从这四个问题入手,再简单介绍训练阶段的流程,以及模型的能力边界。
1. 面试核心
先记住这几条,再读正文- Token 与用量。 Token 数由分词器决定,同一段中文在不同模型下数量不同;输入和输出都占上下文窗口,按不同单价计费,实际用量读取 API 的
usage。卡 · Token 与上下文窗口 - 自回归生成。 自回归生成先预填充,再按已有序列预测、选择并追加下一个 Token,直到结束标记或长度上限。卡 · 一次生成的过程
- 采样与确定性。 temperature 调整概率分布,top-k 保留前 k 个候选,top-p 保留累计概率达到 p 的最小集合;temperature 为 0 时,批次大小引起的浮点误差仍可能改变候选 Token 的排名。 卡 · 采样参数卡 · 采样参数
- 训练阶段。 预训练学习语言和知识,指令微调学习按指令回答,偏好优化使回答更符合偏好。
- 推理预算。 推理模型的输出上限同时包含推理 Token 和可见回答。因此,用户看到的回答很短,也可能已经耗尽输出预算。卡 · 推理预算与输出结束状态
2. Token 与上下文窗口
Token 是模型处理文本的基本单位。本节依次说明文本怎样分词、上下文窗口的限制,以及用量和费用。
2.1 分词器
分词器(Tokenizer)把文本切成模型词表中的片段。词表记录这些片段及其编号,编号称为 Token ID。片段可以是整个单词、单词的一部分,也可以是字节片段。模型接收这些编号后,才能进行后续计算。
英文可以按整词或子词切分,子词就是单词中的一部分。中文可以按字、词组或字节片段切分。下面对比同一段文本在两种编码下的切分结果。
下表数据使用 tiktoken 0.14.0 实测,cl100k_base 是 GPT-4 和 GPT-3.5 Turbo 使用的编码,o200k_base 是 GPT-4o 使用的编码。
| 文本 | cl100k_base(GPT-4) | o200k_base(GPT-4o) |
|---|---|---|
| I'm learning programming on Coding101 | 7 个:I / 'm / ␣learning / ␣programming / ␣on / ␣Coding / 101 | 6 个:I'm / ␣learning / ␣programming / ␣on / ␣Coding / 101 |
| 我正在通过Coding101了解大语言模型 | 12 个:我 / 正在 / 通过 / Coding / 101 / 了 / 解 / 大 / 语 / 言 / 模 / 型 | 9 个:我 / 正在 / 通过 / Coding / 101 / 了解 / 大 / 语言 / 模型 |
| 学习 | 3 个:学 / E4 B9 / A0 | 1 个:学习 |
| 饕餮 | 6 个:E9 / A5 / 95 / E9 / A4 / AE | 4 个:E9 A5 / 95 / E9 A4 / AE |
“␣”表示这个 Token 以空格开头。E4 B9 这类十六进制数是汉字的 UTF-8 字节。
对照表中的文本,可以理解以下五点规律:
- 同一句话,不同分词器切法不同:英文句子中,cl100k_base 把 I'm 切成 I / 'm,o200k_base 保留为一个 Token。中文句子中,“了解”“语言”“模型”在 o200k_base 中各是一个 Token。在 cl100k_base 中,它们各拆成两个字。
- 整词、子词与空格:表中的 learning、programming 和 on 各占一个 Token,前面的空格并入 Token。Coding101 这样的少见词会拆成 Coding / 101 两段。
- 中文词组的覆盖:相比 cl100k_base,o200k_base 收录了更多中文词组。表中的同一句中文从 12 个 Token 降到 9 个。
- 切分依据是频率,不是语义:o200k_base 把“今天天气”切成“今 / 天天 / 气”。“天天”在语料中出现得多,所以合成了一个 Token。
- 词表没有收录的字按字节切分:一个常用汉字的 UTF-8 编码占 3 个字节,“习”是
E4 B9 A0。cl100k_base 收录了“学”,没有收录“习”,所以“学习”切成“学”加上“习”的 2 个字节片段,共 3 个 Token。o200k_base 收录了整个词,只占 1 个。生僻词“饕餮”两种编码都没有收录,分别占 6 个和 4 个 Token。按字节切分保证任何文字都能转成 Token,代价是生僻字更费 Token。
字数与 Token 数没有固定比例,估算要使用对应模型的分词器。
2.2 上下文窗口
上下文窗口是一次推理能容纳的 Token 总量上限。输入、可见输出和推理 Token 都要占用这个空间。输出还有独立的长度上限,因此应用要同时满足两项限制。输入占用越多窗口空间,留给回答和推理的空间就越少。超出窗口时,接口按配置报错或截断内容。
窗口能放下的内容多,不代表模型能用好其中的全部信息。这些内容包括检索到的文档、对话历史和工具返回的结果。输入越长,费用越高,处理时间也越长。在长文档问答等任务中,模型还容易遗漏位于中间的关键信息。因此,应用应只放入与问题相关的内容,并检查回答是否用到了关键信息。
2.3 Token 用量与费用
一次请求的用量由输入和输出 Token 组成。消息模板和工具定义也占用输入空间,实际数值读取 API 返回的用量(usage)。用量和费用需要区分以下部分:
| 部分 | 内容 | 说明 |
|---|---|---|
| 输入 Token | 系统提示、工具定义、对话历史、检索到的文档、本轮输入。系统提示规定模型的任务和行为。工具定义告诉模型有哪些函数可调用,以及参数格式。检索到的文档是程序从知识库中查找后交给模型参考的内容。 | 保留全部历史时,新一轮要处理此前的消息。输入量因此随对话轮数增长。 |
| 输出 Token | 模型生成的回答、工具调用参数,以及推理 Token。推理 Token 是推理模型在生成最终回答前用于内部推理的 Token。 | 输出单价通常高于输入单价,费用按所用模型计算。推理 Token 也按输出计费。 |
费用要按所用模型的输入、输出等计费类别分别计算。不同类别的单价不同,仅看总 Token 数无法直接比较费用。
重复的输入前缀可以命中缓存、按更低价格计费,原理见前缀缓存。
3. 一次生成的过程
一次请求发出后,模型需要先处理输入,再逐个生成 Token。沿着这个过程,可以把一次文本生成分成五个步骤:
- 序列化与分词:服务先按模型的对话模板组织消息,这一步称为序列化。模板用角色等标记区分系统提示、用户消息和工具返回的结果。组织好消息后,分词器再将它们转换成 Token ID 序列,交给模型计算。
- 预填充(prefill):模型先处理整段输入,计算各层的 Key、Value。它们是注意力机制用于匹配和读取已有内容的中间结果。这些结果会存入名为 KV Cache 的缓存,供后续生成复用。未命中前缀缓存时,输入越长,这一步需要的计算就越多。所以,长输入会增加等待首个 Token 的时间。
- 解码(decode):接下来,模型根据已有序列,计算词表中各 Token 作为下一个 Token 的概率。服务再按采样规则选出一个 Token,把它追加到序列末尾。下一步会读取已有的 KV Cache,计算新增 Token 的 Key、Value,以及再下一个 Token 的概率。之所以能复用缓存,是因为旧 Token 的计算只依赖它及其之前的内容。新增 Token 不改变旧 Token 的 Key、Value,所以这部分计算可以省去。基本解码每步只新增一个 Token,输出越长,需要的步骤和总耗时就越多。
- 停止:模型输出特殊的结束 Token 时,本次生成就会结束。调用方也可以设置停止序列,也就是约定用来结束生成的文本标记。此外,生成达到输出上限时也会停止。这几种情况下,应用收到的结果需要分别处理,下面会进一步说明。
- 反分词:服务把生成的 Token 转回文本,供应用展示或解析。非流式接口会等生成结束后再返回,流式接口则边生成边返回文本片段。所以,使用流式接口时,你能更早看到第一段文字,但完整生成仍需要时间。
收到结果后,应用需要区分以下三种情况:
- 正常完成:应用可以按完整回答继续处理。
- 预算耗尽:此时应按未完成结果处理,不能直接当作正常回答解析。
- 请求调用工具:模型给出调用请求后,由程序执行对应的函数。
理解了生成过程,就能区分“开始输出慢”和“完整回答慢”。首 Token 延迟是从发出请求到收到第一个输出 Token 的时间,其中包含以下几部分耗时:
- 请求和响应的网络传输。
- 服务端的排队与调度。
- 处理输入的预填充计算。
- 生成第一个 Token 的计算。
预填充影响的是输入侧的计算时间,而解码步数影响长回答的总耗时。所以,排查延迟时,应用应分别记录首 Token 延迟和完整响应时间。
多轮对话会重复这个生成过程,历史消息则由应用或 API 服务保存。自行管理历史时,应用每轮重新发送需要保留的消息。也可以由服务端保存会话,在下一次推理时补入历史、续接上下文。也就是说,模型能接着聊,是因为历史又被放进了输入。模型本身不会自动记住另一次独立调用的对话。续接的历史仍计入输入用量,所以保留的历史越多,消耗的输入 Token 就越多。
3.1 前缀缓存
多次请求经常会带上相同的系统提示或工具定义。这些内容如果位于输入开头,就有机会通过前缀缓存省去重复计算。
前缀是输入开头连续的一段内容。预填充时,模型为每个输入 Token 计算各层的 Key、Value。在自回归模型中,这些结果只依赖当前 Token 和它之前的 Token。所以,同一模型处理两个请求时,完全相同的前缀可以复用已有的 Key、Value。服务把它们保存下来,就能在后续请求中直接使用。
这里要求前缀完全相同,是因为后续计算依赖前文。前面只要有一个 Token 改变,后续 Token 依赖的前文就变了。这时,服务要从变化的 Token 开始重新计算,变化前的共同前缀仍可复用。所以,组装输入时,应把稳定的系统提示和工具定义放在最前面。
具体的组装顺序见上下文管理。
命中缓存后,服务省去了这段前缀的预填充计算,新增输入仍需要预填充。所以,前缀缓存主要降低首 Token 延迟和输入费用。到了输出阶段,模型仍要逐个 Token 解码,这部分计算并没有减少。因此,回答很长时,逐 Token 生成仍然耗时,前缀缓存对这部分耗时帮助不大。
输入费用降低,也和省去重复计算有关。服务直接读取已保存的 Key、Value,就能省去重复计算前缀的成本,所以缓存命中的输入按更低单价计费。不过,缓存会占用服务端存储,因此有保存期限,长时间不用就会失效。不同提供方的缓存规则也有区别:OpenAI 会自动缓存足够长的相同前缀。Anthropic 则可以显式标记缓存位置,写入缓存的输入按更高单价计费。
读取用量时,要把总量和其中的明细分开看。命中缓存的 Token 数已经包含在输入总量中,推理 Token 数也已经包含在输出总量中。比如,一次请求的用量如下,单位都是 Token:
- 输入为 1000,其中缓存命中为 600。
- 输出为 200,其中推理为 150。
- 输入与输出相加,总用量是 1200。
- 输入减去缓存命中量,未命中的部分是 400。
所以,统计总量时,缓存与推理明细都无需再加一次。
回到 KV Cache,两种复用方式的区别在于使用时机。同一次请求内,解码会复用 KV Cache;前缀缓存则把这些结果保留到后续请求中复用。
KV Cache 的内部机制见 Transformer 与注意力机制。
4. 采样参数
解码时,模型会给出多个候选 Token,接下来需要决定选哪一个。采样就是根据候选概率选出下一个 Token 的过程,采样参数则用来调整这种选择。
模型每一步先输出词表中各候选 Token 的原始分数,这些分数称为 logits。要按概率选择,就需要先把分数转成概率。使用温度 T > 0 时,可以用 softmax(logits / T) 完成转换。其中,softmax 会把分数转换成总和为 1 的概率分布。调整温度或筛选候选,都会影响每一步的选择,所以同一输入会生成不同文本。
调用模型时,可以通过下表中的参数或控制项调整生成:
| 参数或控制项 | 作用 | 常见取值方向与用途 |
|---|---|---|
| temperature | 小于 1 时分布更尖锐,高分候选更占优势。大于 1 时分布更平坦,较低分候选更容易被选中。 | 抽取、分类、代码生成和工具调用从低值开始评测。创作、头脑风暴可比较较高值的效果。 |
| top-k | 只保留概率最高的 k 个候选,再从中采样。 | k 越小,候选范围越窄。它排除概率极低的 Token,避免偶然选中离题或错误的词。 |
| top-p | 按概率从高到低累加,保留累计达到 p 的最小集合。这个方法称为核采样。 | p 越小,候选范围越窄。候选数量随分布变化,调优时与 temperature 先选一个调整。 |
| 最大输出量 | 生成达到输出预算时停止,字段名称取决于 API。 | 按任务需要预留长度,用上限控制长输出和费用。推理模型还要预留内部推理的空间。 |
| stop | 在支持该参数的接口中,指定触发停止的文本序列。 | 适合生成到约定标记为止的任务,防止继续输出后续内容。 |
top-k 和 top-p 都会缩小候选范围,区别在于用什么条件筛选。top-k 固定候选数量,top-p 则按概率分布决定数量。比如,四个候选的概率依次为 0.6、0.25、0.1、0.05。设置 top-k=2 会保留前两个;设置 top-p=0.9 则会保留前三个。这是因为前两个的累计概率只有 0.85,加入第三个才达到阈值。
如果每一步都直接选择分数最高的 Token,这种方式就称为贪心解码。temperature 越接近 0,采样就越趋近于这种选择方式。不过,T=0 时,上面的公式会除以零,无法直接计算。因此,接口一般把 temperature=0 当作贪心解码处理。
4.1 输出一致性
把 temperature 设为 0,可以减少采样的随机性,但仍无法保证同一请求的回答逐字相同。要理解原因,需要看看服务端算出的分数为什么会有细微差别。
理解这种差别,要从浮点数的精度说起。计算机中的浮点数只保留有限精度,加法不满足结合律。也就是说,(a+b)+c 与 a+(b+c) 的结果可能有极小差别。所以,GPU 并行计算时,求和的分组和顺序会影响结果。
实际运行时,推理服务会把多个用户的请求合成一批计算。服务负载一变,同一个请求就会被分进不同大小的批次。为了充分利用 GPU,计算程序会随批次大小调整求和分组。比如,小批次会把一次求和拆给多个计算单元,再合并各组结果。这样一来,浮点数相加的顺序变了,logits 就会出现微小差异。这是服务端输出不一致的主要来源,Thinking Machines Lab 在 2025 年的文章中分析了这一机制。
如果两个候选 Token 的分数非常接近,这点微小差异就足以改变排名。贪心解码仍然选择最高分,却会选出不同的 Token。接下来,每一步都基于已经生成的前文,前文变了,后续预测也会跟着变。所以,最初的一点差异会随着生成继续扩大。
除了批次变化,排查输出差异时,还要留意以下几项变化或限制:
- 模型版本:模型快照是某次发布的固定模型版本。使用不带日期的模型别名时,提供方可能更新它指向的快照。这时,同一个别名对应的模型已经变了,计算结果也会变化。
- 运行环境:服务端更换硬件或推理程序,也会改变计算结果。
- 参数支持:部分推理模型不支持或忽略 temperature,所以设置前要核对模型文档。Anthropic 的官方文档也说明,即使 temperature 为 0,结果仍非完全确定。
要让回答尽量一致,应用侧可以先固定带日期的模型快照,再保持完整输入一致。这里的“完整输入”包括以下几部分内容:
- 系统提示和示例要保持一致。
- 工具定义及其排列顺序要固定。
- 对话历史、检索到的文档和工具返回的结果也要相同。
固定这些内容后,在模型支持时,把 temperature 设为 0 或较低值,可以减少采样随机性。部分接口还提供 seed,也就是控制随机数生成的种子。固定 seed 能帮助尽量复现,但服务端计算的差异仍然存在。
如果回答要交给程序解析,还需要约束格式并检查内容。结构化输出用于约束回答的格式,再由 Schema 校验检查字段和类型是否符合要求。这里的 Schema 就是描述这些要求的结构规则。格式符合要求后,还要做业务校验,比如检查金额是否与订单记录一致。生成失败时,可以设置有限次数的重试。
具体方法见提示词工程。
对于完全相同的输入,如果要求每次回答逐字一致,可以缓存之前的回答,后续直接复用。
自部署模型时,你还可以控制计算环境,固定以下三项条件:
- 使用相同的硬件。
- 使用相同版本的推理程序。
- 保持计算精度一致。
在此基础上,使用批次不变的计算方式,可以让求和分组与顺序不受批次大小影响。也可以采用确定性的计算方式,让相同条件下的重复计算得到相同结果。不过,这些方式会限制并行计算的优化空间。所以,选择时需要权衡一致性与吞吐量,也就是单位时间内能完成的工作量。
评估一致性时,要在上述固定模型快照和完整输入的基础上,再固定采样参数。对同一输入运行多次,重点比较结论和关键字段是否一致,而不只看文字是否逐字相同。如果要比较参数效果,每次只调整一个参数,这样才便于判断变化的原因。
4.2 推理预算与输出结束状态
采样参数决定下一步怎样选择 Token,调用推理模型时还需要留意输出预算。判断预算是否够用,需要把内部推理和最终回答放在一起看。
推理模型在给出回答之前,会先生成一段内部推理,这部分用的 Token 称为推理 Token。推理 Token 和最终回答共用同一个输出上限。也就是说,推理用掉的越多,留给回答的空间就越少。所以有时你会看到这样的情况:回答只有短短一句,甚至一个字都没有,输出预算却已经用完了。
遇到这种情况,应用需要查看接口返回的结束状态。预算耗尽时,接口会把响应标记为未完成。比如,在 OpenAI Responses API 中,max_output_tokens 设置输出上限。达到这个上限而未完成生成时,响应状态会是 incomplete。这时,应用不能直接把已收到的内容当作完整结果解析。例如,一段 JSON 在中途被截断,就需要重新生成或续接,再校验内容是否完整、格式是否正确。
调整时,还要区分推理预算和采样参数各自控制什么。推理预算限制推理用量的上限,采样参数则改变每一步的候选概率。提高预算,是给模型更多可用的推理空间。只有模型实际多用了推理 Token,这部分耗时和费用才会增加。因此,调整预算后,需要同时比较以下三个指标:
- 任务成功率:更多推理空间是否帮助模型完成了任务。
- 延迟:完成一次请求花了多长时间。
- 费用:完成任务实际花了多少钱。
5. 训练阶段与能力边界
前面介绍了调用时怎样生成和控制输出,接下来看看模型的能力从哪里来。训练会通过数据调整模型参数,也就是模型内部参与计算的数值。
不同训练阶段使用的信号不同,也就是告诉模型怎样调整回答的依据不同。下表列出了三个阶段,分别说明模型怎样学习语言、任务和回答偏好:
| 阶段 | 训练信号 | 主要作用 |
|---|---|---|
| 预训练 | 在海量文本上预测下一个 Token,用实际后文纠正预测。 | 学习语言规律,以及训练数据中的知识关联。 |
| 指令微调(SFT,监督微调) | 用指令与高质量回答组成示范。 | 学习按指令完成任务,并遵循对话格式。 |
| 偏好优化 | 使用人类或模型对多个回答的偏好比较或奖励。 | 提高符合偏好的回答的生成倾向,例如更有帮助、更安全、更符合格式要求。 |
在偏好优化中,你会经常看到 RLHF 和 DPO 这两个名称。RLHF 指利用人类反馈进行强化学习。常见做法是先用偏好数据训练一个奖励模型,让它给回答打分,再用这些奖励调整语言模型。
DPO 指直接偏好优化,它直接用偏好对调整模型的回答倾向。所谓偏好对,就是对同一输入给出的两个回答,其中一个被偏好,另一个被拒绝。实际训练时,不同模型会组合使用不同的训练方法。
理解这些训练方式后,还需要知道模型在应用中的四类能力边界:
- 知识截止与私有数据:训练数据有时间范围,所以训练后的新事件需要外部信息补充。企业内部文档若既未进入训练,也未放入当前上下文,就需要程序提供。应用可以先检索相关文档,再把文档交给模型回答,这种方式称为检索增强生成(RAG)。除了 RAG,也可以通过工具补充这些信息。
- 事实可靠性:模型学习的是文本生成规律,所以回答即使流畅,也会包含错误事实。缺少证据时,它仍可能补出看起来合理的细节。因此,应用需要核对来源。
- 精确计算与长链推理:模型做多位数运算或严格计数时容易出错。如果任务需要多步推理,前一步的错误还会影响后续结论。所以,需要精确结果时,应交给代码或工具计算,再校验结果。
- 工具调用:模型通过训练学会的是按格式生成调用请求。有了这个请求后,还需要由程序执行对应的函数,才能完成实际操作。
事实错误的成因与处理方法见模型幻觉。
工具调用的完整链路见 Function Calling。
把这些能力用到具体任务时,可以按需要选择以下三种方式:
- 用提示词说明当前要完成的任务。
- 用 RAG 补充回答所需的相关文档。
- 用微调让模型学会特定任务的格式、风格或领域用语。
具体选择与组合见检索增强生成(RAG)。
6 · 面试题卡片
本页题目与参考回答
6.1 一次模型请求的 Token 用量怎样计算?中文和英文有什么差异?
考察重点:解释分词器造成的中英文用量差异,以及历史增长对输入费用的影响。统计时区分输入、输出与已包含的缓存和推理明细。
相关内容:Token 与上下文窗口、Token 用量与费用。
参考回答
一次请求的总用量是输入与输出 Token 之和,实际数值读取 API 的 usage。
分词器按词表切分文本,常见英文词可以是一个 Token。罕见词会拆分,中文则可以按字、词组或更小的片段切分。词表对中文的覆盖不同,同一段中文的 Token 数也会不同。因此,估算要使用对应模型的分词器,实际用量以接口统计为准。
输入包含系统提示、工具定义、历史、检索到的文档和本轮消息。完整保留对话历史时,后续每轮处理的输入量都会增长。服务端续接历史也要计算这部分输入用量。控制成本时,应关注保留的对话历史和检索文档占了多少 Token。
输出包含回答、工具调用参数,推理模型还包含内部推理 Token。输出单价通常高于输入单价,命中缓存的输入则按缓存价格计算。前缀缓存省去重复前缀的预填充计算。缓存命中的 Token 数属于输入总量,推理 Token 数属于输出总量。两项明细都已计入总量,费用要按各类别的实际单价分别计算。
6.2 完整描述一次大模型生成,底层发生了什么?
考察重点:按顺序解释各生成阶段,说明输入和输出长度怎样影响延迟。能根据结束状态判断结果是否完整。
参考回答
一次生成包含分词、预填充、逐 Token 解码、停止判定和反分词。
服务先按模型模板组织系统提示、工具定义和消息,再转换成 Token ID。预填充处理整段输入,将各层的 Key、Value 存入 KV Cache。输入越长,需要的计算越多,首 Token 的等待时间也会增加。首 Token 延迟还包含网络、排队和调度等耗时。
解码时,模型根据已有序列计算下一 Token 的概率。采样规则选出一个 Token,追加后再进行下一步。KV Cache 复用旧 Token 的 Key、Value,省去重复计算。基本解码每步新增一个 Token,所以长输出需要更多步骤。
结束标记、调用方设置的停止序列或输出上限会终止生成。服务把 Token 转回文本,流式接口可在生成过程中逐段返回。应用要区分正常完成、截断和工具调用,再决定如何处理结果。多轮历史由应用重发或服务端补入下一次上下文,续接仍占输入用量。
6.3 temperature、top-p、top-k 分别是什么?不同场景应该怎样设置?
考察重点:解释三个参数怎样改变下一 Token 的选择,并按任务选择取值方向。理解模型快照、完整输入与输出校验对一致性的影响。
参考回答
temperature 调整概率分布,top-k 按候选数量筛选,top-p 按累计概率筛选。
温度低于 1 时,高分候选更占优势;高于 1 时,分布更平坦。top-k 只保留概率最高的 k 个候选。top-p 保留累计概率达到 p 的最小集合,候选数量随分布变化。
抽取、分类、代码生成和工具调用可从低温度开始评测。它们更关注稳定完成任务,创作和头脑风暴则可比较较高温度的效果。调优时先只改 temperature 或 top-p 中的一项,便于判断原因。参数是否可用,要核对所用模型与接口。
温度接近 0 时,采样接近每步选最高分的贪心解码。批次大小变化会改变求和分组,浮点误差会影响分数接近的候选 Token。因此,低温度也无法保证逐字一致。应用应固定模型快照和完整输入,并用结构化输出、Schema 和业务校验检查结果。生成失败时可有限重试,事实正确性仍需核对证据。
6.4 temperature 已经设为 0,为什么输出仍然不一致?
考察重点:浮点加法、批次大小与候选 Token 排名的关系,以及前文变化对后续生成的影响。
参考回答
temperature 为 0 时,服务端计算差异仍可能改变候选 Token 的排名,导致贪心解码选出不同 Token。
浮点加法不满足结合律,改变求和分组就会产生微小误差。服务把多个请求合成一批,批次大小变化又会改变求和分组。如果两个候选分数很接近,误差就足以让贪心解码选出不同的 Token。后续预测基于不同的前文,差异会继续扩大。
模型别名指向的快照、服务端硬件或推理程序也会更新。此外,部分推理模型不支持或忽略 temperature。判断差异时,要同时考虑参数是否生效和服务端计算是否变化。
6.5 如何让 LLM 每次输出的结果尽量一致?
考察重点:固定模型与输入、降低采样随机性、校验输出和缓存回答各能保证什么。
参考回答
固定模型快照与完整输入,并降低采样随机性,可以让重复生成的结果尽量一致。
应用应选用带日期的模型快照,固定系统提示、工具定义及其顺序和示例。对话历史、检索文档和工具结果也要一致。模型支持时,将 temperature 设为 0 或较低值;接口提供 seed 时,可固定种子以尽量复现。服务端的批次和浮点计算仍会影响结果。
结构化输出与 Schema 校验让字段和类型稳定,业务校验检查内容是否满足要求。完全相同的输入若要求逐字一致,可以缓存并复用之前的回答。自部署时,还可采用批次不变或确定性的计算方式,权衡吞吐量与一致性。
验证时,对同一输入运行多次,比较结论和关键字段是否一致。措辞相近的回答也会给出不同金额或日期,因此要检查具体字段。
6.6 回答很短却耗尽输出预算,应怎样解释?
考察重点:推理 Token、输出上限与未完成状态。
相关内容:推理预算与输出结束状态。
参考回答
推理 Token 也占用输出预算,因此可见回答很短时,预算仍会耗尽。
输出上限同时包含推理 Token 和可见回答。内部推理消耗较多 Token 时,留给最终回答的空间就会减少。应用可读取用量中的推理明细,确认内部推理消耗了多少 Token。
预算耗尽时,接口会把响应标记为未完成。应用应按未完成内容处理,检查剩余上下文空间后,调整输出预算再生成。调整后要同时比较成功率、延迟和费用。
7. 参考资料
- OpenAI:What are tokens and how to count them?
- Hugging Face:Generation strategies
- The Curious Case of Neural Text Degeneration(核采样论文)
- Training language models to follow instructions with human feedback
- OpenAI:Conversation state
- OpenAI:Reasoning models
- Direct Preference Optimization
- Lost in the Middle: How Language Models Use Long Contexts
- PyTorch:Numerical accuracy
- OpenAI:Pricing
- OpenAI:How to count tokens with Tiktoken
- OpenAI:Prompt caching
- Anthropic:Prompt caching
- Thinking Machines Lab:Defeating Nondeterminism in LLM Inference
- Anthropic:Messages API(temperature 说明)
- OpenAI:Advanced usage(输出复现)
- OpenAI:GPT-4o(模型快照说明)