Usa la llamada a función

Con el acceso directo al modelo de ML Kit, puedes usar la llamada a funciones para permitir que los modelos de Gemini Nano generen solicitudes de ejecución de funciones estructuradas (llamadas a herramientas) en lugar de respuestas de texto sin formato. La llamada a función te permite conectar modelos de IA generativa integrados en el dispositivo con herramientas externas, APIs y funciones de apps locales.

Funciones clave

La llamada a funciones proporciona las siguientes capacidades clave:

  • Llamada a función de un solo turno: Gemini Nano predice una o más llamadas a herramientas (FunctionCall), tu app ejecuta las funciones de forma local y el flujo se completa sin necesidad de una respuesta de modelo de seguimiento.
  • Llamada a funciones de varios turnos: Gemini Nano predice una o más llamadas a herramientas (FunctionCall), tu app ejecuta las funciones de forma local y devuelve los resultados (FunctionResponsePart) para recuperar más llamadas a herramientas o una respuesta de texto sintetizada final.

Cuando implementas la llamada a funciones, puedes aprovechar lo siguiente:

  • Definiciones de herramientas programáticas: Construye definiciones de herramientas FunctionDeclaration y FunctionSchema dinámicas en el entorno de ejecución con la API de esquema de IA generativa de ML Kit (com.google.mlkit:genai-schema).
  • Análisis de argumentos estructurados: Recibe valores de argumentos con tipos de datos definidos directamente desde el candidato de respuesta del modelo para ejecutar la lógica de tu app local.

Resultados de ejemplo

La llamada a funciones admite flujos de un solo turno y de varios turnos. En ambos casos, el modelo predice una o más llamadas a herramientas que consisten en el nombre de la función y los argumentos. En el caso de los flujos de varios turnos, después de recibir los resultados de la ejecución de la app, esta puede enviar otra solicitud al modelo con el historial de conversaciones completo para obtener más llamadas a herramientas o una respuesta de texto final para el usuario.

Flujo de ejecución Instrucción del usuario Resultado del modelo
Un solo turno "Enciende las luces de la sala de estar al 80% de brillo". Llamada a la herramienta:
turn_on_light(room="living room", brightness=80)
Un solo turno "Abre la app de Cámara". Llamada a la herramienta:
open_app(appName="Camera")
Varios turnos "¿Cómo está el clima en San Francisco en grados Celsius?" Llamada a la herramienta intermedia:
get_current_weather(location="San Francisco, CA", unit="celsius")

Resultado final del modelo que se muestra al usuario:
In SF it's currently 25 degrees Celsius.

Requisitos previos

Para usar la llamada a función, debes cumplir con los siguientes requisitos de dispositivo y cuenta:

Para verificar que cumpliste con estos requisitos, comprueba que el modelo Gemini Nano 4 Fast esté disponible en la app de AICore: abre la app de AICore, haz clic en el menú desplegable Select a model y verifica que aparezca Gemini Nano 4 Fast. Si el modelo no está allí, hay un problema con la compatibilidad del dispositivo o la inscripción de la cuenta, y la llamada a función no funcionará.

Además, tu proyecto debe cumplir con los siguientes requisitos:

  • Kotlin versión 2.3.0 o posterior
  • Versión mínima del SDK (minSdk) 26 o posterior

Comenzar

Estos son los pasos para comenzar a usar la llamada a funciones.

  1. En el archivo settings.gradle.kts (o settings.gradle) a nivel del proyecto, agrega mavenCentral() al bloque repositories {}.

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    
  2. En el archivo build.gradle.kts (o build.gradle) a nivel del módulo, agrega las dependencias de la API de Prompt y el esquema de ML Kit:

    Kotlin

    plugins {
        id("com.android.application")
        id("org.jetbrains.kotlin.android")
    }
    
    dependencies {
        // ML Kit GenAI Prompt and Schema SDKs
        implementation("com.google.mlkit:genai-prompt:1.0.0-beta5")
        implementation("com.google.mlkit:genai-schema:1.0.0-alpha2")
    }
    

    Groovy

    plugins {
        id 'com.android.application'
        id 'org.jetbrains.kotlin.android'
    }
    
    dependencies {
        // ML Kit GenAI Prompt and Schema SDKs
        implementation 'com.google.mlkit:genai-prompt:1.0.0-beta5'
        implementation 'com.google.mlkit:genai-schema:1.0.0-alpha2'
    }
    
  3. En el archivo build.gradle (o build.gradle.kts) a nivel del módulo, establece la versión de minSdk en 26 o una posterior.

    Kotlin

    android {
        defaultConfig {
            // ...
            minSdk = 26
            // ...
        }
    }
    

    Groovy

    android {
        defaultConfig {
            // ...
            minSdk 26
            // ...
        }
    }
    

Cómo usar la API de llamada a funciones

