教程:使用 Gemini API 进行函数调用


借助函数调用,您可以更轻松地从生成模型中获取结构化数据输出。然后,您可以使用这些输出调用其他 API,并将相关响应数据返回给模型。换言之,函数调用可帮助您将生成模型连接到外部系统,以使生成的内容包含最新且准确的信息。

您可以为 Gemini 模型提供函数说明。这些函数是使用应用的语言编写的(即,它们不是 Google Cloud Functions)。模型可能会要求您调用一个函数并发回结果,以帮助模型处理您的查询。

请参阅函数调用简介了解详情(如果您尚未这样做)。

设置项目

在调用 Gemini API 之前,您需要设置 Xcode 项目,其中包括设置 API 密钥、将 SDK 软件包添加到 Xcode 项目以及初始化模型。

设置函数调用

在本教程中,您将让模型与支持以下参数的假设货币交易所 API 进行交互:

参数 类型 必需 说明
currencyFrom string 要换算的币种
currencyTo string 要换算成的币种

API 请求示例

{
  "currencyFrom": "USD",
  "currencyTo": "SEK"
}

API 响应示例

{
  "base": "USD",
  "rates": {"SEK": 0.091}
}

第 1 步:创建用于发出 API 请求的函数

如果尚未创建用于发出 API 请求的函数,请先创建。

在本教程中出于演示目的,您不会发送实际 API 请求,而是以与实际 API 返回的格式相同的格式返回硬编码值。

func makeAPIRequest(currencyFrom: String,
                    currencyTo: String) -> JSONObject {
  // This hypothetical API returns a JSON such as:
  // {"base":"USD","rates":{"SEK": 0.091}}
  return [
    "base": .string(currencyFrom),
    "rates": .object([currencyTo: .number(0.091)]),
  ]
}

第 2 步:创建函数声明

创建要传递给生成模型的函数声明(本教程的下一步)。

在函数和参数说明中添加尽可能多的详细信息。 生成模型使用这些信息来确定选择哪个函数,以及如何为函数调用中的形参提供值。

let getExchangeRate = FunctionDeclaration(
  name: "getExchangeRate",
  description: "Get the exchange rate for currencies between countries",
  parameters: [
    "currencyFrom": Schema(
      type: .string,
      description: "The currency to convert from."
    ),
    "currencyTo": Schema(
      type: .string,
      description: "The currency to convert to."
    ),
  ],
  requiredParameters: ["currencyFrom", "currencyTo"]
)

第 3 步:在模型初始化期间指定函数声明

在初始化生成模型时,通过设置模型的 tools 参数来指定函数声明:

// Use a model that supports function calling, like a Gemini 1.5 model
let generativeModel = GenerativeModel(
  name: "gemini-1.5-flash",
  apiKey: apiKey,
  // Specify the function declaration.
  tools: [Tool(functionDeclarations: [getExchangeRate])]
)

第 4 步:生成函数调用

现在,您可以使用定义的函数向模型发出提示。

建议使用聊天界面使用函数调用,因为函数调用非常适合聊天的多轮结构。

let chat = generativeModel.startChat()

let prompt = "How much is 50 US dollars worth in Swedish krona?"

// Send the message to the generative model
let response1 = try await chat.sendMessage(prompt)

// Check if the model responded with a function call
guard let functionCall = response1.functionCalls.first else {
  fatalError("Model did not respond with a function call.")
}
// Print an error if the returned function was not declared
guard functionCall.name == "getExchangeRate" else {
  fatalError("Unexpected function called: \(functionCall.name)")
}
// Verify that the names and types of the parameters match the declaration
guard case let .string(currencyFrom) = functionCall.args["currencyFrom"] else {
  fatalError("Missing argument: currencyFrom")
}
guard case let .string(currencyTo) = functionCall.args["currencyTo"] else {
  fatalError("Missing argument: currencyTo")
}

// Call the hypothetical API
let apiResponse = makeAPIRequest(currencyFrom: currencyFrom, currencyTo: currencyTo)

// Send the API response back to the model so it can generate a text response that can be
// displayed to the user.
let response = try await chat.sendMessage([ModelContent(
  role: "function",
  parts: [.functionResponse(FunctionResponse(
    name: functionCall.name,
    response: apiResponse
  ))]
)])

// Log the text response.
guard let modelResponse = response.text else {
  fatalError("Model did not respond with text.")
}
print(modelResponse)