iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
生成式 AI

用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰系列 第 5

Day 05 - 回應風格調控:掌握 Temperature 與 Top-P 設定

  • 分享至 

  • xImage
  •  

在前幾篇文章中,我們已經學會如何呼叫 OpenAI API,並透過提示工程來控制回應的角色與風格。不過在實際應用中,不同情境往往需要截然不同的回答方式:有時候我們希望模型輸出嚴謹且結構明確的內容,有時候則希望它能展現更多創意,提供多樣化的想法。

這樣的差異並不是僅靠提示詞就能完全掌控,而是與生成機率的取樣策略息息相關。在 OpenAI API 中,負責調整這部分的核心參數主要有兩個:temperaturetop_p。今天我們就要深入解析這兩個設定,並透過程式實驗觀察它們對模型輸出的實際影響。

控制回應風格的關鍵

要理解怎麼控制回應風格,可以先用一個簡單的比喻來認識語言模型的運作方式:大語言模型其實就像是在玩「文字接龍」遊戲。

它的核心原理是這樣的:模型會根據你給的輸入文字,去計算「下一個最合理的詞」應該是什麼,然後把這個詞接上去。接著,它再用更新後的內容繼續計算下一個詞,並不斷重複這個動作,最後就組合出一整段文字。

舉個例子,如果你輸入:

JavaScript 是一種用來開發

模型可能會評估接下來最合理的詞是「網頁」、「前端」、「應用程式」等等,並依照機率大小來決定要選哪一個。假設它選了「網頁」,那接下來的輸入就變成:

JavaScript 是一種用來開發網頁

接著它再繼續判斷下一個詞可能是「應用程式」、「互動效果」或「前端功能」,然後選出其中一個。如此循環,直到模型認為回答完成為止。

這個過程看起來好像模型真的「理解」了你在說什麼,但事實上它並不具備真正的語意理解能力,而是根據訓練時學到的龐大語言統計資料,去預測在這樣的語境中,什麼詞最可能出現。

一定要選最有可能的詞嗎?

語言模型的運作雖然像「文字接龍」,每次都在預測下一個最合理的詞,但這並不代表它每次都必須挑選機率最高的那個詞。

如果模型永遠都挑機率最高的詞,那麼輸出的內容會非常穩定、安全,幾乎每次都能得到一樣的答案。這樣的特性在需要精準回覆時非常有用。但缺點是,回答容易變得制式、重複,缺乏新鮮感。

相反地,如果允許模型偶爾選擇一些機率不是最高,但仍合理的詞,那麼輸出就會更有變化,有時甚至會帶來意料之外的創意火花。不過這樣也伴隨風險,可能回答更容易出錯、跑題,甚至產生無意義的片段。

這就是為什麼我們需要能夠控制「隨機性」。它其實就是在穩定性與創造力之間拉一條平衡線。不同的應用場景,需要不同的設定,才能讓模型輸出符合我們的期待。

如何調整模型的隨機性

既然隨機性會影響回答的風格,我們就需要一個方法來控制它,讓模型能在穩定性和創造力之間找到合適的平衡點。

OpenAI API 提供了兩個關鍵參數:

  • temperature:決定模型在選詞時的「自由度」。數值低時,模型傾向選擇最保險的答案,輸出穩定一致;數值高時,它會更大膽嘗試,內容可能更有創意,也更難以預測。
  • top_p:限制模型只從「前幾個最有可能的選項」中挑字。數值小時,模型幾乎只會從常見答案中挑選;數值大時,它能探索更廣的可能性。

接下來我們會分別看看這兩個參數的作用,並透過程式範例觀察它們如何改變模型的回應風格。

temperature:控制模型的創造力

OpenAI 的 temperature 是最常用來調整回應創造力與多樣性的參數。它會影響模型在「預測下一個詞」時,究竟要保守選擇最安全的答案,還是大膽嘗試一些機率較低的選項。

數值範圍通常落在 0 ~ 2,而在 OpenAI API 裡,預設值是 1

  • temperature = 0:完全保守。模型只會挑選最有把握的詞,輸出非常穩定,但內容容易重複,看起來比較「制式化」。
  • temperature = 1:適度隨機。模型會依照機率分布進行抽樣,既能保持合理性,又帶有自然的多樣性。這是最常用的設定。
  • temperature > 1:高創意模式。模型更傾向冒險,會選擇一些平常不會出現的詞彙,輸出更具想像力,但同時也更容易跑題或產生雜訊。

