函数调用简介

函数调用(也称为“工具使用”)可为 LLM 提供外部工具(例如 get_current_weather 函数)的定义。在处理提示时,模型会智能地确定是否需要使用工具,如果需要,则会输出结构化数据,指定要调用的工具及其参数(例如 get_current_weather(location='Boston'))。然后,您的应用会执行此工具,并将结果反馈给模型,从而使模型能够使用动态的真实世界信息或所执行操作的结果来完成回答。这可有效地将 LLM 与您的系统相关联,并扩展其功能。

函数调用交互 

函数调用可实现以下两个主要应用场景:

  • 提取数据:检索最新的信息以用在模型回答中,例如当前天气、货币换算或来自知识库及 API 的特定数据 (RAG)。

  • 执行操作:执行外部操作,例如提交表单、更新应用状态或编排智能体工作流(例如对话移交)。

如需查看更多由函数调用提供支持的应用场景和示例,请参阅应用场景

功能和限制

如何创建函数调用应用

如需使用函数调用,请执行以下任务:

  1. 向模型提交函数声明和提示
  2. 为模型提供 API 输出

第 1 步:向模型提交提示和函数声明

请以与 OpenAPI 架构兼容的架构格式声明 Tool。如需了解详情,请参阅架构示例

以下示例将向 Gemini 模型提交提示和函数声明。

REST

PROJECT_ID=myproject
LOCATION=us-central1
MODEL_ID=gemini-2.0-flash-001

curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:generateContent \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [{
        "text": "What is the weather in Boston?"
      }]
    }],
    "tools": [{
      "functionDeclarations": [
        {
          "name": "get_current_weather",
          "description": "Get the current weather in a given location",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city name of the location for which to get the weather.",
                "default": {
                  "string_value": "Boston, MA"
                }
              }
            },
            "required": [
              "location"
            ]
          }
        }
      ]
    }]
  }'

Python

您可以使用 Python 字典手动指定架构,也可以使用 from_func 辅助函数自动指定架构。以下示例演示了如何手动声明函数。

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

# Initialize Vertex AI
# TODO(developer): Update the project
vertexai.init(project="PROJECT_ID", location="us-central1")

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

# Manual function declaration
get_current_weather_func = FunctionDeclaration(
    name="get_current_weather",
    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.",
              "default": {
                "string_value": "Boston, MA"
              }
           }
        },
    },
)

response = model.generate_content(
    contents = [
      Content(
        role="user",
          parts=[
              Part.from_text("What is the weather like in Boston?"),
          ],
      )
    ],
    generation_config = GenerationConfig(temperature=0),
    tools = [
      Tool(
        function_declarations=[get_current_weather_func],
      )
    ]
)

或者,您可以使用 from_func 辅助函数自动声明该函数,如以下示例所示:

def get_current_weather(location: str = "Boston, MA"):
  """
  Get the current weather in a given location

  Args:
      location: The city name of the location for which to get the weather.

  """
  # This example uses a mock implementation.
  # You can define a local function or import the requests library to call an API
  return {
    "location": "Boston, MA",
    "temperature": 38,
    "description": "Partly Cloudy",
    "icon": "partly-cloudy",
    "humidity": 65,
    "wind": {
        "speed": 10,
        "direction": "NW"
    }
  }
get_current_weather_func = FunctionDeclaration.from_func(get_current_weather)

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-2.0-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);
  }
}

Go

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

了解如何安装或更新 Go

如需了解详情,请参阅 SDK 参考文档

设置环境变量以将 Gen AI SDK 与 Vertex AI 搭配使用:

# Replace the `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION` values
# with appropriate values for your project.
export GOOGLE_CLOUD_PROJECT=GOOGLE_CLOUD_PROJECT
export GOOGLE_CLOUD_LOCATION=global
export GOOGLE_GENAI_USE_VERTEXAI=True

import (
	"context"
	"fmt"
	"io"

	genai "google.golang.org/genai"
)

