接上 SDK 之后第一件事往往就是写 model.generate(...),可参数一多就容易凭感觉填:温度随手调、长度顶格写、采样开关混着用,结果同一提示词两次跑出来差很多,或者明明设了长度还是被截断。这篇不讲概念科普,按「哪些参数必须显式给、哪些留给默认」帮你把常用项过一遍,并给一张按任务类型调参的对照表和排查顺序。
接上 SDK 之后第一件事往往就是写 model.generate(...),可参数一多就容易凭感觉填:温度随手调、长度顶格写、采样开关混着用,结果同一提示词两次跑出来差很多,或者明明设了长度还是被截断。这篇不讲概念科普,按「哪些参数必须显式给、哪些留给默认」帮你把常用项过一遍,并给一张按任务类型调参的对照表和排查顺序。
先记住一个分类思路:参数分成三组,解码策略组管「下一个词怎么挑」,长度组管「生成多少 token」,停止条件组管「什么时候闭嘴」。三组混着调,出了问题你根本分不清是哪个旋钮造成的。下面逐节拆,最后给排查顺序。
先分清哪些参数决定「说什么」,哪些决定「说多长」
- 温度
- 控制候选词分布的陡峭程度,越低越像在挑最高概率那个词,越高越愿意冒险选冷门词
- top_p
- 只在累计概率达到某个比例的那批候选里采样,池子大小由它定
- top_k
- 固定只保留概率最高的前若干个候选,和 top_p 是两种收窄池子的做法
- max_new_tokens
- 只限制新生成的那部分长度,不含输入
- 重复惩罚 / 频率惩罚
- 对已出现过的词降权,用来压住复读,属于补丁不是主菜
- stop 序列
- 命中指定字符串就停止生成,多轮对话和结构化输出里基本必给
长度类参数最容易踩的坑是把 max_new_tokens 顶格写。给太小,输出会被硬切在句子中间;给太大本身不影响正确性,但会拖慢尾延迟,因为框架要按最大长度预分配缓存。按任务实际需要的上限设,比如抽字段给一个刚够装下字段的长度,写长文再放宽。
另一个高频问题是输入加输出超上下文上限。这时有的框架直接报错,有的静默把输入截断,你看到的「模型答偏」其实是它压根没看到后半段提示词。调试阶段把实际送进去的 token 数打出来,比盯着输出猜有用得多。
- 解码策略类参数改成组看:改了一个就固定另一个,别同时乱动,否则说不清是谁的功劳
- max_new_tokens 与输入长度之和要在上下文上限之内,先算再加,别等报错
- 重复惩罚只在输出打转、复读时才动,动过头句子会变得不通顺,宁可小步加
- stop 序列建议显式给,多轮对话里不指定,模型会把后面的角色标签也一起生成出来
- 对比实验固定随机种子,不然你会把随机波动当成参数改进
采样还是贪心:什么任务该锁死,什么任务该放开
要可复现、要抽结构化字段、要做批处理判题,就把采样关掉走贪心或把温度压到接近零,同一输入每次结果应基本一致。要写文案、起名字、头脑风暴这类多样性任务,才开采样并调高温度。温度高到一定程度会开始胡说,具体卡在哪个值要在你自己的任务上试,不要照搬别人的数。
| 任务类型 | 解码方向 | 要盯的参数 | 常见坑 |
|---|---|---|---|
| 字段抽取 / 分类 | 贪心或极低温度 | max_new_tokens、stop 序列 | 温度开高了字段值会漂 |
| 多轮对话 | 低到中温 | stop 序列、上下文长度 | 没给 stop,角色标签被续写 |
| 文案 / 起名 | 采样,温度偏高 | 温度、top_p | 温度和 top_p 一起调,效果不稳 |
| 长文生成 | 采样,温度中等 | max_new_tokens、重复惩罚 | 长度给小了写一半断掉 |
| 代码补全 | 贪心或极低温度 | stop 序列 | 采样开了同一处补出不同代码 |
top_p 和 top_k 是给采样加候选池的两种做法,常见搭配是锁一个、调另一个。两个都调等于两个旋钮互相抵消,你调大温度又收紧 top_p,结果看起来没变化,还以为参数不起作用。选一个当主旋钮,另一个设成足够宽的值当兜底即可。
这里要说清什么情况下不适用:如果任务本身答案唯一(比如按固定格式输出日期),那参数怎么调都救不了格式错误,该修的是提示词和校验逻辑;如果任务本身开放(创意写作),那追求「每次结果一致」就是目标设错了,别拿可复现当标准。
长度、批处理与流式:影响速度的那几个开关
批处理会改变显存占用和单条延迟。批量上去了吞吐好看,但首字更慢,而且单条超长样本会把整批拖住。在线对话和离线跑批该用不同的批大小:在线优先盯首字延迟,把批压小;离线优先盯总吞吐,把批放大,同时给超长样本单独走一条路。
流式和一次性返回对参数的影响主要在停止条件。流式下更要盯 stop 序列和生成长度上限,不然前端会一直等下去,用户看到光标闪了半天没动静。给流式接口设一个兜底的 max_new_tokens,配合 stop 序列,比只靠其中一个稳。
生成速度不只由参数决定,还跟硬件、量化档位和并发有关。先到 [接口测速] 量出你自己的延迟基线,再判断是参数问题还是资源问题。同一套参数换一台机器表现完全不同,这种情况就别在参数上继续折腾了。
- 量基线用固定提示词和固定种子跑若干次,记录首字延迟和总耗时,作为后面所有对比的参照
- 分离变量一次只改一个参数,其他保持不动,改完重跑同样次数,看的是平均值不是单次
- 分场景设批大小在线接口用小批、离线任务用大批,超长样本单独排队,避免一条拖垮一批
- 验停止条件故意喂一个会触发 stop 的输入,确认输出真的停在该停的位置,流式接口尤其要测
效果不对时的排查顺序
很多「模型答偏」其实跟参数无关,顺序错了会白调很久。建议按下面这个顺序走,每一步都能证伪上一步。
- 先确认模型和版本口径对不对,同名模型的快照和别名可能不是一份权重
- 再确认输入是否被截断:把实际送进去的 token 数打出来看
- 然后才是调采样参数,一次只改一个,改完固定种子重跑几遍看稳定性
- 接着检查停止条件,看是不是被 stop 或长度上限提前掐断
- 最后才考虑换提示词结构或换模型,参数能救的范围有限
最后一步尤其要认清边界:给模型超出能力边界的任务,怎么调参数都不行。比如让它做需要精确计算的推理,或者要求它输出训练里根本没见过的私有格式,这类问题该换方案而不是换参数。判断标准很简单:同一提示词换两三个差异很大的参数组合,输出质量没有数量级变化,那瓶颈就不在参数上。
下一步想知道你手上这家接口当前的模型口径、价格和上下文上限,直接去资料页核对当时的数字,再回来定参数范围,别照着旧印象填。→常见问题
温度设成 0 就一定每次结果一样吗?
不一定。多数框架里温度 0 走贪心解码,理论上确定,但批处理拼接方式、浮点运算顺序、并发下的实现差异都可能带来微小抖动。要严格复现就同时固定随机种子、关掉采样、尽量用单条请求,别在小数点上较真。
max_new_tokens 设大一点会不会更贵?
按量计费通常是按实际生成的 token 收,设大但不生成那么多不会多收;自建推理则是设大了会多占 KV 缓存、拖慢并发。所以设这个值的原则是「按任务真实需要留出余量」,不是越大越好也不是越小越省。
为什么同样的参数,换个模型效果差很多?
每个模型训练时的采样习惯不一样,有的在中等温度下才自然,有的低温更稳;而且有的模型对重复惩罚、top_k 这类参数本身就不敏感。换模型后别直接搬参数,先按新模型推荐区间重新试一轮,再回到自己的任务上微调。