白話理解 ChatGPT API 的函式呼叫功能 (function calling)
2025年1月6日
所謂函式呼叫,就是讓你把外部函式的形狀寫入 OpenAI API,這樣 OpenAI API 就能輸出對的格式來呼叫你的函式。
以下我們會用「取得天氣資料」的例子來了解如何使用這個函式呼叫(function calling) 功能。
傳統方式的限制
當你使用 ChatGPT 或 OpenAI 的 API 詢問類似 「台北目前天氣如何」的問題時,若 API 無法即時連網,假設不是即時連網回答模式,API 這時可能會回你
- 亂回答的內容
- 或是回答「訓練資料只到 20XX 年」這類無法即時回應的資訊
若想要解決這個問題,開發者需搭配外部 API,例如天氣 API。但過去的方法可能出現以下問題:
- 格式不一致:即使在 prompt 中要求輸出 JSON,ChatGPT 仍可能加入「好的,以下是 JSON 字串的輸出」這類多餘的文字
- 格式錯誤導致整合失敗:不符合 API 格式的輸出會讓整個流程中斷
函式呼叫功能正是為了解決這些問題而設計,透過明確定義格式,讓 OpenAI API 與外部 API 互動。
在開始程式碼範例之前,我們先看以下為函式呼叫(function calling)的流程示意圖:
函式呼叫的解決方案
使用函式呼叫功能時,OpenAI API 會依據定義好的格式,直接輸出符合需求的內容,避免多餘文字或格式錯誤。
假設有一個天氣 API,其需要輸入格式要有兩個參數:
- 地點(location):字串
- 單位(unit):需要是攝氏(celsius)或華氏(fahrenheit)
範例函式:
function getWeatherAPI({ location, unit }) {
// API 處理邏輯
}
建立函式定義
首先,建立函式定義來描述外部函式的結構與參數。
import { OpenAI } from "openai";
const openai = new OpenAI();
// 定義工具
const tools = [
{
// type 為 functions
type: "function",
function: {
name: "get_weather",
// 定義要回傳的格式
parameters: {
type: "object",
properties: {
location: { type: "string" },
unit: {
type: "string",
enum: ["celsius", "fahrenheit"],
},
},
},
},
},
];
呼叫 OpenAI 的 API
利用上述工具定義,呼叫 OpenAI API 並傳入相關參數。
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "現在在台北的天氣如何?" }],
tools,
});
console.log(response.choices[0].message.tool_calls);
OpenAI API 的回應可能如下:
[
{
id: "call_12345xyz",
type: "function",
function: {
name: "get_weather",
arguments: '{"location":"Taipei", "unit": "celsius"}',
},
},
];
呼叫天氣 API
這時就可以直接使用 OpenAI 的 API 回應的 arguments,
{
"location": "Taipei",
"unit": "celsius"
}
接著呼叫外部的天氣 API 、外部的天氣 API 並返回結果,獲取最新的天氣資訊。例如回覆:
{
"temperature": 22,
"unit": "celsius",
"description": "Sunny"
}
回傳給 OpenAI API
最後再將結果回傳給 OpenAI API,讓 OpenAI API 最後生成自然語言回覆。
curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "現在在台北的天氣如何?"},
{"role": "assistant", "content": null, "function_call": {"name": "get_current_weather", "arguments": "{ \"location\": \"Taipei\"}"}},
{"role": "function", "name": "get_current_weather", "content": "{\"temperature\": 22, \"unit\": \"celsius\", \"description\": \"Sunny\"}"}
],
"functions": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
]
}'
此時,OpenAI API 的回應可能是:
{
"id": "chatcmpl-123",
...
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "台北目前的天氣為 22 度",
},
"finish_reason": "stop"
}]
}
結語
在了解完函式呼叫功能後,大概可以更理解 OpenAI 的未來策略,如同執行長 Sam Altman 先前提到的,不會是再去做 ChatGPT 這種應用;而是會以平台的角度出發。
函式呼叫能讓外部工具更好與 OpenAI API 整合,這會讓 OpenAI 變得更有價值。身為企業或開發者,假如今天 Anthropic Claude 或 Google 的 Gimini 的成果追上 OpenAI 了,企業與開發者還可以選擇能有更好整合性的。