O SDK RAG de IA de borda fornece os componentes fundamentais para construir um pipeline de geração aumentada de recuperação (RAG, na sigla em inglês) com a API de inferência de LLM. Um pipeline de RAG oferece 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 de recuperação de informações adicionais da RAG, os LLMs podem gerar respostas mais precisas e sensíveis ao contexto para casos de uso específicos.
Este guia orienta você em uma implementação básica de um aplicativo de exemplo usando a API LLM Inference com o SDK de RAG de IA. Este guia se concentra na construção de um pipeline RAG. Para mais informações sobre como usar a API LLM Inference, consulte o guia LLM Inference para Android.
Confira 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 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 mais avançados, como Pixel 8, Pixel 9, S23 e S24. Conecte um dispositivo Android à sua 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 do git.
Clone o repositório do Git usando o seguinte comando:
git clone https://github.com/google-ai-edge/ai-edge-apis
Depois de criar uma versão local do código de exemplo, você pode importar o projeto para o Android Studio e executar 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 Gemma. O modelo contém 1 bilhão de parâmetros e pesos abertos.
Depois de fazer o download do Gemma-3 1B do Hugging Face, envie o modelo para o 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 outras etapas de configuração.
Configurar um incorporação
O incorporador pega pedaços de texto dos dados fornecidos pelo usuário e os transforma em representações numéricas vetorizadas que capturam o significado semântico deles. O LLM se refere a esses embeddings para identificar vetores relevantes e incorporar os blocos mais semanticamente relevantes na saída gerada.
O aplicativo de exemplo foi projetado para funcionar com dois incorporadores, o Gemini e o Gecko.
Configurar com o embedder da Gecko
Por padrão, o app de exemplo é configurado para usar o incorporador do Gecko
(GeckoEmbeddingModel
) e executa o modelo completamente no dispositivo.
Fazer o download do Gecko 110m-pt
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 Gecko.
As especificações do modelo podem ser encontradas no nome do arquivo. Exemplo:
Gecko_256_fp32.tflite
: modelo de ponto flutuante compatível com sequências de até 256 tokens.Gecko_1024_quant.tflite
: modelo quantizado que aceita sequências de até 1.024 tokens.
A duração da sequência é o tamanho máximo do bloco que o modelo pode incorporar. Por exemplo,
o modelo Gecko_256_fp32.tflite
recebe um bloco que excede o comprimento da sequência.
O modelo incorpora os primeiros 256 tokens e trunca 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_fp32.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 embeddings com o modelo Gecko na GPU.
companion object {
...
private const val USE_GPU_FOR_EMBEDDINGS = true
}
Configurar com o Gemini Embedder
O Embedder do Gemini (GeminiEmbedder
) cria embeddings usando a API Gemini Cloud. Para executar o aplicativo, é necessário ter uma chave da API Google Gemini, que pode ser
concedida na página de configuração da API Google Gemini.
Conseguir uma chave da API Gemini no Google AI Studio
Adicione sua chave da API Gemini e defina COMPUTE_EMBEDDINGS_LOCALLY
como falso 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 do RAG usa a biblioteca com.google.ai.edge.localagents:localagents-rag
.
Adicione esta dependência ao arquivo build.gradle
do 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 pega partes do
arquivo de texto, cria embeddings dessas partes e se refere a elas 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 exemplo usa para criar
fragmentos. Em seguida, as incorporações são criadas para cada bloco. Em aplicativos de produção,
o tamanho dos blocos é uma consideração importante. Quando um bloco é muito grande, o vetor
não tem especificidade suficiente para ser útil. Quando ele é muito pequeno, ele não tem contexto suficiente.
O aplicativo de exemplo processa o agrupamento pela função memorizeChunks
em
RagPipeline.kt.
Incorporação
O aplicativo oferece duas opções para embedding de texto:
- Embedding da Gecko: extração local (no dispositivo) de embedding de texto com o modelo Gecko.
- Gemini Embedder: extração de embeddings de texto baseada na nuvem com a API do Gênero de linguagem generativa.
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 abaixo 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 incorporação 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
}