采样参数:temperature、top_p,以及它们正在退场

T0-2模块 0 · 大模型基础面试权重 更新于 2026-08
前置T0-1
关联题目Q1-03

这篇学完你能回答什么

  1. temperature 和 top_p 分别在调什么?为什么一般只调一个?
  2. temperature=0 能不能保证同样输入同样输出?
  3. 新一代模型不让设 temperature 了,那「稳定性」这件事该由谁负责?

从一个真实故障讲起

一个发票信息抽取服务。为了追求稳定,团队把 temperature 固定成 0,代码注释写着「保证输出确定」。跑了一年,翻了两次车。

第一次:QA 拿同一张发票连跑 20 遍,其中 2 遍的金额字段差了一位小数。开发的第一反应是「不可能,温度是 0」,于是花了两天去查 OCR、查预处理、查网络重试——最后发现这三处都没问题。

第二次(今年):升级到新一代模型,服务直接 400。报错不是说值不对,是说这个参数不该出现。而 SDK 里字段还在,代码编译得好好的,只有服务端拒。

两次翻车指向同一个认知缺口:把采样参数当成了确定性的保证,而它从来不是;并且到了 2026 年,它连「主要旋钮」都不再是了。

「保证输出确定」这句注释,是错的
发票信息抽取服务把 temperature 固定成 0,跑了一年,翻了两次完全不同的车

  1. temperature 固定成 0

    代码注释写着「保证输出确定」

  2. 同一张发票连跑 20 遍

    QA 回归,验的就是稳定性

  3. 2 遍金额差了一位小数断点

    第一反应「不可能,温度是 0」

  4. 查 OCR、预处理、重试

    两天过去,这三处都没问题

  5. 升级新模型,直接 400

    报错说:这个参数不该出现

同一张发票跑 20 遍注释承诺「输出确定」2 遍金额差一位小数
查错方向OCR / 预处理 / 网络重试两天,三处都没问题
升级到新一代模型SDK 字段还在,编译得过服务端直接返回 400
这层旋钮曾经是「主要旋钮」到 2026 年连主要都算不上
两次翻车指向同一个认知缺口:把采样参数当成了确定性的保证,而它从来不是。第一次的代价是两天查错查在了 OCR 上;第二次的代价是升级当天服务全挂 —— 字段还在、编译得过,只有服务端拒

核心概念:先打比方,再给定义

上一篇讲到,模型每一步吐出的是一个在词表上的概率分布。采样(sampling) 就是从这个分布里挑一个 token 的规则。

把模型想象成一个厨师,每一步都端上一桌候选菜,每道菜标了推荐度:

  • Temperature(温度) 调的是这桌菜「推荐度差距」的对比度。温度低,差距被放大,最推荐的那道几乎必被选;温度高,差距被抹平,冷门菜也有机会。数学上就是把 logits 除以 T 之后再做 softmax。
  • Top_p(核采样 / nucleus sampling) 调的是「允许上桌的范围」。按推荐度从高到低累加,累计概率到 p 就停,后面的直接撤下。
  • Top_k 是更粗暴的同类:只留前 k 个候选。
  • Greedy decoding(贪心解码):永远取概率最高的那个,等价于 T→0。

一句话把两者分开:temperature 改分布的形状,top_p / top_k 砍分布的尾巴。

这也正是「一般只动一个」的原因。两个一起收紧,候选很容易被压到只剩一个,输出变得机械重复;两个一起放开,你就不知道是谁在起作用,调参失去可归因性。

一个拧对比度,一个拧上桌范围
模型每一步端上一桌候选菜,每道菜标了推荐度 —— 两个旋钮拧的是这桌菜的两件事

推荐度差距 · 对比度旋钮

拧低,最推荐那道几乎必被选

拧高,差距被抹平,冷门菜也有机会上桌

对应
Temperature · 温度

改概率分布的形状

数学上就是把 logits 除以 T 之后再做 softmax

logits ÷ T低 → 尖锐高 → 平坦
上桌范围 · 哪些菜端得上来

按推荐度从高到低累加,到 p 停

后面的直接撤下 —— 撤得太狠,桌上就只剩一道菜

对应
Top_p · 核采样

砍概率分布的尾巴

nucleus sampling;top_k 是更粗暴的同类,只留前 k 个

累计概率 ptop_k 只留前 kGreedy = T→0
所以一般只动一个:两个一起收紧,候选很容易被压到只剩一道菜,输出变得机械重复;两个一起放开,你分不清是谁在起作用,调参失去可归因性。另有一个名字要认得:贪心解码永远取概率最高的那个,等价于 T→0。

原理拆解

把温度压到 0,只关掉了最后一层随机
一条链走完才吐出一个 token:改形状 → 转概率 → 砍尾巴 → 重新归一化 → 抽一个

