No.322
同样的输入,模型输出不稳定怎么办?
一句话回答
不稳定主要来自三方面:采样随机性(temperature、top-p 越高越发散)、推理服务层面的数值差异(服务端批处理、GPU 浮点运算顺序不同,所以即使 temperature 为 0 也不保证完全一致)、模型版本变化。应对思路是"减少随机、约束输出、容忍差异":降低 temperature 并设置 seed(同样不保证完全一致),写更明确的指令和示例,用结构化输出和后处理校验,关键判断多次采样投票,固定模型版本,上线前做回归测试。
详细解析
随机性从哪来
- 采样参数:temperature、top-p 越高,越可能选到概率较低的 token,原理见 temperature 和 top-p
- 推理服务的数值差异:服务端会把多个用户的请求拼成批次一起计算,批次大小随负载变化,计算的分块和累加顺序也随之变化。浮点加法不满足结合律,顺序不同,结果就会有极小的差异。两个候选 token 的概率非常接近时,这点差异就可能让贪心解码选中不同的 token,之后的内容沿着不同的分支展开
- 模型版本变化:使用会自动指向新版本的模型别名时,厂商升级后行为可能悄悄改变
- 看起来相同、实际不同的输入:Prompt 里带了当前时间、顺序不固定的检索结果、多余的空格,模型看到的其实是不同的输入
- 指令本身含糊:多种回答都"说得通"时,概率分散在多个方向上,随机性被放大
应对手段
| 手段 | 作用 | 局限 |
|---|---|---|
| 降低 temperature | 分类、抽取等任务设为 0 或接近 0,减少采样随机性 | 消除不了服务端的数值差异;创作类任务需要多样性 |
| 设置 seed | 部分接口支持,尽量复现相同的采样结果 | 通常只承诺尽力而为,服务端配置变化后结果也会不同 |
| 更明确的指令和示例 | 让正确答案更唯一,从源头减少发散 | 需要反复迭代和测试 |
| 结构化输出、枚举值 | 把开放的回答变成有限的选项,见 怎么让大模型稳定地输出 JSON | 只约束格式,不约束内容对错 |
| 后处理归一化和校验 | 统一大小写、同义词、日期格式;不合格就重试 | 只能处理预料到的差异 |
| 多次采样投票 | 取多数结果,分歧大时转人工,见 Self-Consistency | 成本随次数成倍增加 |
| 固定模型版本 | 用带版本号的模型标识,避免被动升级 | 旧版本会下线,迁移前要做回归测试 |
| 缓存结果 | 完全相同的输入直接返回之前的结果 | 只适合答案可以复用的场景 |
把不稳定当成常态来设计
- 测试断言输出的性质,而不是逐字比较:JSON 合法、字段齐全、分类正确、包含关键信息
- 评测时多跑几次:同一个用例跑多次,看通过率和结果的分布,而不是只看一次的结果
- 回归测试:改 Prompt、换模型前后,用同一个评测集对比,重点看变差的样本,见 回归测试
- 线上监控:关注格式错误率、分类结果分布的变化,模型升级后尤其要留意
- 把分歧当作信号:多次采样的结果不一致,说明模型对这个输入没把握,可以交给更强的模型或人工处理
代码示例
TypeScript
// 需要稳定结果的调用。参数名是通用写法,各家 SDK 不同
const res = await llm.chat({
model: 'model-name-with-version', // 用带版本号的固定标识,不用会自动更新的别名
temperature: 0,
seed: 42, // 部分接口支持,只是尽量复现
responseFormat: { type: 'json_schema', schema: LabelSchema }, // 输出限定为固定的枚举值
messages,
})
// 上线前的稳定性检查:每个用例跑多次,统计通过率和不同结果的数量
async function stabilityCheck(cases: { input: string; expected: string }[], runs = 5) {
for (const c of cases) {
const outputs = await Promise.all(Array.from({ length: runs }, () => classify(c.input)))
const passRate = outputs.filter((o) => o === c.expected).length / runs
if (passRate < 1) {
console.log(`不稳定的用例:${c.input}`, { passRate, distinct: new Set(outputs).size, outputs })
}
}
}
面试官可能追问
创作类任务需要多样性,又要质量稳定,怎么平衡?
保留适中的 temperature,让表达有变化,但用指令和结构约束框架,比如固定大纲、风格要求、长度范围。还可以一次生成多个候选,再用规则或模型按标准挑出最好的一个。
用户点"重新生成",得到完全不同的答案,算问题吗?
看场景。开放式的写作、头脑风暴,不同的答案正是用户想要的。事实类问答如果每次结论都不一样,说明模型缺少依据或指令含糊,要补充资料(RAG)、把指令写明确,并降低 temperature。
怎么在自动化测试里断言模型的输出?
用规则断言性质:JSON 能解析、字段符合 Schema、包含或不包含某些内容、长度在范围内。开放式的输出用模型按评分标准打分。每个用例跑多次,用通过率而不是单次结果判断是否合格。
模型厂商升级了模型,输出风格变了,怎么及早发现?
固定模型版本,主动迁移而不是被动升级;迁移前用评测集对比新旧版本;上线后监控格式错误率、用户反馈等指标,见 上线后怎么发现模型效果变差。
易错点
- 以为 temperature 为 0 再加上 seed,就能完全复现
- 测试用逐字比较,导致测试本身就不稳定
- 使用会自动更新的模型别名,行为在不知不觉中改变
- 指令含糊时只降低 temperature,结果只是稳定地输出同一个可能错误的答案
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。