Premiers pas avec l'API Prompt

Cette page explique comment effectuer les opérations suivantes :

  • Configurer votre projet pour utiliser l'API Prompt
  • Fournir une entrée textuelle et recevoir une réponse
  • Fournir des entrées d'image avec une entrée de texte associée et recevoir une réponse

Pour en savoir plus sur l'API Prompt, consultez la documentation de référence pour Kotlin (com.google.mlkit.genai.prompt) et Java (com.google.mlkit.genai.prompt.java, com.google.mlkit.genai.prompt).

Configurer le projet

Ajoutez l'API Prompt de ML Kit en tant que dépendance dans votre configuration build.gradle :

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

Si vous avez besoin de vos réponses dans un certain format à l'aide de l'API Structured Output, vous devez configurer KSP et ajouter des dépendances supplémentaires. Pour en savoir plus, consultez Générer une sortie structurée.

Implémenter un modèle génératif

Pour implémenter le code dans votre projet, procédez comme suit :

  • Créez un objet generativeModel :

    Kotlin

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

    Java

    // Get a GenerativeModel instance
    GenerativeModelFutures generativeModelFutures = GenerativeModelFutures
        .from(Generation.INSTANCE.getClient());
    
  • Vérifiez si Gemini Nano est AVAILABLE,, DOWNLOADABLE ou UNAVAILABLE. Ensuite, téléchargez la fonctionnalité si elle est téléchargeable :

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

Fournir une entrée textuelle uniquement

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();

Vous pouvez également ajouter des paramètres facultatifs :

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();

Pour en savoir plus sur les paramètres facultatifs, consultez Configurations facultatives.

Fournir une entrée multimodale (image et texte)

Regroupez plusieurs images et une entrée de texte dans la fonction generateContentRequest(), le prompt textuel étant une question ou une commande liée à l'image. Vous pouvez regrouper jusqu'à 10 images dans la même requête.

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();

Traiter le résultat de l'inférence

  • Exécutez l'inférence et récupérez le résultat. Vous pouvez choisir d'attendre le résultat complet ou de diffuser la réponse au fur et à mesure qu'elle est générée, pour les requêtes textuelles et multimodales.

    • Cette méthode utilise l'inférence sans flux, qui récupère l'intégralité du résultat du modèle d'IA avant de le renvoyer :

    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();
    
    • Les extraits suivants sont des exemples d'utilisation de l'inférence en streaming, qui récupère le résultat par fragments au fur et à mesure de sa génération :

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

Pour en savoir plus sur l'inférence en streaming et sans streaming, consultez Streaming et non-streaming.

Optimisation de la latence

Pour optimiser le premier appel d'inférence, votre application peut éventuellement appeler warmup(). Cela charge Gemini Nano en mémoire et initialise les composants d'exécution.

Configurations facultatives

Pour chaque GenerateContentRequest, vous pouvez définir les paramètres facultatifs suivants :

  • temperature : contrôle le degré de hasard dans la sélection des jetons.
  • seed : permet de générer des résultats stables et déterministes.
  • topK : contrôle le caractère aléatoire et la diversité des résultats.
  • candidateCount : demande le nombre de réponses uniques renvoyées. Notez que le nombre exact de réponses peut ne pas être identique à candidateCount, car les réponses en double sont automatiquement supprimées.
  • maxOutputTokens : définit le nombre maximal de jetons pouvant être générés dans la réponse.

Pour en savoir plus sur la définition des configurations facultatives, consultez GenerateContentRequest.

Fonctionnalités compatibles et limites

  • L'entrée doit comporter moins de 4 000 jetons (soit environ 3 000 mots en anglais). Pour en savoir plus, consultez la documentation de référence sur countTokens.
  • Évitez les cas d'utilisation qui nécessitent une sortie longue (plus de 4 000 jetons).
  • AICore applique un quota d'inférence par application. Pour en savoir plus, consultez Quota par application.

Problèmes de configuration courants

Les API d'IA générative ML Kit s'appuient sur l'application Android AICore pour accéder à Gemini Nano. Lorsqu'un appareil vient d'être configuré (y compris réinitialisé) ou que l'application AICore vient d'être réinitialisée (par exemple, effacement des données, désinstallation puis réinstallation), l'application AICore peut ne pas avoir assez de temps pour terminer l'initialisation (y compris le téléchargement des dernières configurations depuis le serveur). Par conséquent, les API GenAI de ML Kit risquent de ne pas fonctionner comme prévu. Voici les messages d'erreur de configuration courants que vous pouvez rencontrer et comment les résoudre :

Exemple de message d'erreur Comment répondre à une telle objection
Échec d'AICore avec le type d'erreur 4-CONNECTION_ERROR et le code d'erreur 601-BINDING_FAILURE : échec de la liaison du service AICore. Cela peut se produire lorsque vous installez l'application à l'aide des API GenAI de ML Kit immédiatement après la configuration de l'appareil ou lorsque AICore est désinstallé après l'installation de votre application. Mettre à jour l'application AICore, puis réinstaller votre application devrait résoudre le problème.
AICore a échoué avec le type d'erreur 3-PREPARATION_ERROR et le code d'erreur 606-FEATURE_NOT_FOUND : la fonctionnalité ... n'est pas disponible. Cela peut se produire lorsque AICore n'a pas fini de télécharger les dernières configurations. Lorsque l'appareil est connecté à Internet, la mise à jour prend généralement de quelques minutes à quelques heures. Redémarrer l'appareil peut accélérer la mise à jour.

Notez que si le bootloader de l'appareil est déverrouillé, vous verrez également cette erreur. Cette API n'est pas compatible avec les appareils dont le bootloader est déverrouillé.
AICore a échoué avec le type d'erreur 1-DOWNLOAD_ERROR et le code d'erreur 0-UNKNOWN : la fonctionnalité ... a échoué avec l'état d'échec 0 et l'erreur esz : UNAVAILABLE : Impossible de résoudre l'hôte ... Maintenez la connexion réseau, patientez quelques minutes, puis réessayez.