Premiers pas avec l'API Gemini dans les applications Android (SDK client)

Ce tutoriel explique comment accéder à l'API Gemini directement depuis votre application Android à l'aide du SDK client Google AI pour Android. Vous pouvez utiliser ce SDK client si vous ne souhaitez pas travailler directement avec les API REST ou le code côté serveur (comme Python) pour accéder aux modèles Gemini dans votre application Android.

Dans ce tutoriel, vous allez apprendre à effectuer les opérations suivantes:

Ce tutoriel contient également des sections sur les cas d'utilisation avancés (tels que les jetons de comptage) et sur les options de contrôle de la génération de contenu.

Envisager d'accéder à Gemini sur l'appareil

Le SDK client pour Android décrit dans ce tutoriel vous permet d'accéder aux modèles Geni Pro qui s'exécutent sur les serveurs de Google. Pour les cas d'utilisation impliquant le traitement de données sensibles, la disponibilité hors connexion ou les économies réalisées sur les parcours utilisateur fréquemment utilisés, vous pouvez envisager d'accéder à Gemini Nano, qui s'exécute sur l'appareil. Pour en savoir plus, consultez le tutoriel Android (sur l'appareil).

Prérequis

Dans ce tutoriel, nous partons du principe que vous savez utiliser Android Studio pour développer des applications Android.

Pour suivre ce tutoriel, assurez-vous que votre environnement de développement et votre application Android répondent aux exigences suivantes:

  • Android Studio (dernière version)
  • Votre application Android doit cibler le niveau d'API 21 ou supérieur.

Configurer votre projet

Avant d'appeler l'API Gemini, vous devez configurer votre projet Android, ce qui inclut la définition de votre clé API, l'ajout des dépendances du SDK à votre projet Android et l'initialisation du modèle.

Configurer votre clé API

Pour utiliser l'API Gemini, vous avez besoin d'une clé API. Si vous n'en avez pas, créez-en une dans Google AI Studio.

Obtenir une clé API

Sécuriser votre clé API

Il est vivement recommandé de ne pas vérifier une clé API dans votre système de contrôle des versions. Stockez-la plutôt dans un fichier local.properties (situé dans le répertoire racine de votre projet, mais exclu du contrôle des versions), puis utilisez le plug-in Secrets Gradle pour Android afin de lire votre clé API en tant que variable de configuration de compilation.

Kotlin

// Access your API key as a Build Configuration variable
val apiKey = BuildConfig.apiKey

Java

// Access your API key as a Build Configuration variable
String apiKey = BuildConfig.apiKey;

Tous les extraits de ce tutoriel utilisent cette bonne pratique. De plus, si vous souhaitez voir l'implémentation du plug-in Secrets Gradle, vous pouvez consulter l'application exemple pour ce SDK ou utiliser la dernière version preview d'Android Studio Iguana, qui propose un modèle Gemini API Starter (qui inclut le fichier local.properties pour vous aider à démarrer).

Ajouter la dépendance du SDK à votre projet

  1. Dans le fichier de configuration Gradle de votre module (au niveau de l'application) (comme <project>/<app-module>/build.gradle.kts), ajoutez la dépendance du SDK Google AI pour Android:

    Kotlin

    dependencies {
      // ... other androidx dependencies
    
      // add the dependency for the Google AI client SDK for Android
      implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    }
    

    Java

    Pour Java, vous devez ajouter deux bibliothèques supplémentaires.

    dependencies {
        // ... other androidx dependencies
    
        // add the dependency for the Google AI client SDK for Android
        implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    
        // Required for one-shot operations (to use `ListenableFuture` from Guava Android)
        implementation("com.google.guava:guava:31.0.1-android")
    
        // Required for streaming operations (to use `Publisher` from Reactive Streams)
        implementation("org.reactivestreams:reactive-streams:1.0.4")
    }
    
  2. Synchronisez votre projet Android avec des fichiers Gradle.

Initialiser le modèle génératif

Avant de pouvoir effectuer des appels d'API, vous devez initialiser l'objet GenerativeModel:

Kotlin

val generativeModel = GenerativeModel(
    // Use a model that's applicable for your use case (see "Implement basic use cases" below)
    modelName = "MODEL_NAME",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

Java

Pour Java, vous devez également initialiser l'objet GenerativeModelFutures.

// Use a model that's applicable for your use case (see "Implement basic use cases" below)
GenerativeModel gm = new GenerativeModel(/* modelName */ "MODEL_NAME",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);

// Use the GenerativeModelFutures Java compatibility layer which offers
// support for ListenableFuture and Publisher APIs
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Lorsque vous spécifiez un modèle, tenez compte des points suivants:

  • Utilisez un modèle spécifique à votre cas d'utilisation (par exemple, gemini-pro-vision est destiné à l'entrée multimodale). Dans ce guide, les instructions pour chaque implémentation listent le modèle recommandé pour chaque cas d'utilisation.

Implémenter des cas d'utilisation courants

Maintenant que votre projet est configuré, vous pouvez découvrir comment utiliser l'API Gemini pour mettre en œuvre différents cas d'utilisation:

Générer du texte à partir d'une entrée de texte uniquement

Lorsque l'entrée de la requête n'inclut que du texte, utilisez le modèle gemini-pro avec generateContent pour générer une sortie textuelle:

Kotlin

Notez que generateContent() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val prompt = "Write a story about a magic backpack."
val response = generativeModel.generateContent(prompt)
print(response.text)

Java

Notez que generateContent() renvoie un ListenableFuture. Si vous ne connaissez pas cette API, consultez la documentation Android sur l'utilisation d'un ListenableFuture.

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Content content = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Générer du texte à partir d'une entrée de texte et d'image (multimodale)

Gemini fournit un modèle multimodal (gemini-pro-vision), qui vous permet de saisir à la fois du texte et des images. Veillez à consulter les exigences concernant les images pour les invites.

Lorsque l'entrée de la requête comprend à la fois du texte et des images, utilisez le modèle gemini-pro-vision avec generateContent pour générer une sortie textuelle:

Kotlin

Notez que generateContent() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

val generativeModel = GenerativeModel(
    // For text-and-images input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's different between these pictures?")
}

val response = generativeModel.generateContent(inputContent)
print(response.text)

Java

Notez que generateContent() renvoie un ListenableFuture. Si vous ne connaissez pas cette API, consultez la documentation Android sur l'utilisation d'un ListenableFuture.

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Créer des conversations multitours (chat)

Gemini vous permet de créer des conversations de forme libre sur plusieurs tours. Le SDK simplifie le processus en gérant l'état de la conversation. Ainsi, contrairement à generateContent, vous n'avez pas besoin de stocker l'historique de la conversation vous-même.

Pour créer une conversation multitour (telle qu'un chat), utilisez le modèle gemini-pro, puis initialisez le chat en appelant startChat(). Utilisez ensuite sendMessage() pour envoyer un nouveau message utilisateur, qui ajoute également le message et la réponse à l'historique des discussions.

Deux options sont possibles pour role associé au contenu d'une conversation:

  • user: rôle qui fournit les invites. Cette valeur est la valeur par défaut pour les appels sendMessage.

  • model: rôle qui fournit les réponses. Ce rôle peut être utilisé lorsque vous appelez startChat() avec le history existant.

Kotlin

Notez que generateContent() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val chat = generativeModel.startChat(
    history = listOf(
        content(role = "user") { text("Hello, I have 2 dogs in my house.") },
        content(role = "model") { text("Great to meet you. What would you like to know?") }
    )
)

chat.sendMessage("How many paws are in my house?")

Java

Notez que generateContent() renvoie un ListenableFuture. Si vous ne connaissez pas cette API, consultez la documentation Android sur l'utilisation d'un ListenableFuture.

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

// (optional) Create previous chat history for context
Content.Builder userContentBuilder = new Content.Builder();
userContentBuilder.setRole("user");
userContentBuilder.addText("Hello, I have 2 dogs in my house.");
Content userContent = userContentBuilder.build();

Content.Builder modelContentBuilder = new Content.Builder();
modelContentBuilder.setRole("model");
modelContentBuilder.addText("Great to meet you. What would you like to know?");
Content modelContent = userContentBuilder.build();

List<Content> history = Arrays.asList(userContent, modelContent);

// Initialize the chat
ChatFutures chat = model.startChat(history);

// Create a new user message
Content userMessage = new Content.Builder()
    .setRole("user")
    .addText("How many paws are in my house?")
    .build();

Executor executor = // ...

// Send the message
ListenableFuture<GenerateContentResponse> response = chat.sendMessage(userMessage);

Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

Utiliser le streaming pour des interactions plus rapides

Par défaut, le modèle renvoie une réponse une fois l'ensemble du processus de génération terminé. Vous pouvez obtenir des interactions plus rapides en évitant d'attendre l'intégralité du résultat, et en utilisant plutôt le traitement par flux pour gérer des résultats partiels.

L'exemple suivant montre comment implémenter un flux de données avec generateContentStream pour générer du texte à partir d'une requête d'entrée de texte et d'image.

Kotlin

Notez que generateContentStream() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

val generativeModel = GenerativeModel(
    // For text-and-image input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

var fullResponse = ""
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
    fullResponse += chunk.text
}

Java

Les méthodes de streaming Java de ce SDK renvoient un type Publisher à partir de la bibliothèque Reactive Streams.

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(content);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onSubscribe(Subscription s) { }
});

Vous pouvez adopter une approche similaire pour les cas d'utilisation de la saisie de texte et du chat:

Kotlin

Notez que generateContentStream() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

// Use streaming with text-only input
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
}
// Use streaming with multi-turn conversations (like chat)
val chat = generativeModel.startChat()
chat.sendMessageStream(inputContent).collect { chunk ->
    print(chunk.text)
}

