Gemini函数调用教程:Python Function Calling实战

本文深入讲解 Gemini API 的函数调用功能,涵盖 Interactions API 与 ChatSession 两种方式。通过灯光控制、数学运算、电影查询等示例,展示如何声明工具、处理函数调用、实现自动与手动执行、并行与组合调用,并探讨模式配置。面向有编程基础的开发者,提供环境搭建、代码分析、常见错误排查及生产优化建议,帮助构建可靠的 AI 应用。

技术背景

大型语言模型(LLM)虽能生成自然语言,但无法直接访问外部数据或执行真实操作。函数调用(Function Calling)允许开发者将自定义函数描述传递给模型,模型在需要时返回函数名和参数,由应用执行,从而将 LLM 与外部系统(如数据库、API、设备控制)连接。此技术广泛应用于智能助手、自动化工作流、信息检索等场景。Gemini API 提供两种交互方式:Interactions API(最新,需手动处理函数调用)和 ChatSession(支持自动函数执行)。主要限制包括:模型可能产生幻觉参数、函数描述需精确、复杂调用链可能增加延迟。

核心原理

函数调用的核心是让模型在生成文本时,根据用户输入和工具描述,决定是否调用函数。模型输出包含函数名和参数(JSON 格式),应用执行函数后,将结果以 FunctionResponse 形式返回给模型,模型再生成最终文本。数据流:用户输入 → 模型(结合工具描述)→ FunctionCall → 应用执行函数 → FunctionResponse → 模型 → 文本输出。组件包括:工具声明(FunctionDeclaration)、模型响应(FunctionCall)、执行器(应用代码)、结果回传(FunctionResponse)。关键设计决策:工具描述需包含函数名、描述、参数 schema,模型据此理解何时调用。Interactions API 通过 previous_interaction_id 维护多轮状态,而 ChatSession 自动管理上下文。

架构分析

系统架构分为三层:客户端层(Python SDK)、API 层(Interactions 或 generateContent)、模型层。客户端层提供两种接口:client.interactions.create 和 client.chats.create。Interactions API 采用无状态设计,通过 previous_interaction_id 串联请求,响应包含 steps 列表,每个 step 可能是 function_call、function_result 或 model_output。ChatSession 封装了自动函数调用,内部使用 generateContent,自动处理 FunctionCall 并执行对应 Python 函数。工具声明支持两种形式:字典(Interactions)和 Python 函数(ChatSession 自动生成模式)。设计思想:Interactions 提供细粒度控制,适合复杂工作流;ChatSession 简化常见用例,但灵活性较低。生产环境建议使用 Interactions 以更好地控制错误处理和验证。

完整实战教程

##### 版权所有 2026 Google LLC。

# @title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Gemini API:使用 Python 进行函数调用

函数调用让开发者可以在代码中创建函数的描述,然后在请求中将该描述传递给语言模型。模型的响应包括与描述匹配的函数名称以及调用该函数所需的参数。函数调用允许你在生成式 AI 应用中将函数用作工具,并且可以在单个请求中定义多个函数。

本笔记本提供了代码示例,帮助你快速上手。文档中的快速入门也是理解函数调用的好起点。

注意: 本笔记本使用 Interactions API,这是与 Gemini 模型交互的最新方式。正在寻找 generateContent 版本?请查看 归档分支。

设置

安装依赖

%pip install -U -q "google-genai>=2.9.0"  # 2.0 for Interactions API

设置你的 API 密钥

要运行以下单元格,你的 API 密钥必须存储在名为 GEMINI_API_KEY 的 Colab 密钥中。如果你还没有 API 密钥,或者不确定如何创建 Colab 密钥,请参阅 身份验证 获取详细指南。

from google import genai
from google.colab import userdata

GEMINI_API_KEY = userdata.get("GEMINI_API_KEY")
client = genai.Client(api_key=GEMINI_API_KEY)

选择模型

函数调用适用于所有 Gemini 模型。

