1. 概览
Gemini 中的函数调用是什么?
Vertex AI Gemini API 是 Google DeepMind 开发的一系列生成式 AI 模型,专为多模态应用场景而设计。函数调用是 Gemini 模型的一项功能,可让开发者更轻松地从生成式模型获取结构化数据输出。
然后,开发者可以使用这些输出来调用其他 API,并将相关响应数据返回给模型。换句话说,函数调用可帮助您将生成式模型连接到外部系统,以便生成的内容包含最新、最准确的信息。
函数调用的工作原理
函数使用函数声明来描述,这有助于生成模型了解函数中的用途和参数。在查询中将函数声明传递给生成模型后,该模型会根据用户的查询返回一个结构化对象,其中包含相关函数的名称及其参数。请注意,使用函数调用时,模型实际上并不会调用函数。您可以改为使用返回的函数和参数,以您喜欢的任何语言、库或框架调用该函数!

构建内容
在此 Codelab 中,您将使用 Vertex AI Gemini API 和 Python 构建生成式 AI 流水线。用户可以使用您的应用询问汇率,系统会从外部 API 获取最新数据,并向用户提供回答。
学习内容
- 如何使用 Python 客户端库与 Gemini 模型互动
- 如何定义函数声明并将其注册为工具
- 如何调用 Gemini 并获取函数调用响应
- 如何将函数响应返回给 Gemini 并回复用户
所需条件
- Google Cloud 项目
- 浏览器,例如 Chrome
- Python 开发环境,例如 Colab 或 Colab Enterprise
2. 设置和要求
在 Gemini 中开始使用函数调用之前,您需要启用 Vertex AI API 并安装最新版本的 Vertex AI Python 客户端库。
启用 Vertex AI API
如需启用 Vertex AI API,请按以下步骤操作:
- 在浏览器中,前往 Vertex AI API 服务详情页面。
- 点击启用按钮,以在您的 Google Cloud 云项目中启用 Vertex AI API。
安装 Vertex AI 的 Python 客户端库
如需安装 Python 版 Vertex AI 客户端库,请按以下步骤操作:
- 在开发环境中打开终端。
- 验证您是否拥有有效的 Python 开发环境,如有需要,请参阅这些准则。
- 运行以下命令以安装 Vertex AI 的 Python 客户端库:
pip install --upgrade google-cloud-aiplatform - 如果您在笔记本环境中运行,则可能需要重启运行时/内核才能使用新安装的软件包。
现在,您可以使用 Vertex AI API 了!
3. 了解问题
您是否曾与大语言模型或生成式 AI 模型互动,询问实时信息或当前信息,但得到的回答却包含过时或不准确的信息?
快试试吧!首先,我们将导入相关的 Python 软件包并初始化 Gemini 模型。您可以在 Python 开发环境(例如 Colab 或 Colab Enterprise)中运行以下代码,并安装最新版本的 Vertex AI SDK for Python:
import vertexai
from vertexai.generative_models import GenerativeModel
model = GenerativeModel("gemini-1.5-pro-001")
现在,我们来问一个关于今天不同币种汇率的问题:
response = model.generate_content(
"What's the exchange rate for euros to dollars today?"
)
print(response.text)
模型应该会为您生成有限或过时的回答,类似于:
As an AI language model, I don't have access to real-time currency exchange rates. However, as of my last update in September 2021, the approximate exchange rate between euros (EUR) and US dollars (USD) was: 1 EUR ≈ 1.18 USD Please note that currency exchange rates constantly fluctuate and can vary depending on various factors such as economic conditions, supply and demand, political events, and more. To obtain the most up-to-date and accurate exchange rate, I recommend using a reliable currency converter or financial website that provides live rates. [...]
如果最终用户收到此类响应,则需要切换上下文来查找他们感兴趣的币种,获取最新的汇率,并自行执行任何换算。
理想情况下,生成模型流水线可以为用户处理部分或全部这些任务。在下一部分中,您将尝试一些常见的解决方法,以便从生成式模型获取结构化回答,从而调用外部系统。
4. 尝试常用的解决方法
在需要外部来源的最新信息或数据的场景中使用生成模型时,您可以先调用外部 API,然后将结果反馈给生成模型,以便其在响应中使用。
在调用外部系统之前,您需要确定要使用的正确函数,从用户那里提取相关参数,并将这些参数放入结构化数据对象中。这通常需要进行详尽的提示工程,以强制生成模型输出有效的结构化数据。
让我们重新审视上一部分中提出的问题,并为模型添加一些额外的指令。不妨尝试向 Gemini 模型发送以下请求:
user_prompt = "What's the exchange rate from euros to US dollars today?"
response = model.generate_content("""
Your task is to extract parameters from the user's input and return it as a
structured JSON payload. The user will ask about the exchange rate and which
currency they are converting from and converting to.
User input: {user_prompt}
Please extract the currencies as parameters and put them in a JSON object.
""".format(user_prompt=user_prompt))
print(response.text)
这会生成以下文本响应,该响应不是有效的 JSON,我们很难使用:
```json
{
"currency_from": "euros",
"currency_to": "US dollars"
}
```
具体来说,文本响应的第一行和最后一行包含用于分隔代码块的反引号,第一行包含语言说明符,并且 JSON 对象中的值不是货币兑换 API 作为输入参数所期望的标准三字母货币缩写。
我们可以尝试使用 Python 将此文本后处理为有效的 JSON 和字典,向提示添加更多指令,提供一个或多个所需输出示例,对模型进行微调,或者再次调用生成模型,要求其清理 JSON。
不过,还有一种更具确定性的方法!我们来了解一下如何在 Gemini 中使用函数调用来查询外部服务中的信息,并向最终用户返回相关回答。
5. 函数调用的工作原理
在开始介绍参数提取和函数调用之前,我们先来了解一下函数调用的步骤以及运行时使用的组件。

