打造專屬 ChatGPT(一):Chat Completions API 基礎參數解析 (20260601更新)

A. 前言:為什麼要理解 Chat Completions API 參數?

如果你想自己打造一個類似 ChatGPT 的應用,OpenAI 的 Chat Completions API 是最常被拿來入門的介面之一。

它的核心概念其實很簡單:我們把一組對話訊息傳給模型,模型根據這些訊息產生下一則回覆。這組訊息通常會包含使用者輸入、系統或開發者指令、歷史對話,以及工具呼叫的結果。模型回傳的內容則通常會是一則 assistant message,也就是 AI 助理的回答。

但當我們真的要把它做成一個產品,就不會只需要 model 和 messages 這兩個基本參數而已。

例如:

  • 你希望模型回答穩定一點,還是有創意一點?
  • 你希望模型輸出一般文字,還是固定格式的 JSON?
  • 你希望模型可以呼叫外部工具,例如查資料庫、查天氣、查訂單狀態嗎?
  • 你希望使用者看到文字一段一段串流出現,而不是等整段回答完成才顯示嗎?
  • 你希望記錄每次請求的 metadata,方便日後分析、追蹤或除錯嗎?
  • 你希望限制回答長度、控制成本,或取得 token 使用量嗎?

這些需求都會對應到不同的 API 參數,例如 temperature、top_p、max_completion_tokens、response_format、tools、tool_choice、stream、store、metadata、logprobs 等等。

也就是說,Chat Completions API 不是只有「送出 prompt,拿回答案」這麼簡單。它更像是一個可以控制模型行為的介面。你設定的每個參數,都會影響模型如何理解上下文、如何產生回答、如何輸出格式、如何呼叫工具,以及這次請求如何被記錄和追蹤。

理解這些參數的目的,不是要每次請求都把所有參數填滿。相反地,真正重要的是知道:

  • 哪些參數是必要的?
  • 哪些參數是一般應用最常用的?
  • 哪些參數只適合進階情境?
  • 哪些參數已經屬於相容性或 legacy 用法?
  • 哪些參數會影響成本、延遲、穩定性與可維護性?

這篇文章會用開發者實作的角度,整理 Chat Completions API 的常用與進階參數,並補充每個參數適合的使用情境。目標不是逐字翻譯官方文件,而是建立一張比較容易理解的參數地圖,讓你在打造自己的 ChatGPT、客服機器人、AI 助理、資料抽取工具或 Tool Calling Agent 時,可以更清楚知道每個參數控制的是哪一層行為。

B. 最小可用範例:發出第一個 Chat Completion 請求

在正式介紹所有參數之前,我們先從最小可用範例開始。

雖然 OpenAI 官方 Quickstart 目前較常以 Responses API 作為新專案的入門範例,但 Chat Completions API 仍然保留在 API Reference 中,並且仍可透過 POST /chat/completions 建立對話回覆。這篇文章聚焦在 Chat Completions API,因此以下範例會使用 client.chat.completions.create(…)。

Chat Completions API 最基本需要兩個核心參數:

  • model:指定要使用哪一個模型。
  • messages:提供一組對話訊息,讓模型根據上下文產生回覆。

如果使用 Python,可以先安裝 OpenAI 官方 SDK:

pip install openai

接著設定 API key。實務上不建議把 API key 直接寫死在程式碼裡,比較好的方式是使用環境變數:

export OPENAI_API_KEY="你的 API key"

如果是在 Windows PowerShell,可以使用:

$env:OPENAI_API_KEY="你的 API key"

接著就可以建立第一個 Chat Completion 請求:

from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API 是什麼。"
        }
    ],
)

print(completion.choices[0].message.content)

這段程式做了幾件事。

首先,OpenAI() 會建立一個 API client。預設情況下,它會從環境變數 OPENAI_API_KEY 讀取 API key,所以我們不需要在程式碼中直接放入金鑰。

接著,client.chat.completions.create(…) 會發出一個 Chat Completions API 請求。其中 model 指定這次要使用的模型,messages 則是一個陣列,用來描述目前的對話內容。

在這個最小範例中,我們只傳入一則 user message:

messages=[
    {
        "role": "user",
        "content": "請用一句話解釋 Chat Completions API 是什麼。"
    }
]

role 代表這則訊息的角色,content 則是訊息內容。這裡的 role 是 user,表示這是使用者對模型提出的問題。模型收到這組 messages 之後,會產生一則 assistant 回覆。

回傳結果會放在 completion 物件中。一般最常讀取的欄位是:

completion.choices[0].message.content

其中:

  • choices 是模型產生的候選回覆列表。
  • choices[0] 代表第一個候選回覆。
  • message 是模型產生的 assistant message。
  • content 是 assistant message 的文字內容。

如果執行成功,輸出可能會類似:

Chat Completions API 是一個讓開發者把對話訊息傳給模型,並取得 AI 回覆的介面。

這就是一個最基本的 Chat Completions API 請求。

不過,實務上我們通常不會只傳一則 user message。為了讓模型更符合應用需求,通常會加入應用程式層級的指令,例如要求模型使用繁體中文、限制回答格式,或指定它扮演某種角色。

在較新的模型中,如果要提供開發者層級的指令,建議優先使用 developer message。你仍然可能在舊範例或相容情境中看到 system message,但對 o1 與更新模型而言,官方文件已說明 developer messages 取代先前的 system messages。

例如:

from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "你是一位熟悉 Python 與 API 設計的技術寫作者,請使用繁體中文回答。"
        },
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API 是什麼。"
        }
    ],
)

print(completion.choices[0].message.content)

在這個版本中,developer message 用來提供開發者層級的指令,告訴模型應該遵守什麼規則、使用什麼語言、採用什麼風格,或用什麼方式回答。user message 則是使用者實際提出的問題。

可以把它想成:

  • developer message:應用程式希望模型遵守的規則。
  • user message:使用者這次真正輸入的內容。
  • assistant message:模型產生的回覆。

這也是 Chat Completions API 最重要的心智模型:你不是只傳一段 prompt,而是傳一組有角色、有順序的 messages。模型會根據這些 messages 產生下一則 assistant message。