logits模型这一步的原始打分
÷ T · 改形状
T=0.2 分布尖锐差距被放大,头部几乎必选
T=1.5 分布平坦差距被压缩,冷门也有机会
softmax到这一步才是概率
top_p / top_k · 砍尾巴
top_p 累到 p 就停后面的直接撤下
top_k 只留前 k 个更粗暴的同类
重新归一化 → 抽一个本步输出的 token
同一组 logits 走一遍
这一步算出什么读法
原始 logits8.0 6.0 5.5 2.0 1.0模型这一步的原始打分
÷ T,T=0.240 30 27.5 10 5差距放大 → 分布尖锐
÷ T,T=1.55.3 4.0 3.7 1.3 0.7差距压缩 → 分布平坦
softmax0.55 0.20 0.15 0.06 0.04这才是概率
top_p=0.90.55+0.20+0.15=0.90只保留前 3 个
top_k=2只保留前 2 个更粗暴的同类

贪心解码消掉的只是采样这一层随机,它上游还有四处:浮点加法不满足结合律(GPU 归约顺序随批次与调度变化,末位差异足以翻转两个接近的 logits)、动态批处理(跟谁拼在一个 batch 里会影响 kernel 选择与计算路径)、MoE 路由在批内有交互、版本漂移(同名模型的小版本更新)。

准确的表述只有一句:temperature=0 让输出高度稳定,但不等于确定性可复现。真想复现,靠的是固定模型版本号(不要用浮动别名)、把结构交给约束解码,以及最终 —— 把确定性需求下沉到代码里,别指望模型。
原文示意
logits   [ 8.0   6.0   5.5   2.0   1.0  ... ]
           │
           ├── ÷ T(temperature)
           │     T=0.2 → [40, 30, 27.5, 10, 5]      差距放大 → 分布尖锐
           │     T=1.5 → [5.3, 4.0, 3.7, 1.3, 0.7]  差距压缩 → 分布平坦
           ▼
        softmax → 概率 [0.55  0.20  0.15  0.06  0.04 ...]
           │
           ├── top_p=0.9:0.55+0.20+0.15=0.90 → 只保留前 3 个
           ├── top_k=2  :只保留前 2 个
           ▼
        重新归一化 → 随机抽一个 → 本步输出的 token
def sample(logits, temperature=1.0, top_p=1.0):
    if temperature == 0:
        return int(argmax(logits))              # 贪心:不再随机
    probs = softmax(logits / temperature)       # 改形状
    order = argsort(probs, descending=True)
    cum, keep = 0.0, []
    for i in order:                             # 砍尾巴
        keep.append(i)
        cum += probs[i]
        if cum >= top_p:
            break
    return random_choice(keep, weights=probs[keep])

为什么 temperature=0 也不保证复现——这是本篇最值钱的一段。

贪心解码消除了「采样」这一层随机,但它上游还有一堆不确定:

  1. 浮点加法不满足结合律。GPU 上的归约(reduce)顺序会随批次和调度变化,末位差异足以翻转两个接近的 logits 的大小关系;
  2. 动态批处理(continuous batching)。你的请求跟谁拼在一个 batch 里,会影响 kernel 选择与计算路径;
  3. MoE(专家混合)路由在批内是有交互的;
  4. 版本漂移。供应商随时可能对同名模型做小版本更新。

所以准确的表述是:temperature=0 让输出高度稳定,但不等于确定性可复现。 想真复现,得靠固定模型版本号(不要用浮动别名)、把结构交给约束解码、以及最终——把确定性需求下沉到代码里,别指望模型。

工程实践(截至 2026-08)

表 1:还能调参数时的经验取值

任务 temperature top_p 说明
抽取 / 分类 / 路由 / 生成 JSON 0 ~ 0.2 1.0(不动) 要的是可预期,不是多样性
事实问答 / RAG 生成 0.1 ~ 0.3 1.0 温度高会让模型「发挥」,这正是 RAG 最怕的
文案 / 起名 / 头脑风暴 0.7 ~ 1.0 0.9 ~ 0.95 二选一调,别同时放
self-consistency 多路投票 0.5 ~ 0.8 温度为 0 时多次采样完全相同,投票机制直接失效

表 2:这层旋钮的退场(2026 年的核心考点)

维度 具体情况
参数被弃用 截至 2026-08,Claude Opus 4.7 及以后、Sonnet 5 上,把 temperature / top_p / top_k 设成非默认值直接返回 400。SDK 里字段仍保留以兼容旧模型,代码编译得过,服务端才拒——升级时最容易踩
换成了什么 控制权转到 effort:low / medium / high(默认)/ xhigh / max。它影响的是整个响应的 token 花费,包括工具调用次数,不只是「思考多少」
官方给的判断 复杂问题上推理太浅,应该提高 effort,而不是绕着提示词想办法
隐藏代价 effort 值会渲染进 prompt,同一会话中途改 effort 会让之前的 prompt 缓存失效;官方建议一个会话内保持 effort 恒定

背后是同一条逻辑:推理型模型在内部要跑多条推理路径再择优,把温度压到 0 会让这些路径塌缩成同一条,反而破坏了机制本身。所以厂商干脆把这个旋钮收了回去。OpenAI 侧的推理模型同样拒绝非默认的采样参数——这不是某一家的选择,是一个行业方向。

