函数调用简介

大语言模型 (LLM) 擅长解决许多类型的问题。但是,它们受到以下限制:

  • 模型在训练后被冻结,导致知识过时。
  • 无法查询或修改外部数据。

函数调用可以解决这些缺点。函数调用有时也称为“工具使用”,因为它允许模型使用外部工具,例如 API 和函数。

向 LLM 提交提示时,您还需要向模型提供一组工具,以便模型可以使用这些工具来响应用户提示。例如,您可以提供一个函数 get_weather,该函数接受一个位置参数,并返回该位置的天气状况信息。

处理提示时,该模型可以选择将某些数据处理任务委托给您确定的函数。模型不会直接调用函数。相反,模型会提供结构化数据输出,其中包含要调用的函数和要使用的参数值。例如,对于提示 What is the weather like in Boston?,模型可以将处理委托给 get_weather 函数,并提供位置参数值 Boston, MA

您可以使用模型的结构化输出来调用外部 API。例如,您可以连接到天气服务 API,提供位置 Boston, MA,并接收有关温度、云量和风况的信息。

然后,您可以将 API 输出返回给模型,使模型能够完成对提示的回答。对于天气示例,模型可能会提供以下回答:It is currently 38 degrees Fahrenheit in Boston, MA with partly cloudy skies.

函数调用交互 

支持的模型

以下模型支持函数调用:

模型 版本 函数调用发布阶段 支持并行函数调用 支持强制函数调用
Gemini 1.0 Pro all versions 正式版
Gemini 1.5 Flash all versions 正式版
Gemini 1.5 Pro all versions 正式版

函数调用的应用场景

您可以使用函数调用执行以下任务:

使用场景 示例说明 示例链接
与外部 API 集成 使用气象 API 获取天气信息 笔记本教程
将地址转换为纬度/经度坐标 笔记本教程
使用货币兑换 API 进行货币转换 Codelab
构建高级聊天机器人 回答客户关于产品和服务的问题 笔记本教程
创建一个助理来回答有关公司财务和新闻的问题 笔记本教程
结构和控制函数调用 从原始日志数据中提取结构化实体 笔记本教程
从用户输入中提取单个或多个参数 笔记本教程
在函数调用中处理列表和嵌套数据结构 笔记本教程
处理函数调用行为 处理并行函数调用和响应 笔记本教程
管理模型可以调用的时间和函数 笔记本教程
使用自然语言查询数据库 将自然语言问题转换为适用于 BigQuery 的 SQL 查询 示例应用
多模态函数调用 使用图片、视频、音频和 PDF 作为输入来触发函数调用 笔记本教程

下面是一些其他用例:

  • 解读语音指令:创建与车载任务相对应的函数。例如,您可以创建用于开启电台或启动空调的函数。将用户语音指令的音频文件发送到模型,要求模型将音频转换为文字,并识别用户想要调用的功能。

  • 根据环境触发器自动执行工作流:创建用于表示可自动化的流程的函数。向模型提供来自环境传感器的数据,并要求模型解析和处理数据,以确定是否应激活一个或多个工作流。例如,一个模型可以处理仓库中的温度数据,并选择启用洒水器功能。

  • 自动分配支持服务工单:为模型提供支持服务工单、日志和内容感知规则。让模型处理所有这些信息,以确定应将工单分配给谁。调用一个函数,将工单分配给模型建议的人员。

  • 从知识库中检索信息:创建用于检索并汇总给定主题方面的学术文章的函数。使模型能够回答有关学术主题的问题,并为其答案提供引用。

如何创建函数调用应用

为了让用户能够与模型交互并使用函数调用,您必须创建执行以下任务的代码:

  1. 设置您的环境
  2. 使用函数声明定义和描述一组可用的函数
  3. 向模型提交用户的提示和函数声明
  4. 使用模型输出的结构化数据调用函数
  5. 向模型提供函数输出

您可以创建一个应用来管理所有这些任务。此应用可以是文本聊天机器人、语音客服、自动化工作流或任何其他程序。

您可以使用函数调用生成单个文本回答或支持聊天会话。临时文本回答对于特定的业务任务(包括代码生成)非常有用。聊天会话在形式自由的对话场景中非常有用,这些场景中用户可能会询问后续问题。

如果您使用函数调用生成单个回答,则必须为模型提供互动的完整上下文。另一方面,如果您在聊天会话的上下文中使用函数调用,则会话会为您存储上下文,并将其包含在每个模型请求中。在这两种情况下,Vertex AI 都会将互动的历史记录存储在客户端。

本指南演示了如何使用函数调用生成单个文本响应。如需查看端到端示例,请参阅文本示例。如需了解如何使用函数调用来支持聊天会话,请参阅聊天示例

第 1 步:设置环境

导入所需的模块并初始化模型:

Python

import vertexai
from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerationConfig,
    GenerativeModel,
    Part,
    Tool,
)

# Initialize Vertex AI
# TODO(developer): Update and un-comment below lines
# PROJECT_ID = 'your-project-id'
vertexai.init(project=PROJECT_ID, location="us-central1")

# Initialize Gemini model
model = GenerativeModel(model_name="gemini-1.5-flash-002")

第 2 步:声明一组函数

应用必须声明一组函数,供模型用于处理提示。

请求中可提供的函数声明的最大数量为 128 个。

您必须以与 OpenAPI 架构兼容的架构格式提供函数声明。Vertex AI 对 OpenAPI 架构提供有限支持。支持以下属性:typenullablerequiredformatdescriptionpropertiesitemsenum。不支持以下属性:defaultoptionalmaximumoneOf。如需了解与函数声明相关的最佳实践(包括有关名称和说明的提示),请参阅最佳实践

如果您使用 REST API,请使用 JSON 指定架构。如果您使用的是 Vertex AI SDK for Python,则可以使用 Python 字典手动指定架构,也可以使用 from_func 辅助函数自动指定架构。

JSON

{
  "contents": ...,
  "tools": [
    {
      "function_declarations": [
        {
          "name": "find_movies",
          "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
              },
              "description": {
                "type": "string",
                "description": "Any kind of description including category or genre, title words, attributes, etc."
              }
            },
            "required": [
              "description"
            ]
          }
        },
        {
          "name": "find_theaters",
          "description": "find theaters based on location and optionally movie title which are is currently playing in theaters",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
              },
              "movie": {
                "type": "string",
                "description": "Any movie title"
              }
            },
            "required": [
              "location"
            ]
          }
        },
        {
          "name": "get_showtimes",
          "description": "Find the start times for movies playing in a specific theater",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
              },
              "movie": {
                "type": "string",
                "description": "Any movie title"
              },
              "theater": {
                "type": "string",
                "description": "Name of the theater"
              },
              "date": {
                "type": "string",
                "description": "Date for requested showtime"
              }
            },
            "required": [
              "location",
              "movie",
              "theater",
              "date"
            ]
          }
        }
      ]
    }
  ]
}