另外,這裡的範例先使用最單純的純文字 content。實際上,Chat Completions API 的 message content 也可以依照角色與模型支援,使用 content parts 來表示更複雜的輸入,例如文字、圖片或其他多模態內容。這部分會在後面的多模態段落再介紹。

在後面的段落中,我們會從這個最小範例出發,逐步拆解 model、messages、生成控制、輸出格式、工具呼叫、串流回應與回傳物件等參數。

C. Chat Completions API 的基本結構

在看完最小可用範例之後,我們先把 Chat Completions API 的整體結構整理清楚。

Chat Completions API 可以先用一句話理解:

你把一組 messages 傳給模型,模型根據這組對話內容產生下一則 assistant message。

從 API 的角度來看,它主要可以拆成四個部分:

  • endpoint:請求送到哪裡。
  • request body:這次請求要帶哪些參數。
  • response object:非串流模式下,API 一次回傳的完整結果。
  • streaming chunk:串流模式下,API 分段回傳的片段資料。

C.1 endpoint:請求送到哪裡

Chat Completions API 的建立請求使用:

POST /v1/chat/completions

如果使用 OpenAI Python SDK,通常不需要自己手動組 HTTP request,而是透過:

client.chat.completions.create(...)

來建立一個 Chat Completion。

例如:

from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API。"
        }
    ],
)

這段 SDK 寫法背後對應的就是建立一個 Chat Completion 請求。

C.2 request body:這次請求要帶哪些參數

Chat Completions API 的 request body 是一個 JSON 物件,用來描述這次請求的模型、對話內容,以及各種控制模型輸出的設定。

最小可用的 request body 大致會長這樣:

{
  "model": "gpt-5.5",
  "messages": [
    {
      "role": "user",
      "content": "請用一句話解釋 Chat Completions API。"
    }
  ]
}

其中最核心的兩個欄位是:

  • model:指定要使用的模型。
  • messages:指定目前的對話內容。

除此之外,實務上常見的 request body 還會加入其他參數,例如:

{
  "model": "gpt-5.5",
  "messages": [
    {
      "role": "developer",
      "content": "你是一位技術寫作者,請使用繁體中文回答。"
    },
    {
      "role": "user",
      "content": "請用一句話解釋 Chat Completions API。"
    }
  ],
  "temperature": 0.7,
  "max_completion_tokens": 300,
  "stream": false
}

在這個例子中:

  • developer message 用來設定應用程式層級的指令。
  • user message 是使用者實際提出的問題。
  • temperature 控制輸出的隨機程度。
  • max_completion_tokens 控制模型最多可以產生多少 token。
  • stream 控制是否使用串流回應。

後面的段落會依照不同用途,逐一拆解這些參數。

C.3 response object:非串流模式下的完整回傳結果

當 stream 沒有啟用,或設定為 false 時,API 會等模型產生完整結果後,一次回傳一個 Chat Completion object。

簡化後的回傳結構大致會像這樣:

{
  "id": "chatcmpl_xxx",
  "object": "chat.completion",
  "created": 1710000000,
  "model": "gpt-5.5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Chat Completions API 是一個讓開發者把對話訊息傳給模型,並取得 AI 回覆的介面。"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 30,
    "total_tokens": 50
  }
}

一般開發時,最常讀取的是:

completion.choices[0].message.content

這個欄位代表第一個候選回覆中的 assistant 文字內容。

可以把 response object 想成「這次模型完成回答後的完整紀錄」。它不只包含回答文字,也包含:

  • 這次請求的 id
  • 使用的 model
  • 模型產生的 choices
  • 結束原因 finish_reason
  • token 使用量 usage

其中 usage 對產品開發很重要,因為它可以用來追蹤成本、分析請求量,或估算不同功能的 token 消耗。

C.4 streaming chunk:串流模式下的分段回傳

如果把 stream 設定為 true,API 不會等整段回答完成後才一次回傳,而是會把模型產生的內容分成多個 chunk 逐步送回來。

Python SDK 範例:

from openai import OpenAI

client = OpenAI()

stream = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用三句話介紹 Chat Completions API。"
        }
    ],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

串流模式下,每次收到的不是完整的 Chat Completion object,而是 Chat Completion Chunk object。

簡化後的 chunk 可能長這樣:

{
  "id": "chatcmpl_xxx",
  "object": "chat.completion.chunk",
  "created": 1710000000,
  "model": "gpt-5.5",
  "choices": [
    {
      "index": 0,
      "delta": {
        "content": "Chat"
      },
      "finish_reason": null
    }
  ]
}

下一個 chunk 可能會接著回傳:

{
  "id": "chatcmpl_xxx",
  "object": "chat.completion.chunk",
  "created": 1710000000,
  "model": "gpt-5.5",
  "choices": [
    {
      "index": 0,
      "delta": {
        "content": " Completions"
      },
      "finish_reason": null
    }
  ]
}

直到最後一個 chunk,finish_reason 才會出現,例如:

{
  "id": "chatcmpl_xxx",
  "object": "chat.completion.chunk",
  "created": 1710000000,
  "model": "gpt-5.5",
  "choices": [
    {
      "index": 0,
      "delta": {},
      "finish_reason": "stop"
    }
  ]
}

也就是說,非串流模式下,我們通常讀:

completion.choices[0].message.content

串流模式下,我們則通常逐步讀:

chunk.choices[0].delta.content

這兩者的差異很重要:

  • message:代表完整 assistant message。
  • delta:代表這次 chunk 新增的片段內容。

如果你正在做聊天 UI,通常會使用串流模式,讓使用者看到文字一段一段出現,體驗會更接近 ChatGPT。
如果你是在做批次資料處理、背景任務或結構化資料抽取,則不一定需要串流,一次拿完整 response object 會更容易處理。

C.5 用一張表整理基本結構

結構說明常見位置
endpointAPI 請求位置POST /v1/chat/completions
request body請求參數model、messages、temperature、tools、stream
response object非串流模式的完整回傳結果completion.choices[0].message.content
streaming chunk串流模式的片段回傳結果chunk.choices[0].delta.content

理解這四個結構之後,後面看每個參數會清楚很多。

