Function Calling是Gemini API最实用的能力之一:你在请求中描述一组自己写的函数,模型在对话过程中判断是否需要调用某个函数,并以结构化JSON的形式返回函数名和参数,由你的代码执行后再把结果回传给模型继续生成回答。整个过程里模型并不真正执行函数,它只负责决策与参数组织,执行权完全在你的服务端,这也是Function Calling安全性的核心设计。本文将完整讲解函数声明的写法、自动函数选择的内部逻辑,并给出可直接运行的代码示例。

一、函数声明的基本结构与请求格式
要启用Function Calling,首先需要在请求的tools字段中声明可用函数。每个函数包含名称、描述和参数的JSON Schema定义。描述的质量直接决定自动函数选择的准确率,因为模型主要依靠语义理解来匹配用户意图,描述越清晰,误判越少。
下面是一个通过REST接口声明的完整请求示例,定义了获取天气和查询订单两个函数:
const requestBody = {
contents: [{
role: "user",
parts: [{ text: "帮我查一下上海明天的天气" }]
}],
tools: [{
functionDeclarations: [
{
name: "get_weather",
description: "查询指定城市在指定日期的天气情况,包括温度、湿度、风力",
parameters: {
type: "OBJECT",
properties: {
city: { type: "STRING", description: "城市名称,例如:上海" },
date: { type: "STRING", description: "日期,格式为yyyy-mm-dd" }
},
required: ["city"]
}
},
{
name: "get_order_status",
description: "根据订单编号查询订单的当前状态和物流信息",
parameters: {
type: "OBJECT",
properties: {
order_id: { type: "STRING", description: "订单编号" }
},
required: ["order_id"]
}
}
]
}]
};
// 发送请求
const response = await fetch(
"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-goog-api-key": "你的API密钥"
},
body: JSON.stringify(requestBody)
}
);
const data = await response.json();
当模型判断需要调用函数时,响应中不会直接返回文本,而是返回一个functionCall对象。它的结构大致如下:
{
"candidates": [{
"content": {
"role": "model",
"parts": [{
"functionCall": {
"name": "get_weather",
"args": {
"city": "上海",
"date": "2025-06-10"
}
}
}]
}
}]
}
注意几个细节:参数类型使用大写的OBJECT、STRING、NUMBER等Schema类型名;required数组指明必填参数,模型会尽量为必填参数生成值;如果用户输入缺少必要信息,模型有时会直接反问用户,而不是硬编造参数,这一点比多数同类模型表现更好。
二、自动函数选择机制是如何工作的
自动函数选择指的是模型在没有人工指定的情况下,自行决定调用哪个函数、是否调用函数。它的工作原理可以拆解为三步:第一步,模型对用户输入做语义解析,提取意图关键词;第二步,将解析结果与所有functionDeclarations的名称和描述做匹配度计算;第三步,选择匹配度最高的函数并按Schema组装参数。
理解这个机制对写好函数声明至关重要。例如用户说“我的包裹到哪了”,如果只有get_order_status一个函数,模型会自然选择它;但如果同时存在多个相似函数,比如又加了一个get_logistics_detail,模型的选择就可能出现摇摆。实践中推荐的做法是:让函数职责边界清晰,避免语义重叠;在描述中明确说明适用场景与不适用场景;必要时在函数名中体现业务语义。
模型的函数选择还支持并行调用。当用户一句话包含多个意图,比如“查一下上海天气,顺便看看订单12345的状态”,模型会返回多个functionCall片段:
{
"candidates": [{
"content": {
"role": "model",
"parts": [
{ "functionCall": { "name": "get_weather", "args": { "city": "上海" } } },
{ "functionCall": { "name": "get_order_status", "args": { "order_id": "12345" } } }
]
}
}]
}
处理这种响应时,你的代码要遍历所有parts,逐个执行函数并收集结果。另外,如果你希望模型不要自作主张选函数,Gemini提供了tool_config的functionCallingConfig模式,可以设置为ANY强制调用指定函数,或设置为NONE完全禁用函数调用:
toolConfig: {
functionCallingConfig: {
mode: "ANY", // 强制必须调用函数
allowedFunctionNames: ["get_weather"] // 只允许调用这个函数
}
}
这个配置在构建确定性流程时非常有用,例如表单填写场景中,你明确知道下一步必须调用校验函数,就可以用ANY模式消除模型的不确定性。
三、执行函数并把结果回传给模型
拿到functionCall之后,真正执行函数的是你自己的代码。执行完毕后,需要把结果包装成functionResponse,连同历史消息一起回传给模型,模型才能基于真实数据生成最终回答。完整的循环流程是:用户提问、模型返回函数调用请求、代码执行函数、回传结果、模型生成自然语言回复。
下面是一个完整的Python示例,使用官方SDK实现整个闭环:
import google.generativeai as genai
import json
genai.configure(api_key="你的API密钥")
# 定义本地真实函数
def get_weather(city: str, date: str = None) -> dict:
# 实际项目中这里调用天气服务接口
return {"city": city, "date": date, "temp": "26度", "condition": "多云"}
model = genai.GenerativeModel(
model_name="gemini-1.5-pro",
tools=[{
"function_declarations": [{
"name": "get_weather",
"description": "查询指定城市的天气情况",
"parameters": {
"type_": "OBJECT",
"properties": {
"city": {"type_": "STRING", "description": "城市名称"}
},
"required": ["city"]
}
}]
}]
)
chat = model.start_chat()
response = chat.send_message("上海今天天气怎么样?")
# 检查是否返回了函数调用
for part in response.parts:
if fn := part.function_call:
args = {k: v for k, v in fn.args.items()}
result = get_weather(**args)
# 把执行结果回传给模型
response = chat.send_message({
"function_response": {
"name": fn.name,
"response": result
}
})
print(response.text)
回传结果时有几个要点值得注意。functionResponse中的response字段必须是JSON对象,不能是纯字符串;如果函数执行失败,也应该返回一个包含错误信息的结构化对象,例如{"error": "城市名无法识别"},模型会据此向用户解释或重新发起调用,而不是让程序直接抛异常中断对话。
多轮对话中记得保留完整的消息历史。Gemini需要看到之前的functionCall和functionResponse配对,才能理解上下文。如果只回传函数结果而不带上对应的调用记录,接口会报格式错误。
四、常见问题与排查思路
第一个常见问题是参数幻觉:模型给函数编造了不存在的参数值,比如用户没说日期,模型自己填了一个。解决办法是在参数描述里写明“如果用户未提供,不要猜测”,或者把该参数从required中移除,让模型学会在信息不足时反问用户。
第二个问题是模型选错函数。遇到这种情况,优先检查函数描述是否模糊、函数之间是否存在语义重叠。一个有效的技巧是在描述中加入具体触发例句,例如写上“当用户询问物流、快递、到货时间时使用本函数”,能显著提升选择准确率。
第三个问题是Schema类型不匹配。Gemini对枚举值支持enum字段,对嵌套对象支持properties嵌套定义,但对数组的items定义在不同版本中行为略有差异,建议先用简单类型跑通流程,再逐步增加复杂度。此外,所有Schema属性名要用驼峰式小写开头,type_在Python SDK中由于与关键字冲突需要加下划线。
最后一点关于安全:永远不要把函数执行的决策权交给模型而无校验。在真正执行前,务必对模型返回的参数做类型检查、范围校验和权限验证,尤其是涉及数据库写入、支付、文件操作的函数。Function Calling的架构设计本身就是“模型决策、代码执行”,把这个边界守住,就能在获得灵活性的同时保证系统安全。
Gemini APIFunction Calling自动函数选择修改时间:2026-09-01 07:34:58