跳到主要内容
推理优化

8.5 采样与解码算法:生成质量的后台旋钮

SamplingParams 全参数语义(temperature/top_p/top_k/min_p/惩罚)、logprobs、并行采样 n、beam search 的移除、采样对延迟与质量的影响

采样TemperatureTop-pLogprobs并行采样Beam Search

前几章优化的是”怎么更快地出 token”,8.5 回答”token 是怎么被选出来的”。采样参数(temperature、top-p……)看似简单,实则是质量、多样性、延迟的三角权衡——调错参数,前面所有性能优化都白费(吐一堆废话)。这一节把 vLLM 的 SamplingParams 逐个讲透,并澄清工程实现上的关键差异。

📑 目录


1. 解码的两种模式:贪心与采样

模式行为适用
贪心(Greedy)每步选概率最高的 token确定性任务(抽取、分类、JSON)
采样(Sampling)按概率分布随机抽创意任务(写作、对话、代码注释)

数学上,采样分布 = 模型输出的 logits 经 temperature 缩放 → 惩罚修正 → top-k/top-p/min-p 截断 → softmax → 采样。vLLM 的 SamplingParams 就是这个管线的参数面板。

📌 关键点贪心不是采样参数的”一种取值”,而是独立模式——vLLM 里 temperature=0 即贪心(等价于始终选 argmax)。测试时如果输出不具多样性,先检查是否 temperature 被设成了 0。


2. 核心采样参数逐个拆解

vLLM(v0.26)SamplingParams 的默认值与语义:

参数默认语义常见用法
temperature1.0logits 缩放:logits / T。T>1 更平(随机)、T<1 更尖(确定)0.3-0.8 创作;0 贪心
top_p1.0核采样:保留累计概率 ≥ p 的最小 token 集合0.9-0.95 常用
top_k0(=禁用)只保留概率最高的 k 个 token40-50(旧式)
min_p0.0保留概率 ≥ min_p × 最高概率 的 token0.05-0.1(动态截断)
seedNone随机种子(复现实验)固定 seed 可复现

2.1 temperature 的语义细节

  • T=0:贪心(argmax)
  • T=1:原始分布
  • T>1:分布变平——低概率 token 被放大,多样性↑ 质量↓(幻觉风险↑)
  • T<1:分布变尖——确定性↑,但过度压缩会退化(重复、死板)

2.2 top_p vs top_k vs min_p

三个都是”截断”手段,但机制不同:

原始分布:      [0.50, 0.20, 0.10, 0.05, 0.04, 0.03, ...]
top_k=3:       [0.50, 0.20, 0.10]            ← 固定数量
top_p=0.85:    [0.50, 0.20, 0.10, 0.05]      ← 累计到 0.85(动态数量)
min_p=0.1:     [0.50, 0.20, 0.10, 0.05]      ← 相对最高概率的阈值
  • top_k:固定数量,对分布形状不敏感(分布很平时会砍掉合理的候选)
  • top_p:按概率质量截断,分布平时自动放宽——vLLM 默认仅 top_p=1.0(禁用),推荐开 0.9-0.95
  • min_p:相对阈值,分布自适应——分布尖时保留少、平时保留多,是较新的推荐实践

💡 提示:现代实践倾向 top_p + min_p 组合(替代纯 top_k):top_p 管”总量”,min_p 管”相对下限”,两者配合能在多样性与质量间取得更好平衡。top_k 的”固定数量”问题(对分布形状不敏感)是它渐被替代的原因。


3. 惩罚项:Presence / Frequency / Repetition

参数默认语义
presence_penalty0.0出现过的 token 整体降权(出现一次即惩罚,与次数无关)
frequency_penalty0.0按出现次数降权(出现越多压得越狠)
repetition_penalty1.0按出现次数指数级降权(>1 惩罚重复,<1 鼓励重复)

工程实现细节(OpenAI 兼容层的换算):OpenAI API 的 presence/frequency penalty 取值 [-2, 2],vLLM 内部会做线性映射。正负号语义:

  • 正值:惩罚重复(抑制复读)
  • 负值:奖励重复(鼓励延续话题/模仿风格)

📌 关键点:三个惩罚的作用域差异要分清——presence 治”说过没”(话题多样性),frequency 治”说了几遍”(复读机),repetition 是”次数指数惩罚”(激进防复读)。复读问题优先上 repetition_penalty 1.1-1.3 或 presence_penalty;三个同时拉满会过度扭曲分布,输出生硬。


4. Logprobs:拿到底层概率

logprobs 参数返回每个生成 token 的对数概率(以及候选 top 序列):

resp = client.chat.completions.create(
    model="...",
    messages=[...],
    max_tokens=16,
    logprobs=True,        # 返回 top-5 候选
    top_logprobs=5,
)

用途

  • 置信度评估:输出 token 的平均 logprob → 回答可靠性信号(下游路由/重试依据)
  • 调试:看模型”犹豫”在哪(候选概率接近 = 不确定)
  • Agent 可靠性:工具调用参数的低概率 → 提醒校验

工程注意:prompt_logprobs 返回 prompt 侧概率(诊断 prefill 行为);logprobs 会增加响应体积与内存(每 token 多带 k 个候选),高吞吐场景注意带宽与序列化开销。

