Android 向け LLM 推論ガイド

LLM Inference API を使用すると、Android アプリケーションで大規模言語モデル(LLM)を完全にオンデバイスで実行できます。これにより、テキストの生成、自然言語形式での情報の取得、ドキュメントの要約など、さまざまなタスクを実行できます。このタスクは、複数のテキスト間大規模言語モデルを組み込みでサポートしているため、最新のオンデバイス生成 AI モデルを Android アプリに適用できます。

LLM 推論 API を Android アプリケーションにすばやく追加するには、クイックスタートに沿って操作します。LLM 推論 API を実行する Android アプリケーションの基本的な例については、サンプル アプリケーションをご覧ください。LLM 推論 API の仕組みについて詳しくは、構成オプションモデル変換LoRA チューニングの各セクションをご覧ください。

このタスクの動作については、MediaPipe Studio デモをご覧ください。このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。

クイックスタート

LLM Inference API を Android アプリケーションに追加する手順は次のとおりです。LLM 推論 API は、Google Pixel 8 や Samsung S23 以降などのハイエンド Android デバイス向けに最適化されており、デバイス エミュレータは確実にサポートされません。

依存関係を追加する

LLM Inference API は com.google.mediapipe:tasks-genai ライブラリを使用します。Android アプリの build.gradle ファイルに次の依存関係を追加します。

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

モデルのダウンロード

Hugging Face から 4 ビット量子化形式で Gemma-3 1B をダウンロードします。使用可能なモデルの詳細については、モデルのドキュメントをご覧ください。

output_path フォルダの内容を 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

Task を初期化する

基本的な構成オプションを使用してタスクを初期化します。

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

タスクを実行する

generateResponse() メソッドを使用してテキスト レスポンスを生成します。これにより、1 つの生成されたレスポンスが生成されます。

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

レスポンスをストリーミングするには、generateResponseAsync() メソッドを使用します。

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

llmInference.generateResponseAsync(inputPrompt)

サンプル アプリケーション

LLM 推論 API の動作を確認し、包括的なオンデバイス生成 AI 機能について調べるには、Google AI Edge Gallery アプリをご覧ください。

Google AI Edge Gallery は、デベロッパー向けのインタラクティブなプレイグラウンドとして機能するオープンソースの Android アプリケーションです。このショーケースでは、次のことを紹介します。

  • LLM Inference API をさまざまなタスクに使用する実践的な例(次を含む)。
    • 画像に関する質問: 画像をアップロードして、それについて質問します。説明を取得したり、問題を解決したり、オブジェクトを識別したりできます。
    • プロンプト ラボ: 要約、書き換え、コードの生成、自由形式のプロンプトを使用して、単一ターンの LLM ユースケースを試すことができます。
    • AI チャット: マルチターンの会話を行います。
  • Hugging Face LiteRT コミュニティと Google の公式リリース(Gemma 3N など)から、さまざまな LiteRT 最適化モデルを見つけてダウンロードし、テストできる。
  • さまざまなモデルのオンデバイス パフォーマンスのリアルタイム ベンチマーク(最初のトークンまでの時間、デコード速度など)。
  • 独自のカスタム .litertlm モデルまたは .task モデルをインポートしてテストする方法。

このアプリは、LLM 推論 API の実用的な実装と、オンデバイスの生成 AI の可能性を理解するためのリソースです。ソースコードを確認し、 Google AI Edge Gallery GitHub リポジトリからアプリをダウンロードします。

設定オプション

次の構成オプションを使用して、Android アプリを設定します。

オプション名 説明 値の範囲 デフォルト値
modelPath モデルが保存されているプロジェクト ディレクトリ内のパス。 経路 なし
maxTokens モデルが処理するトークン(入力トークン + 出力トークン)の最大数。 Integer 512
topK モデルが生成の各ステップで考慮するトークンの数。予測を最も確率の高い上位 k 個のトークンに制限します。 Integer 40
temperature 生成時に導入されるランダム性の量。温度が高いほど、生成されるテキストの創造性が高くなります。温度が低いほど、予測可能な生成が行われます。 浮動小数点数 0.8
randomSeed テキスト生成中に使用されるランダム シード。 Integer 0
loraPath デバイス上の LoRA モデルの絶対パス。注: これは GPU モデルとのみ互換性があります。 経路 なし
resultListener 結果を非同期で受け取るように結果リスナーを設定します。非同期生成メソッドを使用している場合にのみ適用されます。 なし なし
errorListener オプションのエラー リスナーを設定します。 なし なし