Para implementar la llamada a funciones, sigue estos pasos:

  1. Define tus herramientas.
  2. Selecciona el modelo.
  3. Adjunta herramientas a tu solicitud.
  4. Controlar las llamadas a herramientas (de un solo turno o de varios turnos)

En las próximas secciones, se muestra un ejemplo de estos pasos.

Define tus herramientas

Crea esquemas de herramientas de forma programática con FunctionDeclaration, FunctionSchema y FunctionType del paquete com.google.mlkit.genai.schema.tools. (Para definir herramientas de forma declarativa en el tiempo de compilación con la anotación @AppFunction de Android con ejecución automática, consulta Cómo definir herramientas).

Por ejemplo, puedes definir una herramienta orientada a la acción (como encender una lámpara inteligente para la ejecución de un solo turno):

import com.google.mlkit.genai.schema.tools.FunctionDeclaration
import com.google.mlkit.genai.schema.tools.FunctionSchema
import com.google.mlkit.genai.schema.tools.FunctionType

val turnOnLightTool = FunctionDeclaration(
    name = "turn_on_light",
    description = "Turn on the lights in a room and set the brightness",
    parameters = FunctionSchema(
        type = FunctionType.OBJECT,
        properties = mapOf(
            "room" to FunctionSchema(
                type = FunctionType.STRING,
                description = "The room name"
            ),
            "brightness" to FunctionSchema(
                type = FunctionType.INTEGER,
                description = "Brightness level from 0 to 100"
            )
        ),
        required = listOf("room")
    )
)

O define una herramienta de recuperación de datos (como recuperar el clima actual para la síntesis de varios turnos):

import com.google.mlkit.genai.schema.tools.FunctionDeclaration
import com.google.mlkit.genai.schema.tools.FunctionSchema
import com.google.mlkit.genai.schema.tools.FunctionType

val getWeatherTool = FunctionDeclaration(
    name = "get_current_weather",
    description = "Get the current weather for a location",
    parameters = FunctionSchema(
        type = FunctionType.OBJECT,
        properties = mapOf(
            "location" to FunctionSchema(
                type = FunctionType.STRING,
                description = "The city and state, e.g. San Francisco, CA"
            ),
            "unit" to FunctionSchema(
                type = FunctionType.STRING,
                description = "The temperature unit, either 'celsius' or 'fahrenheit'"
            )
        ),
        required = listOf("location")
    )
)

Selecciona el modelo

La llamada a funciones requiere Gemini Nano 4. Para acceder a Gemini Nano 4, usa la API de selección de modelos para configurar tu instancia de GenerativeModel para que se oriente a ModelReleaseStage.PREVIEW Y ModelPreference.FAST.

import com.google.mlkit.genai.prompt.Generation
import com.google.mlkit.genai.prompt.ModelPreference
import com.google.mlkit.genai.prompt.ModelReleaseStage
import com.google.mlkit.genai.prompt.generationConfig
import com.google.mlkit.genai.prompt.modelConfig

// Target the preview fast model (Gemini Nano 4)
val config = generationConfig {
    modelConfig = modelConfig {
        releaseStage = ModelReleaseStage.PREVIEW
        preference = ModelPreference.FAST
    }
}
val generativeModel = Generation.getClient(config)

Adjunta herramientas a tu solicitud

Cuando crees un objeto GenerateContentRequest, pasa tu lista de FunctionDeclaration a setTools() en el compilador de solicitudes.

Por ejemplo, para adjuntar una herramienta para una solicitud de acción de un solo turno con una instrucción del sistema, haz lo siguiente:

import com.google.mlkit.genai.prompt.SystemInstruction
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.generateContentRequest

val requestText = "Turn on the living room lights and set brightness to 50"

val request = generateContentRequest(
    SystemInstruction("You are a helpful home automation assistant."),
    TextPart(requestText)
) {
    // Attach the FunctionDeclaration tool schemas
    setTools(listOf(turnOnLightTool))
    temperature = 0.2f
}

// Run non-streaming inference
val response = generativeModel.generateContent(request)

O bien, para adjuntar tu lista de FunctionDeclaration para una consulta de varios turnos, haz lo siguiente:

import com.google.mlkit.genai.prompt.SystemInstruction
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.generateContentRequest

val availableTools = listOf(getWeatherTool)

// Use the generateContentRequest DSL
val request = generateContentRequest(
    TextPart("What is the weather in San Francisco, CA in celsius?")
) {
    setTools(availableTools)
}
val response = generativeModel.generateContent(request)

Controla las llamadas a herramientas

Cuando Gemini Nano decide invocar una herramienta, la respuesta candidata del modelo contiene uno o más objetos FunctionCall en candidate.functionCalls. Para controlar las llamadas a herramientas, tu app primero debe inspeccionar el candidato de respuesta para verificar si se predijeron llamadas a herramientas:

import com.google.mlkit.genai.common.FunctionArgValue
import com.google.mlkit.genai.prompt.Content
import com.google.mlkit.genai.prompt.FunctionCallPart
import com.google.mlkit.genai.prompt.FunctionResponsePart
import com.google.mlkit.genai.prompt.GenerateContentRequest
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.content