// generateWithFuncCall shows how to submit a prompt and a function declaration to the model,
// allowing it to suggest a call to the function to fetch external data. Returning this data
// enables the model to generate a text response that incorporates the data.
func generateWithFuncCall(w io.Writer) error {
	ctx := context.Background()

	client, err := genai.NewClient(ctx, &genai.ClientConfig{
		HTTPOptions: genai.HTTPOptions{APIVersion: "v1"},
	})
	if err != nil {
		return fmt.Errorf("failed to create genai client: %w", err)
	}

	weatherFunc := &genai.FunctionDeclaration{
		Description: "Returns the current weather in a location.",
		Name:        "getCurrentWeather",
		Parameters: &genai.Schema{
			Type: "object",
			Properties: map[string]*genai.Schema{
				"location": {Type: "string"},
			},
			Required: []string{"location"},
		},
	}
	config := &genai.GenerateContentConfig{
		Tools: []*genai.Tool{
			{FunctionDeclarations: []*genai.FunctionDeclaration{weatherFunc}},
		},
		Temperature: genai.Ptr(float32(0.0)),
	}

	modelName := "gemini-2.5-flash"
	contents := []*genai.Content{
		{Parts: []*genai.Part{
			{Text: "What is the weather like in Boston?"},
		},
			Role: "user"},
	}

	resp, err := client.Models.GenerateContent(ctx, modelName, contents, config)
	if err != nil {
		return fmt.Errorf("failed to generate content: %w", err)
	}

	var funcCall *genai.FunctionCall
	for _, p := range resp.Candidates[0].Content.Parts {
		if p.FunctionCall != nil {
			funcCall = p.FunctionCall
			fmt.Fprint(w, "The model suggests to call the function ")
			fmt.Fprintf(w, "%q with args: %v\n", funcCall.Name, funcCall.Args)
			// Example response:
			// The model suggests to call the function "getCurrentWeather" with args: map[location:Boston]
		}
	}
	if funcCall == nil {
		return fmt.Errorf("model did not suggest a function call")
	}

	// Use synthetic data to simulate a response from the external API.
	// In a real application, this would come from an actual weather API.
	funcResp := &genai.FunctionResponse{
		Name: "getCurrentWeather",
		Response: map[string]any{
			"location":         "Boston",
			"temperature":      "38",
			"temperature_unit": "F",
			"description":      "Cold and cloudy",
			"humidity":         "65",
			"wind":             `{"speed": "10", "direction": "NW"}`,
		},
	}

	// Return conversation turns and API response to complete the model's response.
	contents = []*genai.Content{
		{Parts: []*genai.Part{
			{Text: "What is the weather like in Boston?"},
		},
			Role: "user"},
		{Parts: []*genai.Part{
			{FunctionCall: funcCall},
		}},
		{Parts: []*genai.Part{
			{FunctionResponse: funcResp},
		}},
	}

	resp, err = client.Models.GenerateContent(ctx, modelName, contents, config)
	if err != nil {
		return fmt.Errorf("failed to generate content: %w", err)
	}

	respText := resp.Text()

	fmt.Fprintln(w, respText)

	// Example response:
	// The weather in Boston is cold and cloudy with a temperature of 38 degrees Fahrenheit. The humidity is ...

	return nil
}

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-2.0-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;
    }
}

Java

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-2.0-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;
    }
  }
}

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

以下是针对用户提示“波士顿的天气如何?”的模型响应示例。模型建议以参数 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"
            }
          }
        }
      }
    }
  }
  ...
}

第 2 步:向模型提供 API 输出

调用外部 API,并将 API 输出传递回模型。

以下示例使用合成数据来模拟来自外部 API 的响应载荷,并将输出提交回模型。

REST

