采样设置
采样是推理的最后一寸:模型给词表里每个词元打分、你的设置决定那个分布如何变成一个词元。旋钮们相互作用、所以操作顺序比任何单值更重要。
流水线,按顺序
多数引擎大致按这个序列应用采样器:
- Logits——原始分数、词表每个词元一个(50k–150k 条)。
- 重复惩罚——近期见过的词元 logits 被压低。
- 温度——logits 除以 T、把一切削尖或压平。
- top_k——硬上限:只有最好的 k 个词元存活。
- top_p——核采样:覆盖概率质量 p 的最小顶部集合。
- min_p——相对地板:丢掉低于 min_p × P(顶部词元) 的词元。
- 采样——从剩下的里挑一个词元、追加、重复。
早应用的过滤器改变每个后续过滤器看到的。叠加时记住这点。
温度
温度 T 在 softmax 前除 logits。更低的 T 把分布向顶部词元削尖;更高的 T 把它向均匀压平。具体:三个词元上 logits [5.0, 3.0, 1.0]。
| T | P(第一) | P(第二) | P(第三) |
|---|---|---|---|
| 0.5 | 98.1% | 1.8% | 0.03% |
| 1.0 | 86.7% | 11.7% | 1.6% |
| 1.5 | 75.0% | 19.8% | 5.2% |
T → 0 时塌缩为贪心:永远 argmax、完全确定。
抽取、分类、和任何要运行间可复现的东西用温度 0(不允许 0 的引擎用 0.000001)。聊天要 0.6–0.8;创意写作容忍 0.9–1.2。
top_k:硬上限
只保留概率最高的 k 个词元并在其中采样。top_k 40 让第 41 名及以下不可能、无论如何。
它是件钝器。"The capital of France is" 之后 k=40 很宽裕;在只有两个候选要紧的罕见词元位置上浪费得荒唐。常见默认:40。用 min_p 时关掉它(0 或 -1、视引擎)。
top_p:核采样
按概率排序、保留累计概率达到 p 的最小集合、重归一化、采样。
算例:概率 [0.867, 0.117, 0.016] 配 top_p 0.9。顶部词元单独覆盖 0.867 < 0.9;加第二个达到 0.984 ≥ 0.9。你从两个词元采样、重归一化为 [0.88, 0.12]。
模型自信时候选集自动收缩、不确定时增长。典型范围:0.9–0.95。
min_p:本地最爱
只保留概率至少为 min_p × P(顶部词元) 的词元。地板是尺度相对的:
- 模型 99% 自信 → 地板 = 0.05 × 0.99 ≈ 0.05:只有真正的竞争者存活。
- 顶部词元 30% → 地板 = 0.05 × 0.30 = 0.015:多样性存活。
那杀死了经典的 top_k/top_p 失败——对自信分布过度修剪、对平坦分布修剪不足——而 min_p 与高温安全组合。“有创意但连贯”配方:temp 1.0–1.5、min_p 0.05–0.1。常见本地设置:min_p 0.05、top_k 和 top_p 关闭。
repeat_penalty(llama.cpp 家族)
在温度应用之前、近期上下文中出现过的词元的 logits 被除以惩罚值。低于 1.0 的值反而提升重复。合理区间:1.0–1.1。
副作用是真的、因为代码和数据故意重复词元:
- 标识符合法地重复:
counter.count里的count。 - JSON 键和右花括号跨数组中每个对象重复。
- 惩罚 1.2+ 在修复散文循环之前早就弄坏代码和 JSON(丢花括号、“纠正”引号)。
现代 instruct 模型很少需要超过 1.05。对代码和结构化输出、1.0 是合法选择。
frequency 与 presence 惩罚(API 风格)
OpenAI 兼容 API 在 llama.cpp 用 repeat_penalty 的地方暴露 frequency_penalty(随每次重复增长)和 presence_penalty(对任何已见词元的固定惩罚)。同一意图、不同数学。不是每个本地引擎都两者都尊重——把它们叠在一起之前查你的引擎实现了什么:引擎参数。
把采样器叠进死角
temp 0.1 + top_k 10 + top_p 0.5 + min_p 0.2 + repeat_penalty 1.3 一起应用、能遮蔽每个候选词元。症状:NaN logprob 警告、空生成、"sampling returned zero candidates" 中止。
那不是模型坏了——是空候选集。一次松一个旋钮地放宽。完整分诊:故障排查。
有效的预设
| 任务 | temp | top_p | min_p | repeat_penalty |
|---|---|---|---|---|
| 聊天(通用) | 0.7 | 0.90–0.95 | 0.05 | 1.0–1.05 |
| 代码生成 | 0.1–0.2 | 0.9 | — | 1.0 |
| 抽取 / 分类 | 0(贪心) | — | — | 1.0 |
| 创意写作 | 0.9–1.0 | 0.95 | 0.05–0.1 | 1.05–1.1 |
| 翻译 | 0.2–0.4 | 0.9 | — | 1.0 |
聊天行转成 llama.cpp 标志:
llama-server -m model.gguf --temp 0.7 --top-p 0.95 --min-p 0.05 --repeat-penalty 1.05
一次只改一个
把预设当起点、不当法律。如果你把温度和 top_p 一起动而输出变好、你对哪个旋钮要紧一无所获。
- 固定一个测试集:5–10 条练习你在乎的东西的提示词。
- 按配置保存输出;并排 diff。
- 每次运行恰好改一个旋钮。
- 把赢家存成命名预设——每个引擎和 UI 都存它们。
这些旋钮如何映射到引擎标志和 API 字段:引擎参数。