val candidate = response.candidates.firstOrNull()
val functionCalls = candidate?.functionCalls ?: emptyList()

if (functionCalls.isNotEmpty()) {
    // Process tool calls using either the single-turn or multi-turn flow
    // described in the following sections
}

Llamada a funciones de un solo turno

Usa la llamada a función de un solo turno para tareas orientadas a la acción en las que la app cumple directamente con la solicitud (por ejemplo, "Abre la app de la cámara" o "Enciende las luces de la sala de estar"). Una vez que tu app ejecuta la función de forma local, el flujo se completa; no se requiere una respuesta de seguimiento del modelo.

for (functionCall in functionCalls) {
    val name = functionCall.name
    val args = functionCall.arguments // Map<String, FunctionArgValue>

    when (name) {
        "open_app" -> {
            val appName = (args["appName"] as? FunctionArgValue.StringValue)?.value
            launchApp(appName)
        }
        "turn_on_light" -> {
            val room = (args["room"] as? FunctionArgValue.StringValue)?.value
            val brightness = (args["brightness"] as? FunctionArgValue.IntValue)?.value ?: 100
            setLightState(room, brightness)
        }
        else -> Log.w(TAG, "Unhandled tool call: $name")
    }
}

Llamada a funciones de varios turnos

Usa la llamada a funciones de varios turnos cuando el usuario espere una respuesta en lenguaje natural basada en los datos que recuperó la herramienta (por ejemplo, "¿Cómo está el clima en San Francisco?").

En un flujo de varios turnos, tu app hace lo siguiente:

  1. Ejecuta la función solicitada de forma local.
  2. Empaqueta el resultado en un objeto FunctionResponsePart.
  3. Agrega la llamada del modelo (rol MODEL) y el resultado de la ejecución (rol USER) al historial de conversaciones.
  4. Envía una solicitud de seguimiento a Gemini Nano para sintetizar la respuesta final en lenguaje natural.
// 1. Execute each predicted tool call and collect results
val responseParts = mutableListOf<FunctionResponsePart>()

for (functionCall in functionCalls) {
    val responsePart: FunctionResponsePart = when {
        functionCall.name == "get_current_weather" -> {
            val location = (functionCall.arguments["location"] as? FunctionArgValue.StringValue)?.value ?: ""
            val unit = (functionCall.arguments["unit"] as? FunctionArgValue.StringValue)?.value ?: "celsius"

            val weatherData = fetchWeather(location, unit) // Local network/API call

            // Package the tool execution result as a key-value map
            FunctionResponsePart(
                id = functionCall.id,
                name = functionCall.name,
                response = mapOf("result" to weatherData)
            )
        }

        else -> throw IllegalArgumentException("Unknown tool: ${functionCall.name}")
    }
    responseParts.add(responsePart)
}

// 2. Append turns to conversation history to construct the multi-turn context
val history = request.contents.toMutableList().apply {
    // Turn 1: Model's request containing the predicted FunctionCallPart object
    add(
        content(Content.Role.MODEL) {
            for (call in functionCalls) {
                addPart(FunctionCallPart(call))
            }
        }
    )
    // Turn 2: User's response containing the executed FunctionResponsePart object
    add(
        content(Content.Role.USER) {
            for (responsePart in responseParts) {
                addPart(responsePart)
            }
        }
    )
}

// 3. Send the updated history back to Gemini Nano for final text synthesis
val followUpRequest = GenerateContentRequest.Builder(history)
    .setTools(availableTools) // Include tools in case the model requires subsequent tool calls
    .build()

val finalResponse = generativeModel.generateContent(followUpRequest)
val answer = finalResponse.candidates.firstOrNull()?.text

Log.d(TAG, "Final Model Response: $answer")

Código de muestra

Para ver un ejemplo completo de la llamada a funciones en una app para Android, consulta esta app de ejemplo de ML Kit.

Problemas conocidos

  • AppFunctions de AndroidX (@AppFunction) en el acceso directo al modelo (genai-prompt): El descubrimiento y la ejecución de herramientas de @AppFunction en tiempo de compilación directamente a través de la API de Prompt (com.google.mlkit:genai-prompt:1.0.0-beta5) aún no están disponibles. Las herramientas de la biblioteca genai-prompt se deben definir de forma programática con la clase FunctionDeclaration. Para usar las herramientas de @AppFunction hoy, usa flujos de trabajo de agentes (com.google.mlkit:genai-agent).
  • Cuando se usan solicitudes de transmisión (generateContentStream), las llamadas a funciones no se transmiten token por token. En cambio, se emiten objetos FunctionCall completos (a través de StreamingCallback.onNewFunctionCall o en el GenerateContentResponse.candidates[0].functionCalls transmitido final) una vez que el modelo termina de generar la llamada a función.