💡 提示:logprob 是 Agent 生产化的重要信号源——“低置信度 → 重试/换模型/询问用户” 的兜底策略可以完全基于 logprob 实现,不必依赖额外模型打分。但注意 logprob 是”模型自评”,与真实正确率有差距(校准问题),做阈值时要先标定。


5. 并行采样 n 与 Best-of 的工程真相

5.1 n:一个请求生成 n 条候选

resp = client.chat.completions.create(
    model="...",
    messages=[...],
    n=3,          # 同 prompt 生成 3 条独立样本
)
  • 每条样本独立采样(不同随机路径)→ 多样性候选
  • 工程实现:n 个样本共享 prefill(同一 prompt 只算一次),decode 阶段并行推进——比发 n 个请求省 prefill
  • 配合 logprobs 可做”采样-打分-择优”(自洽性方法,Self-Consistency)

5.2 Best-of 的真相

OpenAI 协议里的 best_of 字段(生成 n 条取 logprob 最高者):vLLM 的 SamplingParams 没有独立的 best_of 实现——v0.26 用 n + 客户端择优,或依赖 n 采样后自行排序。别指望服务端自动帮你”选最好的”,“最好”的定义取决于你的任务(多数是外部打分器,不是 logprob)。

📌 关键点n 的代价账:n 条候选 = decode 计算 ×n(共享的只有 prefill)。n=4 时 decode 吞吐降到约 1/4——用 n 换质量必须算吞吐账。生产实践:n 采样主要用于离线批处理(质量优先)或低峰时段;在线高吞吐场景慎用。


6. Beam Search 在 vLLM 的现状

结论先说:vLLM 已不支持 Beam Search(v0.26 的 SamplingParams 中没有 beam 相关参数)。

  • 历史上 vLLM 曾支持 beam search(早期版本),后因实现复杂度与收益比低而移除
  • 原因:beam search 需要并行维护 k 个序列 + 每步去重,与 Continuous Batching 的调度模型冲突;且大模型场景下 beam 的收益(相对 n 采样 + 打分)并不明显
  • 替代路径:n 采样 → 外部评分(logprob / 规则 / 奖励模型)→ 择优——灵活且能与业务评分器结合

💡 提示:需要”结构化搜索”(约束下找最优)时,优先考虑 8.1 的受约束解码 + n 采样 组合,而不是 beam——约束保证合法性,n 提供多样性,打分器择优。这也是现代推理引擎的共识方向。


7. 采样参数与性能的相互作用

7.1 采样对性能的直接影响

因素影响
n 并行采样decode 计算 ×n(最大影响项)
logprobs / top_logprobs每步多算候选概率,响应体积↑(影响小但存在)
max_tokens决定最长 decode 步数——采样质量差 → 输出更长 → 成本更高
stop 序列及时截断废话,间接省 token

7.2 参数与质量的三角

       质量(确定性)
      ╱        ╲
     ╱          ╲
多样性 ──────── 成本
(temperature↑、n↑ 都推高成本)
  • 确定性任务:temperature=0(或极低)+ 结构化输出(8.1)——质量与成本双优
  • 创意任务:temperature 0.7-1.0 + top_p 0.9 + min_p——多样性可控
  • 质量兜底:低 temperature + n 采样 + 打分——成本换质量

📌 关键点采样参数是产品参数,不是性能参数——但性能团队必须懂它:一个”temperature=1 + 无 stop + n=4”的配置,能让所有延迟优化白费。上线前把每个端点的采样配置纳入评审(SLO 的输入之一),跟 7.4 的 goodput 视角闭环。

7.3 快速调参表

症状调整
输出重复/复读repetition_penalty 1.1-1.3 或 presence_penalty 0.5-1.0
输出太随机/幻觉temperature ↓(0.3-0.6)、top_p ↓(0.85-0.9)
输出太死板/千篇一律temperature ↑(0.8-1.0)、min_p 打开
需要可复现seed 固定
需要候选择优n + logprobs + 外部打分

📝 总结

  • 两种模式:贪心(T=0)与采样;采样管线 = logits → 缩放 → 惩罚 → 截断 → softmax → 采样
  • 截断三兄弟:top_k(固定数量)/ top_p(累计质量)/ min_p(相对阈值)——推荐 top_p + min_p
  • 惩罚三件:presence(出现一次即罚)/ frequency(按次数)/ repetition(指数)——各治一种重复
  • logprobs:置信度信号源,可做”低置信→重试”兜底;注意响应体积
  • n 采样:共享 prefill、decode ×n——离线质量优先场景用,在线算清账
  • Beam Search 已移除:替代 = n 采样 + 外部打分
  • 性能联动:采样配置直接影响成本与延迟,纳入上线评审

🎯 自我检验清单

  • temperature=0 是什么模式?T>1 对分布和多样性/质量的影响?
  • top_k / top_p / min_p 的机制差异?为什么推荐 top_p+min_p?
  • presence / frequency / repetition 三个惩罚各治什么?
  • logprobs 能做什么?响应体积影响怎么评估?
  • n 并行采样的成本结构?(共享什么、放大什么)
  • vLLM 为什么移除 beam search?替代方案是什么?
  • 你的端点采样配置和 SLO/成本怎么联动?

📚 参考资料