developers.openai.com/api/docs/guides/function-calling,2026年6月資料),兩個端點的示例均可直接複製執行。
完整呼叫迴圈
1
定義 tools
把函式名、用途描述、引數 JSON Schema 隨請求發給模型
2
模型返回函式呼叫
模型判斷需要呼叫時,返回函式名和 JSON 格式的引數
3
本地執行
你的程式碼解析引數、真正執行函式(查資料庫、調外部 API……)
4
回傳結果
把執行結果連同歷史一起再發一次請求,模型基於結果生成最終回答
兩個端點的關鍵格式差異
同一個功能,/v1/chat/completions 和 /v1/responses 的欄位格式不一樣,這是接入時最容易踩的坑:
Chat Completions 完整示例
以查天氣為例,走完”定義 → 呼叫 → 執行 → 回傳”全迴圈:Responses 完整示例
注意三處不同:tools 定義是扁平的、呼叫以頂層function_call item 返回、回傳用 function_call_output。配合 previous_response_id,第 2 次請求不必重發全部歷史:
strict 嚴格模式(結構化輸出)
strict: true 讓模型輸出的引數嚴格符合你的 JSON Schema,杜絕幻覺欄位和缺欄位。三個要求:
- Schema 裡必須有
"additionalProperties": false - 所有欄位都要出現在
required裡(可選語義用"type": ["string", "null"]表達) - 只能用受支援的 JSON Schema 子集(基本型別、enum、陣列、巢狀物件等)
parallel_tool_calls 與 tool_choice
並行呼叫
parallel_tool_calls 預設開啟,模型可以在一輪裡同時請求多個函式(如同時查北京和上海的天氣)。逐個執行後全部回傳再發起下一次請求,每個結果都要帶對應的 call_id(responses)或 tool_call_id(chat)配對。
tool_choice 控制策略
allowed_tools 限定子集
工具很多但本輪只想開放一部分時,用tool_choice 的 allowed_tools 形式限定可呼叫子集 —— 它不改變 tools 列表本身,因此不破壞 快取 的穩定字首:
流式中的函式呼叫
Chat Completions:按 index 拼接
函式引數在流式裡是分片下發的,按index 累加 arguments 字串,流結束後再 json.loads:
Responses:監聽語義事件
response.function_call_arguments.delta 事件攜帶引數增量,response.function_call_arguments.done 給出完整引數,無需自己按 index 拼。
最佳實踐與踩坑
寫好工具定義:- 函式名和 description 是寫給模型看的:說清楚”什麼時候該調我”,比如
"獲取即時天氣,僅當用戶明確詢問天氣時呼叫" - 引數用 enum 收窄:能列舉就別用自由字串,幻覺引數會少一大半
- 工具定義放 prompt 前部且保持穩定:tools 會參與快取字首比對,定義穩定 = 輸入費打 1 折(見 快取計費)
- Agent 迴圈設最大輪數:避免模型在”調函式 → 回傳 → 又調函式”裡打轉燒錢