Python 字典

以下函数声明接受单个 string 参数:

function_name = "get_current_weather"
get_current_weather_func = FunctionDeclaration(
    name=function_name,
    description="Get the current weather in a given location",
    # Function parameters are specified in JSON schema format
    parameters={
        "type": "object",
        "properties": {
            "location": {"type": "string", "description": "The city name of the location for which to get the weather."}
        },
    },
)

以下函数声明同时接受对象和数组参数:

extract_sale_records_func = FunctionDeclaration(
  name="extract_sale_records",
  description="Extract sale records from a document.",
  parameters={
      "type": "object",
      "properties": {
          "records": {
              "type": "array",
              "description": "A list of sale records",
              "items": {
                  "description": "Data for a sale record",
                  "type": "object",
                  "properties": {
                      "id": {"type": "integer", "description": "The unique id of the sale."},
                      "date": {"type": "string", "description": "Date of the sale, in the format of MMDDYY, e.g., 031023"},
                      "total_amount": {"type": "number", "description": "The total amount of the sale."},
                      "customer_name": {"type": "string", "description": "The name of the customer, including first name and last name."},
                      "customer_contact": {"type": "string", "description": "The phone number of the customer, e.g., 650-123-4567."},
                  },
                  "required": ["id", "date", "total_amount"],
              },
          },
      },
      "required": ["records"],
  },
)

函数中的 Python

以下代码示例声明了一个函数,该函数会对数组中的数字相乘,并使用 from_func 生成 FunctionDeclaration 架构。

# Define a function. Could be a local function or you can import the requests library to call an API
def multiply_numbers(numbers):
  """
  Calculates the product of all numbers in an array.

  Args:
      numbers: An array of numbers to be multiplied.

  Returns:
      The product of all the numbers. If the array is empty, returns 1.
  """

  if not numbers:  # Handle empty array
      return 1

  product = 1
  for num in numbers:
      product *= num

  return product

multiply_number_func = FunctionDeclaration.from_func(multiply_numbers)

'''
multiply_number_func contains the following schema:

name: "multiply_numbers"
description: "Calculates the product of all numbers in an array."
parameters {
  type_: OBJECT
  properties {
    key: "numbers"
    value {
      description: "An array of numbers to be multiplied."
      title: "Numbers"
    }
  }
  required: "numbers"
  description: "Calculates the product of all numbers in an array."
  title: "multiply_numbers"
}
'''

第 3 步:将提示和函数声明提交给模型

当用户提供提示时,应用必须为模型提供用户提示和函数声明。如需配置模型生成结果的方式,应用可以为模型提供生成配置。如需配置模型使用函数声明的方式,应用可以为模型提供工具配置

定义用户提示

以下是用户提示的示例:“波士顿的天气如何?”

以下示例展示了如何定义用户提示:

Python

# Define the user's prompt in a Content object that we can reuse in model calls
user_prompt_content = Content(
    role="user",
    parts=[
        Part.from_text("What is the weather like in Boston?"),
    ],
)

如需了解与用户提示相关的最佳实践,请参阅最佳实践 - 用户提示

生成配置

对于不同的参数值,模型会生成不同的结果。温度参数用于控制此生成中的随机程度。 较低的温度有利于需要确定性参数值的函数,而较高的温度有利于参数接受更具多样性或创造性的参数值的函数。温度为 0 表示确定性。在这种情况下,给定提示的回复大多是确定的,但可能仍然有少量变化。如需了解详情,请参阅 Gemini API

如需设置此参数,请提交生成配置 (generation_config) 以及提示和函数声明。 您可以使用 Vertex AI API 和更新后的 generation_config 在聊天对话期间更新 temperature 参数。如需查看设置 temperature 参数的示例,请参阅如何提交提示和函数声明

如需了解与生成配置相关的最佳实践,请参阅最佳实践 - 生成配置

工具配置

您可以对模型应如何使用您提供的函数声明进行一些限制。例如,您可以强制模型仅预测函数调用(“强制函数调用”或“受控生成的函数调用”)。您还可以选择为模型提供一整套函数声明,但应将其回答限制为其中一部分函数。

如需添加这些约束条件,请提交工具配置 (tool_config) 以及提示和函数声明。在配置中,您可以指定以下模式之一:

模式 说明
AUTO 默认模型行为。模型决定是预测函数调用还是自然语言回答。
ANY 模型被限制为始终预测函数调用。如果未提供 allowed_function_names,模型会从所有可用的函数声明中进行选择。如果提供了 allowed_function_names,则模型会从一组允许的函数中进行选择。
NONE 模型不得预测函数调用。这种行为等同于模型请求没有任何关联的函数声明。

如需查看支持 ANY 模式(“强制函数调用”)的模型列表,请参阅支持的模型

如需了解详情,请参阅 Function Call API

如何提交提示和函数声明

以下示例展示了如何向模型提交提示和函数声明,并限制模型仅预测 get_current_weather 函数调用。

Python

# Define a tool that includes some of the functions that we declared earlier
tool = Tool(
    function_declarations=[get_current_weather_func, extract_sale_records_func, multiply_number_func],
)

# Send the prompt and instruct the model to generate content using the Tool object that you just created
response = model.generate_content(
    user_prompt_content,
    generation_config=GenerationConfig(temperature=0),
    tools=[tool],
    tool_config=ToolConfig(
        function_calling_config=ToolConfig.FunctionCallingConfig(
            # ANY mode forces the model to predict only function calls
            mode=ToolConfig.FunctionCallingConfig.Mode.ANY,
            # Allowed function calls to predict when the mode is ANY. If empty, any  of
            # the provided function calls will be predicted.
            allowed_function_names=["get_current_weather"],
        )
    )
)

如果模型确定它需要特定函数的输出,则应用从该模型收到的响应将包含函数名称以及调用该函数应使用的参数值。

以下是针对用户提示“波士顿的天气如何?”的模型响应示例。模型建议以参数 Boston, MA 调用 get_current_weather 函数。