PROJECT_ID=myproject
MODEL_ID=gemini-2.0-flash
LOCATION="us-central1"

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:generateContent \
-d '{
"contents": [
{
  "role": "user",
  "parts": {
    "text": "What is the weather in Boston?"
  }
},
{
  "role": "model",
  "parts": [
    {
      "functionCall": {
        "name": "get_current_weather",
        "args": {
          "location": "Boston, MA"
        }
      }
    }
  ]
},
{
  "role": "user",
  "parts": [
    {
      "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 name of the location for which to get the weather."
          }
        },
        "required": [
          "location"
        ]
      }
    }
  ]
}
]
}'

Python

function_response_contents = []
function_response_parts = []

# Iterates through the function calls in the response in case there are parallel function call requests
for function_call in response.candidates[0].function_calls:
    print(f"Function call: {function_call.name}")

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    if (function_call.args['location'] == "Boston, MA"):
      api_response = { "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy" }
    if (function_call.args['location'] == "San Francisco, CA"):
      api_response = { "location": "San Francisco, CA", "temperature": 58, "description": "Sunny" }

    function_response_parts.append(
        Part.from_function_response(
            name=function_call.name,
            response={"contents": api_response}
        )
    )
    # Add the function call response to the contents
    function_response_contents = Content(role="user", parts=function_response_parts)

# Submit the User's prompt, model's response, and API output back to the model
response = model.generate_content(
  [
    Content( # User prompt
      role="user",
      parts=[
          Part.from_text("What is the weather like in Boston?"),
      ],
    ),
    response.candidates[0].content,  # Function call response
    function_response_contents   # API output
  ],
  tools=[
    Tool(
      function_declarations=[get_current_weather_func],
    )
  ],
)
# Get the model summary response
print(response.text)

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

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

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

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

It is currently 38 degrees Fahrenheit in Boston, MA with partly cloudy skies.

包含思路的函数调用

在调用启用了 thinking 的函数时,您需要从模型响应对象中获取 thought_signature,并在将函数执行结果发送回模型时返回该值。例如:

Python

# Call the model with function declarations
# ...Generation config, Configure the client, and Define user prompt (No changes)

# Send request with declarations (using a thinking model)
response = client.models.generate_content(
  model="gemini-2.5-flash", config=config, contents=contents)

# See thought signatures
for part in response.candidates[0].content.parts:
  if not part.text:
    continue
  if part.thought and part.thought_signature:
    print("Thought signature:")
    print(part.thought_signature)

虽然无需查看思路签名,但您需要调整第 2 步,以便在返回函数执行结果的同时返回思路签名,这样模型就可以将思路纳入最终回答中:

Python

# Create user friendly response with function result and call the model again
# ...Create a function response part (No change)

# Append thought signatures, function call and result of the function execution to contents
function_call_content = response.candidates[0].content
# Append the model's function call message, which includes thought signatures
contents.append(function_call_content)
contents.append(types.Content(role="user", parts=[function_response_part])) # Append the function response

final_response = client.models.generate_content(
    model="gemini-2.5-flash",
    config=config,
    contents=contents,
)

print(final_response.text)

返回思路签名时,请遵循以下准则:

  • 模型会在回答的其他部分(例如函数调用、文本、文本或思路总结部分)中返回签名。在后续对话轮次中,将包含所有部分的完整回答返回给模型。
  • 请勿将包含签名的部分与也包含签名的另一部分合并。签名不能串联在一起。
  • 请勿将带有签名的部分与不带签名的部分合并。 这会破坏签名所代表的思路的正确位置。

如需详细了解思路签名的限制和使用情况,以及一般的思考模型,请参阅思考页面。

并行函数调用

对于“波士顿和旧金山的详细天气情况如何?”之类的提示,模型可能会提议进行多项并行函数调用。如需查看支持并行函数调用的模型列表,请参阅支持的模型

REST

此示例演示的是包含一个 get_current_weather 函数的场景。用户提示为“波士顿和旧金山的详细天气情况如何?”。该模型建议使用两个并行 get_current_weather 函数调用:一个使用参数 Boston,另一个使用参数 San Francisco

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

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

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

