取樣設定
取樣是推論的最後一吋:模型為詞彙表中的每個 token 打分,而你的設定決定那個分布如何變成一個 token。旋鈕會互動,所以運算順序比任何單一數值重要。
管線,按順序
多數引擎大致按這個順序套用取樣器:
- Logits——原始分數,詞彙表每個 token 一個(5 萬到 15 萬條)。
- 重複懲罰——最近見過的 token 被壓低 logits。
- 溫度——logits 除以 T,把一切變尖或變平。
- top_k——硬上限:只有前 k 個 token 存活。
- top_p——核採樣:涵蓋 p 比例機率質量的最小前段集合。
- min_p——相對地板:丟掉低於 min_p × P(最高 token)的 token。
- 取樣——從剩下的挑一個 token,附加,重複。
早套用的過濾器會改變之後每個過濾器看到的東西。堆疊時記住這點。
溫度
溫度 T 在 softmax 前除以 logits。較低的 T 把分布往最高 token 收尖;較高的 T 把它往均勻壓平。具體例子:三個 token 的 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 個 token 並在其中取樣。top_k 40 讓第 41 名以後不可能中選,無論如何。
它是鈍器。k=40 在「法國的首都是」之後很寬鬆,在只有兩個候選重要的罕見 token 位置則荒謬地浪費。常見預設:40。用 min_p 時停用它(0 或 -1,視引擎而定)。
top_p:核採樣
按機率排序,保留累積機率到達 p 的最小集合,重新正規化,取樣。
實例:機率 [0.867, 0.117, 0.016] 配 top_p 0.9。最高 token 自己涵蓋 0.867 < 0.9;加上第二個達到 0.984 ≥ 0.9。你從兩個 token 取樣,重新正規化為 [0.88, 0.12]。
模型有信心時候選集自動縮小、不確定時變大。典型範圍:0.9–0.95。
min_p:本機圈的最愛
只保留機率至少 min_p × P(最高 token)的 token。地板是相對尺度:
- 模型 99% 有信心 → 地板=0.05 × 0.99 ≈ 0.05:只有真正的競爭者存活。
- 最高 token 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 家族)
在套用溫度之前,最近上下文中出現過的 token,其 logits 會被懲罰值除。低於 1.0 的值反而助長重複。合理範圍:1.0–1.1。
副作用是真的,因為程式碼與資料故意重複 token:
- 識別字合理地重複:
counter.count裡的count。 - JSON 的鍵與右括號在陣列的每個物件中重複。
- 懲罰 1.2+ 早在治好散文迴圈之前,就先弄壞程式碼與 JSON(掉的括號、「被改正」的引號)。
現代 instruct 模型很少需要超過 1.05。對程式碼與結構化輸出,1.0 是合理選擇。
frequency 與 presence 懲罰(API 風格)
OpenAI 相容 API 提供 frequency_penalty(隨重複增加)與 presence_penalty(對已見 token 的一次性懲罰),而 llama.cpp 用的是 repeat_penalty。意圖相同、數學不同。不是每個本機引擎都實作兩者——疊上去之前先確認你的引擎實作了什麼:引擎參數。
把取樣器疊進死角
temp 0.1+top_k 10+top_p 0.5+min_p 0.2+repeat_penalty 1.3 全疊在一起,可以把每個候選 token 都遮掉。症狀: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 欄位:引擎參數。