本文根據 OpenAI 官方《Function calling》整理,資料核對於 2026-11-05。配圖為本站整理的示意圖,不是介面截圖。代碼裏的模型名取自官方當天示例,請以官方模型頁為準。本站(bigolab.com)不是 OpenAI 官方網站。API 是按用量計費的獨立服務,與 ChatGPT 訂閱分開計算,Key 的獲取見 /guides/openai-api-key。
適用於誰
- 想讓模型“動手”的開發者:查數據庫、查天氣、查訂單、發電郵,由模型決定調不調、傳什麼參數;
- 已經能發出第一個請求(見 /guides/openai-api-python-quickstart),但沒寫過工具調用的人;
- 對 Responses 請求格式還不熟的人,可以先看 /guides/openai-responses-api。
結論先說
- 模型自己不會執行你的函數。 它只會返回“我想調用某函數、參數是什麼”,真正執行的是你的程序。
- 一次完整調用要兩次請求以上:第一次帶
tools,第二次把函數結果帶回去,才能得到最終回答。 - 函數用 JSON schema 描述,字段是
type、name、description、parameters、strict。 - 官方建議始終開啟
strict,讓調用嚴格符合你的 schema;開啟後要求每個對象additionalProperties為false,且所有字段都在required裏。 - 回傳結果用
function_call_output,必須帶上對應的call_id,否則模型對不上是哪一次調用。

圖:本站根據 OpenAI 官方《Function calling》 整理的示意圖
一、先認識三個詞
官方用三個詞解釋:
- 工具(tool):你告訴模型“你可以用”的能力,比如
get_weather,參數是location; - 工具調用(tool call):模型看了提示後,認為要完成任務就得用某個工具,於是返回的一種特殊響應;
- 工具調用輸出(tool call output):你的程序執行後產生的結果,可以是 JSON 或純文本,並要引用具體那次調用的
call_id。
官方還區分:函數是用 JSON schema 定義的一種工具;除此之外還有處理自由文本的自定義工具,以及平台內置工具(聯網搜尋、代碼解釋器、MCP 等)。本文只講函數。
二、定義函數
函數通常放在每次請求的 tools 參數裏。官方給的字段:
| 字段 | 含義 |
|---|---|
type | 固定寫 function |
name | 函數名,例如 get_weather |
description | 什麼時候用、怎麼用 |
parameters | 用 JSON schema 定義的參數 |
strict | 是否開啟嚴格模式 |
示例(Python 字典寫法,布爾值是 True、False):
python
tools = [
{
"type": "function",
"name": "get_weather",
"description": "查詢某個城市當前的天氣。",
"strict": True,
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和國家,例如 Bogota, Colombia",
},
"units": {
"type": ["string", "null"],
"enum": ["celsius", "fahrenheit", None],
"description": "溫度單位,不確定時傳 null",
},
},
"required": ["location", "units"],
"additionalProperties": False,
},
}
]
這裏 units 是可選參數,但在 strict 模式下仍然要列進 required,用 ["string", "null"] 表示可以為空,這是官方說明的寫法。enum 裏加 None 是本站為了讓枚舉與 null 類型一致做的補充,官方示例只寫了兩個單位,如遇校驗報錯以官方當天文檔為準。
三、完整示例:Python
下面的結構對應官方五步。函數是本站寫的假數據,只為演示流程:
python
import json
from openai import OpenAI
client = OpenAI()
def get_weather(location, units=None):
# 這裏應當換成真正查天氣的代碼
return {"location": location, "temperature": 25, "unit": units or "celsius"}
input_list = [{"role": "user", "content": "巴黎今天天氣怎麼樣?"}]
# 1. 帶着 tools 發第一次請求
response = client.responses.create(
model="gpt-6-astra", # 以官方模型頁當天為準
tools=tools,
input=input_list,
)
# 保留模型輸出,下一次請求要一起帶上
input_list += response.output
# 2~4. 找出 function_call,執行,把結果加進 input
for item in response.output:
if item.type == "function_call" and item.name == "get_weather":
args = json.loads(item.arguments)
result = get_weather(**args)
input_list.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result, ensure_ascii=False),
})
# 5. 帶着結果再請求一次,拿最終回答
response = client.responses.create(
model="gpt-6-astra",
tools=tools,
input=input_list,
)
print(response.output_text)
三個要點:
item.arguments是 JSON 字符串,要自己json.loads;call_id必須原樣帶回;- 官方說推理模型返回的推理項在回傳結果時也必須一起傳回,上面“整體加入
response.output”的寫法就滿足這一點。
四、完整示例:Node.js
儲存為 .mjs 文件運行。官方 Node 示例還用到一個 toResponseInputItems 輔助函數來整理輸出,這裏為了簡潔,直接展開 response.output;這一處是本站改寫,若你的 SDK 版本提示類型不符,請按官方當天示例使用輔助函數。
javascript
import OpenAI from "openai";
const openai = new OpenAI();
const tools = [
{
type: "function",
name: "get_weather",
description: "查詢某個城市當前的天氣。",
strict: true,
parameters: {
type: "object",
properties: {
location: { type: "string", description: "城市和國家" },
},
required: ["location"],
additionalProperties: false,
},
},
];
function getWeather(location) {
return { location, temperature: 25, unit: "celsius" }; // 換成真實查詢
}
const input = [{ role: "user", content: "巴黎今天天氣怎麼樣?" }];
let response = await openai.responses.create({
model: "gpt-6-astra", // 以官方模型頁當天為準
tools,
input,
});
input.push(...response.output);
for (const item of response.output) {
if (item.type !== "function_call") continue;
if (item.name === "get_weather") {
const { location } = JSON.parse(item.arguments);
input.push({
type: "function_call_output",
call_id: item.call_id,
output: JSON.stringify(getWeather(location)),
});
}
}
response = await openai.responses.create({
model: "gpt-6-astra",
tools,
input,
});
console.log(response.output_text);
五、一次可能有多個調用
官方提醒:模型的響應裏可能有零個、一個或多個函數調用,所以最好假定會有多個。官方的示例裏,一次響應同時包含兩個 get_weather 和一個 send_email。寫法上就是上面那個 for 循環:遍歷 output,每遇到一個 function_call 就執行一次,各自回傳帶自己 call_id 的結果。
如果函數沒有返回值(比如發電郵),官方建議回一個表示成敗的字符串,例如 "success"。如果函數要返回圖片或文件,可以傳圖片或文件對象的數組而不是字符串。
六、strict、tool_choice 和並行調用

