﻿# 淺談 LLM 大型語言模型的 Temperature、Top-P 和 Top-K 參數

深度學習模型在自然語言處理 (NLP) 領域中扮演著重要的角色，而調整模型的參數可以影響生成的文字風格和品質。在大語言模型中，`Temperature`、`Top-P` 和 `Top-K` 是常見的參數，用於控制文字生成過程中的**隨機性**和**創造性**。我自己在開發 LLM 應用時，主要也都只會去調整 `Temperature` 而已，其實 `Top-P` 與 `Top-K` 很少去調他，因為每次調整都沒有什麼好結果，之前因為不太理解這兩個參數的真正含意，最後還是回歸預設值處理。這篇文章我打算好好的理一理這幾個參數的真正含意。

![llm-temperature-topp-topk](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3c808d0ce93baf82f4f8-e80d43ea-67c8-4379-bb6c-0b129d3d7d7c.webp)

### Temperature (溫度)

在自然語言處理中，`Temperature` 就像一個控制語言模型創造力的旋鈕。它調整模型選擇**低機率詞彙**的傾向，進而影響生成文本的多樣性。

設定較高的 Temperature 值意味著鼓勵模型去冒險，選擇較不常見的詞彙，產生更多樣化、出乎意料，甚至天馬行空的文字，適合用於腦力激盪或探索新穎概念。

設定較低的 Temperature 值則讓模型趨於保守，偏好大機率詞彙，生成更保守、符合預期的文字，適合用於講求**準確性**和**一致性**的任務。

