Korzystanie z interfejsu Prompt API

Na tej stronie dowiesz się, jak:

  • Konfigurowanie projektu pod kątem korzystania z Prompt API
  • Podawanie danych wejściowych zawierających tylko tekst i otrzymywanie odpowiedzi
  • Przesyłanie obrazów z powiązanym tekstem i otrzymywanie odpowiedzi

Więcej informacji o interfejsie Prompt API znajdziesz w dokumentacji referencyjnej dotyczącej języków Kotlin (com.google.mlkit.genai.prompt) i Java (com.google.mlkit.genai.prompt.java, com.google.mlkit.genai.prompt).

Konfigurowanie projektu

Dodaj interfejs ML Kit Prompt API jako zależność w konfiguracji build.gradle:

implementation("com.google.mlkit:genai-prompt:1.0.0-beta4")

Jeśli potrzebujesz odpowiedzi w określonym formacie przy użyciu interfejsu Structured Output API, musisz skonfigurować KSP i dodać dodatkowe zależności. Więcej informacji znajdziesz w artykule na temat generowania uporządkowanych danych wyjściowych.

Wdrażanie modelu generatywnego

Aby zaimplementować kod w projekcie:

  • Utwórz obiekt generativeModel:

    Kotlin

    // Get a GenerativeModel instance
    val generativeModel = Generation.getClient()
    

    Java

    // Get a GenerativeModel instance
    GenerativeModelFutures generativeModelFutures = GenerativeModelFutures
        .from(Generation.INSTANCE.getClient());
    
  • Sprawdź, czy Gemini Nano to AVAILABLE, DOWNLOADABLE czy UNAVAILABLE. Następnie pobierz funkcję, jeśli jest dostępna do pobrania:

    Kotlin

    val status = generativeModel.checkStatus()
    when (status) {
        FeatureStatus.UNAVAILABLE -> {
            // Gemini Nano not supported on this device or device hasn't fetched the latest configuration to support it
        }
    
        FeatureStatus.DOWNLOADABLE -> {
            // Gemini Nano can be downloaded on this device, but is not currently downloaded
            generativeModel.download().collect { status ->
                when (status) {
                    is DownloadStatus.DownloadStarted ->
                        Log.d(TAG, "starting download for Gemini Nano")
    
                    is DownloadStatus.DownloadProgress ->
                        Log.d(TAG, "Nano ${status.totalBytesDownloaded} bytes downloaded")
    
                    DownloadStatus.DownloadCompleted -> {
                        Log.d(TAG, "Gemini Nano download complete")
                        modelDownloaded = true
                    }
    
                    is DownloadStatus.DownloadFailed -> {
                        Log.e(TAG, "Nano download failed ${status.e.message}")
                    }
                }
            }
        }
    
        FeatureStatus.DOWNLOADING -> {
            // Gemini Nano currently being downloaded
        }
    
        FeatureStatus.AVAILABLE -> {
            // Gemini Nano currently downloaded and available to use on this device
        }
    }
    

    Java

    ListenableFuture<Integer> status = generativeModelFutures.checkStatus();
    Futures.addCallback(generativeModelFutures.checkStatus(), new FutureCallback<>() {
        @Override
        public void onSuccess(Integer featureStatus) {
            switch (featureStatus) {
                case FeatureStatus.AVAILABLE - > {
                    // Gemini Nano currently downloaded and available to use on this device
                }
                case FeatureStatus.UNAVAILABLE - > {
                    // Gemini Nano not supported on this device or device hasn't fetched the latest configuration to support it
                }
                case FeatureStatus.DOWNLOADING - > {
                    // Gemini Nano currently being downloaded
                }
                case FeatureStatus.DOWNLOADABLE - > {
                    generativeModelFutures.download(new DownloadCallback() {
                        @Override
                        public void onDownloadStarted(long l) {
                            Log.d(TAG, "starting download for Gemini Nano");
                        }
                        @Override
                        public void onDownloadProgress(long l) {
                            Log.d(TAG, "Nano " + l + " bytes downloaded");
                        }
                        @Override
                        public void onDownloadCompleted() {
                            Log.d(TAG, "Gemini Nano download complete");
                        }
                        @Override
                        public void onDownloadFailed(@NonNull GenAiException e) {
                            Log.e(TAG, "Nano download failed: " + e.getMessage());
                        }
                    });
                }
            }
        }
        @Override
        public void onFailure(@NonNull Throwable t) {
            // Failed to check status
        }
    }, ContextCompat.getMainExecutor(context));
    
    