candidates {
  content {
    role: "model"
    parts {
      function_call {
        name: "get_current_weather"
        args {
          fields {
            key: "location"
            value {
              string_value: "Boston, MA"
            }
          }
        }
      }
    }
  }
  ...
}

对于“获取新德里和旧金山的天气详情?”之类的提示,模型可能会建议进行多项并行函数调用。如需了解详情,请参阅并行函数调用示例

第 4 步:调用外部 API

如果应用从模型收到函数名称和参数值,则必须连接到外部 API 并调用该函数。

以下示例使用合成数据来模拟来自外部 API 的响应载荷:

Python

# Check the function name that the model responded with, and make an API call to an external system
if (response.candidates[0].function_calls[0].name == "get_current_weather"):
    # Extract the arguments to use in your API call
    location = response.candidates[0].function_calls[0].args["location"]

    # Here you can use your preferred method to make an API request to fetch the current weather, for example:
    # api_response = requests.post(weather_api_url, data={"location": location})

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    api_response = """{ "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy",
                    "icon": "partly-cloudy", "humidity": 65, "wind": { "speed": 10, "direction": "NW" } }"""

如需了解与 API 调用相关的最佳实践,请参阅最佳实践 - API 调用

第 5 步:向模型提供函数的输出

应用从外部 API 收到响应后,必须将此响应提供给模型。以下示例展示了如何使用 Python 执行此操作:

Python

response = model.generate_content(
    [
        user_prompt_content,  # User prompt
        response.candidates[0].content,  # Function call response
        Content(
            parts=[
                Part.from_function_response(
                    name="get_current_weather",
                    response={
                        "content": api_response,  # Return the API response to Gemini
                    },
                )
            ],
        ),
    ],
    tools=[weather_tool],
)
# Get the model summary response
summary = response.text

如果模型提出了多个并行函数调用,应用必须将所有响应提供给模型。如需了解详情,请参阅并行函数调用示例

模型可能会确定在响应提示时需要另一个函数的输出。在这种情况下,应用从模型收到的响应将包含另一个函数名称和另一组参数值。

如果模型确定 API 响应足以回答用户的提示,则会创建自然语言回答并将其返回给应用。在这种情况下,应用必须将回答传递回用户。以下是回答的示例:

It is currently 38 degrees Fahrenheit in Boston, MA with partly cloudy skies. The humidity is 65% and the wind is blowing at 10 mph from the northwest.

函数调用示例

文本示例

您可以使用函数调用生成单个文本回答。临时文本回答对于特定的业务任务(包括代码生成)非常有用。

如果您使用函数调用生成单个回答,则必须为模型提供互动的完整上下文。Vertex AI 会将互动的历史记录存储在客户端。

Python

此示例演示的是文本场景,其中包含一个函数和一个提示。它使用 GenerativeModel 类及其方法。如需详细了解如何将 Vertex AI SDK for Python 与 Gemini 多模态模型搭配使用,请参阅 Vertex AI SDK for Python 中的多模态类简介

Python

如需了解如何安装或更新 Vertex AI SDK for Python,请参阅安装 Vertex AI SDK for Python。 如需了解详情,请参阅 Python API 参考文档

import vertexai

from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerationConfig,
    GenerativeModel,
    Part,
    Tool,
)

# TODO(developer): Update & uncomment below line
# PROJECT_ID = "your-project-id"

# Initialize Vertex AI
vertexai.init(project=PROJECT_ID, location="us-central1")

# Initialize Gemini model
model = GenerativeModel("gemini-1.5-flash-002")

# Define the user's prompt in a Content object that we can reuse in model calls
user_prompt_content = Content(
    role="user",
    parts=[
        Part.from_text("What is the weather like in Boston?"),
    ],
)

# Specify a function declaration and parameters for an API request
function_name = "get_current_weather"
get_current_weather_func = FunctionDeclaration(
    name=function_name,
    description="Get the current weather in a given location",
    # Function parameters are specified in JSON schema format
    parameters={
        "type": "object",
        "properties": {"location": {"type": "string", "description": "Location"}},
    },
)

# Define a tool that includes the above get_current_weather_func
weather_tool = Tool(
    function_declarations=[get_current_weather_func],
)

# Send the prompt and instruct the model to generate content using the Tool that you just created
response = model.generate_content(
    user_prompt_content,
    generation_config=GenerationConfig(temperature=0),
    tools=[weather_tool],
)
function_call = response.candidates[0].function_calls[0]
print(function_call)

# Check the function name that the model responded with, and make an API call to an external system
if function_call.name == function_name:
    # Extract the arguments to use in your API call
    location = function_call.args["location"]  # noqa: F841

    # Here you can use your preferred method to make an API request to fetch the current weather, for example:
    # api_response = requests.post(weather_api_url, data={"location": location})

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    api_response = """{ "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy",
                    "icon": "partly-cloudy", "humidity": 65, "wind": { "speed": 10, "direction": "NW" } }"""

# Return the API response to Gemini so it can generate a model response or request another function call
response = model.generate_content(
    [
        user_prompt_content,  # User prompt
        response.candidates[0].content,  # Function call response
        Content(
            parts=[
                Part.from_function_response(
                    name=function_name,
                    response={
                        "content": api_response,  # Return the API response to Gemini
                    },
                ),
            ],
        ),
    ],
    tools=[weather_tool],
)

# Get the model response
print(response.text)
# Example response:
# The weather in Boston is partly cloudy with a temperature of 38 degrees Fahrenheit.
# The humidity is 65% and the wind is blowing from the northwest at 10 mph.

C#

此示例演示的是文本场景,其中包含一个函数和一个提示。

C#

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 C# 设置说明执行操作。 如需了解详情,请参阅 Vertex AI C# API 参考文档

如需向 Vertex AI 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


using Google.Cloud.AIPlatform.V1;
using System;
using System.Threading.Tasks;
using Type = Google.Cloud.AIPlatform.V1.Type;
using Value = Google.Protobuf.WellKnownTypes.Value;

