2025年3月7日 星期五

OpenAI API 學習筆記 : API 參數測試 (二)

今天繼續來測試 OpenAI API 的常用參數, 本系列前一篇測試文章參考 :


本系列全部文章索引參考 : 


本篇主要測試 OpenAI API 中與生成回應訊息變化性與隨機性相關的 6 個參數 : 


參數名稱 說明
temperature  控制回應的隨機性 (值 0~2), 值越高, 回應越具創意和變化 (官方建議 值 0~1).
top_p 機率篩選門檻 (值 0~1), 僅考慮累積機率達 top_p 以上的 token. 例如 top_p=0.9 表示只選取最有可能的 90% token, 忽略其他低機率選項.
presence_penalty  懲罰存在性 (值 -2~2), 降低曾經出現過的詞的選取機率, 以提高回應的多樣性與引入新詞.
frequency_penalty  懲罰出現頻率 (值 -2~2),根據詞彙出現的次數進行懲罰, 減少高頻詞的選取機率, 以避免詞彙重複.
logit_bias  調整特定 token 選取機率的字典, 其鍵為 token,值為影響力 (-100~100), -100 表示完全禁止該 token, 100 則是極度偏好它.
seed  使相同 prompt 和 seed 產生一致輸出的隨機種子 (signed int64), 於 temperature=0 時效果最佳 (在較高的 temperature 時仍可能產生變化). 


這些參數都是用來控制模型最後生成語句輸出的變化, GPT 模型可以簡單地理解為一個機率分布驅動的詞彙選擇機制, 它會自動計算接下來最可能的詞組合, 每一個詞彙表中的 token 都會依據出現在目前已生成 token 後面的可能性被計算出一個稱為 logit 的分數, 表示該 token 被選為下一個字的機率, 分數越高越可能被選取為下一個 token, 而上面六個參數就是用來影響 logit 計算的外部控制變數. 

在測試之前先匯入 OpenAI 類別並建立 OpenAI 物件 :

>>> from openai import OpenAI   
>>> api_key='填入 API key'    
>>> client=OpenAI(api_key=api_key)  
>>> type(client)    
<class 'openai.OpenAI'>   


4. temperature 參數 : 

此參數用來控制回應的隨機性與創意性 (預設值為 1), 如果把 GPT 模型比喻為一個封閉的氣體系統, 當系統溫度很低時 (例如接近 0), 氣體分子運動趨於靜止, 被選到的分子較固定, 相對於模型就是偏好選取機率最高者, 生成較保守, 規律, 也較缺乏創意的 token. 溫度值越大, 相當於氣體分子擾動越大, 模型會選擇到較多低機率的詞, 使回應更具創意和多變性, 更具想像力, 有時甚至會出現不可預測的元素, 例如 :

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': '你是誰?'}],
    model='gpt-3.5-turbo',
    temperature=0,
    n=2
    )   

此處溫度設為最低的 0, 並指定生成兩個回應, 因此模型會固定生成兩個完全相同的回應  : 

>>> chat_completion.choices[0].message.content  
'我是一個人工智能助手,可以回答你的問題和提供幫助。有什麼我可以為你做的嗎?'
>>> chat_completion.choices[1].message.content   
'我是一個人工智能助手,可以回答你的問題和提供幫助。有什麼我可以為你做的嗎?'

如果將 temperature 設為 1.5, 則生成的結果變化就很大 :

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': '你是誰?'}],
    model='gpt-3.5-turbo',
    temperature=1.5,
    n=2
    )   
>>> chat_completion.choices[0].message.content  
'我是一個人工智能實體,名為Assistant,具備回答各種問題、提供解決方案和學習技能的能力。要是您有任何問題,隨時都可以問我哦!'
>>> chat_completion.choices[1].message.content     
'我是您的助手AssistBot,有什麼可以幫助您的嗎?'

注意, n 越接近 2 生成回應的時間會越長, 且生成的結果會更出乎意料. 


5. presence_penalty 參數 :   

此參數使用懲罰存在性的方式來控制已生成過的 token 再次出現的機會, 正的參數值會降低其再次出現的機會; 反之, 負的參數值則會增加其再次出現的機會, 例如 :

>>> prompt='請用5句話形容一隻可愛的貓'   
>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    presence_penalty=2
    )  
>>> print(chat_completion.choices[0].message.content)   
這隻貓是一隻毛色橘黃,眼睛大大的和溫柔。
牠常常露出迷人的微笑,像在跟我說話。
每當感到寂寞時,這隻貓就會來陪伴我,讓我的心情立刻煥然一新。
牠愛撒嬌耍賴,喜歡趴在我身上睡覺。
在家裡任何地方都可以找到這隻可愛的貓,牠就像是我的好朋友和忠實的夥伴。

