Utilizzare la chiamata di funzione

Con l'accesso diretto ai modelli di ML Kit, puoi utilizzare la chiamata di funzione per consentire ai modelli Gemini Nano di generare richieste di esecuzione di funzioni strutturate (chiamate di strumenti) anziché risposte in testo normale. La chiamata di funzione consente di connettere i modelli di AI generativa on-device a strumenti esterni, API e funzionalità delle app locali.

Funzionalità chiave

La chiamata di funzione offre le seguenti funzionalità principali:

  • Chiamata di funzione a turno singolo: Gemini Nano prevede una o più chiamate di strumenti (FunctionCall), la tua app esegue le funzioni localmente e il flusso viene completato senza richiedere una risposta di follow-up del modello.
  • Chiamata di funzione in più passaggi: Gemini Nano prevede una o più chiamate di strumenti (FunctionCall), la tua app esegue le funzioni localmente e restituisce i risultati (FunctionResponsePart) per recuperare altre chiamate di strumenti o una risposta di testo sintetizzata finale.

Quando implementi la chiamata di funzione, puoi usufruire di quanto segue:

  • Definizioni degli strumenti programmatici: crea definizioni degli strumenti FunctionDeclaration e FunctionSchema dinamiche in fase di runtime utilizzando l'API ML Kit GenAI Schema (com.google.mlkit:genai-schema).
  • Analisi degli argomenti strutturati: ricevi valori degli argomenti fortemente tipizzati direttamente dal candidato della risposta del modello per eseguire la logica dell'app locale.

Risultati di esempio

La chiamata di funzione supporta flussi sia a turno singolo che multi-turno. In entrambi i casi, il modello prevede una o più chiamate di strumenti costituite dal nome della funzione e dagli argomenti. Per i flussi multi-turn, dopo aver ricevuto i risultati di esecuzione dell'app, l'app può inviare un'altra richiesta al modello con la cronologia completa della conversazione per ottenere altre chiamate dello strumento o una risposta di testo finale per l'utente.

Flusso di esecuzione Prompt dell'utente Output del modello
A turno singolo "Accendi le luci del salotto all'80% di luminosità." Chiamata allo strumento:
turn_on_light(room="living room", brightness=80)
A turno singolo "Apri l'app Fotocamera." Chiamata allo strumento:
open_app(appName="Camera")
In più passaggi "Che tempo fa a San Francisco in gradi Celsius?" Chiamata allo strumento intermedia:
get_current_weather(location="San Francisco, CA", unit="celsius")

Output del modello finale mostrato all'utente:
In SF it's currently 25 degrees Celsius.

Prerequisiti

Per utilizzare la chiamata di funzione, devi soddisfare i seguenti requisiti relativi al dispositivo e all'account:

Per verificare di aver soddisfatto questi requisiti, controlla che il modello Gemini Nano 4 Fast sia disponibile nell'app AICore: apri l'app AICore, fai clic sul menu a discesa Seleziona un modello e controlla che Gemini Nano 4 Fast sia presente nell'elenco. Se il modello non è presente, si è verificato un problema con il supporto del dispositivo o la registrazione dell'account e la chiamata di funzione non funzionerà.

Inoltre, il progetto deve soddisfare i seguenti requisiti:

  • Kotlin versione 2.3.0 o successive
  • SDK minimo (minSdk) versione 26 o successive

Inizia

Ecco i passaggi per iniziare a utilizzare la chiamata di funzione.

  1. Nel file settings.gradle.kts (o settings.gradle) a livello di progetto, aggiungi mavenCentral() al blocco repositories {}.

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    
  2. Nel file build.gradle.kts (o build.gradle) a livello di modulo, aggiungi le dipendenze dell'API Prompt di ML Kit e dello schema:

    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. Nel file build.gradle (o build.gradle.kts) a livello di modulo, imposta la versione di minSdk su 26 o versioni successive.

    Kotlin

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

    Groovy

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

Come utilizzare l'API di chiamata di funzione

Per implementare la chiamata di funzione, segui questi passaggi:

  1. Definisci gli strumenti.
  2. Seleziona il modello.
  3. Allega strumenti alla tua richiesta.
  4. Gestire le chiamate degli strumenti (single-turn o multi-turn).