舉個例子,假設我們問模型:

請用一句話介紹 AI 是什麼?

不同 temperature 設定下,模型可能會給出這樣的回答:

  • temperature = 0

    AI 是人工智慧的縮寫,用來模擬人類智能的技術。

  • temperature = 1

    AI 是一種讓電腦能思考、判斷並學習的技術。

  • temperature = 1.5

    AI 是讓機器解鎖想像力、模仿人腦直覺與夢境的未來工具。

可以發現:temperature 越低,回應越嚴謹可控;temperature 越高,回應越多樣奔放,但也更不可預測。

top_p:限制模型的選詞範圍

OpenAI 的 top_p 是另一個用來控制模型隨機性的參數,也被稱為 核心取樣(Nucleus Sampling)。它的作用是:只允許模型從「機率總和達到某個門檻」的候選詞中挑選下一個詞,而不是從所有詞彙中自由選擇。

數值範圍在 0 ~ 1 之間,代表「選詞時允許的累積機率上限」:

  • top_p = 1:等於不設限,模型可以從所有詞彙中選擇。
  • top_p = 0.9:模型只會考慮「累積機率前 90%」的詞,排除掉最不可能的那部分。
  • top_p = 0.1:只保留極少數的高機率詞,輸出會變得非常保守、缺乏變化。

來看一個例子。假設在某個情境下,模型預測下一個詞的機率分布如下:

機率 累積機率
網頁 35% 35%
應用程式 25% 60%
工具 15% 75%
科技 10% 85%
宇宙 5% 90%
其他(合計) 10% 100%

不同的 top_p 設定會影響模型的候選範圍:

  • top_p = 1:不限範圍,所有詞都可能被選中。
  • top_p = 0.9:取到累積機率 ≥ 90% 的最小集合為 {網頁, 應用程式, 工具, 科技, 宇宙}
  • top_p = 0.75:前三個詞剛好湊到 75%,所以只會挑選 {網頁, 應用程式, 工具}
  • top_p = 0.5:前兩個詞(35%+25%=60% ≥ 50%)就已達標,因此只考慮 {網頁, 應用程式}

由此可見,top_p 的本質是控制「候選答案池的大小」:值越大,範圍越廣,回答更有可能出現意料之外的詞;值越小,輸出則更可控、更安全。

temperature vs. top_p:有什麼不同?

雖然 temperaturetop_p 都能影響模型的「隨機性」,但它們調控的角度完全不同:

  • temperature:調整的是「整體分布的形狀」。數值低會讓分布變得尖銳,機率最高的詞幾乎必定被選中;數值高則會把分布攤平,讓低機率詞也有機會被挑選。
  • top_p:限制的是「候選詞的範圍」。它不會改變分布本身,而是劃一條界線,只保留累積機率達到某個比例的詞,其他候選詞一律排除。

換句話說,temperature 像是在調整「抽籤池裡的權重分布」,決定熱門選項是不是要壓得很重,還是大家機會差不多。top_p 則像是在決定「抽籤池的大小」,是要只放前幾個熱門選項,還是把冷門選項也丟進去。

項目 temperature top_p
控制方式 改變「每個詞的機率分布形狀」 限制「可選詞的總機率範圍」
運作邏輯 每個詞都可能出現,只是機率高低不同 只從總機率最前面的詞彙中選擇
使用直覺 控制回答的 保守或創新程度 控制回答的 可靠性與合理詞彙範圍

什麼時候該用哪一個?

不同的應用場景,對回應的要求並不相同,因此調整的策略也會有所差異:

  • 需要高度可控、格式固定的回答
    適合用在程式碼生成、數學計算或資料轉換這類任務。建議直接將 temperature 設為 0(或接近 0),確保輸出穩定一致,不會因隨機性造成格式錯誤。

  • 需要多樣但仍合理的回答
    適合用在一般對話、客服回覆或內容建議等情境。此時可以透過調整 top_p(常見範圍 0.7 ~ 0.9),讓回答保持一定的多樣性,同時避免出現過於離譜的內容。

  • 需要創意發散或腦力激盪
    適合用在廣告文案、故事生成、腦力激盪這類需要靈感的場合。可以將 temperature 提高到 1.0 ~ 1.2,甚至搭配較大的 top_p,讓模型更敢冒險,產生新奇但可能不可預測的輸出。