public class FunctionCalling
{
    public async Task<string> GenerateFunctionCall(
        string projectId = "your-project-id",
        string location = "us-central1",
        string publisher = "google",
        string model = "gemini-1.5-flash-001")
    {
        var predictionServiceClient = new PredictionServiceClientBuilder
        {
            Endpoint = $"{location}-aiplatform.googleapis.com"
        }.Build();

        // Define the user's prompt in a Content object that we can reuse in
        // model calls
        var userPromptContent = new Content
        {
            Role = "USER",
            Parts =
            {
                new Part { Text = "What is the weather like in Boston?" }
            }
        };

        // Specify a function declaration and parameters for an API request
        var functionName = "get_current_weather";
        var getCurrentWeatherFunc = new FunctionDeclaration
        {
            Name = functionName,
            Description = "Get the current weather in a given location",
            Parameters = new OpenApiSchema
            {
                Type = Type.Object,
                Properties =
                {
                    ["location"] = new()
                    {
                        Type = Type.String,
                        Description = "Get the current weather in a given location"
                    },
                    ["unit"] = new()
                    {
                        Type = Type.String,
                        Description = "The unit of measurement for the temperature",
                        Enum = {"celsius", "fahrenheit"}
                    }
                },
                Required = { "location" }
            }
        };

        // Send the prompt and instruct the model to generate content using the tool that you just created
        var generateContentRequest = new GenerateContentRequest
        {
            Model = $"projects/{projectId}/locations/{location}/publishers/{publisher}/models/{model}",
            GenerationConfig = new GenerationConfig
            {
                Temperature = 0f
            },
            Contents =
            {
                userPromptContent
            },
            Tools =
            {
                new Tool
                {
                    FunctionDeclarations = { getCurrentWeatherFunc }
                }
            }
        };

        GenerateContentResponse response = await predictionServiceClient.GenerateContentAsync(generateContentRequest);

        var functionCall = response.Candidates[0].Content.Parts[0].FunctionCall;
        Console.WriteLine(functionCall);

        string apiResponse = "";

        // Check the function name that the model responded with, and make an API call to an external system
        if (functionCall.Name == functionName)
        {
            // Extract the arguments to use in your API call
            string locationCity = functionCall.Args.Fields["location"].StringValue;

            // Here you can use your preferred method to make an API request to
            // fetch the current weather

            // In this example, we'll use synthetic data to simulate a response
            // payload from an external API
            apiResponse = @"{ ""location"": ""Boston, MA"",
                    ""temperature"": 38, ""description"": ""Partly Cloudy""}";
        }

        // Return the API response to Gemini so it can generate a model response or request another function call
        generateContentRequest = new GenerateContentRequest
        {
            Model = $"projects/{projectId}/locations/{location}/publishers/{publisher}/models/{model}",
            Contents =
            {
                userPromptContent, // User prompt
                response.Candidates[0].Content, // Function call response,
                new Content
                {
                    Parts =
                    {
                        new Part
                        {
                            FunctionResponse = new()
                            {
                                Name = functionName,
                                Response = new()
                                {
                                    Fields =
                                    {
                                        { "content", new Value { StringValue = apiResponse } }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            Tools =
            {
                new Tool
                {
                    FunctionDeclarations = { getCurrentWeatherFunc }
                }
            }
        };

        response = await predictionServiceClient.GenerateContentAsync(generateContentRequest);

        string responseText = response.Candidates[0].Content.Parts[0].Text;
        Console.WriteLine(responseText);

        return responseText;
    }
}

Node.js

此示例演示的是文本场景,其中包含一个函数和一个提示。

Node.js

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 Node.js 设置说明执行操作。 如需了解详情,请参阅 Vertex AI Node.js API 参考文档

如需向 Vertex AI 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

const {
  VertexAI,
  FunctionDeclarationSchemaType,
} = require('@google-cloud/vertexai');

const functionDeclarations = [
  {
    function_declarations: [
      {
        name: 'get_current_weather',
        description: 'get weather in a given location',
        parameters: {
          type: FunctionDeclarationSchemaType.OBJECT,
          properties: {
            location: {type: FunctionDeclarationSchemaType.STRING},
            unit: {
              type: FunctionDeclarationSchemaType.STRING,
              enum: ['celsius', 'fahrenheit'],
            },
          },
          required: ['location'],
        },
      },
    ],
  },
];

const functionResponseParts = [
  {
    functionResponse: {
      name: 'get_current_weather',
      response: {name: 'get_current_weather', content: {weather: 'super nice'}},
    },
  },
];

/**
 * TODO(developer): Update these variables before running the sample.
 */
async function functionCallingStreamContent(
  projectId = 'PROJECT_ID',
  location = 'us-central1',
  model = 'gemini-1.5-flash-001'
) {
  // Initialize Vertex with your Cloud project and location
  const vertexAI = new VertexAI({project: projectId, location: location});

  // Instantiate the model
  const generativeModel = vertexAI.getGenerativeModel({
    model: model,
  });

  const request = {
    contents: [
      {role: 'user', parts: [{text: 'What is the weather in Boston?'}]},
      {
        role: 'ASSISTANT',
        parts: [
          {
            functionCall: {
              name: 'get_current_weather',
              args: {location: 'Boston'},
            },
          },
        ],
      },
      {role: 'USER', parts: functionResponseParts},
    ],
    tools: functionDeclarations,
  };
  const streamingResp = await generativeModel.generateContentStream(request);
  for await (const item of streamingResp.stream) {
    console.log(item.candidates[0].content.parts[0].text);
  }
}

REST

此示例演示的是文本场景,其中包含三个函数和一个提示。

在此示例中,您调用了两次生成式 AI 模型。

第一个模型请求

该请求必须在 text 参数中定义提示。本示例定义了以下提示:“Which theaters in Mountain View show Barbie movie?”(山景城的哪些影院在播放电影《芭比》?)。

该请求还必须定义一个工具 (tools),其中包含一组函数声明 (functionDeclarations)。这些函数声明必须采用与 OpenAPI 架构兼容的格式指定。本示例定义了以下函数:

  • find_movies 查找在影院上播放的电影。
  • find_theatres 根据位置查找影院。
  • get_showtimes 查找在特定影院播放的电影的开场时间。

如需详细了解模型请求的参数,请参阅 Gemini API

my-project 替换为您的 Google Cloud 项目的名称。

第一个模型请求

PROJECT_ID=my-project
MODEL_ID=gemini-1.0-pro
API=streamGenerateContent
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json"  https://us-central1-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:${API} -d '{
"contents": {
  "role": "user",
  "parts": {
    "text": "Which theaters in Mountain View show the Barbie movie?"
  }
},
"tools": [
  {
    "function_declarations": [
      {
        "name": "find_movies",
        "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "description": {
              "type": "string",
              "description": "Any kind of description including category or genre, title words, attributes, etc."
            }
          },
          "required": [
            "description"
          ]
        }
      },
      {
        "name": "find_theaters",
        "description": "find theaters based on location and optionally movie title which are is currently playing in theaters",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "movie": {
              "type": "string",
              "description": "Any movie title"
            }
          },
          "required": [
            "location"
          ]
        }
      },
      {
        "name": "get_showtimes",
        "description": "Find the start times for movies playing in a specific theater",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "movie": {
              "type": "string",
              "description": "Any movie title"
            },
            "theater": {
              "type": "string",
              "description": "Name of the theater"
            },
            "date": {
              "type": "string",
              "description": "Date for requested showtime"
            }
          },
          "required": [
            "location",
            "movie",
            "theater",
            "date"
          ]
        }
      }
    ]
  }
]
}'
  