MODEL_ID = "gemini-3.7-flash" # @param ["gemini-3.1-pro-preview", "gemini-3.7-flash", "gemini-3.5-flash-lite", "gemini-2.5-pro"] {"allow-input":true, isTemplate: true}

将函数设置为工具

要使用函数调用,在创建交互时将函数列表传递给 tools 参数。使用 Interactions API 时,工具以字典形式声明。SDK 也可以从 Python 函数自动生成工具模式。

def enable_lights():
    """Turn on the lighting system."""
    print("LIGHTBOT: Lights enabled.")


def set_light_color(rgb_hex: str):
    """Set the light color. Lights must be enabled for this to work."""
    print(f"LIGHTBOT: Lights set to {rgb_hex}.")

def stop_lights():
    """Stop flashing lights."""
    print("LIGHTBOT: Lights turned off.")

# Map function names to callables for execution
light_functions = {
    "enable_lights": enable_lights,
    "set_light_color": set_light_color,
    "stop_lights": stop_lights,
}

# For interactions.create, tools must be declared as dicts
light_controls = [
    {
        "type": "function",
        "name": "enable_lights",
        "description": "Turn on the lighting system.",
        "parameters": {"type": "object", "properties": {}},
    },
    {
        "type": "function",
        "name": "set_light_color",
        "description": "Set the light color. Lights must be enabled for this to work.",
        "parameters": {
            "type": "object",
            "properties": {
                "rgb_hex": {"type": "string", "description": "The color as an RGB hex string"}
            },
            "required": ["rgb_hex"],
        },
    },
    {
        "type": "function",
        "name": "stop_lights",
        "description": "Stop flashing lights.",
        "parameters": {"type": "object", "properties": {}},
    },
]

instruction = """
  You are a helpful lighting system bot. You can turn
  lights on and off, and you can set the color. Do not perform any
  other tasks.
"""

多轮对话中的基础函数调用

函数调用自然适合多轮对话。使用 Interactions API,模型会返回 function_call 输出,你可以通过 function_result 输入来处理并响应这些输出。

注意: 自动函数调用(即 SDK 自动调用你的函数)是 client.chats.create 的功能。使用 interactions.create 时,你需要手动处理函数调用,这样可以获得更多控制权。

interactions.create 的响应包含一个 steps 列表。对于文本响应,可以通过 interaction.steps[-1].content[0].text 访问输出。
# First turn: ask the model, providing tool declarations
interaction = client.interactions.create(
    model=MODEL_ID,
    input="It's awful dark in here...",
    system_instruction=instruction,
    tools=light_controls,
)

# Check if the model wants to call a function
for step in interaction.steps:
    if step.type == "function_call":
        print(f"Model wants to call: {step.name}({step.arguments})")
        fn = light_functions[step.name]
        result = fn(**step.arguments) if step.arguments else fn() if step.arguments else fn()

检查函数调用与执行历史

通过 Interactions API,对话状态由服务端通过 previous_interaction_id 进行管理。每个交互对象包含该轮次的输出,其中可能包括函数调用、函数结果或文本响应。

from IPython.display import Markdown, display

# Show the outputs of the last interaction
for step in interaction.steps:
    print(f"Type: {step.type}")
    if hasattr(step, 'content') and step.content and step.content[0].text:
        print(f"Text: {step.content[0].text}")

这段历史展示了流程:

  1. 用户:发送消息。
  1. 模型:不返回文本,而是返回一个 FunctionCall,请求调用 enable_lights。
  1. 用户(SDK):由于启用了 automatic_function_calling,ChatSession 自动执行 enable_lights()。它将结果作为 FunctionResponse 发送回去。
  1. 模型:使用函数的结果(“Lights enabled.”)来生成最终的文本响应。

自动函数执行(仅限 client.chats)

Python SDK 中的 ChatSession(即 client.chats.create)有一个强大的功能,称为自动函数执行。当启用时(默认启用),如果模型响应一个 FunctionCall,SDK 将:

  1. 在提供的 tools 中找到对应的 Python 函数。
  1. 使用模型提供的参数执行该函数。
  1. 将函数的返回值以 FunctionResponse 的形式发送回模型。
  1. 仅将模型的最终响应(通常是文本)返回给你的代码。

