National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 15

工具呼叫

tool_calls 的來回流程、參數驗證與錯誤回傳
Interaction實作 30 minute(s)

Learning Objectives

  • 定義工具:名稱、用途說明與參數的 JSON Schema
  • 走完一次完整來回:模型提出呼叫、程式執行、結果以 tool 訊息放回、模型回答
  • 說明模型只提出呼叫,真正執行的是你的程式
  • 驗證參數,並把工具的錯誤回傳給模型
  • 處理模型一次要求多個工具的情況

模型查不到的東西,由程式去查

模型只會產生文字。它不知道你今天的課表,也改不了校務系統裡的資料。要讓它用到這些東西,就要讓它能「請求」你的程式去做:這就是工具呼叫(tool calling,也叫 function calling)。

這一課的情境是校園助手,資料來自虛構的《優學大學學生手冊》,不是任何學校的規定;學號、課表也都是假的,工具全部是範例裡的 Python 函數,不連外。

先記住最重要的一句話:

模型只是提出呼叫,執行的是你的程式。

模型回傳的只是一段「我想呼叫這個函數,參數是這些」的資料。要不要執行、怎麼執行、把什麼結果告訴它,全部由你的程式決定。第 17、18 課談安全時,都建立在這一點上。

逐步看:模型提出一個工具呼叫

程式只呼叫模型一次,還沒有執行任何工具。請看模型這次回傳的和第 7 課有什麼不同。

參數的定義會影響模型怎麼填

上面的 keyword 只寫了「要查的關鍵字」,模型實際填的是 停修 一學期 最多 幾門 課。Schema 只限制型別,內容還是模型依說明猜的。

strict 模式的要求(OpenAI 文件):每個物件都要 additionalProperties: false,properties 裡的欄位全部要列在 required;要讓欄位可省略,就在型別加上 null。Chat Completions 預設不是 strict,要自己打開。

內容只有固定幾種時,用 enum 列出來最可靠。下一個範例把主題寫成 enum,模型就只能從這幾個值裡選:

"properties": {"topic": {"type": "string", "enum": ["停修", "圖書館借閱", "宿舍訪客"]}}

逐步看:完整的一次來回

這次把流程走完:提出呼叫、執行、放回結果、再問一次。注意 messages 怎麼一路變長,模型總共被呼叫了兩次。

一次來回的訊息順序

順序 role 誰寫的 內容
1 user 使用者 一學期最多可以停修幾門課?
2 assistant 模型 content 是空的,tool_calls 提出 search_handbook
3 tool 你的程式 tool_call_id 對應第 2 則,content 是查到的條文
4 assistant 模型 一學期最多可以停修 1 門課……

模型每一輪都不記得上一輪(第 7 課),所以第 2、3 則都要放進 messages 重新送出。工具結果要多長,也就多花多少輸入 token,所以工具不要回傳用不到的欄位。

逐步看:工具出錯時,把錯誤告訴模型

使用者把學號打成小寫。我們的函數會丟出例外。先猜猜看:模型收到錯誤訊息後,會自己改成大寫重試,還是回頭問使用者?

錯誤要回傳給模型,而且要寫得讓它看得懂

上面錄到的結果是:模型沒有自己把 b1123456 改成大寫,而是回覆使用者「請提供 1 個大寫英文字母加 7 位數字的學號」。你可能以為它會自己改成大寫,但錄到的不是這樣;我們的錯誤訊息也沒有說可以自己改。

工具出錯時有兩種常見寫法:

寫法 結果
讓例外往外丟,整支程式中斷 使用者只看到系統錯誤
接住例外,把錯誤內容當成工具結果回傳 模型可以改參數重試,或用白話告訴使用者

錯誤訊息要寫清楚哪裡錯、正確的格式是什麼。不要把程式內部的資訊(資料庫路徑、堆疊追蹤、金鑰)放進去:回傳給模型的內容可能會出現在回答裡。

另一件要記得的事:模型填的參數不可以當作已驗證的資料。 例如 student_id 是模型從對話裡讀來的,程式應該用登入者的身分去查,不是誰說自己是誰就查誰。第 17 課會再談。

逐步看:一次要求多個工具

一句話問了兩件事。請看 tool_calls 有幾個元素,以及少回一則 tool 訊息時 API 怎麼回應。

實作:派送工具呼叫

完成 dispatch(call):依呼叫的名稱執行對應的函數,回傳一則 tool 訊息。這題不呼叫模型,make_call 做出和 SDK 相同寫法的呼叫物件。

content 一律是 JSON 字串:成功時是 {"result": 結果},失敗時是 {"error": 訊息}。要處理這四種失敗,不可以讓程式中斷:

情況 怎麼發現 error 的內容
工具不存在 名稱不在 TOOLS 裡 未知的工具:名稱
參數不是 JSON json.JSONDecodeError 參數不是合法的 JSON
參數和函數對不上 TypeError 參數不符合工具的定義
工具自己回報錯誤 ValueError 例外本身的訊息
你的輸出
預期輸出

小測驗:工具呼叫

1.

模型回傳 finish_reason 是 tool_calls 時,那個工具執行了嗎?

2.

call.function.arguments 的型別是什麼?

3.

把工具結果放回 messages 時,下列哪一則是正確的?

4.

模型一次提出 2 個工具呼叫,你只回了第 1 個的結果就送出下一次請求,會怎樣?

5.

工具的函數丟出例外(例如學號格式錯誤),比較好的做法是什麼?

第 1 次作答

重點整理

  • 模型只提出呼叫,執行的是你的程式;要不要執行,由程式決定。
  • 流程:送出 tools → 模型回 finish_reason: tool_calls → 解析 arguments(JSON 字串)→ 執行 → 以 role: tool 和 tool_call_id 放回 → 再呼叫一次。
  • Schema 管得到型別與格式,管不到內容對不對;參數要在工具裡再驗證。內容只有固定幾種時用 enum。
  • 工具出錯要回傳清楚的錯誤訊息給模型,不要讓程式中斷,也不要放內部資訊。
  • 模型可能一次要求多個工具,每個呼叫都要有一則 tool 訊息。

下一課: 很多任務要查好幾次才做得完,例如先查課表、再查每門課的缺課紀錄。把這個來回放進迴圈,讓模型自己決定下一步,就是 Agent。

這一課完成了!
Next lesson:Agent 迴圈
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。