对于“Which theaters in Mountain View show Barbie movie?”(山景城的哪些影院在播放电影《芭比》?)提示,模型可能会返回带有参数 BarbieMountain View, CA 的函数 find_theatres

对第一个模型请求的响应

[{
"candidates": [
  {
    "content": {
      "parts": [
        {
          "functionCall": {
            "name": "find_theaters",
            "args": {
              "movie": "Barbie",
              "location": "Mountain View, CA"
            }
          }
        }
      ]
    },
    "finishReason": "STOP",
    "safetyRatings": [
      {
        "category": "HARM_CATEGORY_HARASSMENT",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_HATE_SPEECH",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
        "probability": "NEGLIGIBLE"
      }
    ]
  }
],
"usageMetadata": {
  "promptTokenCount": 9,
  "totalTokenCount": 9
}
}]
  

第二个模型请求

此示例使用合成数据,而不是调用外部 API。具有两项结果,每个结果都包含两个参数(nameaddress):

  1. name: AMC Mountain View 16, address: 2000 W El Camino Real, Mountain View, CA 94040
  2. name: Regal Edwards 14, address: 245 Castro St, Mountain View, CA 94040

my-project 替换为您的 Google Cloud 项目的名称。

第二个模型请求

PROJECT_ID=my-project
MODEL_ID=gemini-1.0-pro
API=streamGenerateContent
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json"  https://us-central1-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:${API} -d '{
"contents": [{
  "role": "user",
  "parts": [{
    "text": "Which theaters in Mountain View show the Barbie movie?"
  }]
}, {
  "role": "model",
  "parts": [{
    "functionCall": {
      "name": "find_theaters",
      "args": {
        "location": "Mountain View, CA",
        "movie": "Barbie"
      }
    }
  }]
}, {
  "parts": [{
    "functionResponse": {
      "name": "find_theaters",
      "response": {
        "name": "find_theaters",
        "content": {
          "movie": "Barbie",
          "theaters": [{
            "name": "AMC Mountain View 16",
            "address": "2000 W El Camino Real, Mountain View, CA 94040"
          }, {
            "name": "Regal Edwards 14",
            "address": "245 Castro St, Mountain View, CA 94040"
          }]
        }
      }
    }
  }]
}],
"tools": [{
  "functionDeclarations": [{
    "name": "find_movies",
    "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "description": {
          "type": "STRING",
          "description": "Any kind of description including category or genre, title words, attributes, etc."
        }
      },
      "required": ["description"]
    }
  }, {
    "name": "find_theaters",
    "description": "find theaters based on location and optionally movie title which are is currently playing in theaters",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "movie": {
          "type": "STRING",
          "description": "Any movie title"
        }
      },
      "required": ["location"]
    }
  }, {
    "name": "get_showtimes",
    "description": "Find the start times for movies playing in a specific theater",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "movie": {
          "type": "STRING",
          "description": "Any movie title"
        },
        "theater": {
          "type": "STRING",
          "description": "Name of the theater"
        },
        "date": {
          "type": "STRING",
          "description": "Date for requested showtime"
        }
      },
      "required": ["location", "movie", "theater", "date"]
    }
  }]
}]
}'
  

模型的响应可能类似于以下内容:

对第二个模型请求的响应

{
"candidates": [
  {
    "content": {
      "parts": [
        {
          "text": " OK. Barbie is showing in two theaters in Mountain View, CA: AMC Mountain View 16 and Regal Edwards 14."
        }
      ]
    }
  }
],
"usageMetadata": {
  "promptTokenCount": 9,
  "candidatesTokenCount": 27,
  "totalTokenCount": 36
}
}
  

聊天示例

您可以使用函数调用来支持聊天会话。聊天会话在形式自由的对话场景中非常有用,这些场景中用户可能会询问后续问题。

如果您在聊天会话的上下文中使用函数调用,则会话会为您存储上下文,并将其包含在每个模型请求中。Vertex AI 会将互动的历史记录存储在客户端。

Python

此示例演示的是包含两个函数和两个连续提示的聊天场景。它使用 GenerativeModel 类及其方法。如需详细了解如何将 Vertex AI SDK for Python 与多模态模型搭配使用,请参阅 Vertex AI SDK for Python 中的多模态类简介

如需了解如何安装或更新 Python,请参阅安装 Vertex AI SDK for Python。如需了解详情,请参阅 Python API 参考文档

import vertexai

from vertexai.generative_models import (
    FunctionDeclaration,
    GenerationConfig,
    GenerativeModel,
    Part,
    Tool,
)

# TODO(developer): Update & uncomment below line
# PROJECT_ID = "your-project-id"

# Initialize Vertex AI
vertexai.init(project=PROJECT_ID, location="us-central1")

# Specify a function declaration and parameters for an API request
get_product_sku = "get_product_sku"
get_product_sku_func = FunctionDeclaration(
    name=get_product_sku,
    description="Get the SKU for a product",
    # Function parameters are specified in OpenAPI JSON schema format
    parameters={
        "type": "object",
        "properties": {
            "product_name": {"type": "string", "description": "Product name"}
        },
    },
)

# Specify another function declaration and parameters for an API request
get_store_location_func = FunctionDeclaration(
    name="get_store_location",
    description="Get the location of the closest store",
    # Function parameters are specified in JSON schema format
    parameters={
        "type": "object",
        "properties": {"location": {"type": "string", "description": "Location"}},
    },
)

# Define a tool that includes the above functions
retail_tool = Tool(
    function_declarations=[
        get_product_sku_func,
        get_store_location_func,
    ],
)

# Initialize Gemini model
model = GenerativeModel(
    model_name="gemini-1.5-flash-001",
    generation_config=GenerationConfig(temperature=0),
    tools=[retail_tool],
)

# Start a chat session
chat = model.start_chat()

