TodayAI

GuidesAgents

用 Gemini Function Calling 连接外部动作

把函数描述交给 Gemini,让模型返回要调用的函数名与参数。按官方 Interactions API 示例跑通最小闭环。

基于 Google AI for Developers 整理 · 官方资料 ↗

模型擅长理解自然语言,但它不会自己去开会、调灯光、查内部 API。Function Calling 解决的就是这件事:你先声明有哪些函数可用,模型决定何时调用、传什么参数;真正执行动作的是你的程序。

这篇按 Google AI for Developers 的 Interactions API 示例,从声明一个最小函数开始,一路走到「模型返回 function_call → 应用执行 → 用 function_result 交回 → 得到最终回答」的完整闭环。

Function Calling 到底解决什么

官方文档把 Function Calling 的用途概括成三类:执行动作(调外部系统)、补充知识(查数据库或 API)、扩展能力(用计算器、画图等工具突破纯文本生成的限制)。

关键边界是:模型只负责选函数、填参数。它不会替你执行副作用。开会、改灯、写库表,都必须在你的应用里完成,再把结果交回模型,让它生成面向用户的最终回答。

完整闭环可以记成:prompt → 模型 → function_call → 应用执行 → function_result → 模型最终输出。

定义一个最小 Function

先给模型一份函数声明:名字、用途说明、参数 JSON Schema。官方完整闭环示例用 set_light_values——设置灯光亮度与色温。

官方 set_light_values 声明与本地实现

python
set_light_values_declaration = {
    "type": "function",
    "name": "set_light_values",
    "description": "Sets the brightness and color temperature of a light.",
    "parameters": {
        "type": "object",
        "properties": {
            "brightness": {
                "type": "integer",
                "description": "Light level from 0 to 100",
            },
            "color_temp": {
                "type": "string",
                "enum": ["daylight", "cool", "warm"],
                "description": "Color temperature",
            },
        },
        "required": ["brightness", "color_temp"],
    },
}

def set_light_values(brightness: int, color_temp: str) -> dict:
    """Set the brightness and color temperature of a room light."""
    return {"brightness": brightness, "colorTemperature": color_temp}

声明给模型看;def set_light_values(...) 是你自己的业务代码。两者名字要对齐,参数也要能对上 arguments。

把 Function 提供给 Gemini

创建 genai.Client,在 interactions.create 里传入模型、自然语言输入和 tools。当前官方示例模型为 gemini-3.6-flash。

python
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.6-flash",
    input="Turn the lights down to a romantic level",
    tools=[set_light_values_declaration],
)

若只想先看「模型会不会提出调用」,也可以用官方 schedule_meeting 示例:同样用 tools=[{"type": "function", **schedule_meeting_function}],输入一句排会请求,再从 steps 里读 function_call。

收到 Function Call 后程序要做什么

响应里的 interaction.steps 可能包含 function_call。这类 step 至少带有 name、arguments,以及用于回传结果的 id。

python
fc_step = next(s for s in interaction.steps if s.type == "function_call")
print(fc_step)
# 官方示例中大致形态:
# type='function_call'
# name='set_light_values'
# arguments={'color_temp': 'warm', 'brightness': 25}

接下来必须由你的应用执行函数。模型到此为止;不执行、不回传,就没有完整工具环。

python
if fc_step.name == "set_light_values":
    result = set_light_values(**fc_step.arguments)
    print(f"Function execution result: {result}")

把执行结果交回模型

再发一次 interactions.create:input 使用 type 为 function_result 的内容,带上 name、call_id(对应 fc_step.id)和 result,并传入 previous_interaction_id=interaction.id,让服务端延续上一轮上下文。

python
import json

final_interaction = client.interactions.create(
    model="gemini-3.6-flash",
    input=[
        {
            "type": "function_result",
            "name": fc_step.name,
            "call_id": fc_step.id,
            "result": [{"type": "text", "text": json.dumps(result)}],
        }
    ],
    tools=[set_light_values_declaration],
    previous_interaction_id=interaction.id,
)

print(final_interaction.output_text)

call_id 必须与上一轮 function_call 的 id 对应;漏传 previous_interaction_id 时,模型拿不到完整工具上下文,最终回答容易断掉。

一个最小完整闭环示例

把声明、请求、执行、回传串在一起,就是官方 How function calling works 的最小路径:

基于官方 set_light_values 示例的完整闭环

python
from google import genai
import json

set_light_values_declaration = {
    "type": "function",
    "name": "set_light_values",
    "description": "Sets the brightness and color temperature of a light.",
    "parameters": {
        "type": "object",
        "properties": {
            "brightness": {
                "type": "integer",
                "description": "Light level from 0 to 100",
            },
            "color_temp": {
                "type": "string",
                "enum": ["daylight", "cool", "warm"],
                "description": "Color temperature",
            },
        },
        "required": ["brightness", "color_temp"],
    },
}

def set_light_values(brightness: int, color_temp: str) -> dict:
    return {"brightness": brightness, "colorTemperature": color_temp}

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.6-flash",
    input="Turn the lights down to a romantic level",
    tools=[set_light_values_declaration],
)

fc_step = next(s for s in interaction.steps if s.type == "function_call")
result = set_light_values(**fc_step.arguments)

final_interaction = client.interactions.create(
    model="gemini-3.6-flash",
    input=[{
        "type": "function_result",
        "name": fc_step.name,
        "call_id": fc_step.id,
        "result": [{"type": "text", "text": json.dumps(result)}],
    }],
    tools=[set_light_values_declaration],
    previous_interaction_id=interaction.id,
)

print(final_interaction.output_text)
  • 第一轮 steps 中出现 type == "function_call"
  • name 为 set_light_values,arguments 含 brightness / color_temp
  • 本地函数确实被执行并产生 result
  • 第二轮带 previous_interaction_id 与 function_result 后,能打印 output_text

最容易混淆的地方

以为模型会替你执行函数

官方明确:Execute Function Code 是应用的责任。没有本地执行与 function_result,闭环不完整。

只打印了 function_call 就以为做完了

schedule_meeting 示例适合演示「参数被解析出来」;要得到用户可读最终回答,仍需执行并回传 function_result。

回传时漏了 call_id 或 previous_interaction_id

call_id 用 fc_step.id;延续对话用 previous_interaction_id=interaction.id。两者都按官方 Step 4 传递。

没有 function_call step

检查 tools 是否传入、描述是否清晰;换官方示例那句输入再试,并确认 API Key 与模型名可用。

官方资料

Google AI for Developers

Function calling with the Gemini API