超越 Prompt 工程:如何用「介面契約」思維打造穩定的 Function Calling 系統

許多團隊用 LLM 的 Function Calling 串接工具,卻常陷入 Prompt 工程的迷思。然而,打造可靠 LLM 工具的關鍵,從來不只在提示詞。我們必須將其提升到「介面契約」的層次來思考,穩定性源於精細的 Schema、清晰的語義與程式端的邊界治理。

超越 Prompt 工程:如何用「介面契約」思維打造穩定的 Function Calling 系統

許多團隊用 LLM 的 Function Calling 串接工具,卻常陷入 Prompt 工程的迷思,導致系統穩定性不足。我的觀點是,打造可靠 LLM 工具的關鍵,從來不只在提示詞。我們必須將其提升到「介面契約」(Interface Contract)的層次來思考。穩定性源於精確的 Schema、清晰的語義與程式端的邊界治理。缺乏清楚契約的 Function Calling,只是將機率性的不確定,重新包裝進一個看似結構化的 JSON 裡而已。

為什麼從展示到實作,Function Calling 的穩定性總是如此脆弱?

任何嘗試過將 LLM Function Calling 導入實際產品的人,大概都有類似的經驗:展示(demo)看起來完美無瑕,但一進入實戰場景,系統就變得脆弱不堪。模型可能傳回格式錯誤的 JSON、呼叫了非預期的函式、或是生成了「語法正確但語義錯誤」的參數,導致下游系統崩潰。這之間的巨大落差,根源在於我們往往低估了大型語言模型的內在不確定性。

當我們只依賴自然語言提示詞(prompt)去引導模型,例如在 prompt 裡寫下「如果操作很危險,請先詢問使用者」,這其實是一種不可靠的口頭約定。模型或許在多數情況下會遵守,但在邊界條件或面對模糊指令時,它的行為就難以預測。根據 Zenn 上一位開發者的實務經驗分享,系統的失敗點通常很集中。這告訴我們,問題並非隨機發生,而是系統性地出現在模型與外部工具的「介面」上。

JSON Schema:它如何從單純的格式定義,躍升為與模型溝通的關鍵契約?

要解決這個問題,我們需要轉變思維:真正有效的「prompt」,不是我們寫給模型看的自然語言,而是我們提供給模型的 JSON Schema。這個 Schema 不僅僅是個格式驗證工具,它是一份與模型溝通、具備法律約束力的「技術契約」。一份定義精良的 Schema,能大幅縮減模型的「解釋空間」,從而降低犯錯的機率。

這份契約的精髓在於細節:

  • 精確的 description:每個參數的 description 欄位,是我們注入語義(semantics)的關鍵機會。它不該只是欄位名稱的同義詞,而應該清楚說明該參數的用途、預期內容、以及與其他參數的關聯。例如,與其只寫「使用者 ID」,不如寫「用來識別用戶的唯一 UUID 字串,格式為 8-4-4-4-12」。
  • 嚴格的 enum:當參數的可能值是有限集合時,務必使用 enum。這能將模型的任務從「生成一個合理的字串」簡化為「從給定清單中選擇一項」,犯錯率趨近於零。這也是OpenAI 官方文件中不斷強調的最佳實踐。
  • 善用巢狀結構與型別:透過定義物件的巢狀結構(nested objects)與明確的資料型別(integer, boolean),我們可以引導模型輸出更複雜但結構更穩定的資料。根據前述開發者的經驗,光是透過優化 Schema,就能在實作前消除將近一半的潛在格式錯誤。

將 Schema 視為契約,意味著我們不再是「請求」模型做對,而是透過結構化的方式「限制」它只能做對。

一份模糊的 Schema 是災難的開始。它等同於一份條款不清的合約,當歧義發生時,解釋權完全落在模型那一方,而承擔後果的卻是我們的應用程式。

當 Schema 不足夠時,如何用程式碼建立最後防線?

即使有完美的 Schema,我們也只能防堵「形式上」的錯誤,卻無法完全避免「語義上」的謬誤。例如,模型可能會為一個 user_id 參數生成一個格式完全正確、但實際上不存在的 ID。這時,就需要程式碼層面的邊界治理(Boundary Governance)作為最後一道防線。

這不是什麼新穎的 AI 概念,而是回歸了軟體工程的基本原則:永不信任外部輸入。從 LLM 返回的 JSON,就是一種外部輸入。我們應該在執行任何操作前,建立一個驗證與淨化(validation and sanitization)層。

一個具體的例子是處理高風險操作。與其在 prompt 中要求模型「刪除資料前要小心」,更穩健的作法是在程式碼中建立明確的分支:

if function_parameters.get('confirm_delete') is not True: # 觸發使用者確認流程,而不是直接執行 return ask_for_human_confirmation() else: # 已確認,執行刪除 execute_delete(function_parameters['target_id'])

這種設計將控制權從機率性的模型轉移到確定性的程式碼邏輯上。我們不再是「希望」模型做對,而是「強制」系統在特定條件下必須遵循特定流程。這套思維對於建構能與外部世界互動的工具增強型語言模型(Tool-Augmented Language Models)至關重要,也是打造可信賴 AI Agent 的基石。

總結來說,Function Calling 的穩定性是一項系統工程,而非單純的 prompt 藝術。它始於一份如契約般精確的 JSON Schema,並由程式碼層面的邊界治理來兜底。當我們開始用設計 API 的嚴謹態度來設計 Function Calling 的介面時,才能真正駕馭 LLM 的強大能力,而不是被它的不確定性所反噬。這也是從學術研究中的 AI Agent 概念走向商業落地的必經之路。

延伸閱讀

我是江中喬,專注於 AI Agent Architecture、Memory Governance 與 Cognitive Diversity,持續研究如何打造能夠長期協作、可信任且可治理的 AI 系統。