# Send a prompt for the first conversation turn that should invoke the get_product_sku function
response = chat.send_message("Do you have the Pixel 8 Pro in stock?")

function_call = response.candidates[0].function_calls[0]
print(function_call)

# Check the function name that the model responded with, and make an API call to an external system
if function_call.name == get_product_sku:
    # Extract the arguments to use in your API call
    product_name = function_call.args["product_name"]  # noqa: F841

    # Here you can use your preferred method to make an API request to retrieve the product SKU, as in:
    # api_response = requests.post(product_api_url, data={"product_name": product_name})

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    api_response = {"sku": "GA04834-US", "in_stock": "Yes"}

# Return the API response to Gemini, so it can generate a model response or request another function call
response = chat.send_message(
    Part.from_function_response(
        name=get_product_sku,
        response={
            "content": api_response,
        },
    ),
)
# Extract the text from the model response
print(response.text)

# Send a prompt for the second conversation turn that should invoke the get_store_location function
response = chat.send_message(
    "Is there a store in Mountain View, CA that I can visit to try it out?"
)

function_call = response.candidates[0].function_calls[0]
print(function_call)

# Check the function name that the model responded with, and make an API call to an external system
if function_call.name == "get_store_location":
    # Extract the arguments to use in your API call
    location = function_call.args["location"]  # noqa: F841

    # Here you can use your preferred method to make an API request to retrieve store location closest to the user, as in:
    # api_response = requests.post(store_api_url, data={"location": location})

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    api_response = {"store": "2000 N Shoreline Blvd, Mountain View, CA 94043, US"}

# Return the API response to Gemini, so it can generate a model response or request another function call
response = chat.send_message(
    Part.from_function_response(
        name="get_store_location",
        response={
            "content": api_response,
        },
    ),
)

# Extract the text from the model response
print(response.text)
# Example response:
# name: "get_product_sku"
# args {
#   fields { key: "product_name" value {string_value: "Pixel 8 Pro" }
#   }
# }
# Yes, we have the Pixel 8 Pro in stock.
# name: "get_store_location"
# args {
#   fields { key: "location" value { string_value: "Mountain View, CA" }
#   }
# }
# Yes, there is a store located at 2000 N Shoreline Blvd, Mountain View, CA 94043, US.

Java

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 Java 设置说明执行操作。 如需了解详情,请参阅 Vertex AI Java API 参考文档

如需向 Vertex AI 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.Content;
import com.google.cloud.vertexai.api.FunctionDeclaration;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.Schema;
import com.google.cloud.vertexai.api.Tool;
import com.google.cloud.vertexai.api.Type;
import com.google.cloud.vertexai.generativeai.ChatSession;
import com.google.cloud.vertexai.generativeai.ContentMaker;
import com.google.cloud.vertexai.generativeai.GenerativeModel;
import com.google.cloud.vertexai.generativeai.PartMaker;
import com.google.cloud.vertexai.generativeai.ResponseHandler;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;

public class FunctionCalling {
  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-google-cloud-project-id";
    String location = "us-central1";
    String modelName = "gemini-1.5-flash-001";

    String promptText = "What's the weather like in Paris?";

    whatsTheWeatherLike(projectId, location, modelName, promptText);
  }

  // A request involving the interaction with an external tool
  public static String whatsTheWeatherLike(String projectId, String location,
                                           String modelName, String promptText)
      throws IOException {
    // Initialize client that will be used to send requests.
    // This client only needs to be created once, and can be reused for multiple requests.
    try (VertexAI vertexAI = new VertexAI(projectId, location)) {

      FunctionDeclaration functionDeclaration = FunctionDeclaration.newBuilder()
          .setName("getCurrentWeather")
          .setDescription("Get the current weather in a given location")
          .setParameters(
              Schema.newBuilder()
                  .setType(Type.OBJECT)
                  .putProperties("location", Schema.newBuilder()
                      .setType(Type.STRING)
                      .setDescription("location")
                      .build()
                  )
                  .addRequired("location")
                  .build()
          )
          .build();

      System.out.println("Function declaration:");
      System.out.println(functionDeclaration);

      // Add the function to a "tool"
      Tool tool = Tool.newBuilder()
          .addFunctionDeclarations(functionDeclaration)
          .build();

      // Start a chat session from a model, with the use of the declared function.
      GenerativeModel model = new GenerativeModel(modelName, vertexAI)
          .withTools(Arrays.asList(tool));
      ChatSession chat = model.startChat();

      System.out.println(String.format("Ask the question: %s", promptText));
      GenerateContentResponse response = chat.sendMessage(promptText);

      // The model will most likely return a function call to the declared
      // function `getCurrentWeather` with "Paris" as the value for the
      // argument `location`.
      System.out.println("\nPrint response: ");
      System.out.println(ResponseHandler.getContent(response));

      // Provide an answer to the model so that it knows what the result
      // of a "function call" is.
      Content content =
          ContentMaker.fromMultiModalData(
              PartMaker.fromFunctionResponse(
                  "getCurrentWeather",
                  Collections.singletonMap("currentWeather", "sunny")));
      System.out.println("Provide the function response: ");
      System.out.println(content);
      response = chat.sendMessage(content);

      // See what the model replies now
      System.out.println("Print response: ");
      String finalAnswer = ResponseHandler.getText(response);
      System.out.println(finalAnswer);

      return finalAnswer;
    }
  }
}

Go

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 Go 设置说明执行操作。 如需了解详情,请参阅 Vertex AI Go API 参考文档

如需向 Vertex AI 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"

	"cloud.google.com/go/vertexai/genai"
)

