Leitfaden für die RAG-Funktion für KI-gestützte Edge-Modelle für Android

Das AI Edge RAG SDK bietet die grundlegenden Komponenten zum Erstellen einer RAG-Pipeline (Retrieval Augmented Generation) mit der LLM Inference API. Eine RAG-Pipeline bietet LLMs Zugriff auf von Nutzern bereitgestellte Daten, die aktualisierte, vertrauliche oder domänenspezifische Informationen enthalten können. Durch die zusätzlichen Funktionen zum Abrufen von Informationen von RAG können LLMs genauere und kontextbezogene Antworten für bestimmte Anwendungsfälle generieren.

In dieser Anleitung wird eine einfache Implementierung einer Beispielanwendung mit der LLM Inference API und dem AI Edge RAG SDK beschrieben. In diesem Leitfaden geht es um das Erstellen einer RAG-Pipeline. Weitere Informationen zur Verwendung der LLM Inference API finden Sie im Leitfaden zur LLM Inference API für Android.

Die vollständige Beispielanwendung finden Sie auf GitHub. Erstellen Sie zuerst die Anwendung, lesen Sie die von Nutzern bereitgestellten Daten (sample_context.txt) und stellen Sie dem LLM Fragen zu Informationen in der Textdatei.

Beispielanwendung ausführen

In diesem Leitfaden wird auf ein Beispiel für eine einfache Textgenerierungs-App mit RAG für Android verwiesen. Sie können die Beispiel-App als Ausgangspunkt für Ihre eigene Android-App verwenden oder sich daran orientieren, wenn Sie eine vorhandene App ändern.

Die Anwendung ist für High-End-Geräte wie das Pixel 8, Pixel 9, S23 und S24 optimiert. Verbinden Sie ein Android-Gerät mit Ihrer Workstation und prüfen Sie, ob Sie eine aktuelle Version von Android Studio haben. Weitere Informationen finden Sie in der Android-Einrichtungsanleitung.

Anwendungscode herunterladen

In der folgenden Anleitung wird beschrieben, wie Sie mit dem Git-Befehlszeilentool eine lokale Kopie des Beispielcodes erstellen.

Klonen Sie das Git-Repository mit dem folgenden Befehl:

git clone https://github.com/google-ai-edge/ai-edge-apis

Nachdem Sie eine lokale Version des Beispielcodes erstellt haben, können Sie das Projekt in Android Studio importieren und die App ausführen.

Modell herunterladen

Die Beispielanwendung ist für die Verwendung von Gemma-3 1B konfiguriert. Gemma-3 1B ist Teil der Gemma-Familie von einfachen, hochmodernen offenen Modellen, die auf derselben Forschung und Technologie basieren, die auch zum Erstellen der Gemini-Modelle verwendet werden. Das Modell enthält 1 Milliarde Parameter und offene Gewichte.

Gemma-3 1B herunterladen

Nachdem Sie Gemma-3 1B von Hugging Face heruntergeladen haben, übertragen Sie das Modell auf Ihr Gerät:

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

Sie können auch andere Modelle mit der Beispielanwendung verwenden, dies erfordert jedoch möglicherweise zusätzliche Konfigurationsschritte.

Einbettung einrichten

Der Embedder nimmt Textblöcke aus den vom Nutzer bereitgestellten Daten und wandelt sie in vektorisierte numerische Darstellungen um, die die semantische Bedeutung erfassen. Das LLM greift auf diese Einbettungen zurück, um relevante Vektoren zu identifizieren, und bezieht die semantisch relevantesten Chunks in die generierte Ausgabe ein.

Die Beispielanwendung ist für die Verwendung mit zwei Embeddern konzipiert: dem Gemini-Embedder und dem Gecko-Embedder.

Mit Gecko-Einbettung einrichten

Standardmäßig ist die Beispiel-App so konfiguriert, dass sie den Gecko-Embedder (GeckoEmbeddingModel) verwendet und das Modell vollständig auf dem Gerät ausgeführt wird.

Gecko 110m-en herunterladen

Der Gecko-Embedder ist als Float- und quantisierte Modelle mit mehreren Versionen für verschiedene Sequenzlängen verfügbar. Weitere Informationen finden Sie auf der Gecko-Modellkarte.

Die Modellspezifikationen finden Sie im Dateinamen des Modells. Beispiel:

  • Gecko_256_f32.tflite: Float-Modell, das Sequenzen mit bis zu 256 Tokens unterstützt.
  • Gecko_1024_quant.tflite: Quantisiertes Modell, das Sequenzen mit bis zu 1.024 Tokens unterstützt.

Die Sequenzlänge ist die maximale Blockgröße, die das Modell einbetten kann. Wenn dem Gecko_256_f32.tflite-Modell beispielsweise ein Chunk übergeben wird, der die Sequenzlänge überschreitet, bettet das Modell die ersten 256 Tokens ein und kürzt den Rest des Chunks.

Übertragen Sie das Tokenizer-Modell (sentencepiece.model) und den Gecko-Embedder auf Ihr Gerät:

adb push sentencepiece.model /data/local/tmp/sentencepiece.model
adb push Gecko_256_f32.tflite /data/local/tmp/gecko.tflite

Das Einbettungsmodell ist sowohl mit CPUs als auch mit GPUs kompatibel. Standardmäßig ist die Beispiel-App so konfiguriert, dass Einbettungen mit dem Gecko-Modell auf der GPU extrahiert werden.

companion object {
  ...
  private const val USE_GPU_FOR_EMBEDDINGS = true
}

Mit Gemini Embedder einrichten

Mit dem Gemini Embedder (GeminiEmbedder) werden Einbettungen mit der Gemini Cloud API erstellt. Für die Ausführung der Anwendung ist ein Google Gemini API-Schlüssel erforderlich, den Sie auf der Einrichtungsseite der Google Gemini API erhalten können.

Gemini API-Schlüssel in Google AI Studio abrufen

Fügen Sie Ihren Gemini API-Schlüssel hinzu und setzen Sie COMPUTE_EMBEDDINGS_LOCALLY in RagPipeline.kt auf „false“:

companion object {
  ...
  private const val COMPUTE_EMBEDDINGS_LOCALLY = false
  private const val GEMINI_API_KEY = "<API_KEY>"
}

Funktionsweise

In diesem Abschnitt finden Sie detailliertere Informationen zu den RAG-Pipeline-Komponenten der Anwendung. Den Großteil des Codes finden Sie unter RagPipeline.kt.

Abhängigkeiten

Das RAG SDK verwendet die com.google.ai.edge.localagents:localagents-rag-Bibliothek. Fügen Sie diese Abhängigkeit der Datei build.gradle Ihrer Android-App hinzu:

dependencies {
    ...
    implementation("com.google.ai.edge.localagents:localagents-rag:0.1.0")
    implementation("com.google.mediapipe:tasks-genai:0.10.22")
}

Von Nutzern bereitgestellte Daten

Die vom Nutzer bereitgestellten Daten in der Anwendung sind eine Textdatei mit dem Namen sample_context.txt, die im Verzeichnis assets gespeichert ist. Die Anwendung nimmt Textdateien in Chunks auf, erstellt Einbettungen dieser Chunks und bezieht sich beim Generieren von Ausgabetext auf die Einbettungen.

Das folgende Code-Snippet finden Sie in MainActivity.kt:

class MainActivity : ComponentActivity() {
  lateinit var chatViewModel: ChatViewModel
...
    chatViewModel.memorizeChunks("sample_context.txt")
...
}

Chunking

Zur Vereinfachung enthält die Datei sample_context.txt <chunk_splitter>-Tags, die von der Beispielanwendung zum Erstellen von Chunks verwendet werden. Anschließend werden für jeden Chunk Einbettungen erstellt. In Produktionsanwendungen ist die Größe von Chunks ein wichtiger Aspekt. Wenn ein Chunk zu groß ist, enthält der Vektor nicht genügend Spezifität, um nützlich zu sein. Wenn er zu klein ist, enthält er nicht genügend Kontext.

Die Beispielanwendung verarbeitet die Aufteilung in Chunks über die memorizeChunks-Funktion in RagPipeline.kt.

Einbettung

Die Anwendung bietet zwei Möglichkeiten für Texteinbettungen:

  • Gecko-Embedder: Lokale (auf dem Gerät) Extraktion von Texteinbettungen mit dem Gecko-Modell.
  • Gemini Embedder: Cloudbasierte Extraktion von Texteinbettungen mit der Generative Language Cloud API.

In der Beispielanwendung wird der Einbettungsgenerator danach ausgewählt, ob der Nutzer Einbettungen lokal oder über Google Cloud berechnen möchte. Das folgende Code-Snippet finden Sie in 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
      )
  }

Datenbank

In der Beispielanwendung werden Text-Embeddings in SQLite (SqliteVectorStore) gespeichert. Sie können die DefaultVectorStore-Datenbank auch für nicht persistierenden Vektorspeicher verwenden.

Das folgende Code-Snippet finden Sie in RagPipeline.kt:

private val config = ChainConfig.create(
    mediaPipeLanguageModel, PromptBuilder(QA_PROMPT_TEMPLATE1),
    DefaultSemanticTextMemory(
        SqliteVectorStore(768), embedder
    )
)

In der Beispiel-App wird die Einbettungsdimension auf 768 festgelegt. Das bezieht sich auf die Länge jedes Vektors in der Vektordatenbank.

Kette

Das RAG SDK bietet Chains, die mehrere RAG-Komponenten in einer einzigen Pipeline kombinieren. Mit Chains können Sie Abruf- und Abfragemodelle orchestrieren. Die API basiert auf der Chain-Schnittstelle.

Die Beispielanwendung verwendet die Retrieval and Inference-Kette. Das folgende Code-Snippet finden Sie in RagPipeline.kt:

private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)

Die Kette wird aufgerufen, wenn das Modell Antworten generiert:

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
    }