这大大简化了常见用例的工作流程。

注意: 自动函数执行仅适用于 client.chats.create(其底层使用 generateContent)。对于 Interactions API(client.interactions.create),你需要手动处理函数调用——请参阅下面的手动函数调用。

示例:数学运算

from google.genai import types

def add(a: float, b: float):
    """returns a + b."""
    print(f"  >> add({a}, {b})")
    return a + b

def subtract(a: float, b: float):
    """returns a - b."""
    print(f"  >> subtract({a}, {b})")
    return a - b

def multiply(a: float, b: float):
    """returns a * b."""
    print(f"  >> multiply({a}, {b})")
    return a * b

def divide(a: float, b: float):
    """returns a / b."""
    print(f"  >> divide({a}, {b})")
    if b == 0:
        return "Cannot divide by zero."
    return a / b

operation_tools = [add, subtract, multiply, divide]

chat = client.chats.create(
    model=MODEL_ID,
    config={
        "tools": operation_tools,
        "automatic_function_calling": {"disable": False},  # Enabled by default
    },
)

response = chat.send_message(
    "I have 57 cats, each owns 44 mittens, how many mittens is that in total?"
)

print(response.text)
# Print interaction outputs summary
for step in interaction.steps:
    print(f"Type: {step.type}", end="")
    if step.type == "model_output":
        print(f" | {step.content[0].text[:100]}")
    elif step.type == "function_call":
        print(f" | {step.name}({step.arguments})")
    else:
        print()

自动执行无缝地处理了 multiply 调用。

自动函数模式声明

Python SDK 的一个关键便利之处在于,它能够根据你的 Python 函数自动生成所需的 FunctionDeclaration 模式。它会检查:

当直接使用 Python 函数作为工具时,你通常不需要手动创建 FunctionDeclaration 对象。

然而,如果你需要检查、修改模式,或者在无法直接获得 Python 函数对象的情况下使用它,你可以使用 genai.types.FunctionDeclaration.from_callable 显式生成模式。

使用 .to_json_dict() 获取 JSON 表示形式——这是在使用 client.interactions.create 时作为工具传递的格式。

import json

set_color_declaration = types.FunctionDeclaration.from_callable(
    callable = set_light_color,
    client = client
)

print(json.dumps(set_color_declaration.to_json_dict(), indent=4))

<a name="manual_fc"></a>

手动函数调用

使用 Interactions API(client.interactions.create)时,函数调用始终是手动的——你会收到模型的函数调用请求,并自行处理。这让你对执行、错误处理和验证拥有完全的控制权。

Interactions API 不使用聊天会话,而是通过 previous_interaction_id 将请求串联起来,从而在多次交互中保持对话上下文。

手动工作流如下:

  1. 向 client.interactions.create 发送带有工具声明的提示。
  2. 检查响应中的 steps 是否有 function_call 条目。
  3. 在本地执行相应的函数。
  4. 使用 previous_interaction_id 将结果发送回去以继续对话。

如果你使用 Chat 并设置 "automatic_function_calling": {"disable": True},情况也是如此。

示例:电影

以下示例大致相当于 Python 中的函数调用单轮 curl 示例。它使用返回(模拟)电影播放时间信息的函数,这些信息可能来自一个假设的 API:

def find_movies(description: str, location: str):
    """find movie titles currently playing in theaters."""
    return ["Barbie", "Oppenheimer"]


def find_theaters(location: str, movie: str):
    """Find theaters showing a movie in a location."""
    return ["Googleplex 16", "Android Theatre"]


def get_showtimes(location: str, movie: str, theater: str, date: str):
    """Find the start times for movies playing in a specific theater."""
    return ["10:00", "11:00"]

# Map function names to callables
available_functions = {
    "find_movies": find_movies,
    "find_theaters": find_theaters,
    "get_showtimes": get_showtimes,
}

