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


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

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

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

设置项目

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

设置函数调用

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

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

API 请求示例

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

API 响应示例

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

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

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

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

suspend fun makeApiRequest(
    currencyFrom: String,
    currencyTo: String
): JSONObject {
    // This hypothetical API returns a JSON such as:
    // {"base":"USD","rates":{"SEK": 0.091}}
    return JSONObject().apply {
        put("base", currencyFrom)
        put("rates", hashMapOf(currencyTo to 0.091))
    }
}

第 2 步:创建函数声明

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

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

val getExchangeRate = defineFunction(
  name = "getExchangeRate",
  description = "Get the exchange rate for currencies between countries",
  Schema.str("currencyFrom", "The currency to convert from."),
  Schema.str("currencyTo", "The currency to convert to.")
) { from, to ->
    // Call the function that you declared above
    makeApiRequest(from, to)
}

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

在初始化生成模型时,通过将函数声明传递到模型的 tools 参数来指定函数声明:

val generativeModel = GenerativeModel(
  // Use a model that supports function calling, like a Gemini 1.5 model
  modelName = "gemini-1.5-flash",
  // Access your API key as a Build Configuration variable (see "Set up your API key" above)
  apiKey = BuildConfig.apiKey,
  // Specify the function declaration.
  tools = listOf(Tool(listOf(getExchangeRate)))
)

第 4 步:生成函数调用

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

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

val chat = generativeModel.startChat()

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

// Send the message to the generative model
var response = chat.sendMessage(prompt)

// Check if the model responded with a function call
response.functionCall?.let { functionCall ->
  // Try to retrieve the stored lambda from the model's tools and
  // throw an exception if the returned function was not declared
  val matchedFunction = generativeModel.tools?.flatMap { it.functionDeclarations }
      ?.first { it.name == functionCall.name }
      ?: throw InvalidStateException("Function not found: ${functionCall.name}")

  // Call the lambda retrieved above
  val apiResponse: JSONObject = matchedFunction.execute(functionCall)

  // Send the API response back to the generative model
  // so that it generates a text response that can be displayed to the user
  response = chat.sendMessage(
    content(role = "function") {
        part(FunctionResponsePart(functionCall.name, apiResponse))
    }
  )
}

// Whenever the model responds with text, show it in the UI
response.text?.let { modelResponse ->
    println(modelResponse)
}