temperature 是调用大模型时最核心的生成参数(sampling parameter)。它决定模型在每个 token 上从候选分布里怎么挑,但它不决定模型聪不聪明------这是很多使用误区。
本文讲清三件事:它在算什么、怎么按任务分档用、在 RPA 流程里怎么落地。
一、原理:把分数除以温度再归一化
模型每生成一个 token,都是先对候选词打分(logits),再按分数做 softmax 抽样。temperature 插在打分和 softmax 之间:
p_i = softmax(logits_i / T)
- T < 1:分布变尖(sharpened),高分词稳赢,输出更确定
- T = 1:保持原始分布
- T > 1:分布被抹平(flattened),冷门词也有机会抽中
直观类比:从一箱签筒里抽签。低温相当于先按大小排好序再抽,永远抽最大那支;高温相当于彻底打乱靠手感摸,花样多,也可能摸到空签。
关键点:温度只改变抽签方式,不改变签上写的内容。 模型不知道的事实,调到 0.2 也不会变知道。
二、核心参数与双向后果
| 参数 | 作用 | 太大 | 太小 |
|---|---|---|---|
temperature |
重塑整个分布的尖锐度 | 输出跑偏、JSON 不合法、抽取出格式外的值 | 死胡同:次次一样,且最高分是死胡同时卡住 |
top_p(核采样) |
只在累计概率达 p 的头部候选里抽 | 长尾没切掉,随机性仍偏高 | 只剩一个候选,失去多样性 |
官方建议二者二选一,因为两者修饰同一个分布,同时调的结果无法预测。
各平台取值范围
| 平台 | 范围 | 默认值 |
|---|---|---|
| OpenAI | 0 -- 2 | 1 |
| Anthropic | 0 -- 1 | 1 |
| Gemini | 0 -- 2 | 1 |
⚠️ 推理类模型(o1、Gemini 2.5 Flash 等)普遍锁死该参数,传入直接报错,也有接受后静默忽略的情况。换模型后务必先跑一条样本验证。
三、三种用法与代码示例
1. 固定低温:抽取、分类、判断
python
# 环境:Python 3.12 / openai>=1.55
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4o",
temperature=0.1, # 需要断言的字段:抽取单号、金额、日期
messages=[{"role": "user", "content": "从这段合同里抽出甲方名称和签订日期:......"}],
)
低温带来结果稳定可复现,便于流程断言;代价是需要发散的写法会显得死板。
2. 固定中温:摘要、客服话术、营销文案
python
resp = client.chat.completions.create(
model="gpt-4o",
temperature=0.7, # 只做展示、不需要逐字比对的字段
messages=[{"role": "user", "content": "给这条工单写一句 20 字内的回复。"}],
)
表达更自然,同一单据两次措辞不同------下游若要做文本比对,得先做归一化。
3. 按任务分档:维护映射表
python
TASK_TEMPERATURE = {
"extract": 0.1, # 结构化抽取
"classify": 0.2, # 意图分类
"summarize": 0.6, # 摘要
"rewrite": 0.8, # 文案改写
}
def gen(task: str, prompt: str) -> str:
return client.chat.completions.create(
model="gpt-4o",
temperature=TASK_TEMPERATURE[task],
messages=[{"role": "user", "content": prompt}],
).choices[0].message.content
4. 需要复现时:seed + system_fingerprint
即使 temperature=0,输出也不保证逐字一致,原因是:
- 并行浮点运算不满足结合律,规约顺序不同 → 浮点结果微差 → 影响打分与抽样
- 批次拼批时 padding 长度、算子融合路径可能不同
- MoE 路由结果对浮点误差敏感
真要复现,得靠 seed,并把 system_fingerprint 一起落库:
python
resp = client.chat.completions.create(
model="gpt-4o",
temperature=0,
seed=42,
messages=[{"role": "user", "content": "用一句话介绍你们公司的主营业务。"}],
)
fingerprint = resp.model_extra.get("system_fingerprint")
# 与 seed、时间戳一并写入日志表
5. 低温配 top_p(社区常见写法)
python
resp = client.chat.completions.create(
model="gpt-4o",
temperature=0.3, # 主体走稳定路线
top_p=0.9, # 切掉长尾
messages=[{"role": "user", "content": "给这条工单写一句 20 字内的回复。"}],
)
低温负责稳定、top_p 负责切尾。但不要两个一起反复调------两个旋钮同时动,结果无法预测。
四、在 RPA 流程里的工程实践建议
- 按字段类型分温度:先把「这个字段要不要断言」定下来。要断言的显式传低温,只做展示的放宽。
- 不要让 temperature 和 top_p 同时动:二选一写死在流程配置里。
- 给关键流程固定 seed:seed + system_fingerprint 一起存日志,重跑可复核。
- 换模型前先查参数支持:推理类模型锁死该参数,换完先跑一条样本验证,比等批量跑完才发现省事。
- 低温度下仍需校验 JSON:温度低不等于格式一定合法,解析失败要能回退。
五、动手验证
python
prompt = "用一句话介绍你们公司的主营业务。"
for t in (0.0, 1.0):
print(f"--- T={t} ---")
for _ in range(3):
r = client.chat.completions.create(
model="gpt-4o", temperature=t,
messages=[{"role": "user", "content": prompt}],
)
print(r.choices[0].message.content)
只比较两件事:答案有没有变化,变化的是措辞还是事实。 如果低温三轮几乎一字不差、高温三轮连业务都说歪,说明温度的真实作用范围是表达,不是内容。
总结
temperature 决定模型每一步选词的概率分布,核心是让随机性可调,而不是让模型变聪明。在 RPA 里它的位置很清楚:需要断言的环节调低,需要自然的环节放宽,换模型时先确认参数还在不在。
它是链路上的微调旋钮,不是质量开关。
下期讲提示词的结构化写法。