圖:本站根據 OpenAI 官方《Function calling》 整理的示意圖
strict:設為 true 時,調用會可靠地符合 schema,而不是盡力而為。條件是每個對象 additionalProperties 設為 false、所有 properties 都列在 required。如果你發了 strict: true 但 schema 不滿足,請求會被拒絕並說明缺了哪些約束。官方還說:省略 strict 時,Responses 會盡量把 schema 歸一化成嚴格模式,做不到才回退成非嚴格;想保持非嚴格要顯式寫 strict: false。
tool_choice:預設 auto。required 表示必須調用一個或多個函數;也可以強制調用某個指定函數;allowed_tools 能限定可調用的子集,官方說這樣做不用改動傳入的工具列表,有利於提示詞緩存省錢;設 none 等於沒傳函數。
並行:模型一輪裏可能調多個函數。設 parallel_tool_calls 為 false 可保證每輪最多零個或一個調用。
七、官方的幾條寫法建議
- 函數名、參數說明寫清楚,說明格式和輸出含義;
- 用枚舉和對象結構避免非法狀態,官方舉例
toggle_light(on, off)就允許出現不合法的調用; - 已經知道的參數別讓模型填,比如你手裏已有
order_id,就在代碼裏傳,不要做成參數; - 總是連續調用的函數,合併成一個;
- 一開始可用的函數盡量少,官方軟性建議少於 20 個。
還有一點和費用有關:官方說函數定義會佔上下文,並按輸入 token 計費,函數多或描述長時要注意。價格以官方價格頁當天為準,見 /guides/openai-api-price-official-table。
常見問題
Q:模型返回了函數調用,為什麼 output_text 是空的?
正常。這一輪模型的輸出是 function_call 項,不是文字。執行函數、回傳結果後的那次請求才有最終文字。
Q:想邊生成邊顯示函數參數?
官方說流式也支持函數調用,會出現 response.function_call_arguments.delta 之類的事件,基礎寫法見 /guides/openai-api-streaming。
Q:我要的是固定格式的 JSON 回答,不是調函數?
那是結構化輸出,見 /guides/openai-api-structured-outputs。
Q:請求被限流了?
見 /guides/openai-api-429-error。
參考資料
- OpenAI 官方:Function calling — https://developers.openai.com/api/docs/guides/function-calling
0 條評論
還沒有評論,來搶沙發~