model 和 messages 決定模型要根據什麼內容回答;temperature、top_p、max_completion_tokens 會影響模型如何生成內容;response_format 會影響輸出格式;tools 和 tool_choice 會影響模型是否能呼叫外部工具;stream 則會改變回傳資料的形式。

接下來,我們就可以先從最核心的 messages 開始看起。

D. messages:對話的核心

在 Chat Completions API 裡,messages 是最核心的參數。

很多人剛開始使用 LLM API 時,會把它想成「送出一段 prompt,拿回一段回答」。但在 Chat Completions API 裡,比較精準的理解方式是:

你不是只傳一段 prompt,而是傳一組有角色、有順序的對話訊息。

這組對話訊息就是 messages。

最簡單的 messages 可能只有一則 user message:

[
  {
    "role": "user",
    "content": "請用一句話解釋 Chat Completions API 是什麼。"
  }
]

模型收到這組 messages 之後,會根據目前的對話內容,產生下一則 assistant message。

如果把它放進 Python SDK,會像這樣:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API 是什麼。"
        }
    ],
)

這裡的重點是:messages 是一個陣列,陣列中的每一個物件都是一則訊息。每則訊息至少會有 role,並依照角色不同,帶有 content 或其他欄位。

D.1 messages 的順序很重要

messages 不是單純的資料集合,而是一段有順序的對話紀錄。

模型會按照陣列順序理解上下文。越前面的訊息越像前文,越後面的訊息越接近目前要回答的問題。

例如:

[
  {
    "role": "developer",
    "content": "請使用繁體中文回答,並保持回答簡潔。"
  },
  {
    "role": "user",
    "content": "什麼是 Chat Completions API?"
  }
]

這裡模型會先看到 developer message,知道應該用繁體中文、回答要簡潔,接著再看到 user message,知道使用者真正想問的是什麼。

如果是多輪對話,messages 會包含過去的使用者問題與 assistant 回答:

[
  {
    "role": "developer",
    "content": "請使用繁體中文回答,並保持回答簡潔。"
  },
  {
    "role": "user",
    "content": "什麼是 Chat Completions API?"
  },
  {
    "role": "assistant",
    "content": "Chat Completions API 是一個讓開發者傳入對話訊息,並取得模型回覆的 API。"
  },
  {
    "role": "user",
    "content": "那它和一般 prompt 有什麼不同?"
  }
]

在這個例子裡,最後一則 user message 才是這次真正要回答的問題,但前面的訊息會提供上下文。模型會知道使用者問的「它」指的是 Chat Completions API。

D.2 developer message:開發者層級的指令

developer message 用來放應用程式希望模型遵守的規則。

例如:

{
  "role": "developer",
  "content": "你是一位熟悉 Python 與 API 設計的技術寫作者。請使用繁體中文回答,並優先提供可執行的範例。"
}

developer message 常見用途包括:

  • 指定回答語言。
  • 指定模型扮演的角色。
  • 指定回答格式。
  • 指定語氣與風格。
  • 指定安全、合規或產品規則。
  • 指定工具使用原則。

例如你正在做一個客服機器人,可以在 developer message 中放入:

{
  "role": "developer",
  "content": "你是 TallyTrip 的客服助理。請使用繁體中文回答。若使用者詢問帳務、付款或個人資料問題,請提醒使用者前往官方客服管道確認。"
}

這樣每次請求都可以讓模型知道它不是一般聊天機器人,而是某個產品中的 AI 助理。

在較新的模型中,若要放開發者層級的指令,建議優先使用 developer message。你仍然可能在舊文章、舊 SDK 範例或相容性情境中看到 system message,但對 o1 與更新模型而言,官方文件已說明 developer messages 取代先前的 system messages。(OpenAI Developer Community)

D.3 system message:舊範例中常見的系統指令

system message 過去常用來放高層級指令,例如:

{
  "role": "system",
  "content": "You are a helpful assistant."
}

在許多早期 Chat Completions API 教學裡,你會看到這種寫法:

completion = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "system",
            "content": "你是一位專業的技術寫作者,請使用繁體中文回答。"
        },
        {
            "role": "user",
            "content": "請解釋 API rate limit 是什麼。"
        }
    ],
)

這種寫法在很多舊專案中仍然看得到。不過如果你正在寫新的範例,並且使用較新的模型,建議優先示範 developer message,讓文章和目前 API 文件的用語保持一致。

簡單來說:

role建議用法
developer新範例優先使用,用來放應用程式層級的規則與指令
system舊範例、舊模型或相容性情境中仍可能看到
user使用者輸入
assistant模型過去產生的回答
tool外部工具執行後回傳給模型的結果
functionlegacy 用法,通常不建議新專案使用

D.4 user message:使用者輸入

user message 代表使用者實際輸入的內容。

例如:

{
  "role": "user",
  "content": "請幫我把這段英文翻成繁體中文。"
}

或:

{
  "role": "user",
  "content": "請根據以下訂單資料,整理成客服回覆。"
}

在大多數應用中,user message 會來自前端表單、聊天輸入框、API request,或其他使用者提交的內容。

如果是一般聊天機器人,每次使用者送出新訊息時,你通常會把它加入 messages 陣列的最後面:

messages.append({
    "role": "user",
    "content": user_input
})

接著再把整組 messages 傳給 Chat Completions API。

D.5 assistant message:模型的回答與對話歷史

assistant message 代表模型產生過的回答。

在 API 回傳結果中,模型產生的內容通常會出現在:

completion.choices[0].message

其中 message.role 通常會是 assistant,message.content 則是模型回覆的文字內容。

例如:

{
  "role": "assistant",
  "content": "Chat Completions API 是一個讓開發者傳入對話訊息,並取得模型回覆的 API。"
}

如果你要做多輪對話,必須自己保存對話歷史。Chat Completions API 不會自動記住上一輪對話;每次請求都需要你把需要的上下文放進 messages 裡。

典型流程會像這樣:

messages = [
    {
        "role": "developer",
        "content": "請使用繁體中文回答,並保持回答簡潔。"
    }
]

# 第一輪使用者輸入
messages.append({
    "role": "user",
    "content": "什麼是 Chat Completions API?"
})

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
)

assistant_message = completion.choices[0].message

