LLM Function Calling 完整教學:讓 AI Agent 學會使用工具的核心技術
去年底我幫公司做了一個客服 AI Agent,需要查訂單、查庫存、發退款。一開始我天真地想:「讓 LLM 直接生成 SQL 不就好了?」結果可想而知——AI 幻覺加上直接操作資料庫,差點把正式環境搞炸。後來我重新用 Function Calling 架構設計,每個操作都封裝成獨立工具,AI 只負責「決定呼叫哪個工具、傳什麼參數」,工具的執行和權限控制都由後端處理。整個系統瞬間變得安全又可控。
Function Calling(或叫 Tool Use)是打造 AI Agent 最核心的技術。今天這篇文章,我會從原理到實作,完整帶你走一遍。
什麼是 Function Calling
Function Calling 是一種讓 LLM「呼叫外部工具」的能力。簡單來說,你先告訴 LLM:「你有這些工具可以用」,然後 LLM 會根據使用者的問題,判斷要不要用工具、用哪個工具、傳什麼參數。
重點是:LLM 本身不會執行任何工具。它只是輸出一段結構化的 JSON,告訴你「我想呼叫這個函數,參數是這些」。真正的執行是你的程式負責的。這個設計非常巧妙——LLM 負責理解語意和推理,程式負責實際操作和權限控制。
如果你接觸過 LangChain Agent 功能,你可能已經間接用過 Function Calling 了。LangChain 的 Tool 抽象層底下,其實就是在用各家 LLM 的 Function Calling API。
為什麼 AI Agent 需要工具調用
LLM 本身有幾個天生的限制:
- 知識截止日期:訓練資料有時間限制,無法回答最新資訊
- 沒有執行能力:不能發 HTTP 請求、查資料庫、操作檔案
- 幻覺問題:對於需要精確數字的問題(如查詢價格、庫存),LLM 會瞎掰
- 無法與外部系統互動:不能發郵件、建立工單、更新 CRM
Function Calling 完美解決了這些問題。它讓 LLM 變成一個「指揮官」——理解使用者意圖,然後調度合適的工具去執行。這就是 AI Agent 的核心架構。搭配好的 Prompt Engineering 技巧,你可以讓 Agent 的推理更精準。
Function Calling 的運作流程
不管是 OpenAI 還是 Anthropic,Function Calling 的運作流程都是四步驟:
- 定義工具:用 JSON Schema 描述每個工具的名稱、功能說明、參數格式
- 發送請求:把使用者訊息和工具定義一起送給 LLM
- LLM 回應:LLM 判斷需要呼叫工具,回傳工具名稱和參數(JSON 格式)
- 執行 & 回傳:你的程式執行工具,把結果送回 LLM,LLM 整理後回覆使用者
整個流程是一個「對話循環」:使用者提問 → LLM 判斷要用工具 → 你執行工具 → 結果送回 LLM → LLM 回覆使用者。如果一個問題需要多個工具,這個循環會重複多次。
OpenAI API 實作範例
來看實際的程式碼。先從最基本的 OpenAI Function Calling 開始:
import openai
import json
# 步驟一:定義工具
tools = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "查詢訂單的目前狀態,包含物流追蹤資訊",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "訂單編號,格式為 ORD-XXXXXX"
}
},
"required": ["order_id"]
}
}
},
{
"type": "function",
"function": {
"name": "search_products",
"description": "搜尋商品目錄,回傳符合條件的商品清單",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜尋關鍵字"
},
"category": {
"type": "string",
"enum": ["electronics", "clothing", "food"],
"description": "商品類別篩選"
},
"max_price": {
"type": "number",
"description": "最高價格篩選(新台幣)"
}
},
"required": ["query"]
}
}
}
]
# 步驟二:發送請求
client = openai.OpenAI()
messages = [
{"role": "system", "content": "你是一個電商客服助理。"},
{"role": "user", "content": "我的訂單 ORD-123456 到哪了?"}
]
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto" # 讓 LLM 自己決定要不要用工具
)
# 步驟三:處理 LLM 的回應
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# 步驟四:執行工具
if func_name == "get_order_status":
result = get_order_status(**func_args) # 你的函數
# 把結果送回 LLM
messages.append(message)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
# 再次呼叫 LLM,讓它整理結果
final = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools
)
print(final.choices[0].message.content)
工具定義中的 description 非常重要——LLM 靠這個描述來判斷什麼時候該用這個工具。描述越清楚,LLM 的判斷越準確。
Anthropic Claude Tool Use 差異
Anthropic 的 Claude 也支援 Tool Use,但 API 格式稍有不同:
import anthropic
client = anthropic.Anthropic()
# Claude 的工具定義格式
tools = [
{
"name": "get_order_status",
"description": "查詢訂單的目前狀態",
"input_schema": { # 注意:Claude 用 input_schema,不是 parameters
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "訂單編號"
}
},
"required": ["order_id"]
}
}
]
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "查一下 ORD-123456"}]
)
# Claude 的回應格式:content 是一個 list
for block in response.content:
if block.type == "tool_use":
tool_name = block.name
tool_input = block.input # 已經是 dict,不需要 json.loads
tool_use_id = block.id
主要差異在於:Claude 用 input_schema(而不是 parameters),回應的 content 是一個 block list,工具呼叫的 input 已經是 dict 不需要再 parse。概念完全一樣,只是格式不同。
如果你想要更標準化的工具調用方式,可以看看 MCP 協議教學,它定義了一個跨 LLM 的標準工具介面。
tool_choice 參數與平行調用
tool_choice 參數控制 LLM 使用工具的行為:
"auto":LLM 自己決定要不要用工具(最常用)"none":禁止使用工具,強制用文字回答"required":強制必須使用至少一個工具{"type": "function", "function": {"name": "xxx"}}:強制使用指定的工具
OpenAI 和 Claude 都支援平行工具調用(Parallel Tool Calls)。例如使用者問「我的訂單 A 和訂單 B 分別到哪了?」,LLM 會一次回傳兩個 tool_call,你可以平行執行它們,加快回應速度。
如果你不想要平行調用(例如工具之間有依賴關係),OpenAI 可以設定 parallel_tool_calls=False。
Agent Loop 模式
真正的 AI Agent 不只呼叫一次工具。它需要一個循環:觀察 → 思考 → 行動 → 觀察結果 → 再思考 → 再行動……直到任務完成。這就是 Agent Loop:
def agent_loop(user_message, tools, max_iterations=10):
messages = [
{"role": "system", "content": "你是一個能使用工具的 AI 助理。"},
{"role": "user", "content": user_message}
]
for i in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message)
# 如果沒有工具呼叫,表示 Agent 完成了
if not message.tool_calls:
return message.content
# 執行所有工具呼叫
for tool_call in message.tool_calls:
result = execute_tool(tool_call.function.name,
json.loads(tool_call.function.arguments))
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
return "達到最大迭代次數,任務未完成。"
這個 max_iterations 很重要——防止 Agent 陷入無限循環。在正式環境中,你還需要加上 token 用量追蹤和成本上限。
想做更複雜的多 Agent 協作?可以看看 CrewAI 多 Agent 系統,它把 Agent Loop 封裝得更完整。
安全性考量與最佳實踐
Function Calling 很強大,但也帶來安全風險。以下是我在正式環境踩過坑後整理的建議:
1. 最小權限原則:每個工具只給它需要的最小權限。查詢訂單的工具不應該有修改訂單的權限。
2. 參數驗證:永遠不要相信 LLM 給的參數。在執行工具之前,做完整的輸入驗證:
def get_order_status(order_id: str):
# 永遠驗證參數!
if not re.match(r'^ORD-\d{6}$', order_id):
return {"error": "無效的訂單編號格式"}
# 檢查權限:這個使用者有沒有權限查這筆訂單?
if not user_can_access_order(current_user, order_id):
return {"error": "無權限查看此訂單"}
return db.get_order(order_id)
3. 敏感操作需要確認:刪除、退款、轉帳等操作,不要讓 Agent 自動執行。加一個確認步驟,讓使用者明確同意。
4. 限制工具數量:工具太多會讓 LLM 混淆。如果你有幾十個工具,考慮分層:先讓 LLM 選擇工具類別,再從子集中選具體工具。
5. 工具描述要精確:模糊的描述會導致 LLM 誤判。與其寫「處理訂單相關操作」,不如寫「查詢指定訂單編號的物流狀態和預計到貨日期」。
6. 監控和日誌:記錄每一次工具呼叫的輸入和輸出。出問題時,這些日誌是你 debug 的救命稻草。
7. 設定超時和重試:外部 API 可能會慢或掛掉。給每個工具設定合理的超時時間,失敗時回傳友善的錯誤訊息(不是 stack trace)。
Function Calling 是 AI Agent 的基礎建設。一旦你掌握了這個技術,就能開始打造各種有趣的應用——自動客服、智能助理、資料分析機器人,可能性是無限的。建議你先從一兩個簡單的工具開始,慢慢增加複雜度。最重要的是永遠把安全性放在第一位。
繼續閱讀
AI Agent 多工具調度教學:MCP 多 Server 整合與 Token 成本優化實戰
相關文章
AI Agent 多工具調度教學:MCP 多 Server 整合與 Token 成本優化實戰
學習 AI Agent 多工具調度架構,掌握 MCP 多 Server 整合、動態工具載入與 Token 成本優化策略,立即提升你的 Agent 生產效率。
Microsoft Agent Framework 完整教學:用 AutoGen 與 Semantic Kernel 打造多 Agent AI 系統
Microsoft 將 AutoGen 與 Semantic Kernel 整合為全新的 Agent Framework,同時支援 LLM 驅動與確定性工作流編排。本文完整介紹其核心架構、Graph-based Workflow、多 Agent 協作模式與企業級整合能力,含 Python 實作範例。
你可能也喜歡
探索其他領域的精選好文