Android 向け LLM 推論ガイド

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

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

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

クイックスタート

LLM 推論 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.24'
}

モデルのダウンロード

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

タスクを初期化する

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

// 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() メソッドを使用してテキスト レスポンスを生成します。これにより、生成された単一のレスポンスを生成します。

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 を使用する実用的な例。
    • 画像に質問: 画像をアップロードして、それについて質問します。説明を取得したり、問題を解決したり、オブジェクトを特定したりできます。
    • プロンプト ラボ: 要約、書き換え、コード生成、自由形式プロンプトを使用して、1 回転の LLM のユースケースを探索します。
    • AI チャット: マルチターンの会話に参加します。
  • Hugging Face LiteRT コミュニティと公式の Google リリース(Gemma 3N など)から、LiteRT で最適化されたさまざまなモデルを検出してダウンロードし、テストする機能。
  • さまざまなモデルのリアルタイム オンデバイス パフォーマンス ベンチマーク(最初のトークンまでの時間、デコード速度など)。
  • 独自のカスタム .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 はテキスト レスポンスを提供します。

始めるにあたっては、Gemma 3n の MediaPipe 互換バリアントを使用します。

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

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

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 Inference API のビジョン サポートを有効にするには、グラフ オプションで EnableVisionModality 構成オプションを true に設定します。

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

Gemma-3n はセッションごとに最大 1 つの画像を受け入れるため、MaxNumImages を 1 に設定します。

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

以下は、画像とテキストの入力を処理するように設定された LLM Inference 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();
}

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 Inference 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() メソッドを使用します。