Używaj wywołań funkcji

Dzięki bezpośredniemu dostępowi do modelu w ML Kit możesz używać wywoływania funkcji, aby umożliwić modelom Gemini Nano generowanie ustrukturyzowanych żądań wykonania funkcji (wywołań narzędzi) zamiast odpowiedzi w formie zwykłego tekstu. Wywoływanie funkcji umożliwia łączenie modeli generatywnej AI na urządzeniu z zewnętrznymi narzędziami, interfejsami API i funkcjami aplikacji lokalnych.

Najważniejsze funkcje

Wywoływanie funkcji zapewnia te kluczowe możliwości:

  • Wywoływanie funkcji w jednej turze: Gemini Nano przewiduje jedno lub więcej wywołań narzędzi (FunctionCall), aplikacja wykonuje funkcje lokalnie, a proces kończy się bez konieczności uzyskania odpowiedzi modelu.
  • Wieloturowe wywoływanie funkcji: Gemini Nano przewiduje co najmniej 1 wywołanie narzędzia (FunctionCall), aplikacja wykonuje funkcje lokalnie i przekazuje wyniki (FunctionResponsePart), aby pobrać więcej wywołań narzędzi lub ostateczną, zsyntetyzowaną odpowiedź tekstową.

Podczas implementowania wywoływania funkcji możesz korzystać z tych rozwiązań:

  • Definicje narzędzi automatycznych: twórz dynamiczne definicje narzędzi FunctionDeclaration i FunctionSchema w czasie działania za pomocą interfejsu ML Kit GenAI Schema API (com.google.mlkit:genai-schema).
  • Analiza argumentów strukturalnych: otrzymuj silnie typowane wartości argumentów bezpośrednio z odpowiedzi modelu kandydującego, aby wykonywać lokalną logikę aplikacji.

Przykładowe wyniki

Wywoływanie funkcji obsługuje zarówno przepływy jednoetapowe, jak i wieloetapowe. W obu przypadkach model przewiduje co najmniej 1 wywołanie narzędzia, które składa się z nazwy funkcji i argumentów. W przypadku wieloetapowych procesów po otrzymaniu wyników wykonania aplikacja może wysłać do modelu kolejną prośbę z pełną historią rozmowy, aby uzyskać więcej wywołań narzędzi lub ostateczną odpowiedź tekstową dla użytkownika.

Przepływ wykonywania Prompt użytkownika Dane wyjściowe modelu
Jednoetapowe „Ustaw jasność światła w salonie na 80%”. Wywołanie narzędzia:
turn_on_light(room="living room", brightness=80)
Jednoetapowe „Otwórz aplikację Aparat”. Wywołanie narzędzia:
open_app(appName="Camera")
Wieloetapowe „Jaka jest pogoda w San Francisco w stopniach Celsjusza?” Wywołanie narzędzia pośredniego:
get_current_weather(location="San Francisco, CA", unit="celsius")

Ostateczne dane wyjściowe modelu wyświetlane użytkownikowi:
In SF it's currently 25 degrees Celsius.

Wymagania wstępne

Aby korzystać z wywoływania funkcji, musisz spełniać te wymagania dotyczące urządzenia i konta:

Aby sprawdzić, czy spełniasz te wymagania, upewnij się, że model Gemini Nano 4 Fast jest dostępny w aplikacji AICore: otwórz aplikację AICore, kliknij menu Wybierz model i sprawdź, czy na liście znajduje się Gemini Nano 4 Fast. Jeśli modelu nie ma na liście, oznacza to, że wystąpił problem z obsługą urządzenia lub rejestracją konta i wywoływanie funkcji nie będzie działać.

Projekt musi też spełniać te wymagania:

  • Kotlin w wersji 2.3.0 lub nowszej,
  • Minimalna wersja pakietu SDK (minSdk): 26

Rozpocznij

Aby zacząć korzystać z wywoływania funkcji, wykonaj te czynności.

  1. W pliku settings.gradle.kts (lub settings.gradle) na poziomie projektu dodaj mavenCentral() do bloku repositories {}.

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    
  2. W pliku build.gradle.kts (lub build.gradle) na poziomie modułu dodaj interfejs ML Kit Prompt API i zależności schematu:

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

    Zakręcony

    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. W pliku build.gradle (lub build.gradle.kts) na poziomie modułu ustaw wersję minSdk na 26 lub nowszą.

    Kotlin

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

    Zakręcony

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

Jak korzystać z interfejsu Function Calling API