Java

Les méthodes de streaming Java de ce SDK renvoient un type Publisher à partir de la bibliothèque Reactive Streams.

// Use streaming with text-only input
Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});
// Use streaming with multi-turn conversations (like chat)
ChatFutures chat = model.startChat(history);

Publisher<GenerateContentResponse> streamingResponse =
    chat.sendMessageStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});

Implémenter des cas d'utilisation avancés

Les cas d'utilisation courants décrits dans la section précédente de ce tutoriel vous aideront à vous familiariser avec l'API Gemini. Cette section décrit certains cas d'utilisation qui peuvent être considérés comme plus avancés.

Compter les jetons

Lorsque vous utilisez des invites longues, il peut être utile de compter les jetons avant d'envoyer du contenu au modèle. Les exemples suivants montrent comment utiliser countTokens() pour différents cas d'utilisation:

Kotlin

Notez que countTokens() est une fonction de suspension et doit être appelée à partir d'un champ d'application de coroutine. Si vous ne connaissez pas les coroutines, consultez la page Coroutines Kotlin sur Android.

// For text-only input
val (totalTokens) = generativeModel.countTokens("Write a story about a magic backpack.")

// For text-and-image input (multi-modal)
val multiModalContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

val (totalTokens) = generativeModel.countTokens(multiModalContent)

