Guida RAG per l'AI Edge per Android

L'SDK AI Edge RAG fornisce i componenti fondamentali per costruire una pipeline di Retrieval Augmented Generation (RAG) con l'API LLM Inference. Una pipeline RAG fornisce agli LLM l'accesso ai dati forniti dagli utenti, che possono includere informazioni aggiornate, sensibili o specifiche del dominio. Grazie alle funzionalità di recupero delle informazioni aggiuntive di RAG, gli LLM possono generare risposte più accurate e sensibili al contesto per casi d'uso specifici.

Questa guida illustra un'implementazione di base di un'applicazione di esempio utilizzando l'API LLM Inference con l'SDK AI Edge RAG. Questa guida si concentra sulla costruzione di una pipeline RAG. Per saperne di più sull'utilizzo dell'API LLM Inference, consulta la guida LLM Inference per Android.

Puoi trovare l'applicazione di esempio completa su GitHub. Per iniziare, crea l'applicazione, leggi i dati forniti dall'utente (sample_context.txt) e poni all'LLM domande relative alle informazioni nel file di testo.

Esegui l'applicazione di esempio

Questa guida fa riferimento a un esempio di app di generazione di testo di base con RAG per Android. Puoi utilizzare l'app di esempio come punto di partenza per la tua app Android o farvi riferimento quando modifichi un'app esistente.

L'applicazione è ottimizzata per i dispositivi di fascia alta come Pixel 8, Pixel 9, S23 e S24. Collega un dispositivo Android alla workstation e assicurati di avere una versione attuale di Android Studio. Per ulteriori informazioni, consulta la guida alla configurazione di Android.

Scarica il codice dell'applicazione

Le istruzioni riportate di seguito mostrano come creare una copia locale del codice di esempio utilizzando lo strumento a riga di comando git.

Clona il repository Git utilizzando il seguente comando:

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

Dopo aver creato una versione locale del codice di esempio, puoi importare il progetto in Android Studio ed eseguire l'app.

Scaricare un modello

L'applicazione di esempio è configurata per utilizzare Gemma-3 1B. Gemma-3 1B fa parte della famiglia Gemma di modelli aperti leggeri e all'avanguardia creati sulla base della stessa ricerca e tecnologia utilizzata per creare i modelli Gemini. Il modello contiene 1 miliardo di parametri e pesi aperti.

Scarica Gemma-3 1B

Dopo aver scaricato Gemma-3 1B da Hugging Face, trasferisci il modello sul dispositivo:

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

Puoi anche utilizzare altri modelli con l'applicazione di esempio, ma potrebbero essere necessari passaggi di configurazione aggiuntivi.

Configurare un incorporatore

L'incorporatore prende blocchi di testo dai dati forniti dall'utente e li trasforma in rappresentazioni numeriche vettoriali che ne acquisiscono il significato semantico. L'LLM fa riferimento a questi embedding per identificare i vettori pertinenti e incorpora i blocchi più pertinenti dal punto di vista semantico nell'output generato.

L'applicazione di esempio è progettata per funzionare con due incorporatori: l'incorporatore Gemini e l'incorporatore Gecko.

Configurare con Gecko embedder

Per impostazione predefinita, l'app di esempio è configurata per utilizzare l'embedder Gecko (GeckoEmbeddingModel) ed esegue il modello completamente sul dispositivo.

Scarica Gecko 110m-en

L'incorporatore Gecko è disponibile come modelli float e quantizzati, con più versioni per diverse lunghezze di sequenza. Per ulteriori informazioni, consulta la scheda del modello Gecko.

Le specifiche del modello si trovano nel nome file del modello. Ad esempio:

  • Gecko_256_f32.tflite: Modello float che supporta sequenze di massimo 256 token.
  • Gecko_1024_quant.tflite: Modello quantizzato che supporta sequenze fino a 1024 token.

La lunghezza della sequenza è la dimensione massima del blocco che il modello può incorporare. Ad esempio, se al modello Gecko_256_f32.tflite viene trasmesso un blocco che supera la lunghezza della sequenza, il modello incorpora i primi 256 token e tronca il resto del blocco.

Esegui il push del modello di tokenizzazione (sentencepiece.model) e dell'incorporatore Gecko sul tuo dispositivo:

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

Il modello di incorporamento è compatibile sia con la CPU che con la GPU. Per impostazione predefinita, l'app di esempio è configurata per estrarre gli incorporamenti con il modello Gecko sulla GPU.

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

Configurare con Gemini Embedder

Gemini Embedder (GeminiEmbedder) crea incorporamenti utilizzando l'API Gemini Cloud. Per eseguire l'applicazione è necessaria una chiave API Google Gemini, che puoi ottenere dalla pagina di configurazione dell'API Google Gemini.

Ottenere una chiave API Gemini in Google AI Studio

Aggiungi la chiave API Gemini e imposta COMPUTE_EMBEDDINGS_LOCALLY su false in RagPipeline.kt:

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

Come funziona

Questa sezione fornisce informazioni più approfondite sui componenti della pipeline RAG dell'applicazione. Puoi visualizzare la maggior parte del codice in RagPipeline.kt.

Dipendenze

L'SDK RAG utilizza la libreria com.google.ai.edge.localagents:localagents-rag. Aggiungi questa dipendenza al file build.gradle della tua app per Android:

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

Dati forniti dall'utente

I dati forniti dall'utente nell'applicazione sono un file di testo denominato sample_context.txt, che viene memorizzato nella directory assets. L'applicazione prende blocchi del file di testo, crea incorporamenti di questi blocchi e fa riferimento agli incorporamenti quando genera il testo di output.

Il seguente snippet di codice è disponibile in MainActivity.kt:

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

Chunking

Per semplicità, il file sample_context.txt include tag <chunk_splitter> che l'applicazione di esempio utilizza per creare blocchi. Vengono quindi creati gli incorporamenti per ogni blocco. Nelle applicazioni di produzione, le dimensioni dei chunk sono un aspetto fondamentale. Quando un blocco è troppo grande, il vettore non contiene una specificità sufficiente per essere utile; quando è troppo piccolo, non contiene un contesto sufficiente.

L'applicazione di esempio gestisce la suddivisione in blocchi tramite la funzione memorizeChunks in RagPipeline.kt.

Incorporamento

L'applicazione offre due percorsi per l'incorporamento del testo:

  • Incorporatore Gecko: Estrazione dell'incorporamento del testo locale (sul dispositivo) con il modello Gecko.
  • Gemini Embedder: estrazione di incorporamenti di testo basata sul cloud con l'API Generative Language Cloud.

L'applicazione di esempio seleziona l'incorporatore in base all'intenzione dell'utente di calcolare gli incorporamenti localmente o tramite Google Cloud. Il seguente snippet di codice è disponibile 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
      )
  }

Database

L'applicazione di esempio utilizza SQLite (SqliteVectorStore) per archiviare gli incorporamenti di testo. Puoi anche utilizzare il database DefaultVectorStore per l'archiviazione di vettori non permanenti.

Il seguente snippet di codice si trova in RagPipeline.kt:

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

L'app di esempio imposta la dimensione dell'incorporamento su 768, che si riferisce alla lunghezza di ogni vettore nel database vettoriale.

Chain

L'SDK RAG fornisce catene che combinano diversi componenti RAG in un'unica pipeline. Puoi utilizzare le catene per orchestrare i modelli di recupero e query. L'API si basa sull'interfaccia Chain.

L'applicazione di esempio utilizza la catena Retrieval and Inference. Il seguente snippet di codice si trova in RagPipeline.kt:

private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)

La catena viene richiamata quando il modello genera risposte:

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
    }