目錄
Ollama 工具呼叫(Function Calling)教學
語言模型不會知道今天的天氣、你的資料庫裡有什麼,也不擅長精確計算。工具呼叫(tool calling,也叫 function calling)讓模型可以「請你的程式幫忙執行某個函式」,再根據結果回答。
只有支援工具的模型可以使用,在 ollama.com 的模型頁面上會標示 tools,例如 qwen3、llama3.1、gpt-oss、mistral。
運作流程
1. 你:問題 + 可用工具的說明 ──────────▶ 模型
2. 模型:「請呼叫 get_weather(city="台北")」◀──
3. 你的程式執行 get_weather("台北") → "24°C,多雲"
4. 你:把結果送回 ─────────────────────▶ 模型
5. 模型:「台北現在 24 度、多雲,建議帶件薄外套。」
模型本身不會執行任何程式,它只是決定要呼叫哪個工具、帶什麼參數。真正執行的是你的程式,所以你可以完全控制它能做什麼。
Python 範例
ollama Python 套件可以直接把 Python 函式當作工具傳入,會自動從函式的型別標註和 docstring 產生工具說明:
from ollama import chat
def get_weather(city: str) -> str:
"""
查詢城市目前的天氣。
Args:
city: 城市名稱,例如「台北」
Returns:
天氣描述
"""
fake_data = {"台北": "24°C,多雲", "高雄": "29°C,晴天"}
return fake_data.get(city, "查無資料")
tools = {"get_weather": get_weather}
messages = [{"role": "user", "content": "台北和高雄現在天氣如何?"}]
response = chat(model="qwen3:8b", messages=messages, tools=[get_weather])
messages.append(response.message)
# 模型可能一次要求呼叫多個工具
for call in response.message.tool_calls or []:
fn = tools[call.function.name]
result = fn(**call.function.arguments)
print(f"呼叫 {call.function.name}({call.function.arguments}) → {result}")
messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})
final = chat(model="qwen3:8b", messages=messages)
print(final.message.content)
重點:
- 把模型的回應(包含
tool_calls)加回messages。 - 每個工具的執行結果用
role: "tool"加回去。 - 再呼叫一次
chat,模型就會根據結果回答。
讓模型自己決定要呼叫幾次
有些問題需要連續呼叫多個工具,例如「先查匯率,再算出金額」。用迴圈處理,直到模型不再要求呼叫工具:
from ollama import chat
def get_exchange_rate(currency: str) -> float:
"""取得 1 單位外幣兌換新台幣的匯率。currency 例如 USD、JPY。"""
return {"USD": 32.1, "JPY": 0.21}.get(currency.upper(), 0.0)
def multiply(a: float, b: float) -> float:
"""計算 a 乘以 b。"""
return a * b
tools = {f.__name__: f for f in [get_exchange_rate, multiply]}
messages = [{"role": "user", "content": "350 美元大約是多少新台幣?"}]
while True:
response = chat(model="qwen3:8b", messages=messages, tools=list(tools.values()))
messages.append(response.message)
if not response.message.tool_calls:
break
for call in response.message.tool_calls:
result = tools[call.function.name](**call.function.arguments)
messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})
print(response.message.content)
實務上請加上最多呼叫次數的限制,避免模型陷入無限迴圈。
用 REST API 定義工具
不用 Python 套件時,工具以 JSON Schema 描述:
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{ "role": "user", "content": "台北天氣如何?" }],
"stream": false,
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查詢城市目前的天氣",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名稱" }
},
"required": ["city"]
}
}
}]
}'
回應中的 message.tool_calls:
"tool_calls": [
{ "function": { "name": "get_weather", "arguments": { "city": "台北" } } }
]
執行後,把結果用 {"role": "tool", "tool_name": "get_weather", "content": "24°C,多雲"} 加進 messages 再送一次。
寫好工具說明
模型完全根據名稱和說明來判斷何時使用工具、怎麼填參數:
- 函式名稱清楚表達用途:
search_orders比query1好。 - 說明中寫清楚什麼情況該用、參數的格式與範例。
- 參數盡量少、型別明確,能用列舉(enum)就用列舉。
- 工具數量不要太多,小模型面對十幾個工具時容易選錯。
安全注意事項
- 工具會被模型根據使用者輸入觸發。如果使用者可以控制輸入,就等於使用者可以間接呼叫你的工具。
- 不要提供可以執行任意程式碼、任意 SQL 或刪除資料的工具。
- 有副作用的操作(付款、寄信、刪除)應該在執行前讓使用者確認。
- 檢查模型給的參數,不要直接信任。
更新於 2026年10月12日