# 把 assistant 回覆存回 messages
messages.append({
    "role": "assistant",
    "content": assistant_message.content
})

# 第二輪使用者輸入
messages.append({
    "role": "user",
    "content": "那它和 Responses API 有什麼不同?"
})

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
)

這也是很多人剛開始串接 API 時容易誤解的地方:模型不是靠 API 自動記憶對話,而是靠你每次把必要的對話歷史重新傳給它。

D.6 tool message:工具執行結果

當你使用 Tool Calling 時,模型可能不會直接回答使用者,而是先要求呼叫某個工具。

例如你提供了一個 get_weather 工具,使用者問:

台北今天會下雨嗎?

模型可能會回傳一個 assistant message,其中包含 tool_calls,表示它想呼叫某個工具來取得天氣資料。

簡化後可能像這樣:

{
  "role": "assistant",
  "content": null,
  "tool_calls": [
    {
      "id": "call_abc123",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{\"city\":\"Taipei\"}"
      }
    }
  ]
}

這時候你的程式要做三件事:

  1. 讀取模型要求呼叫的工具名稱與參數。
  2. 在你的後端實際執行這個工具。
  3. 把工具執行結果用 tool message 回傳給模型。

tool message 會像這樣:

{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "{\"city\":\"Taipei\",\"forecast\":\"今天下午有短暫陣雨機率。\"}"
}

其中 tool_call_id 必須對應到前面 assistant message 裡的 tool call id,讓模型知道這是哪一次工具呼叫的結果。

接著你再把更新後的 messages 傳回 API,讓模型根據工具結果產生最後回答。

完整概念大致是:

[
  {
    "role": "developer",
    "content": "你是天氣助理,請根據工具結果回答。"
  },
  {
    "role": "user",
    "content": "台北今天會下雨嗎?"
  },
  {
    "role": "assistant",
    "content": null,
    "tool_calls": [
      {
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\":\"Taipei\"}"
        }
      }
    ]
  },
  {
    "role": "tool",
    "tool_call_id": "call_abc123",
    "content": "{\"city\":\"Taipei\",\"forecast\":\"今天下午有短暫陣雨機率。\"}"
  }
]

模型看到 tool message 後,才會根據工具回傳的資料整理成自然語言回答。

Tool Calling 的細節會在後面的 tools、tool_choice 與 parallel_tool_calls 段落再完整說明。這裡只需要先理解:tool message 不是使用者輸入,也不是模型一般回答,而是你的程式把外部工具執行結果回填給模型的訊息。

D.7 function message:legacy 用法

早期 Chat Completions API 使用 functions、function_call 和 function role 來處理函式呼叫。後來這套用法被 tools、tool_choice 和 tool role 取代。OpenAI API 社群與相關文件長期都將 functions 視為 deprecated,新的工具呼叫流程應優先使用 tools。(OpenAI Developer Community)

你可能會在舊範例中看到這種 message:

{
  "role": "function",
  "name": "get_weather",
  "content": "{\"city\":\"Taipei\",\"forecast\":\"今天下午有短暫陣雨機率。\"}"
}

如果你是在維護舊專案,可能仍然需要理解這種寫法。但如果你正在寫新文章或新程式,建議把它放在 legacy 段落即可,不要把它當成主要推薦用法。

簡單來說:

舊用法新用法
functionstools
function_calltool_choice
function roletool role
function resulttool message with tool_call_id

D.8 content:訊息內容不一定只有字串

在最簡單的範例中,content 通常是一段字串:

{
  "role": "user",
  "content": "請用一句話解釋 Chat Completions API。"
}

但在較新的模型與多模態情境中,content 也可以是 content parts,也就是由多個內容片段組成的陣列。

例如,純文字 content part 可以寫成:

{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "請描述這張圖片。"
    }
  ]
}

如果模型支援圖片輸入,也可能會搭配 image content part。實際可用的 content part 類型會依照模型與 API 文件而有所不同,所以在實作多模態輸入時,應該以你使用的模型支援範圍為準。

在這篇文章中,前面的最小範例先使用字串形式,因為它最容易理解,也足以涵蓋純文字聊天的基本用法。後面的多模態段落再另外整理 content parts 的寫法。

D.9 多輪對話需要自己管理上下文

最後要特別強調一點:Chat Completions API 本身不會替你保存對話狀態。

每次呼叫 API 時,模型只會看到你這次傳入的 messages。如果你希望模型記得前幾輪對話,就必須由你的應用程式保存歷史訊息,並在下一次請求時重新送出必要上下文。

例如:

conversation = [
    {
        "role": "developer",
        "content": "請使用繁體中文回答,並保持簡潔。"
    }
]

def ask(user_input: str) -> str:
    conversation.append({
        "role": "user",
        "content": user_input
    })

    completion = client.chat.completions.create(
        model="gpt-5.5",
        messages=conversation,
    )

    answer = completion.choices[0].message.content

    conversation.append({
        "role": "assistant",
        "content": answer
    })

    return answer

這段程式會把每次使用者輸入與模型回答都存進 conversation,下一次呼叫 API 時再一起送出。這樣模型才有辦法根據前文回答。

不過在實務產品中,不建議無限制地把所有歷史對話都塞進 messages。原因有三個:

  • token 會變多,成本會上升。
  • context 太長,延遲會增加。
  • 過舊或不重要的訊息可能干擾模型回答。

常見做法是只保留最近幾輪對話,或將較早的對話摘要成一段 summary,再放回 messages 中。這樣可以在上下文完整性、成本與延遲之間取得平衡。

D.10 messages 小結

整理一下,messages 是 Chat Completions API 的核心,因為它決定模型看見什麼上下文。

常見 role 可以這樣理解:

role用途
developer應用程式層級的規則與指令,新範例建議優先使用
system舊範例常見的高層級指令,部分相容情境仍會看到
user使用者輸入
assistant模型產生的回答,或包含 tool calls 的訊息
tool外部工具執行後回填給模型的結果
functionlegacy 工具呼叫結果,不建議新專案優先使用

理解 messages 之後,後面介紹其他參數會更容易。因為無論是 temperature、response_format、tools、stream 還是 metadata,本質上都是在控制模型如何根據這組 messages 產生回覆。