Podaj dane wejściowe zawierające tylko tekst

Kotlin

val response = generativeModel.generateContent("Write a 3 sentence story about a magical dog.")

Java

GenerateContentResponse response = generativeModelFutures.generateContent(
  new GenerateContentRequest.Builder(
    new TextPart("Write a 3 sentence story about a magical dog."))
  .build())
  .get();

Możesz też dodać parametry opcjonalne:

Kotlin

val response = generativeModel.generateContent(
    generateContentRequest(
        TextPart("Write a 3 sentence story about a magical dog."),
    ) {
        // Optional parameters
        temperature = 0.2f
        topK = 10
        candidateCount = 3
    },
)

Java

GenerateContentRequest.Builder requestBuilder =
        new GenerateContentRequest.Builder(
                new TextPart("Write a 3 sentence story about a magical dog."));
requestBuilder.setTemperature(.2f);
requestBuilder.setTopK(10);
requestBuilder.setCandidateCount(3);

GenerateContentResponse response =
        generativeModelFutures.generateContent(requestBuilder.build()).get();

Więcej informacji o parametrach opcjonalnych znajdziesz w sekcji Konfiguracje opcjonalne.

Przesyłanie danych multimodalnych (obrazów i tekstu)

Połącz wiele obrazów i tekst w funkcji generateContentRequest(), przy czym prompt tekstowy powinien być pytaniem lub poleceniem związanym z obrazem. W jednym żądaniu możesz przesłać maksymalnie 10 obrazów.

Kotlin

val response = generativeModel.generateContent(
    generateContentRequest(ImagePart(bitmap1), ImagePart(bitmap2), TextPart(textPrompt)) {
        // optional parameters
        ...
    },
)

Java

GenerateContentResponse response = generativeModelFutures.generateContent(
    new GenerateContentRequest.Builder(
        new Content.Builder()
            .addPart(new ImagePart(bitmap1))
            .addPart(new ImagePart(bitmap2))
            .addPart(new TextPart("textPrompt"))
            .build())
    // optional parameters
    .build())
.get();

Przetwarzanie wyniku wnioskowania

  • Uruchom wnioskowanie i pobierz wynik. Możesz poczekać na pełny wynik lub przesyłać odpowiedź strumieniowo w miarę jej generowania zarówno w przypadku promptów tekstowych, jak i multimodalnych.

    • Używa wnioskowania bez strumieniowania, które pobiera cały wynik z modelu AI przed jego zwróceniem:

    Kotlin

    // Call the AI model to generate content and store the complete
    // in a new variable named 'response' once it's finished
    val response = generativeModel.generateContent("Write a 3 sentence story about a magical dog")
    

    Java

    GenerateContentResponse response = generativeModelFutures.generateContent(
            new GenerateContentRequest.Builder(
                    new TextPart("Write a 3 sentence story about a magical dog."))
                    .build())
            .get();
    
    • Poniższe fragmenty kodu to przykłady użycia wnioskowania strumieniowego, które pobiera wynik we fragmentach w miarę jego generowania:

    Kotlin

    // Streaming inference
    var fullResponse = ""
    generativeModel.generateContentStream("Write a 3 sentence story about a magical dog").collect { chunk ->
        val newChunkReceived = chunk.candidates[0].text
        print(newChunkReceived)
        fullResponse += newChunkReceived
    }
    

    Java

    // Streaming inference
    StringBuilder fullResponse = new StringBuilder();
    generativeModelFutures.generateContent(new GenerateContentRequest.Builder(
        (new TextPart("Write a 3 sentence story about a magical dog"))).build(),
            chunk -> {
                Log.d(TAG, chunk);
                fullResponse.append(chunk);
            });
    

