用 Gemma 4 做 AI Agent:Function Calling 实战

2026/04/07

Gemma 4 原生支持函数调用(Function Calling),意味着你可以用它做的不只是聊天——而是真正能调 API、查数据库、搜网页的 AI Agent。这篇教程从零开始,用 Python 带你写一个能用的 Agent。

函数调用是什么?

简单说,就是让模型在需要的时候调用你预先定义好的工具,而不是瞎猜。

比如你问「东京现在天气怎么样?」,模型不会编一个答案,而是输出一个结构化的请求来调你的天气 API,你执行完把结果返回去,模型再基于真实数据生成回答。

流程是这样的:

用户:「东京天气怎么样?」
  → 模型:{"function": "get_weather", "args": {"city": "Tokyo"}}
  → 你的代码调天气 API → 返回 {"temp": 22, "condition": "sunny"}
  → 模型:「东京现在 22°C,晴天。」

用 JSON Schema 定义工具

首先要告诉 Gemma 4 有哪些工具可用。每个工具用 JSON Schema 描述名称、用途和参数:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取城市的当前天气。当用户问天气时使用。",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名,如 'Tokyo'、'Beijing'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算。用户问数学问题时使用。",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如 '2 + 2'、'sqrt(144)'"
                    }
                },
                "required": ["expression"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "搜索网络获取最新信息。用户问近期事件或你不确定的事实时使用。",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索关键词"
                    },
                    "num_results": {
                        "type": "integer",
                        "description": "返回结果数量(默认 3)"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

工具描述写得好不好很关键,模型就是根据描述来决定什么时候调哪个工具的。

完整的 Agent 循环

下面是一个用 Ollama API 跑 Gemma 4 的完整 Python Agent:

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:
    """模拟天气 API —— 实际使用时替换成真实 API"""
    return {
        "city": city,
        "temperature": 22,
        "unit": unit,
        "condition": "sunny",
        "humidity": 45
    }

def calculate(expression: str) -> dict:
    """安全的数学计算"""
    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:
    """模拟搜索 —— 实际使用时替换成真实搜索 API"""
    return {
        "query": query,
        "results": [
            {"title": f"关于 {query} 的结果", "snippet": "相关信息..."}
        ]
    }

# 函数名到实现的映射
TOOL_MAP = {
    "get_weather": get_weather,
    "calculate": calculate,
    "web_search": web_search,
}

def call_gemma(messages: list, tools: list) -> dict:
    """通过 Ollama 调用 Gemma 4"""
    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):
    """多步骤 Agent 循环"""
    messages = [
        {
            "role": "system",
            "content": "你是一个有用的助手。需要时使用提供的工具。天气、计算和实时信息必须使用工具,不要猜测。"
        },
        {"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"  → 调用 {func_name}({func_args})")

                # 执行工具
                if func_name in TOOL_MAP:
                    result = TOOL_MAP[func_name](**func_args)
                else:
                    result = {"error": f"未知工具: {func_name}"}

                # 把工具调用和结果加到消息列表
                messages.append(message)
                messages.append({
                    "role": "tool",
                    "content": json.dumps(result, ensure_ascii=False)
                })
        else:
            # 模型给出最终文本回答
            print(f"Agent: {message['content']}")
            return message["content"]

    return "Agent 达到最大步数,未能完成。"

# 运行
if __name__ == "__main__":
    run_agent("东京天气怎么样?8500 的 15% 是多少?", tools)

这个 Agent 能处理多步骤查询。当你问「东京天气怎么样?8500 的 15% 是多少?」时,Gemma 4 会分别调 get_weathercalculate,然后把两个结果合成一个自然的回答。

多步骤 Agent 模式

真实的 Agent 经常需要链式调用,后面的调用依赖前面的结果:

# 示例:「帮我找附近的餐厅,然后查一下那边的天气」
# 第 1 步:模型调 web_search("附近餐厅")
# 第 2 步:模型看到结果,调 get_weather(从结果中提取的城市)
# 第 3 步:模型综合两个结果给出推荐

# Agent 循环天然支持这种模式——每次工具结果
# 加回对话后,模型根据完整历史决定下一步做什么

结构化输出让工具调用更可靠

Gemma 4 支持结构化输出,可以强制模型按特定 JSON 格式回复。当你需要 Agent 的最终答案是机器可读格式时很有用:

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,不用再解析自由格式的文本碰运气。

实用技巧

技巧原因
工具描述写详细模型靠描述决定用哪个工具
required 标记必填字段防止模型漏掉关键参数
工具数量控制在 5-10 个太多会让模型搞混
描述里加示例"如 'Beijing'、'Shanghai'" 帮模型正确格式化参数
优雅地处理错误返回错误信息让模型可以重试或告知用户
设最大步数限制防止模型一直调工具进入死循环

常见坑

模型无视工具直接回答: 在系统提示里明确要求用工具。加一句「天气、数学、实时信息必须使用工具,绝对不要猜测。」

参数类型不对: 模型给整数参数传了字符串 "3" 而不是 3?在工具实现里加类型转换。

模型不必要地调工具: 工具描述要精确说明什么时候用。「仅当用户明确问天气时使用」比「获取天气信息」好得多。

下一步

函数调用让 Gemma 4 从聊天机器人变成真正的工具。接上真实的 API——天气、搜索、数据库、邮件——你就有了一个能在现实世界执行操作的 AI Agent,全部跑在你自己的机器上。

Gemma 4 AI

Gemma 4 AI

相关教程