// For multi-turn conversations (like chat)
val history = chat.history
val messageContent = content { text("This is the message I intend to send")}
val (totalTokens) = generativeModel.countTokens(*history.toTypedArray(), messageContent)

Java

Notez que countTokens() renvoie un ListenableFuture. Si vous ne connaissez pas cette API, consultez la documentation Android sur l'utilisation d'un ListenableFuture.

Content text = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

// For text-only input
ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(text);

Futures.addCallback(countTokensResponse, new FutureCallback<CountTokensResponse>() {
    @Override
    public void onSuccess(CountTokensResponse result) {
        int totalTokens = result.getTotalTokens();
        System.out.println("TotalTokens = " + totalTokens);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

// For text-and-image input
Bitmap image1 = // ...
Bitmap image2 = // ...

Content multiModalContent = new Content.Builder()
    .addImage(image1)
    .addImage(image2)
    .addText("What's different between these pictures?")
    .build();

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(multiModalContent);

// For multi-turn conversations (like chat)
List<Content> history = chat.getChat().getHistory();

Content messageContent = new Content.Builder()
    .addText("This is the message I intend to send")
    .build();

Collections.addAll(history, messageContent);

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(history.toArray(new Content[0]));

Options pour contrôler la génération de contenu

Vous pouvez contrôler la génération de contenu en configurant des paramètres de modèle et en utilisant des paramètres de sécurité.

Configurer les paramètres du modèle

Chaque invite que vous envoyez au modèle inclut des valeurs de paramètres qui contrôlent la manière dont le modèle génère une réponse. Le modèle peut générer différents résultats pour différentes valeurs de paramètre. Apprenez-en plus sur les paramètres de modèle.

Kotlin

val config = generationConfig {
    temperature = 0.9f
    topK = 16
    topP = 0.1f
    maxOutputTokens = 200
    stopSequences = listOf("red")
}

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    generationConfig = config
)

Java

GenerationConfig.Builder configBuilder = new GenerationConfig.Builder();
configBuilder.temperature = 0.9f;
configBuilder.topK = 16;
configBuilder.topP = 0.1f;
configBuilder.maxOutputTokens = 200;
configBuilder.stopSequences = Arrays.asList("red");

GenerationConfig generationConfig = configBuilder.build();

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    generationConfig
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Utiliser les paramètres de sécurité

Vous pouvez utiliser les paramètres de sécurité pour ajuster la probabilité de recevoir des réponses pouvant être considérées comme nuisibles. Par défaut, les paramètres de sécurité bloquent le contenu ayant une probabilité moyenne et/ou élevée d'être un contenu dangereux dans toutes les dimensions. En savoir plus sur les paramètres de sécurité

Voici comment définir un paramètre de sécurité:

Kotlin

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(
        SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
    )
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Collections.singletonList(harassmentSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Vous pouvez également définir plusieurs paramètres de sécurité:

Kotlin

val harassmentSafety = SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)

val hateSpeechSafety = SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.MEDIUM_AND_ABOVE)

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(harassmentSafety, hateSpeechSafety)
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

SafetySetting hateSpeechSafety = new SafetySetting(HarmCategory.HATE_SPEECH,
    BlockThreshold.MEDIUM_AND_ABOVE);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Arrays.asList(harassmentSafety, hateSpeechSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Étapes suivantes

  • La conception d'invites est le processus de création d'invites qui permettent d'obtenir la réponse souhaitée en utilisant des modèles de langage. Pour rédiger des réponses précises et de haute qualité à partir d'un modèle de langage, il est essentiel de rédiger des invites bien structurées. Découvrez les bonnes pratiques concernant la rédaction de requêtes.

  • Gemini propose plusieurs variantes de modèle pour répondre aux besoins de différents cas d'utilisation, tels que les types et la complexité des entrées, les implémentations pour le chat ou d'autres tâches linguistiques de dialogue, ainsi que les contraintes de taille. Découvrez les modèles Gemini disponibles.

  • Gemini propose des options pour demander des augmentations de la limite de débit. La limite de débit pour les modèles Geni Pro est de 60 requêtes par minute (tr/min).

  • Le SDK client pour Android décrit dans ce tutoriel vous permet d'accéder aux modèles Geni Pro qui s'exécutent sur les serveurs de Google. Pour les cas d'utilisation impliquant le traitement de données sensibles, la disponibilité hors connexion ou les économies réalisées sur les parcours utilisateur fréquemment utilisés, vous pouvez envisager d'accéder à Gemini Nano, qui s'exécute sur l'appareil. Pour en savoir plus, consultez le tutoriel Android (sur l'appareil).