E. 基本必要參數

在 Chat Completions API 裡,最基本、最核心的請求參數是:

  • model
  • messages

如果只想發出一個最小可用請求,通常只需要先理解這兩個參數。

前面已經看過一個最小範例:

from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API 是什麼。"
        }
    ],
)

print(completion.choices[0].message.content)

在這段程式中,model 決定這次要使用哪一個模型,messages 則決定模型這次要根據什麼上下文產生回答。

可以先把它們理解成:

參數作用
model決定使用哪一個模型來產生回覆
messages決定模型看見哪些對話內容與指令

其他參數,例如 temperature、response_format、tools、stream、metadata,都是在這個基礎上進一步控制模型行為或回傳方式。

E.1 model:指定要使用的模型

model 用來指定這次請求要使用哪一個模型。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請介紹 Chat Completions API。"
        }
    ],
)

這裡的:

model="gpt-5.5"

表示這次請求會交給 gpt-5.5 這個模型處理。

不同模型通常會在以下面向有所差異:

  • 推理能力
  • 回答品質
  • 速度
  • 價格
  • context window 大小
  • 是否支援多模態輸入
  • 是否支援音訊輸出
  • 是否支援特定工具或進階功能

因此,選擇 model 不只是選一個名稱,而是在品質、速度、成本與功能之間做取捨。

如果你正在做一般聊天機器人,可能會優先考慮成本與速度;如果你正在做複雜推理、程式碼分析、長文件理解,則可能需要選擇能力更強、context window 更大的模型。

實務上,我通常會用這個方式思考:

使用情境選型考量
一般客服或 FAQ成本、速度、穩定性
技術問答或程式碼分析推理能力、程式碼能力、上下文長度
長文件摘要context window、摘要品質
結構化資料抽取JSON / structured output 穩定性
Tool Calling Agent工具呼叫能力、參數生成穩定性
即時聊天 UI延遲、串流體驗、成本

文章範例中可以使用當前官方文件或官方 Quickstart 常見的模型名稱,但實務專案中,建議你仍然要依照最新的 Models 文件、價格表與專案需求來選擇模型。模型名稱、價格與支援能力會隨時間更新,因此文章中的模型名稱應該視為範例,而不是永遠固定的建議。

E.2 不要把 model 寫死在太多地方

在正式專案中,不建議把模型名稱散落在很多支程式裡。

例如不太建議這樣:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
)

然後在另一個檔案又寫一次:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
)

這樣做的問題是,未來如果要更換模型,需要到處搜尋與修改,容易漏掉。

比較好的方式是把模型名稱集中管理,例如:

CHAT_MODEL = "gpt-5.5"

completion = client.chat.completions.create(
    model=CHAT_MODEL,
    messages=messages,
)

或放在環境變數中:

export OPENAI_CHAT_MODEL="gpt-5.5"

Python 端再讀取:

import os
from openai import OpenAI

client = OpenAI()

CHAT_MODEL = os.getenv("OPENAI_CHAT_MODEL", "gpt-5.5")

completion = client.chat.completions.create(
    model=CHAT_MODEL,
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API。"
        }
    ],
)

這樣做有幾個好處:

  • 開發環境與正式環境可以使用不同模型。
  • A/B testing 時比較容易切換模型。
  • 未來模型升級時,不需要大規模修改程式碼。
  • 成本控管會更容易。

如果你的產品有多種 AI 功能,也可以針對不同任務設定不同模型:

CHAT_MODEL = os.getenv("OPENAI_CHAT_MODEL", "gpt-5.5")
SUMMARY_MODEL = os.getenv("OPENAI_SUMMARY_MODEL", "gpt-5.5")
EXTRACTION_MODEL = os.getenv("OPENAI_EXTRACTION_MODEL", "gpt-5.5")

這樣就可以讓聊天、摘要、資料抽取等功能各自調整模型,而不是全部綁在同一個設定上。

E.3 messages:指定模型看到的對話內容

messages 是一組對話訊息,用來告訴模型目前的上下文。

最簡單的 messages 只有一則 user message:

messages=[
    {
        "role": "user",
        "content": "請用一句話解釋 Chat Completions API 是什麼。"
    }
]

這代表使用者問了一個問題,模型要根據這則訊息產生下一則 assistant 回覆。

如果要加入應用程式層級的規則,可以加入 developer message:

messages=[
    {
        "role": "developer",
        "content": "你是一位熟悉 Python 與 API 設計的技術寫作者,請使用繁體中文回答。"
    },
    {
        "role": "user",
        "content": "請用一句話解釋 Chat Completions API 是什麼。"
    }
]

這裡的 developer message 會先告訴模型應該遵守什麼規則,接著 user message 才是使用者真正提出的問題。

前一段已經詳細介紹過 messages 的各種 role,這裡只需要記住一個重點:

messages 決定模型看見什麼;模型只能根據你這次傳入的 messages 產生回答。

也就是說,如果你沒有把某段上下文放進 messages,模型就不會在這次請求中看到它。

E.4 messages 通常由你的應用程式動態組出來

在實務產品中,messages 通常不是手寫死的,而是由你的應用程式根據使用者輸入、歷史對話、產品規則與外部資料組出來。

例如一個簡單的聊天功能可能會這樣寫:

from openai import OpenAI

client = OpenAI()

def ask(user_input: str) -> str:
    messages = [
        {
            "role": "developer",
            "content": "你是一位客服助理,請使用繁體中文回答,並保持簡潔。"
        },
        {
            "role": "user",
            "content": user_input
        }
    ]

    completion = client.chat.completions.create(
        model="gpt-5.5",
        messages=messages,
    )

    return completion.choices[0].message.content

這個版本每次請求都會建立一組新的 messages,其中:

  • developer message 是固定的產品規則。
  • user message 是這次使用者輸入的內容。

如果要支援多輪對話,就需要把歷史對話也放進 messages:

conversation = [
    {
        "role": "developer",
        "content": "你是一位客服助理,請使用繁體中文回答,並保持簡潔。"
    }
]

def ask(user_input: str) -> str:
    conversation.append({
        "role": "user",
        "content": user_input
    })

    completion = client.chat.completions.create(
        model="gpt-5.5",
        messages=conversation,
    )

    answer = completion.choices[0].message.content

    conversation.append({
        "role": "assistant",
        "content": answer
    })

    return answer

