Pakiet AI Edge RAG SDK udostępnia podstawowe komponenty do tworzenia potoku generowania rozszerzonego przez wyszukiwanie w zapisanych informacjach (RAG) za pomocą interfejsu LLM Inference API. Potok RAG zapewnia LLM dostęp do danych przekazywanych przez użytkowników, które mogą zawierać zaktualizowane, poufne lub specyficzne dla danej domeny informacje. Dzięki dodatkowym możliwościom wyszukiwania informacji, jakie daje RAG, modele LLM mogą generować dokładniejsze i uwzględniające kontekst odpowiedzi w przypadku konkretnych zastosowań.
Ten przewodnik przeprowadzi Cię przez podstawową implementację przykładowej aplikacji przy użyciu interfejsu LLM Inference API z pakietem AI Edge RAG SDK. W tym przewodniku skupimy się na tworzeniu potoku RAG. Więcej informacji o korzystaniu z interfejsu LLM Inference API znajdziesz w przewodniku po interfejsie LLM Inference API na Androida.
Pełną wersję przykładowej aplikacji znajdziesz na GitHub.
Aby rozpocząć, utwórz aplikację, zapoznaj się z danymi przekazanymi przez użytkownika (sample_context.txt
) i zadaj LLM pytania dotyczące informacji w pliku tekstowym.
Uruchamianie przykładowej aplikacji
Ten przewodnik odnosi się do przykładowej podstawowej aplikacji do generowania tekstu z RAG na Androida. Przykładowej aplikacji możesz użyć jako punktu wyjścia do utworzenia własnej aplikacji na Androida lub jako odniesienia podczas modyfikowania istniejącej aplikacji.
Aplikacja jest zoptymalizowana pod kątem urządzeń z wyższej półki, takich jak Pixel 8, Pixel 9, S23 i S24. Podłącz urządzenie z Androidem do stacji roboczej i upewnij się, że masz aktualną wersję Android Studio. Więcej informacji znajdziesz w przewodniku po konfiguracji Androida.
Pobieranie kodu aplikacji
Poniższe instrukcje pokazują, jak utworzyć lokalną kopię przykładowego kodu za pomocą narzędzia wiersza poleceń Git.
Sklonuj repozytorium Git za pomocą tego polecenia:
git clone https://github.com/google-ai-edge/ai-edge-apis
Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Android Studio i uruchomić aplikację.
Pobieranie modelu
Przykładowa aplikacja jest skonfigurowana do korzystania z modelu Gemma-3 1B. Gemma-3 1B należy do rodziny lekkich, zaawansowanych otwartych modeli Gemma, które powstały na podstawie tych samych badań i technologii, które zostały wykorzystane do stworzenia modeli Gemini. Model zawiera 1 mld parametrów i otwarte wagi.
Po pobraniu modelu Gemma-3 1B z Hugging Face przenieś go na urządzenie:
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
W przykładowej aplikacji możesz też używać innych modeli, ale może to wymagać dodatkowych czynności konfiguracyjnych.
Konfigurowanie narzędzia do osadzania
Osadzacz pobiera fragmenty tekstu z danych przekazywanych przez użytkowników i przekształca je w wektorowe reprezentacje numeryczne, które odzwierciedlają ich znaczenie semantyczne. Model LLM odwołuje się do tych wektorów dystrybucyjnych, aby zidentyfikować odpowiednie wektory, i uwzględnia w wygenerowanych wynikach najbardziej trafne semantycznie fragmenty.
Przykładowa aplikacja jest przeznaczona do współpracy z 2 osadzającymi: osadzającym Gemini i osadzającym Gecko.
Konfigurowanie za pomocą komponentu Gecko
Domyślnie przykładowa aplikacja jest skonfigurowana do korzystania z osadzonego komponentu Gecko (GeckoEmbeddingModel
) i uruchamia model w całości na urządzeniu.
Gecko Embedder jest dostępny jako modele zmiennoprzecinkowe i skwantowane w wielu wersjach dla różnych długości sekwencji. Więcej informacji znajdziesz w karcie modelu Gecko.
Specyfikacje modelu znajdziesz w nazwie pliku modelu. Na przykład:
Gecko_256_f32.tflite
: model zmiennoprzecinkowy, który obsługuje sekwencje do 256 tokenów.Gecko_1024_quant.tflite
: skwantyzowany model, który obsługuje sekwencje składające się z maksymalnie 1024 tokenów.
Długość sekwencji to maksymalny rozmiar fragmentu, który model może osadzić. Jeśli na przykład model Gecko_256_f32.tflite
otrzyma fragment, który przekracza długość sekwencji, osadzi pierwsze 256 tokenów i obetnie resztę fragmentu.
Wypchnij model tokenizatora (sentencepiece.model
) i osadzony komponent Gecko na urządzenie:
adb push sentencepiece.model /data/local/tmp/sentencepiece.model
adb push Gecko_256_f32.tflite /data/local/tmp/gecko.tflite
Model osadzania jest zgodny zarówno z procesorem, jak i z kartą graficzną. Domyślnie przykładowa aplikacja jest skonfigurowana tak, aby wyodrębniać wektory za pomocą modelu Gecko na GPU.
companion object {
...
private const val USE_GPU_FOR_EMBEDDINGS = true
}
Konfigurowanie za pomocą Gemini Embedder
Moduł Gemini Embedder (GeminiEmbedder
) tworzy embeddingi za pomocą interfejsu Gemini Cloud API. Do uruchomienia aplikacji wymagany jest klucz interfejsu Google Gemini API, który możesz uzyskać na stronie konfiguracji interfejsu Google Gemini API.
Uzyskiwanie klucza interfejsu Gemini API w Google AI Studio
Dodaj klucz interfejsu Gemini API i ustaw wartość COMPUTE_EMBEDDINGS_LOCALLY
na false w pliku RagPipeline.kt:
companion object {
...
private const val COMPUTE_EMBEDDINGS_LOCALLY = false
private const val GEMINI_API_KEY = "<API_KEY>"
}
Jak to działa
Ta sekcja zawiera bardziej szczegółowe informacje o komponentach potoku RAG aplikacji. Większość kodu możesz zobaczyć w pliku RagPipeline.kt.
Zależności
Pakiet SDK RAG korzysta z biblioteki com.google.ai.edge.localagents:localagents-rag
.
Dodaj tę zależność do pliku build.gradle
w swojej aplikacji na Androida:
dependencies {
...
implementation("com.google.ai.edge.localagents:localagents-rag:0.1.0")
implementation("com.google.mediapipe:tasks-genai:0.10.22")
}
Dane przekazywane przez użytkowników
Dane podane przez użytkownika w aplikacji to plik tekstowy o nazwie sample_context.txt
, który jest przechowywany w katalogu assets
. Aplikacja dzieli plik tekstowy na części, tworzy ich osadzanie i wykorzystuje je podczas generowania tekstu wyjściowego.
Ten fragment kodu znajdziesz w pliku MainActivity.kt:
class MainActivity : ComponentActivity() {
lateinit var chatViewModel: ChatViewModel
...
chatViewModel.memorizeChunks("sample_context.txt")
...
}
Chunking
Dla uproszczenia plik
sample_context.txt
zawiera tagi <chunk_splitter>
, których przykładowa aplikacja używa do tworzenia fragmentów. Następnie dla każdego fragmentu tworzone są wektory. W aplikacjach produkcyjnych rozmiar fragmentów ma kluczowe znaczenie. Gdy fragment jest zbyt duży, wektor nie zawiera wystarczająco szczegółowych informacji, aby był przydatny. Z kolei gdy jest zbyt mały, nie zawiera wystarczającego kontekstu.
Przykładowa aplikacja obsługuje dzielenie na części za pomocą funkcji memorizeChunks
w pliku RagPipeline.kt.
Umieszczanie
Aplikacja oferuje 2 ścieżki osadzania tekstu:
- Gecko embedder: lokalne (na urządzeniu) wyodrębnianie wektorów dystrybucyjnych tekstu za pomocą modelu Gecko.
- Gemini Embedder: wyodrębnianie osadzania tekstu w chmurze za pomocą interfejsu Generative Language Cloud API.
Przykładowa aplikacja wybiera moduł do osadzania na podstawie tego, czy użytkownik chce obliczać osadzanie lokalnie, czy w Google Cloud. Ten fragment kodu znajduje się w pliku 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
)
}
Baza danych
Przykładowa aplikacja używa bazy danych SQLite (SqliteVectorStore
) do przechowywania wektorów tekstowych. Możesz też używać bazy danych DefaultVectorStore
do nietrwałego przechowywania wektorów.
Ten fragment kodu znajdziesz w pliku RagPipeline.kt:
private val config = ChainConfig.create(
mediaPipeLanguageModel, PromptBuilder(QA_PROMPT_TEMPLATE1),
DefaultSemanticTextMemory(
SqliteVectorStore(768), embedder
)
)
Przykładowa aplikacja ustawia wymiar wektora na 768, co odnosi się do długości każdego wektora w bazie danych wektorów.
Łańcuch
Pakiet SDK RAG udostępnia łańcuchy, które łączą kilka komponentów RAG w jeden potok. Łańcuchów możesz używać do koordynowania modeli pobierania i zapytań. Interfejs API jest oparty na interfejsie Chain.
Aplikacja przykładowa korzysta z łańcucha Retrieval and Inference. Ten fragment kodu znajdziesz w pliku RagPipeline.kt:
private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)
Łańcuch jest wywoływany, gdy model generuje odpowiedzi:
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
}