Guide d'inférence LLM pour Android

L'API LLM Inference vous permet d'exécuter de grands modèles de langage (LLM) entièrement sur l'appareil pour les applications Android. Vous pouvez l'utiliser pour effectuer un large éventail de tâches, comme générer du texte, récupérer des informations en langage naturel et résumer des documents. La tâche offre une compatibilité intégrée avec plusieurs grands modèles de langage de texte à texte. Vous pouvez ainsi appliquer les derniers modèles d'IA générative sur l'appareil à vos applications Android.

Pour ajouter rapidement l'API LLM Inference à votre application Android, suivez le guide de démarrage rapide. Pour obtenir un exemple de base d'application Android exécutant l'API LLM Inference, consultez l'application exemple. Pour mieux comprendre le fonctionnement de l'API LLM Inference, consultez les sections Options de configuration, Conversion de modèle et Réglage LoRA.

Vous pouvez voir cette tâche en action dans la démonstration MediaPipe Studio. Pour en savoir plus sur les fonctionnalités, les modèles et les options de configuration de cette tâche, consultez la présentation.

Guide de démarrage rapide

Suivez les étapes ci-dessous pour ajouter l'API LLM Inference à votre application Android. L'API LLM Inference est optimisée pour les appareils Android haut de gamme, tels que le Pixel 8 et le Samsung S23 ou les modèles ultérieurs. Elle n'est pas compatible avec les émulateurs d'appareils.

Ajouter des dépendances

L'API LLM Inference utilise la bibliothèque com.google.mediapipe:tasks-genai. Ajoutez cette dépendance au fichier build.gradle de votre application Android :

dependencies {
    implementation 'com.google.mediapipe:tasks-genai:0.10.27'
}

Télécharger un modèle

Téléchargez Gemma-3 1B au format quantifié sur 4 bits depuis Hugging Face. Pour en savoir plus sur les modèles disponibles, consultez la documentation sur les modèles.

Transférez le contenu du dossier output_path vers l'appareil Android.

$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push output_path /data/local/tmp/llm/model_version.task

Initialiser la tâche

Initialisez la tâche avec les options de configuration de base :

// Set the configuration options for the LLM Inference task
val taskOptions = LlmInferenceOptions.builder()
        .setModelPath('/data/local/tmp/llm/model_version.task')
        .setMaxTopK(64)
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, taskOptions)

Exécuter la tâche

Utilisez la méthode generateResponse() pour générer une réponse textuelle. Cela génère une seule réponse.

val result = llmInference.generateResponse(inputPrompt)
logger.atInfo().log("result: $result")

Pour diffuser la réponse en streaming, utilisez la méthode generateResponseAsync().

val options = LlmInference.LlmInferenceOptions.builder()
  ...
  .setResultListener { partialResult, done ->
    logger.atInfo().log("partial result: $partialResult")
  }
  .build()

llmInference.generateResponseAsync(inputPrompt)

Exemple d'application

Pour voir les API d'inférence LLM en action et explorer une gamme complète de fonctionnalités d'IA générative sur l'appareil, consultez l'application Google AI Edge Gallery.

La galerie Google AI Edge est une application Android Open Source qui sert de playground interactif pour les développeurs. Il présente :

  • Exemples pratiques d'utilisation de l'API LLM Inference pour diverses tâches, y compris :
    • Demander à propos d'une image : importez une image et posez des questions à son sujet. Obtenez des descriptions, résolvez des problèmes ou identifiez des objets.
    • Prompt Lab : résumez, réécrivez ou générez du code, ou utilisez des requêtes au format libre pour explorer les cas d'utilisation des LLM à un tour.
    • Chat IA : engagez des conversations multitours.
  • La possibilité de découvrir, de télécharger et de tester différents modèles optimisés pour LiteRT provenant de la communauté Hugging Face LiteRT et des versions officielles de Google (par exemple, Gemma 3N).
  • Benchmarks des performances en temps réel sur l'appareil pour différents modèles (temps avant le premier jeton, vitesse de décodage, etc.).
  • Comment importer et tester vos propres modèles .litertlm ou .task personnalisés.

