Gemma 4 內建原生函式呼叫支援,這意味著你可以建構不只是生成文字——還能採取行動的 AI 代理。呼叫 API、查詢資料庫、搜尋網路、執行計算。本指南展示如何用 Gemma 4 和 Python 從頭建構一個可運作的代理。
什麼是函式呼叫?
函式呼叫讓模型決定何時使用外部工具而不是猜測答案。與其問 Gemma 4「東京的天氣如何?」得到幻覺式的回應,模型會輸出一個結構化請求呼叫你的天氣 API,你執行它,將結果餵回,然後模型根據真實資料生成自然語言答案。
流程看起來像這樣:
使用者:「東京的天氣如何?」
→ 模型:{"function": "get_weather", "args": {"city": "Tokyo"}}
→ 你的程式碼呼叫天氣 API → 回傳 {"temp": 22, "condition": "sunny"}
→ 模型:「東京現在是攝氏 22 度,天氣晴朗。」用 JSON Schema 定義工具
首先,你需要告訴 Gemma 4 有哪些工具可用。每個工具都用 JSON schema 定義,描述其名稱、用途和參數:
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city. Use this when the user asks about weather conditions.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. 'Tokyo', 'New York'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Perform mathematical calculations. Use for any math the user asks about.",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Math expression to evaluate, e.g. '2 + 2', 'sqrt(144)'"
}
},
"required": ["expression"]
}
}
},
{
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for current information. Use when the user asks about recent events or facts you're unsure about.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query"
},
"num_results": {
"type": "integer",
"description": "Number of results to return (default: 3)"
}
},
"required": ["query"]
}
}
}
]良好的工具描述至關重要。模型依靠它們來決定呼叫哪個工具以及何時呼叫。明確地描述每個工具該在何時使用。
建構代理迴圈
以下是一個透過 Ollama API 使用 Gemma 4 的完整 Python 代理:
import json
import requests
import math
OLLAMA_URL = "http://localhost:11434/api/chat"
MODEL = "gemma4:12b"
# 定義你的工具實作
def get_weather(city: str, unit: str = "celsius") -> dict:
"""Simulated weather API — replace with a real API call"""
# 在正式環境中,呼叫 OpenWeatherMap、WeatherAPI 等
return {
"city": city,
"temperature": 22,
"unit": unit,
"condition": "sunny",
"humidity": 45
}
def calculate(expression: str) -> dict:
"""Safe math evaluation"""
allowed_names = {
"sqrt": math.sqrt,
"sin": math.sin,
"cos": math.cos,
"pi": math.pi,
"e": math.e,
"abs": abs,
"round": round
}
try:
result = eval(expression, {"__builtins__": {}}, allowed_names)
return {"expression": expression, "result": result}
except Exception as e:
return {"expression": expression, "error": str(e)}
def web_search(query: str, num_results: int = 3) -> dict:
"""Simulated web search — replace with real search API"""
return {
"query": query,
"results": [
{"title": f"Result about {query}", "snippet": "Relevant information..."}
]
}
# 將函式名稱對應到實作
TOOL_MAP = {
"get_weather": get_weather,
"calculate": calculate,
"web_search": web_search,
}
def call_gemma(messages: list, tools: list) -> dict:
"""Send a chat request to Gemma 4 via Ollama"""
response = requests.post(OLLAMA_URL, json={
"model": MODEL,
"messages": messages,
"tools": tools,
"stream": False
})
return response.json()
def run_agent(user_input: str, tools: list, max_steps: int = 5):
"""Run the agent loop with multi-step tool use"""
messages = [
{
"role": "system",
"content": "You are a helpful assistant. Use the provided tools when needed. Always use tools for weather, calculations, and current information instead of guessing."
},
{"role": "user", "content": user_input}
]
for step in range(max_steps):
response = call_gemma(messages, tools)
message = response["message"]
# 檢查模型是否要呼叫工具
if "tool_calls" in message and message["tool_calls"]:
# 處理每個工具呼叫
for tool_call in message["tool_calls"]:
func_name = tool_call["function"]["name"]
func_args = tool_call["function"]["arguments"]
print(f" → Calling {func_name}({func_args})")
# 執行工具
if func_name in TOOL_MAP:
result = TOOL_MAP[func_name](**func_args)
else:
result = {"error": f"Unknown tool: {func_name}"}
# 將工具呼叫和結果加到訊息
messages.append(message)
messages.append({
"role": "tool",
"content": json.dumps(result)
})
else:
# 模型給了最終的文字回應
print(f"Agent: {message['content']}")
return message["content"]
return "Agent reached maximum steps without completing."
# 執行代理
if __name__ == "__main__":
run_agent("What's the weather in Tokyo and what's 15% of 8500?", tools)這個代理可以處理多步驟查詢。當你問「東京的天氣如何,以及 8500 的 15% 是多少?」時,Gemma 4 會分別呼叫 get_weather 和 calculate,然後將兩個結果合成為一個自然的回應。
多步驟代理模式
真實的代理通常需要串聯多個工具呼叫,後面的呼叫依賴前面的結果:
# 範例:「找我附近的餐廳並查看那裡的天氣」
# 步驟 1:模型呼叫 web_search("restaurants near me")
# 步驟 2:模型看到結果,呼叫 get_weather(結果中的城市)
# 步驟 3:模型將兩者合成為推薦
# 代理迴圈自然地處理這個——每個工具結果都被
# 加到對話中,模型根據完整歷史決定下一步要做什麼用於可靠工具使用的結構化輸出
Gemma 4 支援結構化輸出,這意味著你可以強制模型以特定的 JSON 格式回應。當你需要代理的最終答案是機器可讀的結構時這很有用:
response = requests.post(OLLAMA_URL, json={
"model": MODEL,
"messages": messages,
"format": {
"type": "object",
"properties": {
"answer": {"type": "string"},
"confidence": {"type": "number"},
"sources": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["answer", "confidence"]
},
"stream": False
})這保證輸出是符合你 schema 的有效 JSON——不再需要解析自由格式文字並祈禱一切順利。
更好函式呼叫的技巧
| 技巧 | 原因 |
|---|---|
| 撰寫詳細的工具描述 | 模型依賴描述來選擇正確的工具 |
在 schema 中使用 required 欄位 | 防止模型遺漏關鍵參數 |
| 工具數量限制在 5-10 個 | 太多工具會讓模型困惑 |
| 在描述中加入範例 | 「例如 'New York'、'London'」幫助模型正確格式化參數 |
| 優雅地處理錯誤 | 回傳錯誤資訊以便模型可以重試或通知使用者 |
| 設定 max_steps 限制 | 防止模型不斷呼叫工具造成無限迴圈 |
常見陷阱
模型忽略工具直接回答: 讓你的 system prompt 明確告訴模型使用工具。加上「絕不猜測天氣/數學/事實——一律使用提供的工具。」
參數型別錯誤: 如果模型為整數參數傳送 "3" 而不是 3,在你的工具實作中加入型別轉換。
模型不必要地呼叫工具: 在工具描述中明確說明何時該使用它們。「僅當使用者明確詢問天氣時使用」比「取得天氣資訊」更好。
下一步
- 想先學 Ollama API 基礎? 查看我們的 Gemma 4 API 教學 作為溫和的入門
- 需要為代理工作負載挑選合適的模型? 12B 模型是最佳點——查看 該用哪個 Gemma 4 模型?
- 建構多模態代理? 閱讀多模態指南 為你的代理加入視覺能力
函式呼叫將 Gemma 4 從聊天機器人轉變為實際的工具。一旦你接上真實 API——天氣、搜尋、資料庫、電子郵件——你就擁有了一個能在現實世界採取有意義行動的 AI 代理,全部在你自己的硬體上本機執行。
Stop reading. Start building.
~/gemma4 $ Get hands-on with the models discussed in this guide. No deployment, no friction, 100% free playground.
Launch Playground />