模型请求

PROJECT_ID=my-project
MODEL_ID=gemini-2.0-flash
LOCATION="us-central1"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:generateContent \
-d '{
"contents": [
{
  "role": "user",
  "parts": {
    "text": "What is difference in temperature in Boston and San Francisco?"
  }
},
{
  "role": "model",
  "parts": [
    {
      "functionCall": {
        "name": "get_current_weather",
        "args": {
          "location": "Boston"
        }
      }
    },
    {
      "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 name of the location for which to get the weather."
          }
        },
        "required": [
          "location"
        ]
      }
    }
  ]
}
]
}'
  

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

模型回答

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

Python

此示例演示的是包含一个 get_current_weather 函数的场景。用户提示为“波士顿和旧金山的天气如何?”。

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

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

# Initialize Vertex AI
# TODO(developer): Update the project
vertexai.init(project="my-project", location="us-central1")

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

# Manual function declaration
get_current_weather_func = FunctionDeclaration(
    name="get_current_weather",
    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.",
              "default": {
                "string_value": "Boston, MA"
              }
          }
        },
    },
)

response = model.generate_content(
    contents = [
      Content(
        role="user",
          parts=[
              Part.from_text("What is the weather like in Boston and San Francisco?"),
          ],
      )
    ],
    generation_config = GenerationConfig(temperature=0),
    tools = [
      Tool(
        function_declarations=[get_current_weather_func],
      )
    ]
)

以下命令演示了如何向模型提供函数输出。

function_response_contents = []
function_response_parts = []

# You can have parallel function call requests for the same function type.
# For example, 'location_to_lat_long("London")' and 'location_to_lat_long("Paris")'
# In that case, collect API responses in parts and send them back to the model

for function_call in response.candidates[0].function_calls:
    print(f"Function call: {function_call.name}")

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    if (function_call.args['location'] == "Boston, MA"):
      api_response = { "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy" }
    if (function_call.args['location'] == "San Francisco, CA"):
      api_response = { "location": "San Francisco, CA", "temperature": 58, "description": "Sunny" }

    function_response_parts.append(
        Part.from_function_response(
            name=function_call.name,
            response={"contents": api_response}
        )
    )
    # Add the function call response to the contents
    function_response_contents = Content(role="user", parts=function_response_parts)

function_response_contents

response = model.generate_content(
    contents = [
        Content(
        role="user",
          parts=[
              Part.from_text("What is the weather like in Boston and San Francisco?"),
          ],
        ),  # User prompt
        response.candidates[0].content,  # Function call response
        function_response_contents,  # Function response
    ],
    tools = [
      Tool(
        function_declarations=[get_current_weather_func],
      )
    ]
)
# Get the model summary response
print(response.text)

Go

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

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