這樣下一次呼叫 API 時,模型才會看到前幾輪對話。

不過,這個範例只是為了說明概念。在正式產品中,通常還需要考慮:

  • 對話歷史要存在哪裡。
  • 要保留最近幾輪對話。
  • 是否要摘要舊對話。
  • 是否要過濾敏感資訊。
  • 是否要限制 token 數量。
  • 是否要分使用者、分 session 管理對話。

E.5 model 與 messages 的關係

model 和 messages 是 Chat Completions API 裡最核心的兩個參數,但它們控制的是不同層面。

可以這樣理解:

參數控制層面問題
model模型能力要讓哪個模型回答?
messages上下文內容要讓模型根據什麼回答?

同樣的 messages,換不同模型,可能會得到不同品質、不同速度、不同成本的結果。

同樣的 model,換不同 messages,也會產生完全不同的回答。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請介紹 Python。"
        }
    ],
)

和:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "請用適合初學者的方式回答,並使用繁體中文。"
        },
        {
            "role": "user",
            "content": "請介紹 Python。"
        }
    ],
)

雖然使用的是同一個模型,但第二個請求加入了 developer message,因此模型會更清楚知道回答語言與目標讀者。

再例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "請用資深後端工程師的角度回答。"
        },
        {
            "role": "user",
            "content": "請介紹 Python。"
        }
    ],
)

這次模型會更偏向從工程實務、語言特性、後端開發場景來介紹 Python。

所以在設計 AI 應用時,不要只關心「要用哪個模型」,也要同時設計「要給模型什麼 messages」。

E.6 基本必要參數小結

整理一下,Chat Completions API 最基本的請求,就是指定 model 與 messages。

最小形式如下:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API。"
        }
    ],
)

如果要讓模型更符合你的應用需求,通常會加入 developer message:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "請使用繁體中文回答,並保持簡潔。"
        },
        {
            "role": "user",
            "content": "請用一句話解釋 Chat Completions API。"
        }
    ],
)

在實務上:

  • model 決定模型能力、成本、速度與功能支援。
  • messages 決定模型看到的上下文、規則與使用者輸入。
  • 多輪對話需要由你的應用程式自行保存並重新傳入 messages。
  • 模型名稱建議集中管理,不要散落在程式各處。
  • 文章範例中的模型名稱只是示範,正式專案應依照最新模型文件與產品需求選擇。

理解 model 與 messages 之後,接下來就可以進一步看控制生成結果的參數,例如 temperature、top_p、max_completion_tokens、presence_penalty 與 frequency_penalty。

F. 控制生成結果的參數

前面介紹的 model 和 messages,決定了「讓哪個模型根據什麼上下文回答」。

接下來這一組參數,則是用來控制模型「怎麼生成回答」。

常見的生成控制參數包括:

  • temperature
  • top_p
  • n
  • stop
  • max_completion_tokens
  • presence_penalty
  • frequency_penalty
  • logit_bias

這些參數會影響模型輸出的隨機程度、長度、重複程度、停止條件,以及特定 token 出現的機率。

不過要先提醒一點:不是每個模型都支援完全相同的參數。有些最新 reasoning models 可能不支援部分傳統生成控制參數,或只支援預設值。因此實務上應該以你實際使用的模型文件為準。這篇文章會先從 Chat Completions API 的一般參數角度說明它們的用途。

F.1 temperature:控制輸出的隨機程度

temperature 用來控制模型輸出的隨機程度。

型別:

number or null

範圍:

0 到 2

一般來說:

  • temperature 越低,輸出越穩定、越集中、越可預期。
  • temperature 越高,輸出越發散、越有變化、越有創意。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "幫我想 5 個旅遊分帳 App 的標語。"
        }
    ],
    temperature=0.9,
)

如果你正在做創意型任務,例如文案、命名、標語、腦力激盪,可以使用較高的 temperature,讓模型產生更多變化。

如果你正在做比較要求穩定的任務,例如客服回答、資料整理、格式化輸出,則可以使用較低的 temperature。

常見設定可以這樣理解:

使用情境建議 temperature
結構化資料抽取0 到 0.3
客服、FAQ、技術說明0.2 到 0.7
一般聊天0.7 到 1
創意寫作、命名、標語0.8 到 1.2

範例:穩定回答

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "請用簡潔、穩定、可預期的方式回答。"
        },
        {
            "role": "user",
            "content": "請解釋什麼是 API rate limit。"
        }
    ],
    temperature=0.2,
)

範例:創意發想

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請幫 TallyTrip 想 10 個產品標語。"
        }
    ],
    temperature=1.0,
)

實務建議:

如果你不知道該怎麼設定,通常可以先使用預設值,等真的遇到「回答太死板」或「回答太發散」時再調整。

F.2 top_p:用 nucleus sampling 控制候選 token 範圍

top_p 是另一種控制隨機性的方式,也稱為 nucleus sampling。

型別:

number or null

範圍:

0 到 1

它的概念是:模型在產生下一個 token 時,不一定要考慮所有可能 token,而是只考慮累積機率達到 top_p 的那一群候選 token。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請幫我寫一段產品介紹。"
        }
    ],
    top_p=0.9,
)

如果 top_p=0.1,代表模型只會從機率最高、累積機率約前 10% 的 token 中取樣,因此輸出會更保守。

如果 top_p 接近 1,代表模型會考慮更多候選 token,輸出會更有變化。

可以這樣理解:

top_p效果
接近 0非常保守,只考慮最高機率候選
0.5較集中
0.9較自然、有變化
1預設範圍,候選 token 最完整

官方通常建議:temperature 和 top_p 擇一調整即可,不建議同時大幅調整兩者。

原因是這兩個參數都會影響隨機性。如果你同時調整,很難判斷輸出變化到底是由哪個參數造成。

實務建議:

  • 一般情況:優先調整 temperature。
  • 需要更精細控制候選 token 範圍時:再考慮調整 top_p。
  • 不熟悉時:保留 top_p 預設值。

F.3 n:一次產生幾個候選回答