# Dict-based tool declarations for interactions.create
theater_functions = [
    {"type": "function", "name": "find_movies",
     "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
     "parameters": {"type": "object", "properties": {
         "description": {"type": "string", "description": "Any kind of description including category or genre"},
         "location": {"type": "string", "description": "The city and state, e.g. San Francisco, CA"}
     }, "required": ["description", "location"]}},
    {"type": "function", "name": "find_theaters",
     "description": "Find theaters based on location and movie title.",
     "parameters": {"type": "object", "properties": {
         "location": {"type": "string"}, "movie": {"type": "string"}
     }, "required": ["location", "movie"]}},
    {"type": "function", "name": "get_showtimes",
     "description": "Find the start times for movies playing in a specific theater.",
     "parameters": {"type": "object", "properties": {
         "location": {"type": "string"}, "movie": {"type": "string"},
         "theater": {"type": "string"}, "date": {"type": "string"}
     }, "required": ["location", "movie", "theater", "date"]}},
]

使用 interactions.create() 提问后,模型会请求一个 function_call:

interaction = client.interactions.create(
    model=MODEL_ID,
    input="Which theaters in Mountain View, CA show the Barbie movie?",
    tools=theater_functions,
)

# Find the function call in the outputs
for step in interaction.steps:
    if step.type == "function_call":
        print(f"Function call: {step.name}")
        print(f"Arguments: {step.arguments}")
        function_call_step = step
        break

由于这里没有使用带有自动函数调用的 ChatSession,你需要自己调用函数。

一个非常简单的方法是使用 if 语句:

if function_call.name == 'find_theaters':
  find_theaters(**function_call.args)
elif ...

不过,既然你已经创建了 theater_functions 列表,这可以简化为:

def call_function(function_call_output, functions):
    function_name = function_call_output.name
    function_args = function_call_output.arguments
    return functions[function_name](**function_args)

result = call_function(function_call_step, available_functions)
print(result)

最后,使用 previous_interaction_id 将函数结果传回,以继续对话并从模型获取最终的文本响应。

# Send the function result back to the model
interaction_2 = client.interactions.create(
    model=MODEL_ID,
    previous_interaction_id=interaction.id,
    input={
        "type": "function_result",
        "name": function_call_step.name,
        "call_id": function_call_step.id,
        "result": str(result),
    },
    tools=theater_functions,
)

# Get the final text response
text_outputs = [o for o in interaction_2.steps if o.type == "text"]
if text_outputs:
    print(text_outputs[-1].text)

这展示了手动工作流:调用、检查、执行、响应、再次调用。

并行函数调用

Gemini API 可以在单轮中调用多个函数。这适用于存在多个可以独立执行的函数调用以完成任务的场景。

首先设置工具。与上面的电影示例不同,这些函数不需要彼此提供输入即可被调用,因此它们是并行调用的理想候选。

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True

