O SDK AI Edge RAG fornece os componentes fundamentais para construir um pipeline de geração aumentada de recuperação (RAG) com a API LLM Inference. Um pipeline de RAG fornece aos LLMs acesso a dados fornecidos pelo usuário, que podem incluir informações atualizadas, sensíveis ou específicas do domínio. Com os recursos adicionais de recuperação de informações da RAG, os LLMs podem gerar respostas mais precisas e contextualizadas para casos de uso específicos.
Este guia mostra uma implementação básica de um aplicativo de amostra usando a API LLM Inference com o SDK RAG de IA na borda. Este guia se concentra na construção de um pipeline de RAG. Para mais informações sobre como usar a API LLM Inference, consulte o guia de inferência de LLM para Android.
Você pode encontrar o aplicativo de exemplo completo no
GitHub.
Para começar, crie o aplicativo, leia os dados fornecidos pelo usuário
(sample_context.txt
)
e faça perguntas ao LLM relacionadas às informações no arquivo de texto.
Executar o aplicativo de exemplo
Este guia se refere a um exemplo de um app básico de geração de texto com RAG para Android. Você pode usar o app de exemplo como ponto de partida para seu próprio app Android ou consultá-lo ao modificar um app existente.
O aplicativo é otimizado para dispositivos de ponta, como Pixel 8, Pixel 9, S23 e S24. Conecte um dispositivo Android à estação de trabalho e confira se você tem uma versão atual do Android Studio. Para mais informações, consulte o guia de configuração do Android.
Fazer o download do código do aplicativo
As instruções a seguir mostram como criar uma cópia local do código de exemplo usando a ferramenta de linha de comando git.
Clone o repositório git usando o comando a seguir:
git clone https://github.com/google-ai-edge/ai-edge-apis
Depois de criar uma versão local do código de exemplo, importe o projeto para o Android Studio e execute o app.
Fazer o download de um modelo
O aplicativo de exemplo está configurado para usar o Gemma-3 1B. O Gemma-3 1B faz parte da família Gemma de modelos abertos leves e de última geração, criados com base na mesma pesquisa e tecnologia usadas para criar os modelos do Gemini. O modelo tem 1 bilhão de parâmetros e pesos abertos.
Fazer o download do Gemma-3 1B
Depois de fazer o download do Gemma-3 1B do Hugging Face, envie o modelo para seu 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
Você também pode usar outros modelos com o aplicativo de exemplo, mas isso pode exigir etapas de configuração adicionais.
Configurar um incorporador
O incorporador usa partes de texto dos dados fornecidos pelo usuário e as transforma em representações numéricas vetorizadas que capturam o significado semântico. O LLM se refere a esses embeddings para identificar vetores relevantes e incorpora os blocos semanticamente mais relevantes na saída gerada.
O aplicativo de exemplo foi projetado para funcionar com dois incorporadores: o do Gemini e o do Gecko.
Configurar com o incorporador Gecko
Por padrão, o app de exemplo é configurado para usar o incorporador Gecko
(GeckoEmbeddingModel
) e executa o modelo completamente no dispositivo.
Fazer o download do Gecko 110m-en
O incorporador do Gecko está disponível como modelos flutuantes e quantizados, com várias versões para diferentes comprimentos de sequência. Para mais informações, consulte o card de modelo do Gecko.
As especificações do modelo podem ser encontradas no nome do arquivo. Exemplo:
Gecko_256_f32.tflite
: modelo de ponto flutuante que aceita sequências de até 256 tokens.Gecko_1024_quant.tflite
: modelo quantizado que aceita sequências de até 1.024 tokens.
O tamanho da sequência é o tamanho máximo de bloco que o modelo pode incorporar. Por exemplo, se o modelo Gecko_256_f32.tflite
receber um bloco que exceda o comprimento da sequência, ele vai incorporar os primeiros 256 tokens e truncar o restante do bloco.
Envie o modelo de tokenizador (sentencepiece.model
) e o incorporador do Gecko para seu dispositivo:
adb push sentencepiece.model /data/local/tmp/sentencepiece.model
adb push Gecko_256_f32.tflite /data/local/tmp/gecko.tflite
O modelo de incorporação é compatível com CPU e GPU. Por padrão, o app de exemplo é configurado para extrair incorporações com o modelo Gecko na GPU.
companion object {
...
private const val USE_GPU_FOR_EMBEDDINGS = true
}
Configurar com o Gemini Embedder
O Gemini Embedder (GeminiEmbedder
) cria embeddings usando a API Cloud do Gemini. Isso exige uma chave da API Google Gemini para executar o aplicativo, que você pode
acessar na página de configuração da API Google Gemini.
Receber uma chave da API Gemini no Google AI Studio
Adicione sua chave de API Gemini e defina COMPUTE_EMBEDDINGS_LOCALLY
como "false" em
RagPipeline.kt:
companion object {
...
private const val COMPUTE_EMBEDDINGS_LOCALLY = false
private const val GEMINI_API_KEY = "<API_KEY>"
}
Como funciona
Esta seção fornece informações mais detalhadas sobre os componentes do pipeline RAG do aplicativo. É possível conferir a maior parte do código em RagPipeline.kt.
Dependências
O SDK de RAG usa a biblioteca com.google.ai.edge.localagents:localagents-rag
.
Adicione esta dependência ao arquivo build.gradle
do seu app Android:
dependencies {
...
implementation("com.google.ai.edge.localagents:localagents-rag:0.1.0")
implementation("com.google.mediapipe:tasks-genai:0.10.22")
}
Dados fornecidos pelo usuário
Os dados fornecidos pelo usuário no aplicativo são um arquivo de texto chamado
sample_context.txt
,
que é armazenado no diretório assets
. O aplicativo usa partes do arquivo de texto, cria embeddings dessas partes e se refere a eles ao gerar o texto de saída.
O snippet de código a seguir pode ser encontrado em MainActivity.kt:
class MainActivity : ComponentActivity() {
lateinit var chatViewModel: ChatViewModel
...
chatViewModel.memorizeChunks("sample_context.txt")
...
}
Divisão
Para simplificar, o arquivo
sample_context.txt
inclui tags <chunk_splitter>
que o aplicativo de amostra usa para criar
pedaços. Em seguida, os embeddings são criados para cada bloco. Em aplicativos de produção, o tamanho dos blocos é uma consideração importante. Quando um trecho é muito grande, o vetor não tem especificidade suficiente para ser útil. Quando é muito pequeno, não tem contexto suficiente.
O aplicativo de exemplo processa o chunking usando a função memorizeChunks
em
RagPipeline.kt.
Incorporação
O aplicativo oferece dois caminhos para embedding de texto:
- Embedder do Gecko: extração local (no dispositivo) de embeddings de texto com o modelo Gecko.
- Gemini Embedder: extração de incorporação de texto baseada na nuvem com a API Generative Language Cloud.
O aplicativo de exemplo seleciona o incorporador com base na intenção do usuário de calcular incorporações localmente ou pelo Google Cloud. O snippet de código a seguir pode ser encontrado em 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
)
}
Banco de dados
O aplicativo de exemplo usa o SQLite (SqliteVectorStore
) para armazenar incorporações de texto. Também é possível usar o banco de dados DefaultVectorStore
para
armazenamento de vetores não persistentes.
O snippet de código a seguir pode ser encontrado em RagPipeline.kt:
private val config = ChainConfig.create(
mediaPipeLanguageModel, PromptBuilder(QA_PROMPT_TEMPLATE1),
DefaultSemanticTextMemory(
SqliteVectorStore(768), embedder
)
)
O app de exemplo define a dimensão de embedding como 768, que se refere ao comprimento de cada vetor no banco de dados de vetores.
Cadeia
O SDK da RAG oferece cadeias, que combinam vários componentes da RAG em um único pipeline. Você pode usar cadeias para orquestrar modelos de recuperação e consulta. A API é baseada na interface Chain.
O aplicativo de exemplo usa a cadeia de recuperação e inferência. O snippet de código a seguir pode ser encontrado em RagPipeline.kt:
private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)
A cadeia é invocada quando o modelo gera respostas:
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
}