Cette application est une ressource permettant de comprendre l'implémentation pratique de l'API LLM Inference et le potentiel de l'IA générative sur l'appareil. Explorez le code source et téléchargez l'application depuis le dépôt GitHub Google AI Edge Gallery.

Options de configuration

Utilisez les options de configuration suivantes pour configurer une application Android :

Nom de l'option Description Plage de valeurs Valeur par défaut
modelPath Chemin d'accès à l'emplacement où le modèle est stocké dans le répertoire du projet. CHEMIN N/A
maxTokens Nombre maximal de jetons (jetons d'entrée + jetons de sortie) que le modèle peut traiter. Nombre entier 512
topK Nombre de jetons que le modèle prend en compte à chaque étape de la génération. Limite les prédictions aux k jetons les plus probables. Nombre entier 40
temperature Degré d'aléatoire introduit lors de la génération. Une température plus élevée rend le texte généré plus créatif, tandis qu'une température plus basse le rend plus prévisible. Float 0,8
randomSeed Source aléatoire utilisée lors de la génération de texte. Nombre entier 0
loraPath Chemin absolu du modèle LoRA localement sur l'appareil. Remarque : Cette fonctionnalité n'est compatible qu'avec les modèles de GPU. CHEMIN N/A
resultListener Définit l'écouteur de résultat pour recevoir les résultats de manière asynchrone. Ne s'applique que lorsque vous utilisez la méthode de génération asynchrone. N/A N/A
errorListener Définit un écouteur d'erreur facultatif. N/A N/A

Requêtes multimodales

Les API Android LLM Inference sont compatibles avec les requêtes multimodales avec des modèles qui acceptent les entrées de texte, d'image et audio. Lorsque la multimodalité est activée, les utilisateurs peuvent inclure une combinaison d'images et de texte, ou d'audio et de texte dans leurs requêtes.Le LLM fournit ensuite une réponse textuelle.

Pour commencer, utilisez une variante de Gemma 3n compatible avec MediaPipe :

  • Gemma-3n E2B : un modèle 2B efficace de la famille Gemma-3n.
  • Gemma-3n E4B : un modèle 4B efficace de la famille Gemma-3n.

Pour en savoir plus, consultez la documentation Gemma-3n.

Suivez les étapes ci-dessous pour activer l'entrée d'image ou audio pour l'API LLM Inference.

Image d'entrée

Pour fournir des images dans une requête, convertissez les images ou les frames d'entrée en objet com.google.mediapipe.framework.image.MPImage avant de les transmettre à l'API LLM Inference :

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()

Pour activer la prise en charge de la vision pour l'API LLM Inference, définissez l'option de configuration EnableVisionModality sur true dans les options du graphique :

LlmInferenceSession.LlmInferenceSessionOptions sessionOptions =
  LlmInferenceSession.LlmInferenceSessionOptions.builder()
    ...
    .setGraphOptions(GraphOptions.builder().setEnableVisionModality(true).build())
    .build();

Définissez le nombre maximal d'images par session sur 10.

LlmInferenceOptions options = LlmInferenceOptions.builder()
  ...
  .setMaxNumImages(10)
  .build();

Voici un exemple d'implémentation de l'API LLM Inference configurée pour gérer les entrées de vision et de texte :

MPImage image = getImageFromAsset(BURGER_IMAGE);

LlmInferenceSession.LlmInferenceSessionOptions sessionOptions =
  LlmInferenceSession.LlmInferenceSessionOptions.builder()
    .setTopK(10)
    .setTemperature(0.4f)
    .setGraphOptions(GraphOptions.builder().setEnableVisionModality(true).build())
    .build();

try (LlmInference llmInference =
    LlmInference.createFromOptions(ApplicationProvider.getApplicationContext(), options);
  LlmInferenceSession session =
    LlmInferenceSession.createFromOptions(llmInference, sessionOptions)) {
  session.addQueryChunk("Describe the objects in the image.");
  session.addImage(image);
  String result = session.generateResponse();
}

Entrée audio

Activer la prise en charge audio dans LlmInferenceOptions

val inferenceOptions = LlmInference.LlmInferenceOptions.builder()
  ...
  .setAudioModelOptions(AudioModelOptions.builder().build())
  .build()

Activer la prise en charge audio dans sessionOptions

    val sessionOptions =  LlmInferenceSessionOptions.builder()
      ...
      .setGraphOptions(GraphOptions.builder().setEnableAudioModality(true).build())
      .build()

Envoyez des données audio pendant l'inférence. Remarque : L'audio doit être au format .wav et en canal mono.


val audioData: ByteArray = ...
inferenceEngine.llmInferenceSession.addAudio(audioData)

Voici un exemple d'implémentation de l'API LLM Inference configurée pour gérer les entrées audio et de texte :

val audioData: ByteArray = ...
val inferenceOptions = LlmInference.LlmInferenceOptions.builder()
  ...
  .setAudioModelOptions(AudioModelOptions.builder().build())
  .build()
val sessionOptions =  LlmInferenceSessionOptions.builder()
  ...
  .setGraphOptions(GraphOptions.builder().setEnableAudioModality(true).build())
  .build()

LlmInference.createFromOptions(context, inferenceOptions).use { llmInference ->
  LlmInferenceSession.createFromOptions(llmInference, sessionOptions).use { session ->
    session.addQueryChunk("Transcribe the following speech segment:")
    session.addAudio(audioData)
    val result = session.generateResponse()
  }
}

Personnalisation LoRA

L'API LLM Inference est compatible avec le réglage LoRA (Low-Rank Adaptation) à l'aide de la bibliothèque PEFT (Parameter-Efficient Fine-Tuning). Le réglage LoRA personnalise le comportement des LLM grâce à un processus d'entraînement économique. Il crée un petit ensemble de pondérations entraînables basées sur de nouvelles données d'entraînement au lieu de réentraîner l'intégralité du modèle.

L'API LLM Inference permet d'ajouter des pondérations LoRA aux couches d'attention des modèles Gemma-2 2B, Gemma 2B et Phi-2. Téléchargez le modèle au format safetensors.

Le modèle de base doit être au format safetensors pour que vous puissiez créer des pondérations LoRA. Après l'entraînement LoRA, vous pouvez convertir les modèles au format FlatBuffers pour les exécuter sur MediaPipe.

Préparer les pondérations LoRA

Utilisez le guide Méthodes LoRA de PEFT pour entraîner un modèle LoRA affiné sur votre propre ensemble de données.

L'API LLM Inference n'est compatible qu'avec LoRA sur les couches d'attention. Par conséquent, ne spécifiez que les couches d'attention dans LoraConfig :

# For Gemma
from peft import LoraConfig
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

# For Phi-2
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "dense"],
)