用户向 Gemini API 提供的输入
用户的提示会发送到 Gemini API,在对 Gemini 模型的该 API 调用中,开发者已在工具中定义了一个或多个函数声明,以便 Gemini 模型知道它可以调用哪些函数以及如何调用这些函数。
Gemini API 返回函数调用
根据用户输入和提示的内容,Gemini 将返回一个函数调用响应,其中包含结构化数据,包括要调用的函数名称和要使用的相应参数。
发出 API 请求
然后,您将使用函数名称和参数发出 API 请求,以从外部系统或 API 检索信息。此 API 请求和响应由开发者在应用代码中实现,并且发生在 Gemini API 和 SDK 的范围之外。例如,您可以在 Python 中使用 requests 库来调用 REST API 并接收 JSON 响应。或者,您也可以使用自己偏好的方法和客户端库来调用该函数。
将 API 响应返回给 Gemini
最后,您需要将 API 响应传递回 Gemini 模型,以便该模型可以针对最终用户的初始提示生成响应,或者在 Gemini 模型确定需要更多信息时调用另一个函数调用响应。
6. 选择 API
现在,您已经了解了函数调用的总体流程和具体步骤,接下来将构建一个生成式 AI 流水线来获取最新的货币汇率。首先,我们需要选择要用作信息来源的 API。
对于我们的货币兑换应用,我们将使用 https://www.frankfurter.app/ 上的 REST API 来获取有关全球汇率的最新信息。
为了与此 REST API 进行交互,我们可能会在 Python 中使用 requests 进行 REST API 调用,如下所示:
import requests
url = "https://api.frankfurter.app/latest"
response = requests.get(url)
response.text
或 cURL 请求,例如:
curl https://api.frankfurter.app/latest
该命令会返回类似于以下内容的响应:
{
"amount": 1,
"base": "EUR",
"date": "2023-12-20",
"rates": {
"AUD": 1.6186, "BGN": 1.9558, "BRL": 5.3287,
"CAD": 1.4609, "CHF": 0.946, "CNY": 7.8121,
"CZK": 24.538, "DKK": 7.4565, "GBP": 0.86555,
"HKD": 8.5439, "HUF": 385.23, "IDR": 16994,
"ILS": 3.9983, "INR": 91.06, "ISK": 150.3,
"JPY": 157.12, "KRW": 1425.62, "MXN": 18.6867,
"MYR": 5.0977, "NOK": 11.2895, "NZD": 1.7421,
"PHP": 60.991, "PLN": 4.3413, "RON": 4.9699,
"SEK": 11.129, "SGD": 1.4562, "THB": 38.252,
"TRY": 31.883, "USD": 1.0944, "ZAR": 20.111
}
}
由于 Gemini 中的函数调用实际上不会为您进行外部 API 调用,因此您使用的 API 类型不受此类限制!您可以使用 Cloud Run 服务、Cloud Function、针对 Google Cloud 服务的 API 请求或任何外部 REST API。
7. 定义函数和工具
现在,您已选择要使用的 REST API,接下来可以定义 API 规范并在工具中注册该函数。
确保您已安装最新版本的 Vertex AI SDK for Python。
然后,从 Python SDK 导入必要的模块并初始化 Gemini 模型:
from vertexai.generative_models import (
Content,
FunctionDeclaration,
GenerativeModel,
Part,
Tool,
)
model = GenerativeModel("gemini-1.5-pro-001")
回到 https://api.frankfurter.app/ 的 REST API,我们可以看到它接受以下输入参数:
参数 | 类型 | 说明 |
| 字符串 | 要转换的币种 |
| 字符串 | 要换算成的币种 |
| 字符串 | 要获取的汇率对应的日期 |
使用这些参数,此 REST API 的部分 OpenAPI 规范(采用 YAML 格式)如下所示:
openapi: 3.0.0
info:
title: Frankfurter Exchange Rate API
description: This API provides current and historical exchange rates
version: 1.0.0
servers:
- url: https://api.frankfurter.app
paths:
/{date}:
get:
summary: Get the latest currency exchange rates.
parameters:
- name: date
in: path
description: Get currency rates for a specific date or 'latest' if a date is not specified
required: true
schema:
type: string
- name: from
in: query
description: The currency to convert from.
required: true
schema:
type: string
- name: to
in: query
description: The currency to convert to.
schema:
type: string
现在,我们使用适用于 Gemini 的 Python SDK 将其注册为 FunctionDeclaration:
get_exchange_rate_func = FunctionDeclaration(
name="get_exchange_rate",
description="Get the exchange rate for currencies between countries",
parameters={
"type": "object",
"properties": {
"currency_date": {
"type": "string",
"description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
},
"currency_from": {
"type": "string",
"description": "The currency to convert from in ISO 4217 format"
},
"currency_to": {
"type": "string",
"description": "The currency to convert to in ISO 4217 format"
}
},
"required": [
"currency_from",
"currency_date",
]
},
)
请务必在函数和参数说明中尽可能详细地说明,因为生成模型会使用此信息来确定要选择哪个函数以及如何在函数调用中填充参数。
最后,您将定义一个包含函数声明的 Tool:
exchange_rate_tool = Tool(
function_declarations=[get_exchange_rate_func],
)
在此示例中,您在工具中使用了一个函数声明,但请注意,您可以在工具中注册一个或多个函数声明,模型会在运行时选择要使用的相应函数。如需详细了解 Gemini SDK for Python 中的 FunctionDeclaration、Tool 和相关类,请参阅 Gemini API 中的函数调用文档。
您已完成函数和工具定义的配置。在下一部分中,我们将使用此工具调用生成模型,并返回一个可用于调用 REST API 的函数调用。
8. 生成函数调用
现在,您可以向生成模型发出提示,并包含您定义的 tool:
prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""
response = model.generate_content(
prompt,
tools=[exchange_rate_tool],
)
我们来看一下响应对象:
print(response.candidates[0].content)
role: "model"
parts {
function_call {
name: "get_exchange_rate"
args {
fields {
key: "currency_to"
value {
string_value: "SEK"
}
}
fields {
key: "currency_from"
value {
string_value: "AUD"
}
}
fields {
key: "currency_date"
value {
string_value: "latest"
}
}
}
}
}
看起来,模型选择了一个可用的函数,并返回了 get_exchange_rate 函数的函数调用以及参数。并且参数的格式符合我们的要求。太棒了,现在可以从生成式模型获取结构化回答了!
在下一部分中,您将使用响应中的信息发出 API 请求。
9. 发出 API 请求
请注意,Gemini 中的函数调用实际上并不会为您进行外部 API 调用。您可以随意使用任何语言、库或框架!
在此处,您将使用 Python 中的 requests 库来调用汇率 REST API。
让我们将响应解压缩到 Python 字典中:
params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
params[key[9:]] = value
params
现在,我们可以调用 requests 或任何其他方法:
import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text
这会生成类似于以下内容的响应:
'{"amount":1.0,"base":"AUD","date":"2024-01-16","rates":{"SEK":6.8682}}'
我们收到了来自 REST API 的响应,其中包含今天的最新汇率信息。在下一部分中,我们将把此信息传递回模型,以便模型可以为用户生成相关回答。
10. 生成回答
最后,让我们在下一个对话轮次中将函数响应传递回模型,从而为用户生成回答:
response = model.generate_content(
[
Content(role="user", parts=[
Part.from_text(prompt + """Give your answer in steps with lots of detail
and context, including the exchange rate and date."""),
]),
Content(role="function", parts=[
Part.from_dict({
"function_call": {
"name": "get_exchange_rate",
}
})
]),
Content(role="function", parts=[
Part.from_function_response(
name="get_exchange_rate",
response={
"content": api_response.text,
}
)
]),
],
tools=[exchange_rate_tool],
)
response.candidates[0].content.parts[0].text
将函数响应传递回模型后,模型会根据用户提示以及 API 响应中的相关信息做出回答。
The exchange rate from Australian dollars to Swedish krona on January 16, 2024, is 1 Australian dollar is equal to 6.8663 Swedish krona. So, 500 Australian dollars would be worth 500 * 6.8663 = 3,433.15 Swedish krona.
11. 查看完整代码示例
此时,您可以将 Python 代码放入使用 Cloud Run 服务、Cloud Function 或其他 Cloud 服务的后端 API 中,并部署一个使用此后端 API 来执行模型查询和 API 调用的前端应用。
以下是最终解决方案的完整代码示例:
import requests
from vertexai.generative_models import (
Content,
FunctionDeclaration,
GenerativeModel,
Part,
Tool,
)
model = GenerativeModel("gemini-1.5-pro-001")
get_exchange_rate_func = FunctionDeclaration(
name="get_exchange_rate",
description="Get the exchange rate for currencies between countries",
parameters={
"type": "object",
"properties": {
"currency_date": {
"type": "string",
"description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
},
"currency_from": {
"type": "string",
"description": "The currency to convert from in ISO 4217 format"
},
"currency_to": {
"type": "string",
"description": "The currency to convert to in ISO 4217 format"
}
},
"required": [
"currency_from",
"currency_date",
]
},
)
exchange_rate_tool = Tool(
function_declarations=[get_exchange_rate_func],
)
prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""
response = model.generate_content(
prompt,
tools=[exchange_rate_tool],
)
response.candidates[0].content
params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
params[key[9:]] = value
params
import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text
response = model.generate_content(
[
Content(role="user", parts=[
Part.from_text(prompt + """Give your answer in steps with lots of detail
and context, including the exchange rate and date."""),
]),
Content(role="function", parts=[
Part.from_dict({
"function_call": {
"name": "get_exchange_rate",
}
})
]),
Content(role="function", parts=[
Part.from_function_response(
name="get_exchange_rate",
response={
"content": api_response.text,
}
)
]),
],
tools=[exchange_rate_tool],
)
response.candidates[0].content.parts[0].text
在此实现中,我们向生成模型发出了两个请求:一个请求用于生成函数调用,另一个请求用于返回函数响应。请注意,这只是使用 Gemini 处理函数调用和函数响应的一种方法。您还可以进行额外的函数调用,以获取有关查询的更多信息,或者将函数调用与聊天和异步方法搭配使用。
如需查看其他代码示例,请参阅 Gemini 中的函数调用示例笔记本。
12. 恭喜
您已成功使用 Gemini 中的函数调用功能构建了一个生成式 AI 流水线,该流水线可与 Vertex AI Gemini API 和 Python 搭配使用!用户可以询问汇率,系统会从外部 API 获取最新数据并给出回答。
在 Gemini 中,函数调用功能可根据最终用户的提示选择合适的函数、从提示中提取参数,并返回一个结构化数据对象,供您进行外部 API 调用。
Gemini 中的函数调用功能旨在让您能够以确定性的方式提取参数,同时将摘要生成和内容创作任务交给生成模型,从而兼顾两者的优势。您可以随意尝试流水线中的其他 API 和提示,并探索与 Vertex AI Gemini API 相关的其他可用功能。

清理
您可以执行以下清理操作,以避免系统因本 Codelab 中使用的资源向您的 Google Cloud 账号收取费用:
- 为避免产生不必要的 Google Cloud 费用,请使用 Google Cloud 控制台删除您不需要的项目。
- 如果您想停用 Vertex AI 的 API,请前往 Vertex AI API 服务详情页面,然后点击停用 API 并确认。
了解详情
请参阅以下指南和资源,继续了解对话式 AI 和生成式 AI:
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。