此例 presence_penalty 設為 2, 對已出現過的 token 扣分較多, 這使得模型會刻意避免重複出現的詞彙, 使回應更加多樣化. 

如果設為 -2 的話, 模型會傾向於重複使用已經出現的詞, 導致回應內容較為單調, 可能會不斷使用相同的描述方式或詞彙, 例如 : 

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    presence_penalty=-2
    )  
>>> print(chat_completion.choices[0].message.content)   
這隻貓一雙明亮的大眼睛,看起來像兩顆炙熱的星星。
它的毛色潔白潔白的,蓬鬆的尾巴不停地搖擺。
貓咪發出溫柔的咕嚕聲,一點一點的走向你,想讓你撫摸。
它總是躺在溫暖的陽光下,優雅地搔著自己的下巴。
這隻貓有著一雙軟綿綿的耳朵,看起來就像是一隻可愛的毛絨玩偶。

從 "一雙", "潔白潔白" 與 "一點一點" 的重複性可知其用詞較為貧乏. 


6. frequency_penalty 參數 : 

此參數使用懲罰頻率的方式來控制已生成過的 token 再次出現的機會, 正的參數值會降低其再次出現的機會; 反之, 負的參數值則會增加其再次出現的機會, 例如 :

>>> prompt='請寫一首關於星空的四句詩'    
>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    frequency_penalty=2
    ) 
>>> print(chat_completion.choices[0].message.content)   
在無垠的夜空中閃爍
星星如詩如畫,照亮著夢想
眺望遙不可及的宇宙
讓心靈自由飄向遠方

此例 frequency_penalty 設為 2, 會積極尋找不同的詞彙來表達同樣的概念, 刻意避免重複出現相同的 token, 這使得回應更加多樣化.

如果設為 -2 的話, 模型會傾向於重複使用相同的 token, 導致回應可能有較多重複的詞彙, 例如 : 

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    frequency_penalty=-2
    )  
>>> print(chat_completion.choices[0].message.content)   
在夜的黑幕下,星星閃閃發亮  
星星閃閃,閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃閃

哇, 極端的 -2 讓詩人閃到不行. 如果改成 -1 就不會這麼嚴重了 :

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    frequency_penalty=-1
    )  
>>> print(chat_completion.choices[0].message.content)   
繁星點點映夜空
夜深人靜仰頭望
星空

負值的參數對重複用詞有加分作用, 導致 '如' 這個字出現了 7 次之多. 


7. seed 參數 : 

seed 參數是一個用來固定生成結果的隨機種子 (預設值是 None), 其值可以是任何整數. 預設情況下對於相同的 prompt, 模型每次生成的結果幾乎都不同, 例如 : 

>>> prompt='請寫一首關於星空的四句詩'     
>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo'
    ) 
>>> print(chat_completion.choices[0].message.content)    
璀璨星空點綴夜空
繁星閃爍如璀璨珠
彷彿無盡的宇宙深淵
讓人迷失在星河中

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo'
    )   
>>> print(chat_completion.choices[0].message.content)   
星空灑落無數閃爍之光,
照耀著夜空中的浩瀚無垠,
彷彿是宇宙的明信片,
讓人心靈被撫慰深深。

但是如果傳入相同的 seed 參數, 則會得到相同的結果, 例如 :  

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    seed=42
    )  
>>> print(chat_completion.choices[0].message.content)    
璀璨星空高掛天際
微光點點閃爍如織
遙望無垠宇宙浩瀚
寂靜夜晚獨立凝視

此處我們設定隨機種子 42, 如果再次傳入 seed=42 將會得到一樣的生成結果 : 

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    seed=42
    )   
>>> print(chat_completion.choices[0].message.content)    
璀璨星空高掛天際
微光點點閃爍如織
遙望無垠宇宙浩瀚
寂靜夜晚獨立凝視

不過要注意的是, seed 必須搭配 temperature=0 才會生成相同結果, 因為 temperature 控制隨機性, temperature=0 會讓模型總是選擇機率最高的 token, 因此確保生成相同結果. 上面範例未傳入 temperature 參數預設就是 0. 

下面是 temperature 設為 1, seed 設為 42, 執行兩次生成的結果 :

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    temperature=1,
    seed=42
    )   
>>> print(chat_completion.choices[0].message.content)    
璀璨星空高掛天際
微風撫摸著我臉頰
夜色深沉如墨染
星辰間閃爍著希望
>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': prompt}],
    model='gpt-3.5-turbo',
    temperature=1,
    seed=42
    )   
>>> print(chat_completion.choices[0].message.content)    
璀璨星空高掛天際,
微光點點閃爍如織,
夜深人靜仰望星辰,
心中的寂寥漸漸消退。

可見即使是相同的 seed, 但若 temperature 不是 0, 生成的結果仍會有所不同. 

沒有留言 :