2.4 采样参数如何影响 Agent 的稳定性
一句话结论:温度、top-p 这些参数不是"创意旋钮",而是在控制"模型有多愿意选它的第二答案"。Agent 场景的默认取向应该是尽量低方差——因为你需要的是可复现的行为,而不是惊艳的措辞。
读这篇之前
需要先读 2.1(模型在预测下一个 Token 的概率分布)。这一篇就是把那个"概率分布"拿出来,看你怎么从里面挑。
一、先看懂"采样"这件事
2.1 说过:模型输出的是概率分布,然后从里面挑一个 Token 放上去。
问题来了:怎么挑?
如果永远挑概率最高的那个(贪心),输出就完全确定——同样输入永远同样输出。如果按概率随机挑,输出就有变化。
这两种做法各有用处,于是有了几个参数来调节中间地带:
| 参数 | 控制什么 | 直觉解释 |
|---|---|---|
| temperature(温度) | 概率分布的"平坦程度" | 越低越保守,越高越冒险 |
| top-p(核采样) | 只从累计概率前 p 的候选里挑 | 砍掉长尾的离谱选项 |
| top-k | 只从概率最高的 k 个候选里挑 | 硬性限制候选数量 |
| max tokens | 最多生成多少 Token | 硬性截断 |
| stop | 遇到指定字符串就停 | 控制输出的结束点 |
二、温度到底在做什么
温度的工作方式很直接:它在缩放概率分布。
假设模型对下一个词给出的概率是:
"好": 0.60 "热": 0.25 "冷": 0.10 "雨": 0.05
- 温度低(趋近 0):放大高概率项 → 几乎总选"好"。输出确定、保守。
- 温度 = 1:按原始概率抽样 → 60% 选"好",有时选别的。输出自然、有变化。
- 温度高(>1):压平分布 → "雨"也可能被选中。输出发散、易跑题。
一句话:温度不改变模型的"知识",只改变它有多愿意选次优答案。
这对 Agent 意味着什么
Agent 的每一步输出都是后续步骤的输入。这意味着低概率的选择会在循环里被放大:
第 1 轮:正常判断(温度高时偶尔偏一下)
第 2 轮:基于偏了的判断继续
第 3 轮:偏离累积,任务方向已经变了
最终:结果完全不对,但你从单步看不出哪里错了
这就是为什么长链路 Agent 对温度的敏感度远高于单轮问答——单轮错一次只是答案不好,长链路错一次会导致整条轨迹跑偏。
三、top-p 与 top-k:砍掉长尾
温度和 top-p 的配合关系常被误解。它们的区别是:
| 温度 | top-p | |
|---|---|---|
| 作用对象 | 所有候选的概率,整体缩放 | 按累计概率截断候选集 |
| 效果 | 改变"冒险程度" | 改变"候选范围" |
| 极端值风险 | 温度太高 → 完全乱 | p 太小 → 输出呆板重复 |
top-p 的价值在于"排除离谱选项":即使温度高,也不会选到概率极低(明显不合理)的 Token。
实践中常见的组合是:温度适中 + top-p 适中,既不过度呆板,也不至于跑飞。
四、Agent 场景的默认取值建议
这里给的是方向性建议,不是绝对数值——具体值要按模型文档调整。
| 场景 | 温度 | 理由 |
|---|---|---|
| 工具调用 / 结构化输出 | 尽量低 | 需要格式稳定、参数准确;创意毫无价值 |
| 规划与拆解 | 低到中 | 需要合理,不需要花样 |
| 代码生成 | 低 | 正确性优先,且要可复现 |
| 写作 / 头脑风暴 | 中到高 | 此时多样性就是价值 |
| 需要多次采样择优 | 高 | 靠多样化得到更好的候选 |
一条通用原则:
凡是"输出会被程序读取"的环节,温度就该低;凡是"输出给人看"的环节,温度可以高。
这个原则的推论很实用:同一个 Agent 里,不同环节可以用不同的温度。 规划阶段低、内容生成阶段高,是很好的组合。
五、稳定性还有别的来源
温度只是稳定性的一部分。一个 Agent 行为不稳定,常见原因至少有五个:
| 原因 | 表现 | 手段 |
|---|---|---|
| 采样随机 | 同样输入不同输出 | 降温度(本篇) |
| 上下文顺序不固定 | 同样的信息,排在不同位置,结果不同 | 固定前缀顺序(5.3) |
| 工具结果本身有波动 | 接口返回顺序不固定、时间戳变化 | 工具层做归一化 |
| 历史累积不同 | 上次跑得久,这次跑得短 | 每轮重置显式状态 |
| 模型版本变化 | 供应商静默升级 | 锁定版本号 + 评测回归(第 13 章) |
这张表说明一件事:调温度只能解决第一行。如果你的 Agent 不稳定,先去确认是不是后四行的问题——它们更常见,而且更隐蔽。
六、一个实际的调试方法
当 Agent 行为不稳定时,按这个顺序排查:
① 把温度设到最低,连跑 3 次
├─ 还是不稳定 → 不是采样问题,去查 ②③④⑤
└─ 稳定了 → 就是采样问题,按场景定温度
② 检查上下文里有没有"每次都变"的东西
(时间戳、随机 ID、接口返回顺序)
③ 检查工具结果是否每次一致
(同一输入调两次,对比返回)
④ 检查每轮是否会注入新的历史摘要
(摘要本身不稳定 → 累积漂移)
⑤ 确认模型版本是否被静默更换
这个流程的价值在于:它把"玄学不稳定"变成了一次可执行的排查。
七、两个常被忽略的变量:位置与噪声
温度的讨论有一个隐含前提:输入是固定的,只有输出在变。但实际系统里,输入也在变。
模型的注意力对位置是敏感的:同样两段信息,一段放在开头、一段放在结尾,与反过来的排法,可能得到不同结论。原因在 2.2 讲过的那半台检索引擎——它是按"相关度"捞内容,而位置会影响相关度的判断。
这带来三个实践结论:
| 结论 | 做法 |
|---|---|
| 重要的事放两端 | 关键约束既在开头重申,也在结尾复述 |
| 上下文顺序要固定 | 每次拼装按同一模板,不要依赖字典遍历顺序 |
| 别让无关内容打断相关段落 | 相关的证据要连续排列 |
这也解释了为什么第 5.3 节的「前缀稳定」既能省钱(缓存)又能提稳(减少位置漂移)。
另一个隐蔽来源:工具返回的"噪声"
同样的工具调用,两次返回可能不同:
- 接口返回的列表顺序不固定
- 返回值里带时间戳、请求 ID、耗时
- 分页结果边界不同
这些差异会进入上下文,进而让模型下一轮的判断发生变化。表面上看是"模型不稳定",实际是"输入不稳定"。
处理办法很简单:在工具层做归一化——排序固定、剔除时间戳与 ID、只保留模型真正需要的字段。
这还有一个附带好处:返回值更短,省 Token。
八、参数之外:怎么让 Agent 更可预测
最后给一组不依赖参数的稳定性手段,按性价比排序:
| # | 手段 | 效果 | 代价 |
|---|---|---|---|
| 1 | 结构化输出 + schema 校验 | 消除格式类不稳定 | 低 |
| 2 | 温度按环节分开设 | 规划稳、表达活 | 低 |
| 3 | 工具返回归一化 | 消除输入噪声 | 低 |
| 4 | 显式状态外显(2.2 状态栏) | 消除计数/进度类错误 | 低 |
| 5 | 固定上下文模板与顺序 | 减少位置漂移 | 低 |
| 6 | 锁定模型版本 + 评测回归 | 防止静默退化 | 中 |
| 7 | 多采样投票(高价值场景) | 提升正确率 | 高(成本翻倍) |
前五条几乎都是免费的,却常常被忽视——团队往往一上来就调温度,而真正的问题在后面五条。
九、动手:给出一个可直接抄的参数配置
抽象讲"该低该高"不够,这里给出按环节划分的配置。
params:
# 工具调用 / 结构化输出
tool_call:
temperature: 0.0
top_p: 1.0
max_tokens: 500
# 意图分类 / 路由
classify:
temperature: 0.0
max_tokens: 50
# 规划拆解
planning:
temperature: 0.2
max_tokens: 1500
# 代码生成
code:
temperature: 0.1
max_tokens: 4000
# 内容写作
writing:
temperature: 0.7
top_p: 0.95
max_tokens: 3000
# 头脑风暴(要多样)
brainstorm:
temperature: 1.0
top_p: 1.0
三个配置要点
| 要点 | 理由 |
|---|---|
| tool_call 用 0.0 | 工具名与参数不能有创意 |
| classify 用 0.0 | 分类要稳定可复现 |
| writing/brainstorm 才调高 | 那里需要多样性 |
如果只能记一条:"输出会被程序读"的环节,温度必须 0 或接近 0。
十、一个被忽略的问题:max_tokens 与截断
温度控制"选哪个词",max_tokens 控制"说多少"——它同样会影响可用性。
| 设太小 | 后果 |
|---|---|
| 工具调用被截断 | JSON 不完整 → 解析失败 |
| 推理被截断 | 结论没出来 |
| 代码被截断 | 语法不完整 |
一个常见事故:工具调用参数里有长文本(比如要写入的文件内容),max_tokens 设了 1000,结果 JSON 被切断,整轮失败。
建议:工具调用环节的 max_tokens 要按"最大参数长度"估算,宁大勿小。
与预算的关系
max_tokens 是"单轮上限",不是"总预算"
总预算要靠轮数上限 + 累计 Token 统计(10.2)
两者都要有,缺一个就会失控。
十一、常见误区
误区一:温度越高越聪明。
不是。温度只改变抽样策略,不增加知识。高温产生的是"更多样",不是"更正确"。
误区二:温度设为 0 就能完全复现。
接近,但不保证。底层并行计算、浮点非确定性、上下文顺序变化都可能带来微小差异。要真正可复现,还需要固定输入顺序与模型版本。
误区三:调参数是"最后一公里"的优化。
恰恰相反,结构化输出必须先把温度降下来,否则你会在"格式解析失败"上浪费大量时间。这是起点,不是收尾。
误区四:一个温度设全流程。
不必。规划、执行、表达三个阶段对稳定性的要求完全不同,分开设置是更成熟的做法。
误区五:Agent 不稳定一定是模型的问题。
多数情况是上下文或工具的问题。温度只是最容易调、也最容易被当成替罪羊的那一个。
十二、三个稳定性问题的实测对比
| 问题 | 症状 | 实测差异(同样 20 次运行) |
|---|---|---|
| 温度 0.8 vs 0.0(工具调用) | 工具名/参数错 | 错 4 次 vs 错 0 次 |
| 工具返回带时间戳 vs 归一化 | 结果被判"变了" | 20 次全不同 vs 20 次一致 |
| 上下文顺序固定 vs 随机 | 结论漂移 | 结论一致 vs 2 次相反 |
第一行只是"常见",第三行才是"致命"——顺序随机时,同样的输入能得出相反结论。
而第三行几乎没人检查:因为没人会怀疑"顺序"。
检查方法:把同样的上下文用两种顺序各跑 5 次,看结论是否一致。
十三、第 2 章小结(采样部分)
| 要点 | 结论 |
|---|---|
| 温度控制什么 | 只有"冒险程度",不改变知识 |
| 长链路更敏感 | 低概率选择会在轮次里累积 |
| 输出被程序读 | 温度必须接近 0 |
| max_tokens | 太小结导致 JSON 截断 |
| 真正的不稳定源 | 顺序、噪声、历史,常不是温度 |
一句话:先修输入的不确定性,再调温度。
十四、一个最后的提醒
温度、top-p、max_tokens 都只是旋钮。它们不能让一个不合适的 Agent 架构变好。
三个顺序不能反:
① 先确认任务需要 Agent(1.4 五道题)
② 再确认上下文装得对(第 5 章)
③ 最后才调采样参数(本篇)
如果顺序反了,你会花大量时间调参数,而问题在架构。
十五、13、下一篇
到现在,我们已经把模型这一侧的约束讲完了:Token 计量、上下文窗口、幻觉、采样随机性。
还剩最后一个问题,它看起来像哲学问题但其实是工程问题:为什么模型明明"什么都知道",却不能自己"动手"把事情办了?
下一篇收束第 2 章,也解释清楚 Agent 为什么必须存在。