temperature=0、seed=0 也不等于完全确定, 工程实践的过程中总会有取舍, 请允许理想与现实的偏差.
概览
在真实工程环境下,做到如下:
temperature = 0- 随机种子(seed)固定为 0
- 模型权重不变
LLM 输出依然不能保证严格的确定性。
原因来自多个层级:采样配置、数值误差、批量调度、MoE 架构、基础建设等。
工程实践中,更现实的目标不是“位级完全一致”,而是用参数 + 架构 + 缓存,把模型行为控制在业务可接受的稳定性范围内。
下文按“出现概率”给一个原因排行榜,再给出可操作的规避策略与代价。
参数如何影响推理
理想化推理链路:
固定权重 + 固定输入 + greedy 解码(每步选 argmax) + 完全确定的数值计算
⇒ 输出必然完全一致。
temperature 符合直觉:
- 越高 → 分布越“平”,更多随机采样;
- 越低 → 分布越“尖”,趋向于 greedy;
- 理论上
temperature=0会极端放大最大 logit,对应“总是选最大值”。
seed 作用更窄:
- 仅控制“伪随机数生成器”的序列;
- 只对依赖随机采样的步骤生效;
- 对数值并行、batch 调度、非确定性 kernel 没有直接约束。
因此,温度=0 + 种子固定,最多是“更接近 deterministic”,而不是“数学意义的 deterministic”。介不就是光速与绝对零度嘛。

工程中概率排行
配置没有真正关掉随机性
高频误区:
- 仍然在用采样:
top_p < 1、top_k > 1,只是温度降到 0; - 请求
n > 1,服务端对多条采样结果再做内部选择; - provider 对
temperature=0做了特殊处理或者忽略0,比如强制改成一个很小但非 0 的温度; - 文档写的是 “mostly deterministic” 或 “best effort reproducibility”,并未承诺严格一致。
这些都意味着你以为关掉了随机性,实际上还在采样,而且 seed 只保证“这条采样序列可复现”,并不保证不采样。工程上遇到的多数“T=0 还在变”的案例,根因都在这一层。
1 | |
批次产生差异
在云端 API 上,请求通常如下情况:
- 被和其他用户的请求一起打包进不同大小的 batch;
- 由底层推理引擎根据 batch 维度选择不同的并行 kernel 或归约策略。
这会导致:
- 浮点加法顺序变化(不满足结合律);
- attention / matmul / RMSNorm 的归约路径不同;
- logits 在 1e-6 量级上产生差异;
- 若两个 token 概率本来就非常接近,argmax 可能翻转,后续生成路径完全分叉。
《Non-Determinism of “Deterministic” LLM Settings》在理论“应当确定”的配置下反复测试,发现输出字符串的一致率明显小于100%,下游任务准确率在不同 run 间可以差十几个百分点。
对云 API 来说,这是最常见且几乎不可控的非确定性来源。用户也不可能决定好每个批次元素的归约顺序.
浮点并行本身就是非确定性的
即便你在本地单机推理,只要使用 GPU / 并行 kernel,也会碰到:
- 并行归约(
atomicAdd等)导致累加顺序未定义; - cudnn/cublas/自定义 kernel 采用了不同实现路径;
- 多线程抢占导致不同 run 间执行顺序略有差异。
数值差异微小,但 softmax + argmax 会放大这些差异;自回归生成会进一步放大第一步 argmax 的差异。
PyTorch 论坛中多次讨论:即使 model.eval(),也需要额外开启 deterministic 模式,
否则多次 inference 仍然无法 bit-wise 一致。
批次与浮点计算可以合在一起看,下图是一个简单的归因链路示意:

解码实现细节
不同框架/服务对于 “temperature=0” 的实现并不统一:
- 有的分支直接走 greedy,不采样;
- 有的把 0 改成一个很小的正数,仍然进行采样;
- 有的在低温下仍然允许 nucleus / top-k 筛选后采样。
再叠加 tie-breaking 策略:
- 概率相等或近似相等时,是按 token id 排序选第一个
- 还是仍然用 RNG 做一次随机决策
这些实现级细节,很容易在“理论上相同配置”的两次调用之间,积累成肉眼可见的输出差异。
实际代码里,几个主流高 star 项目对 temperature=0 的处理就已经完全不一样:Transformers 直接视为非法值, vLLM 把它解释成“强制 greedy 并重写 top_p/top_k”, llama.cpp 则在不同版本中先后把非正温度当作 greedy 的捷径、后来又要求配合 top‑k 才能得到真正的 greedy 行为。
这本身就说明:“temperature=0”的语义强依赖具体框架实现,目前并没有统一标准。
模型架构的非确定性(MoE 路由等)
对采用 Mixture-of-Experts(MoE)的模型:
- 每个 token 会先经过 gating 网络决定路由到哪些专家子网络;
- 为了负载均衡,路由逻辑中可能包含截断、近似甚至随机裁剪;
- 当不同 batch 下竞争同一专家时,调度顺序变化会改变路由结果。
模型/系统版本漂移
在云端服务里,以下情况都很常见:
- 模型权重热更新、系统 prompt 调整;
- 不同 region / 集群挂载了略有差异的模型快照;
- 路由策略在多个版本间做灰度。
同一个 model name 在不同时刻/不同 region 调用,底层实际上可能已经不是同一个模型实例。
这更常见于“隔一段时间”再次调用发现结果不同,而非“连续两次立刻不同”。
输入并非真正完全一致
常见人祸因素:
- prompt 拼装引入 time、userid、skill 等隐变量;
- system prompt / few-shot demo 在不同调用间细微变化;
- 不可见字符(BOM、零宽空格)或换行差异。
日志里看上去完全一样,但序列化出来并不一样。这一类问题本身不深,只说明排查非确定性前先校验输入字节级是否一致。
如何尽量确定性
下面区分两种场景:云 API 调用 / 自建推理。
云场景
参数层面尽量去随机
- 使用:
temperature非 0 但极低(如 0.01–0.1),避免 0 被特殊处理; top_p = 1、不使用top_k、n = 1;- 查阅各家文档中关于 deterministic / best-effort 的说明,按官方建议配置参数。
- 使用:
利用 seed + 缓存,构造“业务上的确定性”
- 定义一个请求签名:
(model, temperature, top_p, system prompt, user prompt, seed, 其他参数); - 请求真实调用 API,确认符合后缓存完整输出;
- 后续相同签名的请求,直接返回缓存结果。
- “相同参数 + prompt ⇒ 永远返回同一条缓存结果”。
- 定义一个请求签名:
把 LLM 当作带噪声组件,用上层逻辑兜底
- 结构化输出(JSON、SQL、DSL):
- LLM 生成候选 → 用 schema / parser 严格校验 → 不合格则重试/修正;
- 分类/打标/评分任务:
- 多次调用 + 多数票 / 平均;
- 业务侧预期里显式允许小范围不一致,不要把一次 LLM 响应当作“权威真相”。
- 结构化输出(JSON、SQL、DSL):

自建场景
- 禁用采样,使用 greedy / 确定性 beam
- 在 vLLM / Transformers 中显式设置:
do_sample=False; - 不设
top_p/top_k,尽量使用纯 greedy; - 使用 beam search 时,禁用任何随机 beam 相关功能。
- 代价:输出模式更单一,对需要发散思维的任务不友好, 专一模型尚可如此。
固定所有可见随机种子
torch.manual_seed(seed);torch.cuda.manual_seed_all(seed);- 同时固定 Python / NumPy 等种子。
- 只能控制“采样/随机算子”的不确定性,对浮点并行无能为力。
开启框架 deterministic 模式,禁用非确定性 CUDA 算子, 以 PyTorch 为例:
torch.use_deterministic_algorithms(True);- 关闭
torch.backends.cudnn.benchmark; - 配置
CUBLAS_WORKSPACE_CONFIG等环境变量。 - 代价: 性能显著下降(吞吐、延迟都会受影响),部分高性能 kernel 不可用,只能退回更保守实现。
控制 batch 行为,必要时牺牲拼 batch
- 不跨请求拼 batch,每个请求单独跑;
- 或使用专门实现了 batch-invariant kernel 的推理库。
- 代价:GPU 利用率显著下降,成本上升;在高 QPS 场景往往难以接受,只适合“离线评测 / 基准测试 / 审计”这类场景。

总结
从研究与工程实践看:
- 即使在 temperature=0、seed 固定的配置下,LLM 仍然表现出显著的非确定性;
- 想在云端 API 上做到严格 deterministic,几乎不现实;
- 在自建推理里,做到“足够接近 deterministic”往往需要明显牺牲性能与吞吐。
更合理的心智模型是:
LLM = 强大但带噪声的推理器
——在设计系统时,默认它“不完全可复现”,通过参数、缓存和上层逻辑来吸收这种噪声。
适合追求强一致性的环节(计费、风控、合规决策),应优先考虑确定性模型或规则系统;
LLM 更适合作为“辅助决策 + 文本代理”,而不是唯一的“权威判官”。
这样设计出来的系统,更符合当下大模型技术的真实边界。
文章主要借助
Perplexity检索文献和生成配图,对其中一篇核心参考强烈推荐原文阅读 Defeating Nondeterminism in LLM Inference