// parallelFunctionCalling shows how to execute multiple function calls in parallel
// and return their results to the model for generating a complete response.
func parallelFunctionCalling(w io.Writer, projectID, location, modelName string) error {
	// location = "us-central1"
	// modelName = "gemini-2.0-flash-001"
	ctx := context.Background()
	client, err := genai.NewClient(ctx, projectID, location)
	if err != nil {
		return fmt.Errorf("failed to create GenAI client: %w", err)
	}
	defer client.Close()

	model := client.GenerativeModel(modelName)
	// Set temperature to 0.0 for maximum determinism in function calling.
	model.SetTemperature(0.0)

	funcName := "getCurrentWeather"
	funcDecl := &genai.FunctionDeclaration{
		Name:        funcName,
		Description: "Get the current weather in a given location",
		Parameters: &genai.Schema{
			Type: genai.TypeObject,
			Properties: map[string]*genai.Schema{
				"location": {
					Type: genai.TypeString,
					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.",
				},
			},
			Required: []string{"location"},
		},
	}
	// Add the weather function to our model toolbox.
	model.Tools = []*genai.Tool{
		{
			FunctionDeclarations: []*genai.FunctionDeclaration{funcDecl},
		},
	}

	prompt := genai.Text("Get weather details in New Delhi and San Francisco?")
	resp, err := model.GenerateContent(ctx, prompt)

	if err != nil {
		return fmt.Errorf("failed to generate content: %w", err)
	}
	if len(resp.Candidates) == 0 {
		return errors.New("got empty response from model")
	} else if len(resp.Candidates[0].FunctionCalls()) == 0 {
		return errors.New("got no function call suggestions from model")
	}

	// In a production environment, consider adding validations for function names and arguments.
	for _, fnCall := range resp.Candidates[0].FunctionCalls() {
		fmt.Fprintf(w, "The model suggests to call the function %q with args: %v\n", fnCall.Name, fnCall.Args)
		// Example response:
		// The model suggests to call the function "getCurrentWeather" with args: map[location:New Delhi]
		// The model suggests to call the function "getCurrentWeather" with args: map[location:San Francisco]
	}

	// Use synthetic data to simulate responses from the external API.
	// In a real application, this would come from an actual weather API.
	mockAPIResp1, err := json.Marshal(map[string]string{
		"location":         "New Delhi",
		"temperature":      "42",
		"temperature_unit": "C",
		"description":      "Hot and humid",
		"humidity":         "65",
	})
	if err != nil {
		return fmt.Errorf("failed to marshal function response to JSON: %w", err)
	}

	mockAPIResp2, err := json.Marshal(map[string]string{
		"location":         "San Francisco",
		"temperature":      "36",
		"temperature_unit": "F",
		"description":      "Cold and cloudy",
		"humidity":         "N/A",
	})
	if err != nil {
		return fmt.Errorf("failed to marshal function response to JSON: %w", err)
	}

	// Note, that the function calls don't have to be chained. We can obtain both responses in parallel
	// and return them to Gemini at once.
	funcResp1 := &genai.FunctionResponse{
		Name: funcName,
		Response: map[string]any{
			"content": mockAPIResp1,
		},
	}
	funcResp2 := &genai.FunctionResponse{
		Name: funcName,
		Response: map[string]any{
			"content": mockAPIResp2,
		},
	}

	// Return both API responses to the model allowing it to complete its response.
	resp, err = model.GenerateContent(ctx, prompt, funcResp1, funcResp2)
	if err != nil {
		return fmt.Errorf("failed to generate content: %w", err)
	}
	if len(resp.Candidates) == 0 || len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("got empty response from model")
	}

	fmt.Fprintln(w, resp.Candidates[0].Content.Parts[0])
	// Example response:
	// The weather in New Delhi is hot and humid with a humidity of 65 and a temperature of 42°C. The weather in San Francisco ...

	return nil
}

函数调用模式

您可以通过在 function_calling_config 中设置模式来控制模型使用所提供工具(函数声明)的方式。

模式 说明
AUTO 默认模型行为。模型会根据上下文决定是预测函数调用还是以自然语言回答。这是最灵活的模式,建议在大多数情况下使用。
VALIDATED(预览版) 模型会受到限制,只能预测函数调用或自然语言,并确保符合函数架构。如果未提供 allowed_function_names,模型会从所有可用的函数声明中进行选择。如果提供了 allowed_function_names,模型会从一组允许的函数中进行选择。
ANY 模型会受到限制,始终预测一个或多个函数调用,并确保符合函数架构。如果未提供 allowed_function_names,模型会从所有可用的函数声明中进行选择。如果提供了 allowed_function_names,模型会从一组允许的函数中进行选择。 如果您需要针对每个提示(如果适用)获得函数调用响应,请使用此模式。
NONE 模型禁止进行函数调用。这相当于发送不含任何函数声明的请求。使用此模式可暂时停用函数调用,而无需移除工具定义。

强制函数调用