Note:OpenAI 官方建議大部分情況下 只調整其中一個參數 就好。若同時大幅修改 temperaturetop_p,兩者效果可能互相疊加,導致模型行為過於混亂,難以掌控。

實作:讓 Chatbot 支援隨機性參數調整

理解了 temperaturetop_p 的差異之後,我們就能更靈活地根據應用情境調整模型的回答風格。

接下來要做的事,就是在我們之前實作的 CLI Chatbot 上加上這兩個參數,讓使用者在啟動程式時,就能透過命令列選項直接控制模型的「創造力」與「回應範圍」。

調整主程式:加入參數設定

我們將使用 yargs 這個 CLI 參數解析套件,新增兩個選項:

  • --temperature(或 -t):控制模型的創造力。
  • --top-p(或 --tp):限制模型的選詞範圍。

以下是修改後的 src/index.ts

// src/index.ts
import 'dotenv/config';
import readline from 'readline';
import yargs, { Arguments } from 'yargs';
import { hideBin } from 'yargs/helpers';
import { OpenAI } from 'openai';
import { roles } from './prompts';

interface Argv {
  role: keyof typeof roles;
  temperature: number;
  top_p: number;
}

const argv = yargs(hideBin(process.argv))
  .option('role', {
    alias: 'r',
    type: 'string',
    choices: Object.keys(roles) as (keyof typeof roles)[],
    default: 'default',
    description: '指定助理角色',
  })
  .option('temperature', {
    alias: 't',
    type: 'number',
    description: '控制模型的創造力 (0 ~ 2)',
    default: 1,
  })
  .option('top_p', {
    alias: 'tp',
    type: 'number',
    description: '限制模型的選詞範圍 (0 ~ 1)',
    default: 1,
  })
  .help()
  .parseSync();

async function main(argv: Arguments<Argv>) {
  const openai = new OpenAI();
  const messages = [...roles[argv.role]];

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  console.log('GPT Chatbot 已啟動,輸入訊息開始對話(按 Ctrl+C 離開)。\n');
  rl.setPrompt('> ');
  rl.prompt();

  rl.on('line', async (input) => {
    messages.push({ role: 'user', content: input });

    try {
      const stream = await openai.chat.completions.create({
        model: 'gpt-4o-mini',
        stream: true,
        temperature: argv.temperature,
        top_p: argv.top_p,
        messages,
      });

      let reply = '';

      process.stdout.write('\n');
      for await (const chunk of stream) {
        const content = chunk.choices[0]?.delta?.content || '';
        process.stdout.write(content);
        reply += content;
      }
      process.stdout.write('\n\n');

      messages.push({ role: 'assistant', content: reply });
    } catch (err) {
      console.error(err);
    }

    rl.prompt();
  });
}

main(argv);

啟動與測試

完成修改後,就可以在命令列啟動聊天機器人,並嘗試不同參數組合。

預設參數temperature = 1top_p = 1):

npm run dev

模型會在穩定與多樣性之間取得平衡。

提高創意temperature = 1.5):

npm run dev -- --temperature 1.5

回應更自由、具想像力,但也更容易出現意料之外的答案。

限制選詞範圍top_p = 0.5):

npm run dev -- --top-p 0.5

只保留前半數高機率的候選詞,回應更集中、更保守。

透過以上測試,你會發現:同樣的問題,在不同參數下,AI 的回應長度、語氣、選詞甚至結論都可能不同。這種「可調控的隨機性」正是生成式 AI 的特色之一。

小結

今天我們探討了如何透過 temperaturetop_p 調整 AI 的「隨機性」,進而控制回應的穩定性與創造力:

  • 語言模型像是在玩「文字接龍」,每次預測下一個詞,但不一定要選機率最高的詞。
  • temperature:決定選詞的保守或奔放程度,低值輸出嚴謹穩定,高值輸出多樣且具創意。
  • top_p:限制候選詞的總機率範圍,值越小輸出越保守,值越大回答更有變化。
  • 兩者差異:temperature 改變「分布形狀」,top_p 控制「候選池大小」。
  • 實務建議:追求穩定可調低 temperature,強調創意可拉高 temperature,而想控制回答的保守程度或多樣性則可調整 top_p

掌握這兩個設定,可以幫助我們在「可靠答案」與「創意靈感」之間找到合適平衡,讓 AI 更符合不同場景需求。


上一篇
Day 04 - 提示工程與角色設計:打造回應清楚的 AI 助理
系列文
用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言