借助函数调用,您可以将模型连接到外部工具和 API。 该模型不会生成文本回答,而是会了解何时调用特定函数,并提供执行实际操作所需的参数。这样,模型就可以充当自然语言与现实世界操作和数据之间的桥梁。函数调用有 3 种主要用例:
- 扩充知识:访问数据库、API 和知识库等外部来源中的信息。
- 扩展功能:使用外部工具执行计算,并扩展模型的限制,例如使用计算器或创建图表。
- 执行操作:使用 API 与外部系统互动,例如安排预约、创建账单、发送电子邮件或控制智能家居设备
函数调用的工作原理
函数调用涉及应用、模型和外部函数之间的结构化交互。具体流程如下:
- 定义函数声明:在应用代码中定义函数声明。函数声明用于向模型描述函数的名称、参数和用途。
- 使用函数声明调用 LLM:将用户提示以及函数声明发送给模型。它会分析请求,并确定是否有必要进行函数调用。如果是,则会使用结构化 JSON 对象进行响应。
- 执行函数代码(您的责任):模型本身不会执行函数。您的应用有责任处理响应并检查是否有函数调用(如果有,则
- 是:提取函数的名称和实参,并在应用中执行相应的函数。
- 否:模型已直接针对问题提供文本回答(此流程在示例中没有得到太多强调,但也是一种可能的结果)。
- 创建符合用户体验的回答:如果执行了函数,请捕获结果,并在后续对话回合中将其发送回模型。它将使用该结果生成最终的用户友好型回答,其中包含函数调用中的信息。
此过程可在多次转弯中重复,从而实现复杂的互动和工作流。该模型还支持在单个转弯(并行函数调用)和顺序(组合函数调用)中调用多个函数。
第 1 步:定义函数声明
在应用代码中定义一个函数及其声明,以允许用户设置灯光值并发出 API 请求。此函数可以调用外部服务或 API。
from google.genai import types
# Define a function that the model can call to control smart lights
set_light_values_declaration = {
"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. Zero is off and 100 is full brightness",
},
"color_temp": {
"type": "string",
"enum": ["daylight", "cool", "warm"],
"description": "Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.",
},
},
"required": ["brightness", "color_temp"],
},
}
# This is the actual function that would be called based on the model's suggestion
def set_light_values(brightness: int, color_temp: str) -> dict[str, int | str]:
"""Set the brightness and color temperature of a room light. (mock API).
Args:
brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.
Returns:
A dictionary containing the set brightness and color temperature.
"""
return {"brightness": brightness, "colorTemperature": color_temp}
import { Type } from '@google/genai';
// Define a function that the model can call to control smart lights
const setLightValuesFunctionDeclaration = {
name: 'set_light_values',
description: 'Sets the brightness and color temperature of a light.',
parameters: {
type: Type.OBJECT,
properties: {
brightness: {
type: Type.NUMBER,
description: 'Light level from 0 to 100. Zero is off and 100 is full brightness',
},
color_temp: {
type: Type.STRING,
enum: ['daylight', 'cool', 'warm'],
description: 'Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.',
},
},
required: ['brightness', 'color_temp'],
},
};
/**
* Set the brightness and color temperature of a room light. (mock API)
* @param {number} brightness - Light level from 0 to 100. Zero is off and 100 is full brightness
* @param {string} color_temp - Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.
* @return {Object} A dictionary containing the set brightness and color temperature.
*/
function setLightValues(brightness, color_temp) {
return {
brightness: brightness,
colorTemperature: color_temp
};
}
第 2 步:使用函数声明调用模型
定义函数声明后,您可以提示模型使用该函数。它会分析提示和函数声明,并决定直接响应还是调用函数。如果调用了函数,响应对象将包含函数调用建议。
from google import genai
# Generation Config with Function Declaration
tools = types.Tool(function_declarations=[set_light_values_declaration])
config = types.GenerateContentConfig(tools=[tools])
# Configure the client
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
# Define user prompt
contents = [
types.Content(
role="user", parts=[types.Part(text="Turn the lights down to a romantic level")]
)
]
# Send request with function declarations
response = client.models.generate_content(
model="gemini-2.0-flash", config=config, contents=contents
)
print(response.candidates[0].content.parts[0].function_call)
import { GoogleGenAI } from '@google/genai';
// Generation Config with Function Declaration
const config = {
tools: [{
functionDeclarations: [setLightValuesFunctionDeclaration]
}]
};
// Configure the client
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Define user prompt
const contents = [
{
role: 'user',
parts: [{ text: 'Turn the lights down to a romantic level' }]
}
];
// Send request with function declarations
const response = await ai.models.generateContent({
model: 'gemini-2.0-flash',
contents: contents,
config: config
});
console.log(response.functionCalls[0]);
然后,模型会在与 OpenAPI 兼容的架构中返回 functionCall
对象,指定如何调用一个或多个已声明的函数以回答用户的问题。
id=None args={'color_temp': 'warm', 'brightness': 25} name='set_light_values'
{
name: 'set_light_values',
args: { brightness: 25, color_temp: 'warm' }
}
第 3 步:执行 set_light_values 函数代码
从模型的响应中提取函数调用详细信息,解析参数,并在代码中执行 set_light_values
函数。
# Extract tool call details
tool_call = response.candidates[0].content.parts[0].function_call
if tool_call.name == "set_light_values":
result = set_light_values(**tool_call.args)
print(f"Function execution result: {result}")
// Extract tool call details
const tool_call = response.functionCalls[0]
let result;
if (tool_call.name === 'set_light_values') {
result = setLightValues(tool_call.args.brightness, tool_call.args.color_temp);
console.log(`Function execution result: ${JSON.stringify(result)}`);
}
第 4 步:使用函数结果创建用户友好的回答,然后再次调用模型
最后,将函数执行结果发送回模型,以便模型将此信息纳入其对用户的最终回答中。
# Create a function response part
function_response_part = types.Part.from_function_response(
name=tool_call.name,
response={"result": result},
)
# Append function call and result of the function execution to contents
contents.append(types.Content(role="model", parts=[types.Part(function_call=tool_call)])) # Append the model's function call message
contents.append(types.Content(role="user", parts=[function_response_part])) # Append the function response
final_response = client.models.generate_content(
model="gemini-2.0-flash",
config=config,
contents=contents,
)
print(final_response.text)
// Create a function response part
const function_response_part = {
name: tool_call.name,
response: { result }
}
// Append function call and result of the function execution to contents
contents.push({ role: 'model', parts: [{ functionCall: tool_call }] });
contents.push({ role: 'user', parts: [{ functionResponse: function_response_part }] });
// Get the final response from the model
const final_response = await ai.models.generateContent({
model: 'gemini-2.0-flash',
contents: contents,
config: config
});
console.log(final_response.text);
至此,函数调用流程已完成。模型成功使用了 set_light_values
函数来执行用户的请求操作。
函数声明
在提示中实现函数调用时,您需要创建一个 tools
对象,其中包含一个或多个 function declarations
。您可以使用 JSON 定义函数,具体而言,使用 OpenAPI 架构格式的部分子集。单个函数声明可以包含以下参数:
name
(字符串):函数的唯一名称 (get_weather_forecast
、send_email
)。请使用不含空格或特殊字符的描述性名称(使用下划线或驼峰式命名法)。description
(字符串):清晰详细地说明函数的用途和功能。这对于模型了解何时使用该函数至关重要。请具体说明,并提供示例(“根据位置和影院正在上映的电影名(可选)查找影院。”)。parameters
(对象):定义函数预期的输入参数。type
(字符串):指定整体数据类型,例如object
。properties
(对象):列出各个参数,每个参数均包含以下信息:type
(字符串):参数的数据类型,例如string
、integer
、boolean, array
。description
(字符串):参数用途和格式的说明。提供示例和限制条件(“城市和州,例如“加利福尼亚州旧金山”或邮政编码(例如'95616'.")。enum
(数组,可选):如果参数值来自固定集,请使用“枚举”列出允许的值,而不是仅在说明中对其进行描述。这有助于提高准确性(“enum”:[“daylight”“cool”“warm”])。
required
(数组):一个字符串数组,用于列出函数运行所必需的参数名称。
并行函数调用
除了单轮函数调用之外,您还可以一次调用多个函数。并行函数调用可让您一次执行多个函数,适用于函数彼此不依赖的情况。在从多个独立来源收集数据(例如从不同的数据库检索客户详细信息、检查各个仓库中的库存水平,或执行多项操作,例如将公寓改造成迪斯科舞厅)等场景中,此功能非常有用。
power_disco_ball = {
"name": "power_disco_ball",
"description": "Powers the spinning disco ball.",
"parameters": {
"type": "object",
"properties": {
"power": {
"type": "boolean",
"description": "Whether to turn the disco ball on or off.",
}
},
"required": ["power"],
},
}
start_music = {
"name": "start_music",
"description": "Play some music matching the specified parameters.",
"parameters": {
"type": "object",
"properties": {
"energetic": {
"type": "boolean",
"description": "Whether the music is energetic or not.",
},
"loud": {
"type": "boolean",
"description": "Whether the music is loud or not.",
},
},
"required": ["energetic", "loud"],
},
}
dim_lights = {
"name": "dim_lights",
"description": "Dim the lights.",
"parameters": {
"type": "object",
"properties": {
"brightness": {
"type": "number",
"description": "The brightness of the lights, 0.0 is off, 1.0 is full.",
}
},
"required": ["brightness"],
},
}
import { Type } from '@google/genai';
const powerDiscoBall = {
name: 'power_disco_ball',
description: 'Powers the spinning disco ball.',
parameters: {
type: Type.OBJECT,
properties: {
power: {
type: Type.BOOLEAN,
description: 'Whether to turn the disco ball on or off.'
}
},
required: ['power']
}
};
const startMusic = {
name: 'start_music',
description: 'Play some music matching the specified parameters.',
parameters: {
type: Type.OBJECT,
properties: {
energetic: {
type: Type.BOOLEAN,
description: 'Whether the music is energetic or not.'
},
loud: {
type: Type.BOOLEAN,
description: 'Whether the music is loud or not.'
}
},
required: ['energetic', 'loud']
}
};
const dimLights = {
name: 'dim_lights',
description: 'Dim the lights.',
parameters: {
type: Type.OBJECT,
properties: {
brightness: {
type: Type.NUMBER,
description: 'The brightness of the lights, 0.0 is off, 1.0 is full.'
}
},
required: ['brightness']
}
};
使用可以使用所有指定工具的指令调用模型。此示例使用 tool_config
。如需了解详情,请参阅配置函数调用。
from google import genai
from google.genai import types
# Set up function declarations
house_tools = [
types.Tool(function_declarations=[power_disco_ball, start_music, dim_lights])
]
config = {
"tools": house_tools,
"automatic_function_calling": {"disable": True},
# Force the model to call 'any' function, instead of chatting.
"tool_config": {"function_calling_config": {"mode": "any"}},
}
# Configure the client
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
chat = client.chats.create(model="gemini-2.0-flash", config=config)
response = chat.send_message("Turn this place into a party!")
# Print out each of the function calls requested from this single call
print("Example 1: Forced function calling")
for fn in response.function_calls:
args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
print(f"{fn.name}({args})")
import { GoogleGenAI } from '@google/genai';
// Set up function declarations
const houseFns = [powerDiscoBall, startMusic, dimLights];
const config = {
tools: [{
functionDeclarations: houseFns
}],
// Force the model to call 'any' function, instead of chatting.
toolConfig: {
functionCallingConfig: {
mode: 'any'
}
}
};
// Configure the client
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Create a chat session
const chat = ai.chats.create({
model: 'gemini-2.0-flash',
config: config
});
const response = await chat.sendMessage({message: 'Turn this place into a party!'});
// Print out each of the function calls requested from this single call
console.log("Example 1: Forced function calling");
for (const fn of response.functionCalls) {
const args = Object.entries(fn.args)
.map(([key, val]) => `${key}=${val}`)
.join(', ');
console.log(`${fn.name}(${args})`);
}
输出的每个结果都反映了模型请求的单个函数调用。如需发回结果,请按请求的顺序添加响应。
Python SDK 支持一项名为自动函数调用的功能,该功能可将 Python 函数转换为声明,并为您处理函数调用执行和响应周期。以下是我们的迪斯科舞厅用例示例。
from google import genai
from google.genai import types
# Actual implementation functions
def power_disco_ball_impl(power: bool) -> dict:
"""Powers the spinning disco ball.
Args:
power: Whether to turn the disco ball on or off.
Returns:
A status dictionary indicating the current state.
"""
return {"status": f"Disco ball powered {'on' if power else 'off'}"}
def start_music_impl(energetic: bool, loud: bool) -> dict:
"""Play some music matching the specified parameters.
Args:
energetic: Whether the music is energetic or not.
loud: Whether the music is loud or not.
Returns:
A dictionary containing the music settings.
"""
music_type = "energetic" if energetic else "chill"
volume = "loud" if loud else "quiet"
return {"music_type": music_type, "volume": volume}
def dim_lights_impl(brightness: float) -> dict:
"""Dim the lights.
Args:
brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
Returns:
A dictionary containing the new brightness setting.
"""
return {"brightness": brightness}
config = {
"tools": [power_disco_ball_impl, start_music_impl, dim_lights_impl],
}
chat = client.chats.create(model="gemini-2.0-flash", config=config)
response = chat.send_message("Do everything you need to this place into party!")
print("\nExample 2: Automatic function calling")
print(response.text)
# I've turned on the disco ball, started playing loud and energetic music, and dimmed the lights to 50% brightness. Let's get this party started!
组合函数调用
Gemini 2.0 支持组合函数调用,这意味着模型可以将多个函数调用链接在一起。例如,为了回答“获取我当前所在位置的温度”,Gemini API 可能会同时调用一个 get_current_location()
函数和一个将位置作为参数的 get_weather()
函数。
# Light control schemas
turn_on_the_lights_schema = {'name': 'turn_on_the_lights'}
turn_off_the_lights_schema = {'name': 'turn_off_the_lights'}
prompt = """
Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
"""
tools = [
{'code_execution': {}},
{'function_declarations': [turn_on_the_lights_schema, turn_off_the_lights_schema]}
]
await run(prompt, tools=tools, modality="AUDIO")
// Light control schemas
const turnOnTheLightsSchema = { name: 'turn_on_the_lights' };
const turnOffTheLightsSchema = { name: 'turn_off_the_lights' };
const prompt = `
Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
`;
const tools = [
{ codeExecution: {} },
{ functionDeclarations: [turnOnTheLightsSchema, turnOffTheLightsSchema] }
];
await run(prompt, tools=tools, modality="AUDIO")
函数调用模式
借助 Gemini API,您可以控制模型使用所提供工具(函数声明)的方式。具体而言,您可以在 function_calling_config
中设置模式。
AUTO (Default)
:模型会根据提示和上下文决定是生成自然语言回答还是建议函数调用。这是最灵活的模式,适用于大多数场景。ANY
:模型会受到限制,始终预测函数调用并保证函数架构遵从。如果未指定allowed_function_names
,模型可以从任何提供的函数声明中进行选择。如果allowed_function_names
以列表的形式提供,则模型只能从该列表中的函数中进行选择。如果您需要针对每个提示(如果适用)进行函数调用,请使用此模式。NONE
:模型禁止进行函数调用。这相当于发送不含任何函数声明的请求。您可以使用此方法暂时停用函数调用,而无需移除工具定义。
from google.genai import types
# Configure function calling mode
tool_config = types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(
mode="ANY", allowed_function_names=["get_current_temperature"]
)
)
# Create the generation config
config = types.GenerateContentConfig(
temperature=0,
tools=[tools], # not defined here.
tool_config=tool_config,
)
import { FunctionCallingConfigMode } from '@google/genai';
// Configure function calling mode
const toolConfig = {
functionCallingConfig: {
mode: FunctionCallingConfigMode.ANY,
allowedFunctionNames: ['get_current_temperature']
}
};
// Create the generation config
const config = {
temperature: 0,
tools: tools, // not defined here.
toolConfig: toolConfig,
};
自动函数调用(仅限 Python)
使用 Python SDK 时,您可以直接将 Python 函数作为工具提供。SDK 会自动将 Python 函数转换为声明,并为您处理函数调用执行和响应周期。然后,Python SDK 会自动执行以下操作:
- 检测模型中的函数调用响应。
- 在代码中调用相应的 Python 函数。
- 将函数响应发送回模型。
- 返回模型的最终文本响应。
如需使用此方法,请使用类型提示和文档字符串定义函数,然后将函数本身(而非 JSON 声明)作为工具传递:
from google import genai
from google.genai import types
# Define the function with type hints and docstring
def get_current_temperature(location: str) -> dict:
"""Gets the current temperature for a given location.
Args:
location: The city and state, e.g. San Francisco, CA
Returns:
A dictionary containing the temperature and unit.
"""
# ... (implementation) ...
return {"temperature": 25, "unit": "Celsius"}
# Configure the client and model
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY")) # Replace with your actual API key setup
config = types.GenerateContentConfig(
tools=[get_current_temperature]
) # Pass the function itself
# Make the request
response = client.models.generate_content(
model="gemini-2.0-flash",
contents="What's the temperature in London?",
config=config,
)
print(response.text) # The SDK handles the function call and returns the final text
您可以使用以下方法停用自动函数调用:
# To disable automatic function calling:
config = types.GenerateContentConfig(
tools=[get_current_temperature],
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True)
)
自动函数架构声明
从 Python 函数自动提取架构并不适用于所有情况。例如,它无法处理您描述嵌套字典对象字段的情况。该 API 能够描述以下任意类型:
AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType])
如需查看推断出的架构的显示效果,您可以使用 from_callable
进行转换:
def multiply(a: float, b: float):
"""Returns a * b."""
return a * b
fn_decl = types.FunctionDeclaration.from_callable(callable=multiply, client=client)
# to_json_dict() provides a clean JSON representation.
print(fn_decl.to_json_dict())
多工具使用:将原生工具与函数调用结合使用
借助 Gemini 2.0,您可以同时启用多个工具,将原生工具与函数调用结合使用。下面的示例展示了如何使用 Live API 在请求中启用两种工具:使用 Google 搜索进行查询和代码执行。
# Multiple tasks example - combining lights, code execution, and search
prompt = """
Hey, I need you to do three things for me.
1. Turn on the lights.
2. Then compute the largest prime palindrome under 100000.
3. Then use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024.
Thanks!
"""
tools = [
{'google_search': {}},
{'code_execution': {}},
{'function_declarations': [turn_on_the_lights_schema, turn_off_the_lights_schema]} # not defined here.
]
# Execute the prompt with specified tools in audio modality
await run(prompt, tools=tools, modality="AUDIO")
// Multiple tasks example - combining lights, code execution, and search
const prompt = `
Hey, I need you to do three things for me.
1. Turn on the lights.
2. Then compute the largest prime palindrome under 100000.
3. Then use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024.
Thanks!
`;
const tools = [
{ googleSearch: {} },
{ codeExecution: {} },
{ functionDeclarations: [turnOnTheLightsSchema, turnOffTheLightsSchema] } // not defined here.
];
// Execute the prompt with specified tools in audio modality
await run(prompt, {tools: tools, modality: "AUDIO"});
Python 开发者可以在 Live API Tool Use 笔记本中试用此功能。
支持的模型
但不包括实验性模型。您可以在模型概览页面上找到这些功能。
型号 | 函数调用 | 并行函数调用 | 组合函数调用 (仅限 Live API) |
---|---|---|---|
Gemini 2.0 Flash | ✔️ | ✔️ | ✔️ |
Gemini 2.0 Flash-Lite | X | X | X |
Gemini 1.5 Flash | ✔️ | ✔️ | ✔️ |
Gemini 1.5 Pro | ✔️ | ✔️ | ✔️ |
最佳做法
- 函数和参数说明:说明要非常清晰、具体。模型依赖于这些信息来选择正确的函数并提供适当的参数。
- 命名:使用描述性函数名称(不含空格、句点或短划线)。
- 强类型:为参数使用特定类型(整数、字符串、枚举)以减少错误。如果参数只有一组有限的有效值,请使用枚举。
- 提示工程:
- 提供上下文:告知模型其角色(例如,“您是一位乐于助人的天气助理。”)。
- 提供说明:指定如何以及何时使用函数(例如“请勿猜测日期;预测时请始终使用未来的日期。”)。
- 鼓励澄清:指示模型根据需要提出澄清性问题。
- 温度:使用低温(例如0),以实现更具确定性和可靠性的函数调用。
- 验证:如果函数调用会产生重大后果(例如下单),请在执行之前先向用户验证该调用。
- 错误处理:在函数中实现强大的错误处理功能,以妥善处理意外输入或 API 失败。返回信息丰富的错误消息,供模型使用以向用户生成有用的回答。
- 安全:调用外部 API 时,请注意安全性。使用适当的身份验证和授权机制。避免在函数调用中泄露敏感数据。
- 令牌限制:函数说明和参数会计入输入令牌限制。如果您达到了令牌限制,请考虑限制函数数量或说明长度,并将复杂任务拆分成更小、更专注的函数集。
注意事项和限制
- 仅支持 OpenAPI 架构的一部分。
- Python 中支持的参数类型有限。
- 自动函数调用仅适用于 Python SDK。