マルチモーダル プロンプト

LLM Inference API Android API は、テキスト、画像、音声の入力を受け付けるモデルを使用したマルチモーダル プロンプトをサポートしています。マルチモーダルを有効にすると、ユーザーはプロンプトに画像とテキスト、音声とテキストの組み合わせを含めることができます。LLM はテキスト レスポンスを返します。

まず、MediaPipe 互換の Gemma 3n のバリアントを使用します。

  • Gemma-3n E2B: Gemma-3n ファミリーの有効な 2B モデル。
  • Gemma-3n E4B: Gemma-3n ファミリーの有効な 4B モデル。

詳細については、Gemma-3n のドキュメントをご覧ください。

次の手順に沿って、LLM 推論 API の画像入力または音声入力を有効にします。

画像入力

プロンプト内で画像を提供するには、入力画像またはフレームを com.google.mediapipe.framework.image.MPImage オブジェクトに変換してから、LLM 推論 API に渡します。

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

LLM 推論 API のビジョン サポートを有効にするには、グラフ オプション内で EnableVisionModality 構成オプションを true に設定します。

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

セッションあたりの画像の最大数を 10 に設定します。

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

以下は、ビジョン入力とテキスト入力を処理するように設定された LLM 推論 API の実装例です。

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

音声入力

LlmInferenceOptions で音声サポートを有効にする

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

sessionOptions で音声サポートを有効にする

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

推論中に音声データを送信します。注: 音声は .wav 形式のモノラル チャンネルである必要があります


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

以下は、音声入力とテキスト入力を処理するように設定された LLM 推論 API の実装例です。

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

LoRA のカスタマイズ

LLM Inference API は、PEFT(パラメータ エフィシエント ファインチューニング)ライブラリを使用した LoRA(Low-Rank Adaptation)チューニングをサポートしています。LoRA チューニングは、費用対効果の高いトレーニング プロセスを通じて LLM の動作をカスタマイズします。モデル全体を再トレーニングするのではなく、新しいトレーニング データに基づいてトレーニング可能な重みの小さなセットを作成します。

LLM Inference API は、Gemma-2 2BGemma 2BPhi-2 モデルのアテンション レイヤに LoRA 重みを追加することをサポートしています。モデルを safetensors 形式でダウンロードします。

LoRA 重みを作成するには、ベースモデルが safetensors 形式である必要があります。LoRA トレーニングの後、モデルを FlatBuffers 形式に変換して MediaPipe で実行できます。

LoRA 重みを準備する

PEFT の LoRA メソッドガイドを使用して、独自のデータセットでファインチューニングされた LoRA モデルをトレーニングします。

LLM 推論 API はアテンション レイヤでの LoRA のみをサポートしているため、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"],
)

準備したデータセットでトレーニングを行い、モデルを保存すると、ファインチューニングされた LoRA モデルの重みが adapter_model.safetensors で使用できるようになります。safetensors ファイルは、モデル変換中に使用される LoRA チェックポイントです。

モデル変換

MediaPipe Python パッケージを使用して、モデルの重みを Flatbuffer 形式に変換します。ConversionConfig には、ベースモデル オプションと追加の LoRA オプションを指定します。

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)

コンバータは、ベースモデル用と LoRA モデル用の 2 つの Flatbuffer ファイルを生成します。

LoRA モデルの推論

Android は、初期化中に静的 LoRA をサポートします。LoRA モデルを読み込むには、LoRA モデルのパスとベース LLM を指定します。

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

LoRA で LLM 推論を実行するには、ベースモデルと同じ generateResponse() または generateResponseAsync() メソッドを使用します。