Le sezioni successive illustrano un esempio che mostra questi passaggi.

Definisci gli strumenti

Crea gli schemi degli strumenti in modo programmatico utilizzando FunctionDeclaration, FunctionSchema e FunctionType del pacchetto com.google.mlkit.genai.schema.tools. (Per definire gli strumenti in modo dichiarativo in tempo di compilazione utilizzando l'annotazione @AppFunction di Android con esecuzione automatica, consulta Definisci gli strumenti.)

Ad esempio, puoi definire uno strumento orientato all'azione (come l'accensione di una luce smart per l'esecuzione in un singolo 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")
    )
)

In alternativa, definisci uno strumento di recupero dei dati (ad esempio, il recupero del meteo attuale per la sintesi multi-turn):

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

Seleziona il modello

La chiamata di funzione richiede Gemini Nano 4. Per accedere a Gemini Nano 4, utilizza l'API di selezione del modello per configurare la tua istanza GenerativeModel in modo che abbia come target ModelReleaseStage.PREVIEW E 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)

Allega strumenti alla tua richiesta

Quando crei un oggetto GenerateContentRequest, passa l'elenco FunctionDeclaration a setTools() nel generatore di richieste.

Ad esempio, per collegare uno strumento per una richiesta di azione single-turn con un'istruzione di sistema:

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)

In alternativa, per allegare l'elenco FunctionDeclaration per una query con più turni:

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)

Gestisci le chiamate agli strumenti

Quando Gemini Nano decide di richiamare uno strumento, la risposta candidata del modello contiene uno o più oggetti FunctionCall in candidate.functionCalls. Per gestire le chiamate agli strumenti, l'app deve prima esaminare il candidato alla risposta per verificare se sono state previste chiamate agli strumenti:

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
}

Chiamata di funzione a turno singolo

Utilizza la chiamata di funzione a turno singolo per attività orientate all'azione in cui l'app soddisfa direttamente la richiesta (ad esempio, "Apri l'app Fotocamera" o "Accendi le luci del salotto"). Una volta che l'app esegue la funzione localmente, il flusso è completo; non è richiesta alcuna risposta del modello di follow-up.

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

Chiamata di funzione multi-turn

Utilizza la chiamata di funzione multi-turn quando l'utente si aspetta una risposta in linguaggio naturale basata sui dati recuperati dallo strumento (ad esempio, "Che tempo fa a San Francisco?").

In un flusso a più turni, l'app esegue le seguenti operazioni:

  1. Esegue la funzione richiesta localmente.
  2. Pacchettizza il risultato in un oggetto FunctionResponsePart.
  3. Aggiunge alla cronologia delle conversazioni sia la chiamata del modello (ruolo MODEL) sia il risultato dell'esecuzione (ruolo USER).
  4. Invia una richiesta di follow-up a Gemini Nano per sintetizzare la risposta finale in linguaggio naturale.
// 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")

Codice campione

Per un esempio completo e funzionante di chiamata di funzione in un'app per Android, consulta questa app di esempio di ML Kit.

Problemi noti

  • AndroidX AppFunctions (@AppFunction) nell'accesso diretto al modello (genai-prompt): il rilevamento e l'esecuzione degli strumenti @AppFunction in fase di compilazione direttamente tramite l'API Prompt (com.google.mlkit:genai-prompt:1.0.0-beta5) non sono ancora disponibili; gli strumenti nella libreria genai-prompt devono essere definiti in modo programmatico utilizzando la classe FunctionDeclaration. Per utilizzare gli strumenti di @AppFunction oggi, utilizza i workflow agentici (com.google.mlkit:genai-agent).
  • Quando utilizzi le richieste di streaming (generateContentStream), le chiamate agli strumenti non vengono trasmesse in streaming token per token. Vengono invece emessi oggetti FunctionCall completi (tramite StreamingCallback.onNewFunctionCall o nel GenerateContentResponse.candidates[0].functionCalls finale in streaming) una volta che il modello ha terminato di generare la chiamata allo strumento.