LLM 的輸出本質是「下一個 token 的機率分佈」、不是直接的 token。從機率分佈挑下一個 token 的具體方法、就是 sampling / decoding 策略。同一個模型、同一個 prompt、不同 sampling 策略會給出顯著不同的輸出。

本章拆開主流 sampling 策略的機制、各自適合的場景、以及 temperaturetop_p 這些常見參數在這條鏈上的位置。

本章目標

讀完本章後、你應該能:

  1. 解釋 temperature=0temperature=0.8 的具體差別。
  2. 區分 top-k、top-p、min-p 三者的機制。
  3. 看到 repetition_penalty=1.1 設定時、知道它解什麼問題。
  4. 解釋為什麼確定性測試要設 temperature=0 + seed

從 logits 到下個 token

複習一下 LLM 輸出端的鏈:

1final hidden states → output projection → logits → temperature → softmax → 機率分佈
2→ sampling 策略 → 下個 token

各環節在 sampling 中的位置:

環節對 sampling 的影響
logits模型給每個 token 的原始分數、還沒正規化
temperature在 softmax 前除以 T、調整分佈尖銳度
softmax把 logits 轉成機率分佈
top-k / top-p / min-p過濾低機率 token、把候選集縮小
重新正規化把過濾後的剩餘 token 重新正規化成機率分佈
取樣從正規化分佈中隨機選一個 token
repetition penalty對已出現的 token 降權、避免重複

實際參數順序視推論伺服器實作而異、但概念上是這條鏈。

Greedy Decoding:永遠選機率最大

Greedy decoding 的核心定義是「每步選 softmax 後機率最大的 token」:

1next_token = argmax(probabilities)

特性:

  • 確定性:同 prompt 永遠生同樣輸出。
  • :不用 sampling、不用算 cumulative probabilities。
  • 缺點:傾向選最常見 pattern、輸出單調;常陷入 repetition loop。

實務用途:

  • Reproducible 評估:跑 benchmark、自動測試。
  • 單元測試:確保模型輸出可預測。
  • 某些 reasoning chain:選最有信心的下一步。

效果上等同 temperature=0、許多推論伺服器把兩者當同義詞。

Beam Search:保留 top-K 條候選序列

Beam search 的核心想法是「每步保留累積機率最大的 K 條序列、每條繼續展開、最後選整體機率最高的」。K 叫 beam size。

Beam size行為
1等同 greedy
3 ~ 5翻譯、摘要等任務常用
10+高品質生成、但計算成本高

特性:

  • 全局較優:不只看當步、考慮整段序列。
  • 適合「有正確答案」的任務:翻譯、摘要、code 生成。
  • 缺點:對 open-ended 生成(聊天、創意寫作)會 collapse 到平庸、缺乏多樣性。

具體失效症狀:K=5 在 chat 場景常產生「Sure!」「Thank you」「That’s a great question」這種高頻 boilerplate、各 beam 探索的方向都收斂到相似的平庸開頭、明明 logit 分佈本來該保留的多樣性被 beam 平均化掉。

Chat / 對話場景多半不用 beam search、用 sampling 策略保留多樣性。

Temperature:調分佈尖銳度

Temperature 的機制在 模組二 2.1 已經詳細展開。簡單回顧:

1adjusted_logits = logits / temperature
2probabilities = softmax(adjusted_logits)
Temperature效果
0等同 greedy(argmax)
0.2 ~ 0.4寫 code、回答事實問題、減少 hallucination
0.7預設、平衡多樣性與品質
0.9 ~ 1.0創意寫作、保留多樣性
> 1.5隨機性極高、輸出可能變混亂

實務經驗:

  • 寫 code 場景設 0.2 ~ 0.4 較穩。
  • 創意任務(寫故事、brainstorming)設 0.8 ~ 1.0。
  • Reproducible 測試設 0 + 固定 seed。
  • T > 1.5 失效症狀:產出開始出現拼字錯誤、語法破洞、UTF-8 byte 混亂、甚至跨語言突然切換;極端 T 等同近 uniform 分佈、模型結構被當作 dice。

Temperature 在 sampling 鏈上的位置(行 26 的流程鏈)跟其他過濾步驟有疊加順序、值得展開:

  1. Temperature 先動分佈尖銳度:高 T 把分佈拉平、低 T 拉尖。
  2. 再過 top-p / top-k / min-p:在拉平 / 拉尖後的分佈上做候選過濾。
  3. 兩者相乘的常見坑:高 T(如 1.5)+ 低 top-p(如 0.5)= 「分佈被拉平、然後只挑前幾名」、實際出現的多樣性反而被壓縮、容易出現語義跳動。穩健做法:固定其中一個(多半是 top-p=0.9)、調另一個。
  4. Reasoning model 的特殊性:o1、DeepSeek-R1 等內建 chain-of-thought 的模型、官方建議 T=0 或 1.0、調 T 會破壞 reasoning trace 連貫性。

Top-K Sampling

Top-K sampling 的核心定義是「只考慮機率最大的 K 個 token、其他設 0、重新正規化後取樣」:

11. 對機率排序、取最大的 K 個。
22. 其他設 0。
33. 重新正規化(讓總和為 1)。
44. 從正規化分佈取樣。

K 控制候選範圍:

K行為
1等同 greedy
40預設常用值
100+接近完全 sampling、限制較小

