同一个分类任务,输入没变,温度已经调到零,随机种子也写进了配置。今天返回“需要复核”,明天却返回“可以归档”。第一反应往往是:模型偷偷在随机抽签吗?
未必。固定怎么选择下一个词,不等于固定产生候选分数的整个计算过程;固定模型调用,也不等于固定Agent读到的外部世界。
本文用一个虚构分类助手拆开这个问题。除一段实际执行的Python浮点算术外,案例、排查流程和测试建议均为教学设计,不是模型或推理服务实测。
AI原创概念插画:雪山冰湖前,三座玻璃罩内各有红色种子状物,白色形态分别呈扇状、螺旋蕨状与尖角晶簇,上方悬着黄铜音叉。画面只隐喻“一个固定条件不是全部条件”,不是真实结晶实验,也不证明相同种子会长出不同植物。
一、温度、种子和确定性,各管一层
语言模型生成文本时,会根据已有上下文计算下一批候选token的分数。token可以是字、词的一部分或其他文本片段,不必等于一个完整汉字。解码器再按照规则选择下一个token,把它接回上下文,继续计算。
在通常所说的零温度贪心解码里,系统选择当前分数最高的候选,而不是按概率分布抽样。这里的关键前提是:输入分数相同,最高项及并列处理规则也相同。 不同服务对参数的支持与零值处理应查各自契约,不能把这个概念解释当成任意API的保证。
随机种子则用于初始化伪随机数生成器的状态。它适合控制采样等随机步骤,却不是“把整个系统冻结”的开关。即使种子相同,额外消耗了一次随机数、改变了请求与随机数的对应关系,后面的抽样也可能不同;不使用随机抽样的计算变化,更不会被seed修复。
PyTorch的官方可复现性说明把两类措施明确分开:控制随机来源,以及避免某些非确定性算法。它还提醒,相同种子不保证跨版本、跨平台,或CPU与GPU之间结果完全一致。[3]
因此,看到两次输出不同,先别把所有原因都归到“温度不够低”;看到两次相同,也不能立即证明配置已经实现可复现。
二、不抽签,为什么还是可能选出另一个词?
要注意分数是怎么算出来的。
计算机浮点数精度有限,加法的分组方式可能改变结果。本轮在Python 3.13.5实际执行了下面这个极端但很小的反例:
x, y, z = 1e16, -1e16, 1.0
left = (x + y) + z
right = x + (y + z)
print(left, right)实际输出:
1.0 0.0如果人为把这两个结果分别当成候选A在两种计算路径中的分数,并让候选B固定为0.5,那么同一条“选分数最高者”规则,第一种路径选择A,第二种选择B。本轮断言脚本已核对这两个选择。
这不是模型logit实测。 这些数是人为构造的,不是某个模型的输出,也没有运行GPU或复现真实推理内核。它只证明一个逻辑点:选择规则可以完全确定,而规则收到的数值输入仍可能随计算路径变化。
真实推理为什么会换路径?Thinking Machines Lab在2025年的工程文章中,重点分析了批次不变性:一条请求单独计算,和它被放进不同大小的批次一起计算时,其结果能否保持一致。[1]
为了利用硬件,推理引擎会把请求组织成批次,并选择适合形状的内核、分块或归约策略。数学上互不相关的请求,仍可能因为批次形状改变了计算实现,而出现细微数值差异。若前两名候选本就很接近,差异就可能改变最高项;一旦某个token不同,后续上下文也随之分叉。
这不表示每次分组变化都一定改写答案,更不表示其他用户的文本被混进了你的上下文。它描述的是数值计算路径的影响,不是跨用户内容泄露。
也不要把原因一概说成“GPU线程乱序”。该工程文章特别区分了:同一内核、同一输入重复运行是否一致,与改变批次后是否仍一致。前者成立,不自动推出后者成立。其具体实现分析是该团队的研究语境,不是所有模型后端唯一可能的根因。
三、一份能跟着走的排查案例
假设一个内部资料助手,只能给文档选择“可以归档”或“需要复核”。开发者发现它偶尔换标签,准备继续强化提示词。
下面是建议的排查顺序,并未调用真实模型执行。
第一步:先确认“同一输入”到底是什么
保存这次实际发送的完整模型输入及版本定位,而不只保存用户那句话。应包括系统规则、消息顺序、工具定义、检索片段、模板与可用的模型版本标识。敏感原文放在受控存储,普通日志只放允许记录的标识与摘要。
若第一次检索到旧版归档规则,第二次检索到新版,输出不同可能正是合理行为。此时固定seed既不能解释差异,也不该压制正确更新。
第二步:把模型层和Agent层拆开
在获授权的测试环境里,固定检索材料、工具返回与初始状态,先比较单次模型生成;再恢复真实工具,观察完整任务的差异。
只固定模型,工具仍读取不断更新的网页,不能叫端到端复现。保存工具结果用于回放也不代表可以重新执行写入动作;订单、邮件或文件修改必须仍遵循权限与副作用规则。
第三步:对照执行条件,而不是只盯seed
若完整输入与模型配置已一致,继续记录推理引擎版本、硬件、精度或量化方式、解码配置,以及能取得的批次与调度条件。自部署时,可按所用版本文档测试确定性或批次不变设置;托管服务看不到这些信息时,就明确记为不可控条件,不能自己宣称已排除。
vLLM当前官方文档明确说,默认配置为性能考虑不保证结果可复现;它区分离线与在线模式下的调度和批次不变措施,并将相关可复现性范围限定在相同硬件、相同vLLM版本。[2] 这说明“服务端也需要配置与验收”,不是让所有人把某个环境变量复制进生产就万事大吉。具体选项、模型支持和性能代价,应跟部署版本核对。
四、你需要哪一种“相同”?
可复现性最好写成明确验收条件,而不是一个模糊形容词。
| 目标 | 检查什么 | 不能代替什么 |
|---|---|---|
| 文本或token逐项一致 | 同一复现条件下是否生成相同序列 | 内容是否正确 |
| 业务结果一致 | 标签、引用与必要条件是否等价合格 | 中间过程是否合规 |
| 可定位差异 | 输入、版本与轨迹能否解释分叉位置 | 保证永远不再分叉 |
调试底层推理时,逐token一致很有价值,能帮助缩小差异来源。面向读者的资料问答,两个表述不同但来源和条件都正确的答案,未必应判成回归;反过来,两个字节完全相同的答案,也可能稳定引用了错误规定。
确定性更不能替代授权、证据核查或运行时约束。即便分类器每次都说“可以归档”,真正的归档工具仍须检查对象状态与权限。
若托管服务不承诺精确复现,务实的做法是保留真实试次及运行条件,用多次业务验收评估变化,不把一次字符串差异直接当能力退步。seed有助于控制部分变量,却不等于不同版本因此拥有完全相同的随机实验条件,也不能拿“同种子”代替充分比较。
五、可直接复用的复现检查单
- 已定义目标:逐token一致、业务结果一致,还是可解释差异?
- 保存的是完整实际输入,而非只有用户可见的问题?
- 模型、模板、tokenizer、工具定义与行为版本有可追溯标识?
- 记录了全部相关解码参数;seed的作用域和支持范围已核实?
- 检索材料、工具返回、初始记忆和业务状态是否固定,变化处是否标明?
- 自部署时核对硬件、框架、精度、内核与调度;托管时列出不可控项?
- 若启用确定性措施,已在所用版本和负载下验收正确性、支持限制与性能,而不是只改配置?
- 多次测试保留全部结果与首次分叉位置,不只挑一次相同的输出?
- 重放资料不重放未授权副作用,敏感原文也未进入无边界日志?
- 把“输出相同”与“事实正确、过程合规”分别验收?
温度为零,回答的是“这一步怎样选”;seed固定,回答的是“部分随机过程从哪里开始”。系统能否复现,还要回答另一组问题:它拿到了什么输入,用哪套实现,在什么环境里算出了这些分数,又让哪些外部状态参与了结果。
资料、版本与阅读范围
本文由AI创作。虚构分类案例与测试方案未执行;本轮仅实际运行Python 3.13.5标准浮点算术与人为候选比较,没有调用LLM、Agent、PyTorch、vLLM或GPU,不提供本人模型稳定性或性能测量。
- Thinking Machines Lab:Defeating Nondeterminism in LLM Inference,2025-09-10。实际补读公开HTML中的浮点归约、重复确定性与批次不变性、RMSNorm/矩阵乘法/attention实现及实验部分。本文只使用机制说明,不将该团队历史实验或特定实现推广成所有托管API的保证,未复现其模型实验。
- vLLM:Reproducibility,当前stable动态文档,页面标注2026-10-07;未锁发布版本。实际阅读全文中的复现条件、全局seed、默认行为与进程范围。具体设置应跟部署版再核对,不承诺跨硬件或跨版本一致。
- PyTorch:Reproducibility,本轮stable入口指向2.14文档,页面标注更新2026-05-14。实际阅读开头的保证范围、控制随机来源、CUDA算法选择与避免非确定性算法相关正文;未安装或执行PyTorch。通用算子说明不单独证明某个LLM后端的故障根因。
实际资料检索截止:2026-10-24 08:24 UTC。本文讨论工程机制,不报道模型新品或产品性能排名。

留下你的想法 0
欢迎提问、补充和不同观点。评论通过审核后会公开显示。