// functionCallsChat opens a chat session and sends 4 messages to the model:
// - convert a first text question into a structured function call request
// - convert the first structured function call response into natural language
// - convert a second text question into a structured function call request
// - convert the second structured function call response into natural language
func functionCallsChat(w io.Writer, projectID, location, modelName string) error {
	// location := "us-central1"
	// modelName := "gemini-1.5-flash-001"
	ctx := context.Background()
	client, err := genai.NewClient(ctx, projectID, location)
	if err != nil {
		return fmt.Errorf("unable to create client: %w", err)
	}
	defer client.Close()

	model := client.GenerativeModel(modelName)

	// Build an OpenAPI schema, in memory
	paramsProduct := &genai.Schema{
		Type: genai.TypeObject,
		Properties: map[string]*genai.Schema{
			"productName": {
				Type:        genai.TypeString,
				Description: "Product name",
			},
		},
	}
	fundeclProductInfo := &genai.FunctionDeclaration{
		Name:        "getProductSku",
		Description: "Get the SKU for a product",
		Parameters:  paramsProduct,
	}
	paramsStore := &genai.Schema{
		Type: genai.TypeObject,
		Properties: map[string]*genai.Schema{
			"location": {
				Type:        genai.TypeString,
				Description: "Location",
			},
		},
	}
	fundeclStoreLocation := &genai.FunctionDeclaration{
		Name:        "getStoreLocation",
		Description: "Get the location of the closest store",
		Parameters:  paramsStore,
	}
	model.Tools = []*genai.Tool{
		{FunctionDeclarations: []*genai.FunctionDeclaration{
			fundeclProductInfo,
			fundeclStoreLocation,
		}},
	}
	model.SetTemperature(0.0)

	chat := model.StartChat()

	// Send a prompt for the first conversation turn that should invoke the getProductSku function
	prompt := "Do you have the Pixel 8 Pro in stock?"
	fmt.Fprintf(w, "Question: %s\n", prompt)
	resp, err := chat.SendMessage(ctx, genai.Text(prompt))
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has returned a function call to the declared function `getProductSku`
	// with a value for the argument `productName`.
	jsondata, err := json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "function call generated by the model:\n\t%s\n", string(jsondata))

	// Create a function call response, to simulate the result of a call to a
	// real service
	funresp := &genai.FunctionResponse{
		Name: "getProductSku",
		Response: map[string]any{
			"sku":      "GA04834-US",
			"in_stock": "yes",
		},
	}
	jsondata, err = json.MarshalIndent(funresp, "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "function call response sent to the model:\n\t%s\n\n", string(jsondata))

	// And provide the function call response to the model
	resp, err = chat.SendMessage(ctx, funresp)
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has taken the function call response as input, and has
	// reformulated the response to the user.
	jsondata, err = json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "Answer generated by the model:\n\t%s\n\n", string(jsondata))

	// Send a prompt for the second conversation turn that should invoke the getStoreLocation function
	prompt2 := "Is there a store in Mountain View, CA that I can visit to try it out?"
	fmt.Fprintf(w, "Question: %s\n", prompt)

	resp, err = chat.SendMessage(ctx, genai.Text(prompt2))
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has returned a function call to the declared function `getStoreLocation`
	// with a value for the argument `store`.
	jsondata, err = json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "function call generated by the model:\n\t%s\n", string(jsondata))

	// Create a function call response, to simulate the result of a call to a
	// real service
	funresp = &genai.FunctionResponse{
		Name: "getStoreLocation",
		Response: map[string]any{
			"store": "2000 N Shoreline Blvd, Mountain View, CA 94043, US",
		},
	}
	jsondata, err = json.MarshalIndent(funresp, "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "function call response sent to the model:\n\t%s\n\n", string(jsondata))

	// And provide the function call response to the model
	resp, err = chat.SendMessage(ctx, funresp)
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has taken the function call response as input, and has
	// reformulated the response to the user.
	jsondata, err = json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.MarshalIndent: %w", err)
	}
	fmt.Fprintf(w, "Answer generated by the model:\n\t%s\n\n", string(jsondata))
	return nil
}

Node.js

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 Node.js 设置说明执行操作。 如需了解详情,请参阅 Vertex AI Node.js API 参考文档

如需向 Vertex AI 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

const {
  VertexAI,
  FunctionDeclarationSchemaType,
} = require('@google-cloud/vertexai');

const functionDeclarations = [
  {
    function_declarations: [
      {
        name: 'get_current_weather',
        description: 'get weather in a given location',
        parameters: {
          type: FunctionDeclarationSchemaType.OBJECT,
          properties: {
            location: {type: FunctionDeclarationSchemaType.STRING},
            unit: {
              type: FunctionDeclarationSchemaType.STRING,
              enum: ['celsius', 'fahrenheit'],
            },
          },
          required: ['location'],
        },
      },
    ],
  },
];

const functionResponseParts = [
  {
    functionResponse: {
      name: 'get_current_weather',
      response: {name: 'get_current_weather', content: {weather: 'super nice'}},
    },
  },
];

/**
 * TODO(developer): Update these variables before running the sample.
 */
async function functionCallingStreamChat(
  projectId = 'PROJECT_ID',
  location = 'us-central1',
  model = 'gemini-1.5-flash-001'
) {
  // Initialize Vertex with your Cloud project and location
  const vertexAI = new VertexAI({project: projectId, location: location});

  // Instantiate the model
  const generativeModel = vertexAI.getGenerativeModel({
    model: model,
  });

  // Create a chat session and pass your function declarations
  const chat = generativeModel.startChat({
    tools: functionDeclarations,
  });

  const chatInput1 = 'What is the weather in Boston?';

  // This should include a functionCall response from the model
  const result1 = await chat.sendMessageStream(chatInput1);
  for await (const item of result1.stream) {
    console.log(item.candidates[0]);
  }
  await result1.response;

  // Send a follow up message with a FunctionResponse
  const result2 = await chat.sendMessageStream(functionResponseParts);
  for await (const item of result2.stream) {
    console.log(item.candidates[0]);
  }

  // This should include a text response from the model using the response content
  // provided above
  const response2 = await result2.response;
  console.log(response2.candidates[0].content.parts[0].text);
}

并行函数调用示例

对于“获取新德里和旧金山的天气详情?”之类的提示,模型可能会建议进行多项并行函数调用。如需查看支持并行函数调用的模型列表,请参阅支持的模型

REST

此示例演示的是包含一个 get_current_weather 函数的场景。用户提示为“获取新德里和旧金山的天气详情?”。该模型建议使用两个并行 get_current_weather 函数调用:一个使用参数 New Delhi,另一个使用参数 San Francisco

如需详细了解模型请求的参数,请参阅 Gemini API

{
"candidates": [
  {
    "content": {
      "role": "model",
      "parts": [
        {
          "functionCall": {
            "name": "get_current_weather",
            "args": {
              "location": "New Delhi"
            }
          }
        },
        {
          "functionCall": {
            "name": "get_current_weather",
            "args": {
              "location": "San Francisco"
            }
          }
        }
      ]
    },
    ...
  }
],
...
}

以下命令演示了如何向模型提供函数输出。将 my-project 替换为您的 Google Cloud 项目的名称。

模型请求