Więcej informacji o wnioskowaniu strumieniowym i niestrumieniowym znajdziesz w artykule Wnioskowanie strumieniowe i niestrumieniowe.

Optymalizacja czasu oczekiwania

Aby zoptymalizować pierwsze wywołanie wnioskowania, aplikacja może opcjonalnie wywołać funkcję warmup(). Spowoduje to wczytanie Gemini Nano do pamięci i zainicjowanie komponentów środowiska wykonawczego.

Konfiguracje opcjonalne

W ramach każdego parametru GenerateContentRequest możesz ustawić te opcjonalne parametry:

  • temperature : określa stopień losowości wyboru tokenów.
  • seed : umożliwia generowanie stabilnych i deterministycznych wyników.
  • topK : określa losowość i różnorodność wyników.
  • candidateCount : żąda liczby zwróconych unikalnych odpowiedzi. Pamiętaj, że dokładna liczba odpowiedzi może nie być taka sama jak candidateCount, ponieważ duplikaty odpowiedzi są automatycznie usuwane.
  • maxOutputTokens : określa maksymalną liczbę tokenów, które można wygenerować w odpowiedzi.

Więcej informacji o konfigurowaniu ustawień opcjonalnych znajdziesz w artykule GenerateContentRequest.

Obsługiwane funkcje i ograniczenia

  • Dane wejściowe muszą zawierać mniej niż 4000 tokenów (czyli około 3000 słów w języku angielskim). Więcej informacji znajdziesz w dokumentacji countTokens.
  • Należy unikać przypadków użycia, które wymagają długich danych wyjściowych (ponad 4 tys. tokenów).
  • AICore egzekwuje limit wnioskowania na aplikację. Więcej informacji znajdziesz w sekcji Limit na aplikację.

Typowe problemy z konfiguracją

Interfejsy ML Kit GenAI API korzystają z aplikacji Android AICore, aby uzyskać dostęp do Gemini Nano. Gdy urządzenie jest dopiero konfigurowane (w tym resetowane) lub aplikacja AICore jest dopiero resetowana (np. wyczyszczone dane, odinstalowana i ponownie zainstalowana), aplikacja AICore może nie mieć wystarczająco dużo czasu na zakończenie inicjowania (w tym pobranie najnowszych konfiguracji z serwera). W związku z tym interfejsy ML Kit GenAI API mogą nie działać zgodnie z oczekiwaniami. Oto typowe komunikaty o błędach konfiguracji, które mogą się pojawić, oraz sposoby ich rozwiązywania:

Przykładowy komunikat o błędzie Jak odpowiedzieć
Wystąpił błąd AICore typu 4-CONNECTION_ERROR z kodem błędu 601-BINDING_FAILURE: nie udało się powiązać usługi AICore. Może się tak zdarzyć, gdy zainstalujesz aplikację za pomocą interfejsów API ML Kit GenAI natychmiast po skonfigurowaniu urządzenia lub gdy AICore zostanie odinstalowany po zainstalowaniu aplikacji. Problem powinien zostać rozwiązany po zaktualizowaniu aplikacji AICore i ponownym zainstalowaniu aplikacji.
AICore: błąd typu 3-PREPARATION_ERROR i kod błędu 606-FEATURE_NOT_FOUND: funkcja … jest niedostępna. Może się tak zdarzyć, gdy AICore nie zakończy pobierania najnowszych konfiguracji. Gdy urządzenie jest połączone z internetem, aktualizacja trwa zwykle od kilku minut do kilku godzin. Ponowne uruchomienie urządzenia może przyspieszyć aktualizację.

Pamiętaj, że jeśli program rozruchowy urządzenia jest odblokowany, również zobaczysz ten błąd – ten interfejs API nie obsługuje urządzeń z odblokowanymi programami rozruchowymi.
Błąd AICore typu 1-DOWNLOAD_ERROR i kod błędu 0-UNKNOWN: funkcja … nie powiodła się ze stanem błędu 0 i błędem esz: UNAVAILABLE: nie można rozpoznać hosta … Utrzymaj połączenie sieciowe, poczekaj kilka minut i spróbuj ponownie.