您可以强制模型仅预测函数调用,而不是允许模型在自然语言回答和函数调用之间进行选择。这称为“强制函数调用”。您还可以选择为模型提供一整套函数声明,但将其回答限制为其中一部分函数。

以下示例强制模型仅预测 get_weather 函数调用。

Python

response = model.generate_content(
    contents = [
      Content(
        role="user",
          parts=[
              Part.from_text("What is the weather like in Boston?"),
          ],
      )
    ],
    generation_config = GenerationConfig(temperature=0),
    tools = [
      Tool(
        function_declarations=[get_weather_func, some_other_function],
      )
    ],
    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_weather"],
        )
    )
)

函数架构示例

函数声明与 OpenAPI 架构兼容。我们支持以下属性:typenullablerequiredformatdescriptionpropertiesitemsenumanyOf$ref$defs。不支持其余属性。

包含对象和数组参数的函数

以下示例使用 Python 字典声明了一个同时接收对象和数组参数作为输入的函数:

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 字典声明了一个接收整数 enum 参数作为输入的函数:

set_status_func = FunctionDeclaration(
  name="set_status",
  description="set a ticket's status field",
  # Function parameters are specified in JSON schema format
  parameters={
      "type": "object",
      "properties": {
        "status": {
          "type": "integer",
          "enum": [ "10", "20", "30" ],   # Provide integer (or any other type) values as strings.
        }
      },
  },
)
  

包含 ref 和 def 的函数

以下 JSON 函数声明使用了 refdefs 属性:

{
  "contents": ...,
  "tools": [
    {
      "function_declarations": [
        {
          "name": "get_customer",
          "description": "Search for a customer by name",
          "parameters": {
            "type": "object",
            "properties": {
              "first_name": { "ref": "#/defs/name" },
              "last_name": { "ref": "#/defs/name" }
            },
            "defs": {
              "name": { "type": "string" }
            }
          }
        }
      ]
    }
  ]
}
  

使用说明:

  • 与 OpenAPI 架构不同,需指定 refdefs,但不要使用 $ 符号。
  • ref 必须引用 defs 的直接子级;不得使用外部引用。
  • 嵌套架构的最大深度为 32。
  • defs(自引用)中的递归深度限制为 2。

包含数组参数的 from_func

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

from typing import List

# Define a function. Could be a local function or you can import the requests library to call an API
def multiply_numbers(numbers: List[int] = [1, 1]) -> int:
  """
  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': {'properties': {'numbers': {'items': {'type': 'INTEGER'},
    'description': 'list of numbers',
    'default': [1.0, 1.0],
    'title': 'Numbers',
    'type': 'ARRAY'}},
  'description': 'Calculates the product of all numbers in an array.',
  'title': 'multiply_numbers',
  'property_ordering': ['numbers'],
  'type': 'OBJECT'}}
"""
  

函数调用的最佳实践

撰写清晰而详尽的函数名称、参数说明和指令

  • 函数名称应以字母或下划线开头,且只能包含 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

使用强类型参数

如果参数值来自有限集,请添加 enum 字段,而不是将值集放入说明中。如果参数值始终是整数,请将类型设置为 integer,而不是 number

工具选择

虽然模型可以使用任意数量的工具,但提供的工具过多可能会增加选择错误或次优工具的风险。为获得最佳效果,请尽量仅提供与上下文或任务相关的工具,最好将有效工具集保持在 10-20 个以内。如果您有大量工具,请考虑根据对话上下文动态选择工具。

如果您提供通用型低级工具(例如 bash),模型可能会更频繁地使用该工具,但准确性会降低。如果您提供的是特定的高级别工具(例如 get_weather),模型将能够更准确地使用该工具,但该工具的使用频率可能不会太高。

使用系统说明

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

提示工程

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

  • 模型的其他上下文,例如 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 个字符。

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

函数调用的应用场景

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

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

下面是一些其他用例:

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

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

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

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

后续步骤