PROJECT_ID=my-project
MODEL_ID=gemini-1.5-pro-002
VERSION="v1"
LOCATION="us-central1"
ENDPOINT=${LOCATION}-aiplatform.googleapis.com
API="generateContent"
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json"  https://${ENDPOINT}/${VERSION}/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:${API} -d '{
"contents": [
    {
        "role": "user",
        "parts": {
            "text": "What is difference in temperature in New Delhi and San Francisco?"
        }
    },
    {
        "role": "model",
        "parts": [
            {
                "functionCall": {
                    "name": "get_current_weather",
                    "args": {
                        "location": "New Delhi"
                    }
                }
            },
            {
                "functionCall": {
                    "name": "get_current_weather",
                    "args": {
                        "location": "San Francisco"
                    }
                }
            }
        ]
    },
    {
        "role": "user",
        "parts": [
            {
                "functionResponse": {
                    "name": "get_current_weather",
                    "response": {
                        "temperature": 30.5,
                        "unit": "C"
                    }
                }
            },
            {
                "functionResponse": {
                    "name": "get_current_weather",
                    "response": {
                        "temperature": 20,
                        "unit": "C"
                    }
                }
            }
        ]
    }
],
"tools": [
    {
        "function_declarations": [
            {
                "name": "get_current_weather",
                "description": "Get the current weather in a specific location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
                        }
                    },
                    "required": [
                        "location"
                    ]
                }
            }
        ]
    }
]
}'
  

模型创建的自然语言回复类似于以下内容:

模型回答

[
{
    "candidates": [
        {
            "content": {
                "parts": [
                    {
                        "text": "The temperature in New Delhi is 30.5C and the temperature in San Francisco is 20C. The difference is 10.5C. \n"
                    }
                ]
            },
            "finishReason": "STOP",
            ...
        }
    ]
    ...
}
]
  

Python

import vertexai

from vertexai.generative_models import (
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

# TODO(developer): Update & uncomment below line
# PROJECT_ID = "your-project-id"

# Initialize Vertex AI
vertexai.init(project=PROJECT_ID, location="us-central1")

# Specify a function declaration and parameters for an API request
function_name = "get_current_weather"
get_current_weather_func = FunctionDeclaration(
    name=function_name,
    description="Get the current weather in a given location",
    parameters={
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location for which to get the weather. \
                  It can be a city name, a city name and state, or a zip code. \
                  Examples: 'San Francisco', 'San Francisco, CA', '95616', etc.",
            },
        },
    },
)

# In this example, we'll use synthetic data to simulate a response payload from an external API
def mock_weather_api_service(location: str) -> str:
    temperature = 25 if location == "San Francisco" else 35
    return f"""{{ "location": "{location}", "temperature": {temperature}, "unit": "C" }}"""

# Define a tool that includes the above function
tools = Tool(
    function_declarations=[get_current_weather_func],
)

# Initialize Gemini model
model = GenerativeModel(
    model_name="gemini-1.5-pro-002",
    tools=[tools],
)

# Start a chat session
chat_session = model.start_chat()
response = chat_session.send_message(
    "Get weather details in New Delhi and San Francisco?"
)

function_calls = response.candidates[0].function_calls
print("Suggested finction calls:\n", function_calls)

if function_calls:
    api_responses = []
    for func in function_calls:
        if func.name == function_name:
            api_responses.append(
                {
                    "content": mock_weather_api_service(
                        location=func.args["location"]
                    )
                }
            )

    # Return the API response to Gemini
    response = chat_session.send_message(
        [
            Part.from_function_response(
                name="get_current_weather",
                response=api_responses[0],
            ),
            Part.from_function_response(
                name="get_current_weather",
                response=api_responses[1],
            ),
        ],
    )

    print(response.text)
    # Example response:
    # The current weather in New Delhi is 35°C. The current weather in San Francisco is 25°C.

函数调用的最佳实践

函数名称

函数名称应以字母或下划线开头,并且只能包含字母 a-z、A-Z、数字 0-9、下划线、句点或短划线,长度上限为 64 个字符。

函数说明

清晰而详细地撰写函数说明。例如,对于 book_flight_ticket 函数:

  • 下面是一个良好的函数说明示例:book flight tickets after confirming users' specific requirements, such as time, departure, destination, party size and preferred airline
  • 下面是一个不良的函数说明示例:book flight ticket

函数参数

函数参数和嵌套属性名称应以字母或下划线开头,并且只能包含字母 a-z、A-Z、数字 0-9 或下划线,长度不得超过 64 个字符。请勿在函数参数名称和嵌套属性中使用英文句点 (.)、短划线 (-) 或空格字符。 请改用下划线 (_) 字符或任何其他字符。

说明

编写清晰而详细的参数说明,包括首选格式或值等详细信息。例如,对于 book_flight_ticket 函数:

  • 以下是 departure 参数说明的一个良好示例:Use the 3 char airport code to represent the airport. For example, SJC or SFO. Don't use the city name.
  • 以下是 departure 参数说明的一个不良示例:the departure airport

类型

尽可能使用强类型参数来减少模型幻觉。例如,如果参数值来自有限集,请添加 enum 字段,而不是将值集放入说明中。如果参数值始终是整数,请将类型设置为 integer,而不是 number

系统指令

使用包含日期、时间或位置参数的函数时,请在系统说明中添加当前日期、时间或相关位置信息(例如城市和国家/地区)。这样可以确保模型具有必要的上下文来准确处理请求,即使用户提示缺少详细信息也是如此。

用户提示

为获得最佳结果,请在用户提示前面加上以下详细信息:

  • 模型的其他上下文,例如 You are a flight API assistant to help with searching flights based on user preferences.
  • 有关如何及何时使用函数的详细信息或说明,例如 Don't make assumptions on the departure or destination airports. Always use a future date for the departure or destination time.
  • 在用户查询不明确时询问澄清性问题的说明,例如 Ask clarifying questions if not enough information is available.

生成配置

对于温度参数,请使用 0 或其他较低值。这会指示模型生成置信度更高的结果并减少幻觉。

API 调用

如果模型建议调用一个会发送订单、更新数据库或以其他方式产生重大后果的函数,请在执行之前先向用户验证该函数调用。

价格

函数调用的价格取决于文本输入和输出中的字符数。如需了解详情,请参阅 Vertex AI 价格

在本示例中,文本输入(提示)是指当前对话轮次的用户提示、当前对话轮次的函数声明以及对话历史记录。对话的历史记录包括查询、函数调用以及上一轮对话的函数回答。Vertex AI 会将对话历史记录截断为 32,000 个字符。

文本输出(回答)是指当前对话轮次的函数调用和文本回答。

后续步骤