n 用來指定每個輸入要產生幾個 chat completion choices。

型別:

number or null

範圍:

最小 1

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "幫我想 3 個部落格文章標題。"
        }
    ],
    n=3,
)

這樣 API 會回傳 3 個候選結果,你可以用:

for choice in completion.choices:
    print(choice.message.content)

逐一讀取。

不過實務上,n 要小心使用。因為產生多個 choices 時,費用會依照所有產生的 tokens 計算,而不是只算你最後選用的那一個。

例如 n=3,代表模型會產生 3 份回答,生成 token 數量與成本通常也會跟著增加。

實務建議:

  • 一般聊天 UI:保持 n=1。
  • 需要產生多個候選文案:可以考慮 n=3 或更多。
  • 想控制成本:盡量維持 n=1。
  • 如果只是想要多個點子,也可以讓模型在單一回答裡列出多個選項,而不是使用 n。

例如比起這樣:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    n=5,
)

很多時候可以改成:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請幫我列出 5 個候選標題。"
        }
    ],
)

這樣通常更容易控制成本,也更容易處理回傳結果。

F.4 stop:指定停止生成的字串

stop 用來指定模型遇到某些字串時停止生成。

型別:

string、array of strings 或 null

最多可以設定 4 組 stop sequences。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請輸出一段簡短說明,結尾遇到 END 就停止。"
        }
    ],
    stop=["END"],
)

當模型生成內容時,如果遇到 END,就會停止繼續生成,而且回傳內容通常不會包含這個 stop sequence。

stop 常見用途包括:

  • 限制模型不要繼續輸出後續段落。
  • 處理自訂格式的分隔符。
  • 避免模型生成下一個不該出現的區塊。
  • 模擬舊式 prompt completion 的停止條件。

例如你希望模型只輸出第一段,不要繼續產生下一個角色對話,可以設定:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請產生客服回覆,遇到「使用者:」就停止。"
        }
    ],
    stop=["使用者:"],
)

不過在 Chat Completions API 裡,很多時候你不一定需要 stop。因為 messages 本身已經用角色結構區分了 user、assistant、tool 等訊息,不像傳統 completion API 那樣需要大量依賴停止字串來切斷輸出。

另外要注意:部分最新 reasoning models 不支援 stop,所以如果你使用的是這類模型,應該先確認模型是否支援。

實務建議:

  • 一般聊天:通常不需要設定 stop。
  • 自訂文字格式:可以使用 stop。
  • 結構化輸出:優先考慮 response_format 或 JSON Schema,而不是依賴 stop。
  • 使用 reasoning models:先確認是否支援 stop。

F.5 max_completion_tokens:限制模型最多生成多少 token

max_completion_tokens 用來設定模型最多可以產生多少 completion tokens。

型別:

number or null

它是生成長度與成本控制中很重要的參數。

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請用 300 字介紹 Chat Completions API。"
        }
    ],
    max_completion_tokens=500,
)

這裡的 max_completion_tokens=500,表示模型最多可以產生 500 個 completion tokens。

要注意的是,max_completion_tokens 是 token 數,不是中文字數、英文字數或句數。Token 可以粗略理解成模型處理文字的基本單位,但它不等於一個字,也不等於一個單詞。

另外,對於支援 reasoning tokens 的模型,max_completion_tokens 的上限也可能包含 visible output tokens 和 reasoning tokens。也就是說,你設定的上限不一定全部都會變成使用者看得到的文字。

舊版參數 max_tokens 現在已經不建議新專案使用,應優先改用 max_completion_tokens。

實務建議:

  • 一般短回答:可以設定 200 到 500。
  • 長摘要或文章草稿:可以設定更高。
  • 結構化資料抽取:設定足夠容納 JSON 的長度。
  • 成本敏感功能:務必設定合理上限。
  • 新專案:使用 max_completion_tokens,不要再優先使用 max_tokens。

範例:限制客服回答不要太長

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "developer",
            "content": "你是客服助理,請用簡潔方式回答。"
        },
        {
            "role": "user",
            "content": "請問我可以如何重設密碼?"
        }
    ],
    max_completion_tokens=200,
)

範例:讓模型產生較完整的文章段落

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請寫一段 500 字左右的文章前言,主題是旅遊分帳工具。"
        }
    ],
    max_completion_tokens=900,
)

F.6 presence_penalty:降低已出現主題再次出現的機率

presence_penalty 用來根據某個 token 是否已經出現在目前生成內容中,調整模型再次使用它的機率。

型別:

number or null

範圍:

-2.0 到 2.0

正值會讓模型比較傾向談到新的主題或新的詞彙;負值則會讓模型比較不排斥回到已經出現過的內容。

可以簡單理解成:

presence_penalty 比較像是在問:「這個 token 有沒有出現過?」

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請幫我列出 10 個旅遊 App 的功能點子。"
        }
    ],
    presence_penalty=0.6,
)

這樣模型比較可能避免一直圍繞同一個功能打轉,而是提出較多不同方向的點子。

常見用途:

  • 腦力激盪。
  • 產生多樣化候選項目。
  • 避免回答一直繞著同一個主題。
  • 鼓勵模型探索新的面向。

實務建議:

使用情境presence_penalty
穩定問答0
一般創意發想0.3 到 0.8
強烈鼓勵多樣性0.8 以上
希望模型維持同一主題不建議調高

不要把 presence_penalty 當成「防止重複字句」的唯一工具。它主要影響的是模型是否傾向引入新主題,而不是單純處理同一句話重複很多次。

F.7 frequency_penalty:降低重複用詞的機率

frequency_penalty 用來根據某個 token 已經出現的頻率,調整模型再次使用它的機率。

型別:

number or null

範圍:

-2.0 到 2.0

正值會降低模型重複使用相同 token 的機率,尤其是已經出現多次的 token。

可以簡單理解成:

frequency_penalty 比較像是在問:「這個 token 已經出現幾次了?」

例如:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請寫一段產品介紹,不要一直重複產品名稱。"
        }
    ],
    frequency_penalty=0.5,
)

這樣可以降低模型在回答中反覆使用同一個詞或同一句話的機率。

presence_penalty 和 frequency_penalty 的差異可以這樣理解:

參數判斷方式主要效果
presence_penalty是否出現過鼓勵談新主題
frequency_penalty出現幾次降低重複用詞

實務建議:

使用情境frequency_penalty
一般聊天0
文章寫作0.2 到 0.6
避免重複口號或產品名0.4 到 0.8
需要保留固定術語不宜設太高

如果你的輸出需要反覆使用同一個專有名詞,例如產品名稱、API 名稱、欄位名稱,就不要把 frequency_penalty 設得太高。否則模型可能會為了避免重複而改用不精確的代稱,反而讓文章變得不清楚。

F.8 logit_bias:調整特定 token 出現機率

logit_bias 是比較進階的生成控制參數。

它可以針對特定 token ID 調整出現機率。值的範圍通常是:

-100 到 100

概念上:

  • 正值:提高該 token 出現機率。
  • 負值:降低該 token 出現機率。
  • 接近 -100:幾乎禁止該 token。
  • 接近 100:強烈鼓勵該 token。

範例形式大致會像這樣:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        {
            "role": "user",
            "content": "請輸出 yes 或 no。"
        }
    ],
    logit_bias={
        "1234": 5,
        "5678": -5
    },
)

這裡的 “1234” 和 “5678” 是 token ID,不是普通字串。

這也是 logit_bias 比較不好使用的地方:你必須先知道目標文字對應到哪些 token ID,而且同一個文字在不同 tokenizer、不同前後空白或不同語言環境下,可能會被切成不同 token。

常見用途:

  • 降低某些詞出現機率。
  • 強化特定答案選項。
  • 避免模型輸出某些格式字元。
  • 做非常細緻的輸出控制。

不過在大多數產品情境中,logit_bias 不是第一優先選項。

如果你只是想讓模型不要提到某些內容,通常可以先用:

  • developer message 明確規範。
  • response_format 限制輸出格式。
  • 後處理過濾輸出。
  • 安全與合規檢查。

只有在你真的需要 token 層級控制時,再考慮使用 logit_bias。

實務建議:

  • 一般聊天機器人:通常不用。
  • 結構化分類任務:可以考慮,但要小心 token ID。
  • 嚴格禁止特定 token:可以使用負 bias,但仍不應把它當成唯一安全機制。
  • 不熟悉 tokenizer 時:先不要用。

F.9 生成控制參數的實務組合

實務上,我通常不會一次調整所有生成控制參數,而是根據任務類型選擇少數幾個。

一般客服或 FAQ

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=0.3,
    max_completion_tokens=300,
)

特點:

  • 回答要穩定。
  • 不需要太多創意。
  • 長度要可控。

創意文案或標語發想

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=1.0,
    presence_penalty=0.5,
    max_completion_tokens=800,
)

特點:

  • 允許比較多變化。
  • 鼓勵不同方向。
  • 適合產生多個候選點子。

結構化資料抽取

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=0,
    max_completion_tokens=1000,
)

特點:

  • 要求穩定。
  • 不需要創意。
  • 通常會搭配 response_format 或 JSON Schema。

長文摘要

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=0.4,
    max_completion_tokens=1200,
)

特點:

  • 需要一定自然度。
  • 但不能太發散。
  • 需要設定足夠的輸出上限。

F.10 生成控制參數小結

整理一下:

參數用途常見建議
temperature控制隨機程度一般優先調這個
top_p控制候選 token 範圍通常不要和 temperature 同時大幅調整
n產生多個候選回答成本會增加,預設保持 1
stop遇到指定字串停止生成一般聊天少用,格式控制可用
max_completion_tokens限制最多生成 token 數控制成本與長度的重要參數
presence_penalty鼓勵模型談新主題適合點子發想
frequency_penalty降低重複用詞適合文章寫作或避免重複
logit_bias調整特定 token 機率進階用法,一般產品少用

如果你是第一次設計 Chat Completions API 請求,我建議先從這三個參數開始:

completion = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=0.7,
    max_completion_tokens=500,
)

也就是:

  • 先選好 model
  • 組好 messages
  • 設定合理的 temperature
  • 設定合理的 max_completion_tokens

等產品需求更明確後,再逐步調整 top_p、presence_penalty、frequency_penalty 或其他進階參數。

接下來,我們會介紹控制輸出格式的參數,也就是 response_format。這會影響模型回傳的是一般文字、JSON object,還是符合 JSON Schema 的結構化資料。

結語:先理解基礎參數,再進入產品級功能

到這裡,我們已經把 Chat Completions API 的基礎結構整理完了。

這一篇主要聚焦在幾個最核心的概念:

  • model 決定要使用哪一個模型。
  • messages 決定模型看見哪些對話內容與指令。
  • developer、user、assistant、tool 等 role 讓對話結構更清楚。
  • temperature、top_p、max_completion_tokens 等參數則用來控制生成結果的穩定性、發散程度與輸出長度。

如果只是要建立一個基本的 AI 對話功能,理解這些參數就已經足夠開始實作。你可以從最小可用範例出發,逐步加入 developer message、多輪對話記錄,以及適合任務的生成控制參數。

不過,當你想把 Chat Completions API 做成更完整的產品時,通常還會遇到更多需求:

  • 讓模型輸出可以被程式穩定解析的 JSON。
  • 使用 JSON Schema 限制模型回傳格式。
  • 讓模型在需要時呼叫後端工具或內部 API。
  • 讓聊天 UI 像 ChatGPT 一樣即時串流顯示文字。
  • 處理圖片、音訊或檔案等多模態輸入。

這些就不是單純調整 temperature 或 messages 就能完成的事情,而會用到 response_format、tools、tool_choice、stream、content parts 等更進階的參數。

下一篇會接著介紹:

打造專屬 ChatGPT(二):結構化輸出、Tool Calling 與 Streaming

我們會從 response_format 開始,看如何讓模型輸出 JSON 或符合 JSON Schema 的結構化資料;接著介紹 Tool Calling,讓模型可以決定何時呼叫你的後端函式;最後再整理 Streaming 串流回應,讓聊天介面可以即時顯示模型輸出。

第一篇是在建立 Chat Completions API 的基礎心智模型,第二篇就會進一步把它推向更接近正式產品的使用方式。