OpenAI API 函數調用(function calling)怎麼寫:tools 定義、function_call_output 回傳、strict 模式

想讓模型調用你自己的函數查天氣、查訂單?Responses API 裏在 tools 中聲明函數,模型返回 function_call,你執行後用 function_call_output 把結果發回去。本文給 Python 和 Node 完整示例,講 strict、tool_choice、並行調用,和官方的最佳實踐。

NNathaniel bigo··原創首發·AI 輔助撰寫
9 分鐘讀完
資料核對於 2026-11-05 · 依據官方文檔與公開資料整理 其他 帳號
本文根據 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。

結論先說

  1. 模型自己不會執行你的函數。 它只會返回“我想調用某函數、參數是什麼”,真正執行的是你的程序。
  2. 一次完整調用要兩次請求以上:第一次帶 tools,第二次把函數結果帶回去,才能得到最終回答。
  3. 函數用 JSON schema 描述,字段是 type、name、description、parameters、strict。
  4. 官方建議始終開啟 strict,讓調用嚴格符合你的 schema;開啟後要求每個對象 additionalProperties 為 false,且所有字段都在 required 裏。
  5. 回傳結果用 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 和並行調用

tool_choice 的設定:auto、required、指定函數、allowed_tools、none

圖:本站根據 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

Nathaniel 的更多內容

  1. 01

    Claude Code 在 Windows 上的常見坑:Git Bash 還是 PowerShell、路徑反斜槓、假報錯、WSL 怎麼選

    Windows 上用 Claude Code,裝好之後最容易踩的是:用哪個 shell、路徑寫法不一致、grep 沒匹配就報錯、鉤子沒生效、WSL 和原生怎麼選。本文逐條按官方文檔整理原因和處理辦法,附三段提示詞和一張對照表。

    Claude0
  2. 02

    Claude Code Hooks 實戰「提交前自動跑測試」:PreToolUse 攔住 git commit,測試不過就退出碼 2,附 Windows 注意點

    只寫一個完整例子:讓 Claude Code 每次要執行 git commit 之前,先自動跑項目測試,沒通過就攔下並把輸出交給它修。本文按官方 Hooks 文檔給出腳本、settings.json 配置、測試方法、排錯和 Windows 的兩處坑。

    Claude0
  3. 03

    Claude Code 自定義斜槓命令與 Skill 實戰:從零寫一個「生成更新日誌」的 /release-notes,含傳參、預執行命令和調試

    概念看過了,還是不知道從哪下手?本文按 Claude Code 官方「Extend Claude with skills」寫一個完整可用的例子:用 /release-notes 根據 git 記錄生成更新日誌,覆蓋目錄、frontmatter、傳參、預執行命令、預授權和調試。

    Claude0
  4. 04

    Claude Code 部署網站:先寫 Dockerfile 和 compose 在本機跑通,再按清單上雲伺服器,別讓它直接改線上

    想讓 Claude Code 幫你把網站部署到雲伺服器。本文只寫通用做法,按 Docker 官方文檔講:讓它寫 Dockerfile、.dockerignore 和 compose,在本機跑通,端口和數據卷怎麼設,再給出上線清單,並說明為什麼不要讓它直接動線上機器。

    Claude0
  5. 05

    Claude Code 寫爬蟲與數據清洗:先查 robots.txt 和網站條款,控制頻率,原始數據留一份再清洗

    想讓 Claude Code 寫爬蟲抓數據再清洗。本文先講合規:robots.txt 不是授權也不是安全措施、網站條款要自己讀;再講怎麼用 Python 標準庫檢查規則、小樣本先試、儲存原始數據,以及用 pandas 清洗,附四段提示詞。

    Claude0
  6. 06

    Claude Code 寫 Chrome 擴展:按 Manifest V3 起步,加載未打包的擴展,改了哪些文件要重新加載

    想讓 Claude Code 幫你寫一個 Chrome 擴展。本文按 Chrome 官方擴展文檔講:manifest.json 的最小寫法、在 chrome://extensions 加載未打包的擴展、哪些改動要刷新、怎麼看控制檯和報錯,再給四段提示詞,以及權限要盡量少。

    Claude0

同產品的其他教學

  1. 01

    OpenAI API 的 token 怎麼算、怎麼估算費用:input_tokens 計數接口、tiktoken 和隱藏的輸出 token

    發請求前想知道會用多少 token?官方有 Responses 的 input_tokens 計數接口,能把文字、圖片、文件、工具定義一起算準;本地 tiktoken 只適合純文本。本文給 Python 和 Node 示例,講輸出 token 為什麼可能比看到的多,以及怎麼估算費用。

    ChatGPT0
  2. 02

    OpenAI API Node.js / TypeScript 快速上手:npm install openai、example.mjs 第一個請求,到流式、函數調用、聯網搜尋

    用 Node.js 調 OpenAI API:設定 OPENAI_API_KEY 環境變量,npm install openai,新建 example.mjs,用 client.responses.create 發出第一個請求。並列出圖片、文件、流式、函數調用、聯網搜尋和錯誤捕獲的 Node 寫法。

    ChatGPT0
  3. 03

    OpenAI API 用量層級(usage tiers)與速率限制怎麼提升:Free、Build、Launch、Grow 和後台 Limits 頁

    OpenAI API 的限速不是固定的:官方按累計購買額度把組織分成 Free、Build、Launch、Grow 四個層級,達到門檻自動升級。本文講 RPM、TPM 等指標、怎麼在後台查自己的限額、響應頭怎麼讀、花費上限和限速的區別,以及怎麼讓限額變得夠用。

    ChatGPT0
  4. 04

    OpenAI API 報錯 400、401、403、404、429、500、503 怎麼排查:按官方錯誤碼頁逐個看原因和解決辦法

    調用 OpenAI API 返回 400、401、403、404、429、500、503,各自什麼意思?本文按官方 Error codes 頁,每個狀態碼一節,寫清官方給的原因和解決辦法,並說明 404 在官方頁面裏的位置、429 的六種情形,附 Python 和 Node 的錯誤捕獲寫法。

    ChatGPT0
  5. 05

    OpenAI Realtime API 是什麼:語音到語音會話、WebRTC 與 WebSocket、臨時密鑰和事件機制

    Realtime API 讓模型直接處理音頻,做可以隨時打斷的語音助手。本文按官方文檔講它是什麼、什麼時候用、瀏覽器接入的流程、session 與事件、可用聲音、60 分鐘會話上限、安全標識,以及它和轉寫、文字轉語音的分工。

    ChatGPT0
  6. 06

    OpenAI 圖像生成 API 怎麼用:gpt-image 系列、images.generate 與 Responses 工具、尺寸質素和遮罩編輯

    用 OpenAI API 生成或編輯圖片,有 Image API 和 Responses 裏的 image_generation 工具兩條路。本文按官方文檔給 Python 和 Node 示例,講 gpt-image 模型選擇、尺寸質素格式參數、遮罩編輯、被攔截時的錯誤處理,以及需要組織驗證的提醒。

    ChatGPT0

0 條評論

登入 後參與評論

還沒有評論,來搶沙發~