Après l'entraînement sur l'ensemble de données préparé et l'enregistrement du modèle, les pondérations du modèle LoRA affiné sont disponibles dans adapter_model.safetensors. Le fichier safetensors est le point de contrôle LoRA utilisé lors de la conversion du modèle.

Conversion de modèles

Utilisez le package Python MediaPipe pour convertir les pondérations du modèle au format Flatbuffer. ConversionConfig spécifie les options du modèle de base ainsi que les options LoRA supplémentaires.

import mediapipe as mp
from mediapipe.tasks.python.genai import converter

config = converter.ConversionConfig(
  # Other params related to base model
  ...
  # Must use gpu backend for LoRA conversion
  backend='gpu',
  # LoRA related params
  lora_ckpt=LORA_CKPT,
  lora_rank=LORA_RANK,
  lora_output_tflite_file=LORA_OUTPUT_FILE,
)

converter.convert_checkpoint(config)

Le convertisseur génère deux fichiers Flatbuffer : un pour le modèle de base et un autre pour le modèle LoRA.

Inférence du modèle LoRA

Android est compatible avec LoRA statique lors de l'initialisation. Pour charger un modèle LoRA, spécifiez le chemin d'accès au modèle LoRA ainsi que le LLM de base.

// Set the configuration options for the LLM Inference task
val options = LlmInferenceOptions.builder()
        .setModelPath(BASE_MODEL_PATH)
        .setMaxTokens(1000)
        .setTopK(40)
        .setTemperature(0.8)
        .setRandomSeed(101)
        .setLoraPath(LORA_MODEL_PATH)
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, options)

Pour exécuter l'inférence LLM avec LoRA, utilisez les mêmes méthodes generateResponse() ou generateResponseAsync() que le modèle de base.