def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters."""
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."

def dim_lights(brightness: float) -> bool:
    """Dim the lights."""
    print(f"Lights are now set to {brightness:.0%}")
    return True

house_functions = {
    "power_disco_ball": power_disco_ball,
    "start_music": start_music,
    "dim_lights": dim_lights,
}

house_fns = [
    {"type": "function", "name": "power_disco_ball", "description": "Powers the spinning disco ball.",
     "parameters": {"type": "object", "properties": {"power": {"type": "boolean"}}, "required": ["power"]}},
    {"type": "function", "name": "start_music", "description": "Play some music matching the specified parameters.",
     "parameters": {"type": "object", "properties": {
         "energetic": {"type": "boolean"}, "loud": {"type": "boolean"}, "bpm": {"type": "integer"}
     }, "required": ["energetic", "loud", "bpm"]}},
    {"type": "function", "name": "dim_lights", "description": "Dim the lights.",
     "parameters": {"type": "object", "properties": {"brightness": {"type": "number"}}, "required": ["brightness"]}},
]

现在调用模型,并给出一个可以使用所有指定工具的指令。

# Use "any" mode via tool_config is not yet supported in Interactions API.
# Instead, we make a direct call and handle functions manually.
interaction = client.interactions.create(
    model=MODEL_ID,
    input="Turn this place into a party!",
    tools=house_fns,
)

prev_id = interaction.id
while any(s.type == "function_call" for s in interaction.steps):
    results = []
    for step in interaction.steps:
        if step.type == "function_call":
            print(f"Calling: {step.name}({step.arguments})")
            fn = house_functions[step.name]
            result = fn(**step.arguments) if step.arguments else fn() if step.arguments else fn()
            results.append({
                "type": "function_result",
                "name": step.name,
                "call_id": step.id,
                "result": str(result),
            })
    interaction = client.interactions.create(
        model=MODEL_ID,
        input=results,
        previous_interaction_id=prev_id,
        tools=house_fns,
    )
    prev_id = interaction.id

for step in interaction.steps:
    if step.type == "model_output":
        print(f"\nModel: {step.content[0].text}")

注意,单次模型回合包含三个 FunctionCall 部分,SDK 在执行这些调用后才获得最终的文本响应。

组合式函数调用

模型可以在多轮对话中链式调用函数,利用一次调用的结果来指导下一次调用。这支持复杂的多步骤推理和任务完成。

示例:查找特定电影场次

让我们复用 theater_functions,并提出一个更复杂的查询,该查询需要先查找电影,然后可能查找影院,最后查找场次。

interaction = client.interactions.create(
    model=MODEL_ID,
    input="""
    Find comedy movies playing in Mountain View, CA on 01/01/2025.
    First, find the movie titles.
    Then, find the theaters showing those movies.
    Finally, find the showtimes for each movie at each theater.
