AI Edge RAG SDK は、LLM 推論 API を使用して検索拡張生成(RAG)パイプラインを構築するための基本コンポーネントを提供します。RAG パイプラインは、LLM にユーザー提供のデータへのアクセスを提供します。このデータには、更新された情報、機密情報、ドメイン固有の情報が含まれる場合があります。RAG から追加された情報取得機能により、LLM は特定のユースケースに対してより正確でコンテキストを認識したレスポンスを生成できます。
このガイドでは、AI Edge RAG SDK で LLM 推論 API を使用するサンプル アプリケーションの基本的な実装について説明します。このガイドでは、RAG パイプラインの構築に焦点を当てています。LLM 推論 API の使用について詳しくは、Android 向け LLM 推論ガイドをご覧ください。
完全なサンプル アプリケーションは GitHub で入手できます。まず、アプリケーションをビルドし、ユーザーが提供したデータ(sample_context.txt
)を読み取り、テキスト ファイル内の情報に関連する質問を LLM に行います。
サンプル アプリケーションを実行する
このガイドでは、Android 用の RAG を使用した基本的なテキスト生成アプリの例を参照します。サンプルアプリは、独自の Android アプリの出発点として使用することも、既存のアプリを変更する際に参照することもできます。
このアプリケーションは、Google Pixel 8、Google Pixel 9、Samsung Galaxy S23、Samsung Galaxy S24 などのハイエンド デバイス向けに最適化されています。Android デバイスをワークステーションに接続し、最新バージョンの Android Studio がインストールされていることを確認します。詳しくは、Android 設定ガイドをご覧ください。
アプリケーション コードをダウンロードする
次の手順では、git コマンドライン ツールを使用してサンプルコードのローカルコピーを作成する方法について説明します。
次のコマンドを使用して、Git リポジトリのクローンを作成します。
git clone https://github.com/google-ai-edge/ai-edge-apis
サンプルコードのローカル バージョンを作成したら、プロジェクトを Android Studio にインポートしてアプリを実行できます。
モデルのダウンロード
サンプル アプリケーションは、Gemma-3 1B を使用するように構成されています。Gemma-3 1B は、Gemini モデルの作成に使用されたものと同じ研究とテクノロジーに基づいて構築された、軽量で最先端のオープンモデルの Gemma ファミリーの一部です。このモデルには 10 億個のパラメータとオープン ウェイトが含まれています。
Hugging Face から Gemma-3 1B をダウンロードしたら、モデルをデバイスに push します。
cd ~/Downloads
tar -xvzf gemma3-1b-it-int4.tar.gz
$ 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
サンプル アプリケーションで他のモデルを使用することもできますが、追加の構成手順が必要になる場合があります。
エンベッダーを設定する
エンベッダーは、ユーザーが提供したデータからテキストのチャンクを取得し、その意味論的な意味を捉えるベクトル化された数値表現に変換します。LLM はこれらのエンベディングを参照して関連するベクトルを特定し、意味的に最も関連性の高いチャンクを生成された出力に組み込みます。
このサンプル アプリケーションは、Gemini エンベッダーと Gecko エンベッダーの 2 つのエンベッダーで動作するように設計されています。
Gecko エンベッダでセットアップする
デフォルトでは、サンプルアプリは Gecko エンベッダー(GeckoEmbeddingModel
)を使用するように構成されており、モデルは完全にオンデバイスで実行されます。
Gecko エンベッダーは、浮動小数点モデルと量子化モデルとして利用できます。シーケンス長ごとに複数のバージョンがあります。詳細については、Gecko モデルカードをご覧ください。
モデルの仕様は、モデルのファイル名で確認できます。次に例を示します。
Gecko_256_f32.tflite
: 最大 256 個のトークンのシーケンスをサポートする浮動小数点モデル。Gecko_1024_quant.tflite
: 最大 1,024 個のトークンのシーケンスをサポートする量子化モデル。
シーケンス長は、モデルが埋め込むことができる最大チャンクサイズです。たとえば、Gecko_256_f32.tflite
モデルにシーケンス長を超えるチャンクが渡されると、モデルは最初の 256 個のトークンをエンベディングし、チャンクの残りの部分を切り捨てます。
トークナイザ モデル(sentencepiece.model
)と Gecko エンベッダをデバイスに push します。
adb push sentencepiece.model /data/local/tmp/sentencepiece.model
adb push Gecko_256_f32.tflite /data/local/tmp/gecko.tflite
エンベディング モデルは CPU と GPU の両方に対応しています。デフォルトでは、サンプルアプリは GPU 上の Gecko モデルでエンベディングを抽出するように構成されています。
companion object {
...
private const val USE_GPU_FOR_EMBEDDINGS = true
}
Gemini Embedder で設定する
Gemini Embedder(GeminiEmbedder
)は、Gemini Cloud API を使用してエンベディングを作成します。これには、アプリケーションを実行するための Google Gemini API キーが必要です。このキーは、Google Gemini API の設定ページで取得できます。
Google AI Studio で Gemini API キーを取得する
Gemini API キーを追加し、RagPipeline.kt で COMPUTE_EMBEDDINGS_LOCALLY
を false に設定します。
companion object {
...
private const val COMPUTE_EMBEDDINGS_LOCALLY = false
private const val GEMINI_API_KEY = "<API_KEY>"
}
仕組み
このセクションでは、アプリケーションの RAG パイプライン コンポーネントについて詳しく説明します。コードのほとんどは RagPipeline.kt で確認できます。
依存関係
RAG SDK は com.google.ai.edge.localagents:localagents-rag
ライブラリを使用します。この依存関係を Android アプリの build.gradle
ファイルに追加します。
dependencies {
...
implementation("com.google.ai.edge.localagents:localagents-rag:0.1.0")
implementation("com.google.mediapipe:tasks-genai:0.10.22")
}
ユーザー提供データ
アプリケーション内のユーザー提供データは、assets
ディレクトリに保存されている sample_context.txt
という名前のテキスト ファイルです。アプリケーションはテキスト ファイルのチャンクを取得し、それらのチャンクのエンベディングを作成し、出力テキストを生成するときにエンベディングを参照します。
次のコード スニペットは MainActivity.kt にあります。
class MainActivity : ComponentActivity() {
lateinit var chatViewModel: ChatViewModel
...
chatViewModel.memorizeChunks("sample_context.txt")
...
}
チャンキング
簡略化のため、sample_context.txt
ファイルには、サンプル アプリケーションがチャンクの作成に使用する <chunk_splitter>
タグが含まれています。次に、チャンクごとにエンベディングが作成されます。本番環境のアプリケーションでは、チャンクのサイズが重要な考慮事項となります。チャンクが大きすぎると、ベクトルには有用な固有性が十分にありません。小さすぎると、コンテキストが十分にありません。
サンプル アプリケーションは、RagPipeline.kt の memorizeChunks
関数を介してチャンク処理を行います。
埋め込み
このアプリケーションでは、テキスト エンベディングに次の 2 つのパスが用意されています。
- Gecko エンベッダー: Gecko モデルを使用したローカル(デバイス上)のテキスト エンベディング抽出。
- Gemini Embedder: Generative Language Cloud API を使用したクラウドベースのテキスト エンベディング抽出。
サンプル アプリケーションは、ユーザーがエンベディングをローカルで計算するか、Google Cloud を介して計算するかによって、エンベッダーを選択します。次のコード スニペットは RagPipeline.kt にあります。
private val embedder: Embedder<String> = if (COMPUTE_EMBEDDINGS_LOCALLY) {
GeckoEmbeddingModel(
GECKO_MODEL_PATH,
Optional.of(TOKENIZER_MODEL_PATH),
USE_GPU_FOR_EMBEDDINGS,
)
} else {
GeminiEmbedder(
GEMINI_EMBEDDING_MODEL,
GEMINI_API_KEY
)
}
データベース
サンプル アプリケーションは、SQLite(SqliteVectorStore
)を使用してテキスト エンベディングを保存します。DefaultVectorStore
データベースは、非永続ベクトルの保存にも使用できます。
次のコード スニペットは RagPipeline.kt にあります。
private val config = ChainConfig.create(
mediaPipeLanguageModel, PromptBuilder(QA_PROMPT_TEMPLATE1),
DefaultSemanticTextMemory(
SqliteVectorStore(768), embedder
)
)
サンプルアプリでは、エンベディングの次元が 768 に設定されています。これは、ベクトル データベース内の各ベクトルの長さを指します。
チェーン
RAG SDK には、複数の RAG コンポーネントを 1 つのパイプラインに結合するチェーンが用意されています。チェーンを使用して、取得モデルとクエリモデルをオーケストレートできます。この API は Chain インターフェースに基づいています。
このサンプル アプリケーションでは、検索と推論のチェーンを使用します。次のコード スニペットは RagPipeline.kt にあります。
private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)
チェーンは、モデルがレスポンスを生成するときに呼び出されます。
suspend fun generateResponse(
prompt: String,
callback: AsyncProgressListener<LanguageModelResponse>?
): String =
coroutineScope {
val retrievalRequest =
RetrievalRequest.create(
prompt,
RetrievalConfig.create(2, 0.0f, TaskType.QUESTION_ANSWERING)
)
retrievalAndInferenceChain.invoke(retrievalRequest, callback).await().text
}