Naive-N0.5-Flash 同一个提示词两次输出长度差很多,通常不是模型随机性本身的问题,而是采样参数没有固定、或者停止条件在中途把生成切断。可以先做一件事:把温度和 top-p 这类采样项、以及 max_tokens 和 stop 这类边界项,各固定成一组默认值,然后再逐项对照。这样做的目的是让「改了哪个变量导致长度变化」可以被归因,而不是靠感觉调参。
同提示词输出忽长忽短时,先固定温度、top_p、top_k、max_tokens 与 stop 这五项,再逐项对照。适用于能改服务配置或能改请求体的自建推理服务;若参数被网关或 SDK 覆盖,需要先确认实际生效的是哪一层。验证方式是同一提示词重复多次,看 finish_reason 与输出长度是否收敛。停止符冲突没排除之前,不要下关于采样参数的结论。
先固定一组默认采样参数并只改一个变量
先把这几项抄下来,作为这一轮排查的基线:temperature、top_p、top_k、max_tokens(有的接口叫 max_new_tokens)、repetition_penalty,以及 stop。seed 如果接口支持也一并固定,它对复现最直接。基线建议取温度偏低、top_p 不完全放开、max_tokens 写成一个明确上限,让输出长度先落在可控区间里,再谈更细的调法。
设好基线之后,每轮只改一项,其余全部保持和基线一致。同时改两项以上,长度变了也说不清是哪一项造成的。记录表按下面这几列写,用表格文件或笔记本都行:
| 轮次 | 只改的项 | 改成什么 | 其余参数 | 提示词 | 输出字符数 | finish_reason | 是否命中停止符 |
|---|---|---|---|---|---|---|---|
| 1 | temperature | 0.3 | 所有项同基线 | 写完整 | — | — | — |
| 2 | top_p | 0.9 | 温度已定 | 同上 | — | — | — |
提示词那一列要写完整,包括系统提示和模板符号。finish_reason 有的接口会返回 length、stop、eos 之类的值,它是区分「模型自然结束」和「被长度上限截断」最直接的字段;拿不到这个字段时,先看响应里有没有等价的结束标记,再退回去数输出长度。
分别测温度与 top-p 对输出长度的影响
先测温度,把 top_p 固定成 1.0,其它项照基线。取值可以选 0、0.3、0.7、1.0 这几档,每档用同一个提示词跑 3 到 5 次——只跑一次看不出波动,跑太多次又不好整理,这个次数通常够判断离散程度。每次都记录输出字符数、token 数(接口返回时)、finish_reason,以及是否命中停止符。
温度测完,把它固定在波动最小的那一档,再对 top_p 做同样梯度的对照,比如 1.0、0.9、0.8。重点看两件事:同一取值内多次输出长度的离散程度,以及不同取值之间平均长度有没有明显移动。如果某一项改完长度分布几乎不动,说明它对长度影响有限,可以先把这项定下来不再动它。
有个容易踩的点:温度与 top_p 一起动的时候,效果会互相掩盖。所以这两轮分开做,不要合并成一轮。
检查停止符是否与提示词模板冲突
如果输出总是在某个固定位置戛然而止,而且长度看起来「刚好卡住」,优先怀疑停止符,而不是采样参数。常见冲突有这么几种:
- 停止串本身出现在提示词正文里。比如提示词示例中写了 Human: 或 ###,模型一复述就触发停止。
- 停止串与角色模板符号重合。例如 <|im_end|>、</s> 这类本来由模板层处理的分隔符,同时又被写进了 stop。
- 客户端和服务端各配了一套 stop,两边叠加后实际生效的是并集,比你以为的更早截断。
- 停止串里含换行或前后空白,请求经过序列化后写法变了,等于没生效,或者生效位置和预期不同。
排查顺序建议是:先打印真实请求体,确认最终下发的 stop 到底是什么;再把调用方自定义的 stop 全部去掉,只留服务端默认,看中断是否消失;然后在提示词正文里逐个搜索这些串,确认它们没有出现在不该出现的位置;最后才回头对比采样参数。顺序反过来做,很容易把停止符造成的中断误判成温度太高。
把稳定下来的参数写成服务默认配置
收敛出一组参数之后,不要留在调用方代码里靠记忆传。建议把它写成服务侧默认值,调用方不显式传参时就落到这套值上。骨架大致这样:
defaults:
temperature: 0.3
top_p: 0.9
top_k: 0
max_tokens: 512
stop:
- Human:
- '<|im_end|>'
allow_request_override: true
生效范围要写清楚:服务级默认对不传这几个键的调用生效;请求级参数通常优先级更高,调用方只要传了 temperature,就会覆盖默认值。要真正复现,可以在一段时间内要求调用方不要覆盖这几个键,或者把 allow_request_override 关掉,具体能不能关需要结合所用服务的配置项确认。
回滚方式提前准备两份东西:一份是改动前的配置备份,一份是这次改动的说明(改了哪些键、从什么改成什么)。出问题时把配置文件换回备份,重启服务或触发一次配置重载即可,不用回滚代码。改完验证一次:同一个提示词连续跑几次,看 finish_reason 和输出长度是否稳定在同一区间;如果仍然漂移,说明还有别的变量在起作用,回到第二节继续做单变量对照。