Aby wdrożyć wywoływanie funkcji, wykonaj te czynności:

  1. Określ narzędzia.
  2. Wybierz model.
  3. Dołącz narzędzia do prośby.
  4. obsługiwać wywołania narzędzi (jedno- lub wieloetapowe);

W kolejnych sekcjach znajdziesz przykład, który ilustruje te kroki.

Definiowanie narzędzi

Twórz schematy narzędzi automatycznie, używając FunctionDeclaration, FunctionSchema i FunctionType z pakietu com.google.mlkit.genai.schema.tools. (Aby zdefiniować narzędzia deklaratywnie w czasie kompilacji za pomocą adnotacji @AppFunction na Androidzie z automatycznym wykonywaniem, zapoznaj się z artykułem Definiowanie narzędzi).

Możesz na przykład zdefiniować narzędzie zorientowane na działanie (takie jak włączenie inteligentnego oświetlenia w ramach pojedynczego wykonania):

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

Możesz też zdefiniować narzędzie do pobierania danych (np. pobieranie aktualnej pogody na potrzeby syntezy wieloetapowej):

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

Wybierz model.

Wywoływanie funkcji wymaga Gemini Nano 4. Aby uzyskać dostęp do Gemini Nano 4, użyj interfejsu API do wyboru modelu i skonfiguruj instancję GenerativeModel tak, aby była kierowana na ModelReleaseStage.PREVIEW ORAZ 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)

Dołącz narzędzia do prośby

Podczas tworzenia obiektu GenerateContentRequest przekaż listę FunctionDeclaration do setTools() w kreatorze żądań.

Aby na przykład dołączyć narzędzie do prośby o działanie w jednej turze z instrukcją systemową:

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)

Możesz też dołączyć listę FunctionDeclaration w przypadku zapytania wieloetapowego:

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)

Obsługa wywołań narzędzi

Gdy Gemini Nano zdecyduje się wywołać narzędzie, odpowiedź modelu zawiera co najmniej 1 obiekt FunctionCall w candidate.functionCalls. Aby obsłużyć wywołania narzędzi, aplikacja musi najpierw sprawdzić kandydata odpowiedzi, aby zweryfikować, czy zostały przewidziane jakieś wywołania narzędzi:

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
}

Jednoetapowe wywoływanie funkcji

Używaj wywoływania funkcji w jednej turze w przypadku zadań zorientowanych na działanie, w których aplikacja bezpośrednio realizuje żądanie (np. „Otwórz aplikację aparatu” lub „Włącz światła w Living Room”). Gdy aplikacja wykona funkcję lokalnie, proces jest zakończony. Nie jest wymagana żadna dalsza odpowiedź modelu.

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

Wieloetapowe wywoływanie funkcji

Używaj wieloetapowego wywoływania funkcji, gdy użytkownik oczekuje odpowiedzi w języku naturalnym na podstawie danych pobranych przez narzędzie (np. „Jaka jest pogoda w San Francisco?”).

W przepływie wieloetapowym aplikacja wykonuje te czynności:

  1. Wykonuje żądaną funkcję lokalnie.
  2. Pakuje wynik w obiekt FunctionResponsePart.
  3. Dołącza do historii rozmowy zarówno wywołanie modelu (rola MODEL), jak i wynik wykonania (rola USER).
  4. wysyła do Gemini Nano prośbę o dalsze działania, aby wygenerować ostateczną odpowiedź w języku naturalnym.
// 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")

Przykładowy kod

Pełny, działający przykład wywoływania funkcji w aplikacji na Androida znajdziesz w tej przykładowej aplikacji ML Kit.

Znane problemy

  • AndroidX AppFunctions (@AppFunction) w ramach bezpośredniego dostępu do modelu (genai-prompt): wykrywanie i wykonywanie narzędzi @AppFunction w czasie kompilacji bezpośrednio za pomocą interfejsu Prompt API (com.google.mlkit:genai-prompt:1.0.0-beta5) nie jest jeszcze dostępne. Narzędzia w bibliotece genai-prompt muszą być definiowane programowo za pomocą klasy FunctionDeclaration. Aby korzystać z narzędzi @AppFunction, używaj Agentic Workflows (com.google.mlkit:genai-agent).
  • W przypadku żądań strumieniowych (generateContentStream) wywołania narzędzi nie są przesyłane strumieniowo token po tokenie. Zamiast tego po zakończeniu generowania wywołania narzędzia przez model emitowane są kompletne obiekty FunctionCall (za pomocą StreamingCallback.onNewFunctionCall lub w końcowym strumieniu GenerateContentResponse.candidates[0].functionCalls).