缺點:K 是固定值、無法適應分佈尖銳度。當分佈尖銳時(一個 token 機率 90%)、K=40 包括很多近 0 機率的雜訊;當分佈平坦時(每個 token 機率 1%)、K=40 過於限制。具體失效症狀:在 code 生成情境、模型對「下一個 token 是 )」極度確定(95%+ 機率)時、K=40 把後面 39 個近零雜訊也納入候選、偶爾 sample 出語法錯的字元;改用 top-p 或 min-p 可避開。

Top-P / Nucleus Sampling

Top-P sampling(也叫 nucleus sampling、Holtzman et al., 2019)的核心想法是「動態決定候選集大小」:

11. 對機率從大到小排序。
22. 從大到小累加、直到累積機率 ≥ P(如 0.9)。
33. 只保留這些 token、其他設 0。
44. 重新正規化、取樣。

例:

  • 分佈尖銳(一個 token 機率 95%):P=0.9 可能只選 1 ~ 2 個 token。
  • 分佈平坦(top 10 各 5%):P=0.9 可能選 15 ~ 20 個 token。

P 的常用值:

P行為
0.5較保守、傾向選機率高的
0.9預設、保留合理多樣性
0.95略放寬
1.0等同關閉 top-p、用完整分佈

在 chat / coding 場景下 top-p 是主流選擇、比 top-K 彈性;reproducible 評估則回到 greedy(T=0)、不用 sampling。多數推論伺服器預設 top_p=0.9。

Min-P:自適應閾值 sampling

Min-P sampling(2024 ~)的核心想法是「設一個機率閾值、最大機率 token × P_min 以下的全部去掉」:

11. 找出最大機率 p_max。
22. 閾值 = p_max × P_min(如 0.1)。
33. 機率 < 閾值的 token 全部設 0、重新正規化。

特性:

  • 自動適應分佈尖銳度(用比例而非絕對值)。
  • 比 top-P 更穩定、近一兩年在開源社群興起。
  • LM Studio、llama.cpp 等支援。

P_min 常用值:

P_min行為
0.05保留多樣性
0.1平衡
0.2較保守

Repetition Penalty

Repetition penalty 的核心想法是「對已出現的 token 降低機率、避免無限重複」:

1adjusted_logit(token) = logit(token) / repetition_penalty   if token 已出現
2                      = logit(token)                          if token 沒出現

P 大於 1 時、已出現 token 的 logit 被降低、後續 sampling 較難選到。

Penalty效果
1.0關閉
1.05輕微抑制
1.1預設常用
1.3+強烈抑制、可能過度避免合理重複

代價:寫 code 場景下、ifforreturn 等關鍵字常出現、太高的 repetition penalty 會壞掉 code。寫 code 場景 penalty 設低(1.0 ~ 1.05)或關閉;creative writing 場景則設 1.1 ~ 1.2、避免段落 / 句子層級的重複。

Seed:固定 sampling 的隨機性

Sampling 用 random number generator 取樣。設定 seed 讓 RNG 確定性、相同 prompt + 相同 seed 給相同輸出:

1{
2  "temperature": 0.7,
3  "top_p": 0.9,
4  "seed": 42
5}

實務用途:

  • Reproducible 評估:跑 benchmark 要可重複。
  • A/B 測試:對比不同 prompt 在同 seed 下的差異。
  • Debug:重現一個錯誤輸出。

注意:seed 不是所有伺服器都支援、OpenAI API 是 best-effort(同 seed 不保證完全一致)、本地伺服器多半支援嚴格 seed 控制。

Logit Bias:強制 / 排除特定 token

Logit bias 的機制是「對特定 token 的 logit 加減一個固定值」:

1adjusted_logit(token) = logit(token) + bias(token)

用途:

  • 強制特定 token:bias = +100、softmax 後機率近 1。
  • 完全禁止:bias = -100、softmax 後機率近 0。
  • 微調傾向:bias = ±5、輕微傾斜。

實務用例:

  • 強制輸出 JSON 格式:對 { 加 bias 在開頭。
  • 避免特定詞:對敏感詞加負 bias。
  • 約束輸出:限制只能用特定 vocabulary。

OpenAI、Ollama 等多數推論伺服器支援 logit_bias 參數。

Structured Output / Constrained Decoding

Structured output 的核心想法是「sampling 時加 grammar 約束、強制輸出符合特定結構(JSON、SQL、regex 等)」。實作方法:

  • JSON mode:每步只允許「能讓 JSON 仍合法」的 token。
  • Grammar-based:用 BNF / lark / etc. 定義語法、sampling 時 reject 違反語法的 token。
  • Token mask:依當前狀態決定哪些 token 合法、不合法的 logit 設 -∞。

實務工具:

  • llama.cpp 的 grammar 參數。
  • Outlines、LMQL 等 framework。
  • OpenAI 的 response_format: { type: "json_schema" }

寫 code 場景中、structured output 對「要可解析的輸出」(如 commit message 格式、structured API call)很有用。

Decoding 策略對體感的影響

下表是寫 code 場景下、不同 decoding 配置的體感:

配置體感
temperature=0、greedy確定、可重複、但可能單調
temperature=0.2、top_p=0.95穩定、寫 code 主流
temperature=0.7、top_p=0.9平衡、預設
temperature=1.0、top_p=0.95、min_p=0.05創意、多樣
temperature=1.5過於隨機、code 容易壞
repetition_penalty=1.3、寫 code 場景抑制太強、會壞掉 keyword 重複用法

實務建議:寫 code 場景下 temperature=0.2 ~ 0.4、top_p=0.9 ~ 0.95、其他保留預設就好。Continue.dev 等 IDE 整合多半自動調整。

下一章

下一章:3.6 tokenization 算法、補完 input / output 端的細節。