Instructivo: Llama a funciones con la API de Gemini


La llamada a funciones facilita la obtención de resultados de datos estructurados de modelos generativos. Luego, puedes usar estos resultados para llamar a otras APIs y mostrar los datos de respuesta relevantes al modelo. En otras palabras, la llamada a funciones te ayuda a conectar modelos generativos a sistemas externos para que el contenido generado incluya la información más actualizada y precisa.

Puedes proporcionar descripciones de funciones a los modelos de Gemini. Son funciones que escribes en el lenguaje de tu app (es decir, no son Google Cloud Functions). El modelo puede pedirte que llames a una función y envíes el resultado para ayudar al modelo a controlar tu consulta.

Si aún no lo has hecho, consulta la Introducción a las llamadas a funciones para obtener más información.

Configura tu proyecto

Antes de llamar a la API de Gemini, debes configurar tu proyecto de Xcode, lo que incluye configurar tu clave de API, agregar el paquete del SDK a tu proyecto de Xcode y, luego, inicializar el modelo.

Cómo configurar una llamada a función

En este instructivo, harás que el modelo interactúe con una API hipotética de intercambio de monedas que admita los siguientes parámetros:

Parámetro Tipo Obligatorio Descripción
currencyFrom cadena Moneda desde la que se convertirá
currencyTo cadena Moneda a la que se convertirá

Ejemplo de solicitud a la API

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

Ejemplo de respuesta de la API

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

Paso 1: Crea la función que realiza la solicitud a la API

Si aún no lo has hecho, comienza por crear la función que realiza una solicitud a la API.

Para la demostración de este instructivo, en lugar de enviar una solicitud a la API real, mostrarás valores codificados en el mismo formato que mostraría una API real.

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)]),
  ]
}

Paso 2: Crea una declaración de función

Crea la declaración de función que pasarás al modelo generativo (siguiente paso de este instructivo).

Incluye tantos detalles como sea posible en las descripciones de funciones y parámetros. El modelo generativo usa esta información para determinar qué función seleccionar y cómo proporcionar valores para los parámetros en la llamada a función.

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"]
)

Paso 3: Especifica la declaración de la función durante la inicialización del modelo

Para especificar la declaración de la función cuando inicialices el modelo generativo, configura el parámetro tools del modelo:

// 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])]
)

Paso 4: Genera una llamada a función

Ahora puedes indicarle al modelo con la función definida.

La forma recomendada de usar la llamada a funciones es a través de la interfaz de chat, ya que las llamadas a funciones se ajustan perfectamente a la estructura de varios turnos del chat.

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)