我以 OpenAI 的 API 為例 ([API Reference](https://platform.openai.com/docs/api-reference/introduction))，[Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 的 `temperature` 的範圍是 `0.0` 到 `2.0` 之間，您可以根據具體需求調整這個參數，控制生成文字的風格和創造性。官方文件有特別舉例，設定 `0.2` 的值會導致生成的文字更具有決定性，而設定 `0.8` 的值會導致更隨機的結果。

若以 Gemini 的 API 為例 ([Generative Language API](https://ai.google.dev/api/rest))，[models.generateContent](https://ai.google.dev/api/rest/v1/models/generateContent) 的 [GenerationConfig](https://ai.google.dev/api/rest/v1/GenerationConfig) 也有個 `temperature` 參數，設定值一樣是 `0.0` ~ `2.0` 之間。不過官方文件並沒有舉例，您可以自行嘗試不同的值，看看生成的文字風格有何不同。

我以 OpenAI 的 GPT-3.5 Turbo 為例，當我查詢的條件為：

-   系統提示 = `You are a helpful assistant. You will help user calculate math.`
-   使用者提示 = `請告訴我 0 ~ 100 的所有質數`
-   Temperature = `2.0`

我連續執行 4 次，每次都不一樣，這就是所謂的**隨機性**(Randomness)：

1.  第一次嘗試
    
    ```
    0到100之間的所有質數如下：
    
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
    
    這些數字都是只能被1和自己整除的數字（不包括1）。
    ```
    
2.  第二次嘗試
    
    ```
    0 到 100 之間的質數為：
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97。
    ```
    
3.  第三次嘗試
    
    ```
    0 到 100 的質數列表如下：
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97。
    ```
    
4.  第四次嘗試
    
    ```
    0 到 100 裡的質數有：
    
    2, 3, 5, 7, 11,
    13, 17, 19, 23, 29,
    31, 37, 41, 43, 47,
    53, 59, 61, 67, 71,
    73, 79, 83, 89, 97.
    ```
    

這種**隨機性**的應用場景，通常用於生成**對話**、**創意寫作**、甚至**遊戲劇情**等，讓模型能夠產生更多元化、更具創造性的內容。

接著我繼續測試，參數如下：

-   系統提示 = `You are a helpful assistant. You will help user calculate math.`
-   使用者提示 = `請告訴我 0 ~ 100 的所有質數`
-   Temperature = `0.0`

1.  第一次嘗試
    
    ```
    0 到 100 之間的質數有：2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97。
    ```
    
2.  第二次嘗試
    
    ```
    0 到 100 之間的質數有：
    
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
    ```
    
3.  第三次嘗試
    
    ```
    0 到 100 之間的質數有：2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97。
    ```
    
4.  第四次嘗試
    
    ```
    0 到 100 之間的質數有：
    
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
    ```
    

有趣的地方是，當我設定 `Temperature` 為 `0.0` 時，生成的文字風格變得更加**穩定**和**一致**，但並不是**完全一樣**，因此對於某些需要精準回應的場景，可能還需要額外下點苦工！例如 Function calling (OpenAI) 或 Tool use (Claude) 或 JSON mode (Gemini) 就是個還不錯的解決方案，他可以強制模型回應 JSON 格式的回應，只要稍微做一點「提示工程」的技巧，提醒模型回應的格式，就可以得到更加一致的結果。

### Top-P (Nucleus Sampling) (核心採樣)

`Top-P` 又稱為**核心採樣** (`Nucleus Sampling`)，是一個用於控制語言模型文本生成的**機率篩選器**。這些大語言模型在生成文字時，其實是以 `Token` 為單位，而在文字生成的過程中，所有的 Tokens 會先依據「**機率**」進行排序，排序完之後，模型會根據 `Top-P` 的設定，只考慮**最可能**的 `Tokens`，這樣可以避免生成**不合理**或**不合適**的文字。

你可以將 `Top-P` 視為一種**取樣**的替代方法，跟 `temperature` 有點類似，但 `temperature` 是用來控制**整體的創造性**，而 `Top-P` 則提供更精細的控制。

我以 OpenAI 的 API 為例 ([API Reference](https://platform.openai.com/docs/api-reference/introduction))，[Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 的 `top_p` 的範圍是 `0.1` 到 `1.0` 之間，如果你設定為 `0.1` 的話，則意味著你讓模型僅考慮包含前 `10%` **機率質量** (probability mass) 的 Tokens。

> **機率質量** (probability mass) 這個術語在**統計學**和**機率論**中具有特定的含義。在機率論和統計學中，**機率質量函式** (probability mass function，簡稱為 `PMF`) 是一種數學函式，它計算一個**離散隨機變數**恰好為**特定值**的**機率**。換句話說，**機率質量函式**為**離散隨機變數**的每個可能值賦予了一個特定的機率。因此，**機率質量函式**描述了**離散變數**的**整個值範圍的機率分佈**。

由於我們無法得知這些大語言模型的內部運作，因此 `Top-P` 比較難以預測哪些 Tokens 的機率比較高，就算你調整了，也很難看出明顯的變化。也因為這樣，OpenAI 的 API 參考文件就寫了，你可以選擇 `temperature` 或 `top_p` 來控制生成的文字，但建議不要兩個都設定，因為一般人真的很難駕馭這兩個參數。

> 備註: OpenAI 的 [Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 其 `temperature` 的預設值為 `1` (介於 0 ~ 2 中間)，而 `top_p` 的預設值為 `1` (介於 0.1 ~ 1.0 中間)。這也意味著，OpenAI 的 Chat Completion API 在生成文字時，並不會刻意的透過**機率質量** (probability mass) 來篩選 Tokens，主要透過 `temperature` 來控制生成的文字風格。

### Top-K (Top-K Sampling)

`Top-K` 就像一個 `Tokens` 排名榜，你可以設定一個固定數量 (`k`)，模型只會從機率最高的 `k` 個 `Tokens` 中進行選擇。

舉例來說，如果 `Top-K` 設定為 `64`，模型只會考慮機率最高的 `64` 個詞彙，並從中隨機選擇下一個 `Tokens`。通過限制選擇範圍，`Top-K` 能夠確保生成的文字更集中、更符合主題，避免出現過於發散或不相關的內容。

我以 OpenAI 的 API 為例 ([API Reference](https://platform.openai.com/docs/api-reference/introduction))，[Chat Completion API](https://platform.openai.com/docs/api-reference/chat/create) 並沒有所謂的 `top_k` 參數，所以你沒辦法調整這個參數。但是，OpenAI 的 API 有提供 `logit_bias` 參數，用於修改模型生成輸出中指定 `Tokens` 出現的機率，這個參數接受一個 JSON 物件，將 `Tokens` 映射到相關偏差值，從 `-100` (禁止出現) 到 `100` (一定會出現) 等機率設定。這是一個相當有趣的參數，詳情請見 [Using logit bias to alter token probability with the OpenAI API](https://help.openai.com/en/articles/5247780-using-logit-bias-to-alter-token-probability-with-the-openai-api) 文章說明。

> 我在 Facebook 的 [Generative AI 技術交流中心](https://www.facebook.com/groups/gaitech) 社團中曾經[有一則貼文](https://www.facebook.com/groups/gaitech/posts/1147304109787136/)分享了 `GPT-4o` 的 Tokenizer 詞彙表擴充了兩倍，加入了一些「母湯」的詞彙，如果你不想要在生成的文字中出現這些詞彙，就可以透過這個 `logit_bias` 參數來控制，將這些「母湯」的詞彙直接封鎖，把機率降為 `-100%` 即可！

在 `Gemini API` 中，Google 有提供 `topK` 參數，但不同模型之間的預設值差別蠻大的，有些模型 `topK` 的預設值為 `0`，通常意味著這個模型的 `topK` 是不允許設定的。

以下就是我從 [models.list](https://ai.google.dev/api/rest/v1/models/list) API 整理出來的各項超參數預設值：

| Name | Version | Temperature | Top P | Top K |
| --- | --- | --- | --- | --- |
| `models/chat-bison-001` | 001 | 0.25 | 0.95 | 40  |
| `models/text-bison-001` | 001 | 0.7 | 0.95 | 40  |
| `models/embedding-gecko-001` | 001 | \-  | \-  | \-  |
| `models/gemini-1.0-pro` | 001 | 0.9 | 1   | \-  |
| `models/gemini-1.0-pro-001` | 001 | 0.9 | 1   | \-  |
| `models/gemini-1.0-pro-latest` | 001 | 0.9 | 1   | \-  |
| `models/gemini-1.0-pro-vision-latest` | 001 | 0.4 | 1   | 32  |
| `models/gemini-1.5-flash-latest` | 001 | 1   | 0.95 | 64  |
| `models/gemini-1.5-pro-latest` | 001 | 1   | 0.95 | 64  |
| `models/gemini-pro` | 001 | 0.9 | 1   | \-  |
| `models/gemini-pro-vision` | 001 | 0.4 | 1   | 32  |
| `models/embedding-001` | 001 | \-  | \-  | \-  |
| `models/text-embedding-004` | 004 | \-  | \-  | \-  |
| `models/aqa` | 001 | 0.2 | 1   | 40  |

這些不同模型的 `Temperature`, `Top P`, `Top K` 參數預設值，肯定是 Google 的研發團隊經過多次測試，才得出這些數值，從我們局外人的眼裡，其實很難知道最好的數值為何，除非你能比 Google 做更多的科學實驗，才有可能找到最佳的數值。

不過，即便如此，像是 Gemini 最新的 `models/gemini-1.5-flash-latest` 與 `models/gemini-1.5-pro-latest` 模型，都有提供 `Top-P` 與 `Top-K` 參數可供你微調，如此一來你就能依據不同的應用場景，調校出最適合的參數組合。

> 可惜 Gemini 並沒有提供 `logit_bias` 參數來控制 Tokens 出現的機率，可能跟 Google 至今不願意開源 Tokenizer 的詞彙表有關，沒有詞彙表，就找不出 Tokens 的代號，沒有代號，自然就無法精細的控制 Tokens 的機率。很自然的，也就不會有 `logit_bias` 這個參數了。

### 總結

開發 LLM 應用程式最難的地方，除了 Prompting engineering (提示工程) 之外，就是去調整這些參數了，因為 LLM 的應用範圍太廣，不同的應用場景就可能需要不同的參數組合，這就是為什麼我們在開發 LLM 應用程式時，需要不斷的嘗試，最終才能找到最適合的參數組合。

最後用幾個列點來總結一下：

-   `Temperature` 控制整體的創造性，`Top-P` 和 `Top-K` 則提供更精細的控制。
-   `Top-P` 根據累積**機率**動態調整選擇範圍，`Top-K` 根據排名設定固定的 Tokens 選擇**數量**。
-   選擇哪個參數來設定，或者如何組合使用，取決於您的具體需求和應用場景，沒有標準答案！

應用場景：

-   文本生成： `Top-K` 可以控制模型生成的文本的多樣性，而 `Top-P` 可以控制文本的流暢度。
-   機器翻譯： `Top-K` 和 `Top-P` 可以幫助模型選擇最有可能的翻譯。
-   問答系統： `Top-K` 和 `Top-P` 可以幫助模型選擇最有可能的答案。

舉例：

假設模型預測下一個詞彙的可能性列表如下：

| 詞彙  | 可能性 |
| --- | --- |
| 狗   | 0.3 |
| 貓   | 0.2 |
| 鳥   | 0.1 |
| 魚   | 0.1 |
| 樹   | 0.05 |
| 花   | 0.05 |

-   TopK=2: 模型會選擇可能性最高的兩個詞彙，即「狗」和「貓」。
-   TopP=0.6: 模型會選擇累積可能性達到 60% 的詞彙，即「狗」、「貓」和「鳥」。

### 相關連結

-   Gemini
    -   [GenerationConfig (v1) | Google AI for Developers | Google for Developers](https://ai.google.dev/api/rest/v1/GenerationConfig)
    -   [GenerationConfig (v1beta) | Google AI for Developers | Google for Developers](https://ai.google.dev/api/rest/v1beta/GenerationConfig)
    -   [Method: models.list | Google AI for Developers | Google for Developers](https://ai.google.dev/api/rest/v1/models/list)
-   OpenAI
    -   [API Reference - OpenAI API](https://platform.openai.com/docs/api-reference/introduction)
    -   [Using logit bias to alter token probability with the OpenAI API](https://help.openai.com/en/articles/5247780-using-logit-bias-to-alter-token-probability-with-the-openai-api)
    -   [Using logprobs](https://cookbook.openai.com/examples/using_logprobs)
    -   [Azure OpenAI Basic Samples](https://github.com/Azure-Samples/openai/blob/main/Basic_Samples/README.md)