避坑清单

  1. 别在代码里无条件塞 temperature 字段。 跨模型的网关层要按模型能力白名单剔除参数,否则每次升级模型必炸。这是 2026 年最常见的一类 400。
  2. 别把 temperature=0 当「确定性」写进设计文档。 写「高度稳定」,并配一个多次采样一致率的指标。
  3. 稳定性的责任要重新分配:格式稳定交给结构化输出(T1-2),事实稳定交给检索与校验,风格稳定交给系统提示词,深度与成本交给 effort。一个参数扛不动四件事。
  4. 迁移时要重做效果基线。 参数没了不是「降级」,是控制维度换了一套,旧的调参经验不能直接映射过去。
旋钮被收走了,稳定性得重新分配
还能调的时候按任务取值;到 2026 年,这层参数在新模型上直接 400,控制权转给 effort

还能调参数时的经验取值
任务temperature / top_p说明
抽取 / 分类 / 路由 / 生成 JSON开篇故障就在这一行0 ~ 0.2 / 1.0(不动)要的是可预期,不是多样性
事实问答 / RAG 生成0.1 ~ 0.3 / 1.0温度高会让模型「发挥」,这正是 RAG 最怕的
文案 / 起名 / 头脑风暴0.7 ~ 1.0 / 0.9 ~ 0.95二选一调,别同时放
self-consistency 多路投票0.5 ~ 0.8 / —温度为 0 时多次采样完全相同,投票机制直接失效
退场与避坑(截至 2026-08)
参数被弃用
Claude Opus 4.7 及以后、Sonnet 5 上,temperature / top_p / top_k 设成非默认值直接返回 400
换成了什么
控制权转到 effort:low / medium / high(默认)/ xhigh / max,管的是整个响应的 token 花费,含工具调用次数
官方给的判断
复杂问题上推理太浅,应该提高 effort,而不是绕着提示词想办法
隐藏代价
effort 值会渲染进 prompt,中途改会让之前的 prompt 缓存失效,官方建议一个会话内保持恒定
网关必须做的事
按模型能力白名单剔除参数,别无条件塞 temperature 字段 —— 这是 2026 年最常见的一类 400
责任重新分配
格式交给结构化输出(T1-2)、事实交给检索与校验、风格交给系统提示词、深度与成本交给 effort
厂商收回旋钮不是任性:推理型模型内部要跑多条推理路径再择优,把温度压到 0 会让这些路径塌缩成同一条,反而破坏了机制本身。OpenAI 侧的推理模型同样拒绝非默认采样参数 —— 这是一个行业方向,不是某一家的选择。

面试视角

面试官下一句一定是「那能复现吗」
形状 vs 尾巴 → 场景取值 → 反向判断;第三段是拿分点,前两段只是入场券

  1. 先讲分工形状 vs 尾巴:一个改分布,一个砍尾巴
  2. 再给场景取值抽取 0~0.2、文案 0.7~1.0,并说清怎么定的
  3. 最后反向判断0 不等于确定性;这层旋钮正在被收回
只读过:这些回答会暴露你
  • temperature 说成「创造力」
  • 建议「两个都调到 0.2 更稳」
  • 认为 temperature=0 输出必然一致
  • 不知道推理型模型已经不接受这个参数
真做过:这些细节骗不了人
  • 说得出自己项目里两类任务用了不同取值,以及是怎么定的
  • 能把「稳定性」拆给格式、事实、风格、深度四个责任方
  • 说得出 0 仍然不一致的机制:浮点归约 / 动态批处理 / 版本漂移
  • 知道跨模型网关要按能力白名单剔参数,否则升级必炸
2026 年新增的压力分支是「你依赖 temperature=0 的服务遇到参数被弃用,怎么办」。它考的其实不是参数,是你有没有真把稳定性拆给过四个责任方 —— 答得出这四家,这道题就翻篇了。

面试官怎么问。 一面必问基础版(Q1-03);有经验的面试官会在你答完后立刻追一句「那 temperature=0 能保证复现吗」——这是最经典的一道分水岭;2026 年新增的压力分支是「你依赖 temperature=0 的服务遇到参数被弃用怎么办」。

答题结构建议:形状 vs 尾巴(讲清分工)→ 场景取值(给具体数)→ 反向判断(0 不等于确定性;这层旋钮正在被收回)。第三段是拿分点,前两段只是入场券。

分水岭信号

  • 只读过:把 temperature 说成「创造力」;建议「两个都调到 0.2 更稳」;认为 temperature=0 输出必然一致;不知道推理型模型不接受这个参数。
  • 真做过:说得出自己项目里两类任务用了不同取值以及是怎么定的;说得出 temperature=0 仍然不一致的具体机制(浮点归约 / 动态批处理 / 版本漂移);知道跨模型网关要按能力剔参数;能把「稳定性」拆给四个不同的责任方。

小结与延伸

一句话收口:temperature 改形状、top_p 砍尾巴,两个都不给你确定性;而在 2026 年,这层旋钮正被 effort 这类「花多少力气」的高层控制取代。

  • 关联题目:Q1-03
  • 延伸:T0-5(思考档位:从 budget_tokens 到 effort)、T1-2(结构化输出与兜底)、Q6-09(token 成本治理)

继续深入

本篇归属第 1 章「LLM 与 Prompt 基础」,去做这一章的题