""",
    tools=theater_functions,
)

prev_id = interaction.id
while any(s.type == "function_call" for s in interaction.steps):
    results = []
    for step in interaction.steps:
        if step.type == "function_call":
            print(f"Calling: {step.name}({step.arguments})")
            fn = available_functions[step.name]
            result = fn(**step.arguments) if step.arguments else fn()
            results.append({
                "type": "function_result",
                "name": step.name,
                "call_id": step.id,
                "result": str(result),
            })
    interaction = client.interactions.create(
        model=MODEL_ID,
        input=results,
        previous_interaction_id=prev_id,
        tools=theater_functions,
    )
    prev_id = interaction.id

for step in interaction.steps:
    if step.type == "model_output":
        print(step.content[0].text)

在这里你可以看到,模型为了回答你的问题进行了七次调用,并在后续调用和最终答案中使用了这些调用的输出。

使用模式配置函数调用

注意: tool_config 模式(AUTO、ANY、NONE)是 generateContent API 的功能。它们尚不可用于 Interactions API。下面的示例使用 client.interactions.create 来展示等效的变通方法。

使用 generateContent,您可以通过 tool_config 参数精确控制模型何时以及可以调用哪些函数。

tool_config 接受一个 ToolConfig 对象,其中包含一个 FunctionCallingConfig,具有两个主要字段:

以下是每种模式的工作原理以及如何使用 Interactions API 实现类似行为:

AUTO(默认模式)

# In Interactions API, there is no "auto" mode config.
# The model will naturally decide whether to call tools.
interaction = client.interactions.create(
    model=MODEL_ID,
    input="Turn on the lights!",
    system_instruction=instruction,
    tools=light_controls,
)

for step in interaction.steps:
    if step.type == "function_call":
        print(f"Function call: {step.name}({step.arguments})")
        fn = light_functions[step.name]
        result = fn(**step.arguments) if step.arguments else fn() if step.arguments else fn()
    elif step.type == "model_output":
        print(f"Model: {step.content[0].text}")

NONE 模式

# "none" mode equivalent: don't pass any tools
interaction = client.interactions.create(
    model=MODEL_ID,
    input="Hello light-bot, what can you do?",
    system_instruction=instruction,
    # No tools provided = model can't call functions
)

for step in interaction.steps:
    if step.type == "model_output":
        print(f"Model: {step.content[0].text}")

ANY 模式

以下是一个使用 tool_config 的 generateContent API 示例:

from google.genai import types

response = client.models.generate_content(
    model=MODEL_ID,
    contents="Make this place PURPLE!",
    config=types.GenerateContentConfig(
        system_instruction=instruction,
        tools=light_controls,
        tool_config=types.ToolConfig(
            function_calling_config=types.FunctionCallingConfig(
                mode="ANY",
            ),
        ),
    ),
)

使用 Interactions API 时,你只需传入工具并手动处理调用:

# Force function calling by providing tools
interaction = client.interactions.create(
    model=MODEL_ID,
    input="Make this place PURPLE!",
    system_instruction=instruction,
    tools=light_controls,
)

# Manual function execution loop
prev_id = interaction.id
while any(s.type == "function_call" for s in interaction.steps):
    results = []
    for step in interaction.steps:
        if step.type == "function_call":
            print(f"Calling: {step.name}({step.arguments})")
            fn = light_functions[step.name]
            result = fn(**step.arguments) if step.arguments else fn() if step.arguments else fn()
            results.append({
                "type": "function_result",
                "name": step.name,
                "call_id": step.id,
                "result": str(result),
            })
    interaction = client.interactions.create(
        model=MODEL_ID,
        input=results,
        previous_interaction_id=prev_id,
        tools=light_controls,
    )
    prev_id = interaction.id

for step in interaction.steps:
    if step.type == "model_output":
        print(f"Model: {step.content[0].text}")

后续步骤

有用的 API 参考:

相关示例

查看这些使用函数调用的示例,为您提供更多关于如何使用这一非常有用功能的思路:

* Barista Bot,一个用于订购咖啡的代理

* Browser-as-a-tool,使用函数调用调用 Web 浏览器。

* 使用函数调用重新排序搜索结果。

* 将工具与 Live API 结合使用,将函数调用和其他工具与 Live API 结合使用。

继续探索 Gemini API

在 函数调用配置 快速入门中了解如何控制 Gemini API 与您的函数的交互方式,在 JSON 或使用 Enum 中了解如何控制模型输出,或了解 Gemini API 如何使用 代码执行 自行生成和运行代码。

常见问题

常见错误:1) API 密钥未设置或无效,导致认证失败;2) 工具声明格式错误,如缺少 required 字段;3) 函数参数类型不匹配,模型返回的参数无法直接解包;4) 未处理 function_call 步骤,导致对话中断;5) 在 Interactions API 中误用自动函数调用。排查方法:检查响应 steps 类型,打印 function_call 的 name 和 arguments;验证函数映射字典键与声明名称一致;使用 try-except 捕获参数解析错误;确保 previous_interaction_id 正确传递。生产优化:使用缓存减少重复调用;设置超时和重试机制;对函数结果进行验证和清洗;监控函数调用频率和延迟;考虑使用异步执行提升吞吐量。

企业应用扩展

可扩展方向:1) 将函数调用与外部 API 集成,如数据库查询、REST 服务;2) 实现多代理系统,每个代理负责特定工具集;3) 结合流式输出,实时展示函数调用过程;4) 使用函数调用实现复杂任务分解,如研究助手、代码生成器;5) 探索 Live API 与函数调用的结合,实现实时交互。参考官方示例:Barista Bot(对话式代理)、Browser-as-a-tool(浏览器控制)、Search reranking(搜索重排)。

总结

本文深入讲解 Gemini API 的函数调用功能,涵盖 Interactions API 与 ChatSession 两种方式。通过灯光控制、数学运算、电影查询等示例,展示如何声明工具、处理函数调用、实现自动与手动执行、并行与组合调用,并探讨模式配置。面向有编程基础的开发者,提供环境搭建、代码分析、常见错误排查及生产优化建议,帮助构建可靠的 AI 应用。

内容来源与验证

继续系统学习

站内还有更多完整实战教程

加入会员,解锁全部教程、完整代码与持续更新内容。

加入会员
查看全部API 与工程实践教程