AI Edge RAG SDK는 LLM 추론 API를 사용하여 검색 증강 생성 (RAG) 파이프라인을 구성하는 기본 구성요소를 제공합니다. RAG 파이프라인은 업데이트된 민감한 정보 또는 도메인별 정보가 포함될 수 있는 사용자 제공 데이터에 대한 액세스를 LLM에 제공합니다. RAG의 정보 검색 기능이 추가되어 LLM은 특정 사용 사례에 맞게 더 정확하고 맥락을 인식하는 응답을 생성할 수 있습니다.
이 가이드에서는 AI Edge RAG SDK와 함께 LLM 추론 API를 사용하는 샘플 애플리케이션의 기본 구현을 안내합니다. 이 가이드에서는 RAG 파이프라인 구성에 중점을 둡니다. LLM 추론 API 사용에 관한 자세한 내용은 Android용 LLM 추론 가이드를 참고하세요.
전체 샘플 애플리케이션은 GitHub에서 확인할 수 있습니다.
시작하려면 애플리케이션을 빌드하고, 사용자가 제공한 데이터(sample_context.txt
)를 읽고, 텍스트 파일의 정보와 관련된 질문을 LLM에 합니다.
예시 애플리케이션 실행
이 가이드에서는 Android용 RAG를 사용하는 기본 텍스트 생성 앱의 예를 참고합니다. 샘플 앱을 자체 Android 앱의 시작점으로 사용하거나 기존 앱을 수정할 때 참고할 수 있습니다.
이 애플리케이션은 Pixel 8, Pixel 9, S23, S24와 같은 고급 기기에 최적화되어 있습니다. Android 기기를 워크스테이션에 연결하고 최신 버전의 Android 스튜디오가 설치되어 있는지 확인합니다. 자세한 내용은 Android 설정 가이드를 참고하세요.
애플리케이션 코드 다운로드
다음 안내에서는 git 명령줄 도구를 사용하여 예시 코드의 로컬 사본을 만드는 방법을 보여줍니다.
다음 명령어를 사용하여 git 저장소를 클론합니다.
git clone https://github.com/google-ai-edge/ai-edge-apis
예시 코드의 로컬 버전을 만든 후 프로젝트를 Android 스튜디오로 가져와 앱을 실행할 수 있습니다.
모델 다운로드
샘플 애플리케이션은 Gemma-3 1B를 사용하도록 구성되어 있습니다. Gemma-3 1B는 Gemini 모델을 만드는 데 사용된 것과 동일한 연구 및 기술로 빌드된 최첨단 경량 개방형 모델인 Gemma 제품군에 속합니다. 이 모델은 10억 개의 매개변수와 개방형 가중치를 포함합니다.
Hugging Face에서 Gemma-3 1B를 다운로드한 후 모델을 기기에 푸시합니다.
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
샘플 애플리케이션과 함께 다른 모델을 사용할 수도 있지만 추가 구성 단계가 필요할 수 있습니다.
삽입 도구 설정
삽입기는 사용자 제공 데이터에서 텍스트 청크를 가져와 시맨틱 의미를 포착하는 벡터화된 숫자 표현으로 변환합니다. LLM은 이러한 임베딩을 참조하여 관련 벡터를 식별하고 생성된 출력에 가장 의미론적으로 관련성이 높은 청크를 통합합니다.
샘플 애플리케이션은 두 개의 삽입 도구인 Gemini 삽입 도구와 Gecko 삽입 도구와 함께 작동하도록 설계되었습니다.
Gecko 삽입기로 설정
기본적으로 샘플 앱은 Gecko 삽입기(GeckoEmbeddingModel
)를 사용하도록 구성되며 모델을 완전히 기기 내에서 실행합니다.
Gecko 삽입기는 부동 소수점 및 정규화된 모델로 제공되며, 시퀀스 길이에 따라 여러 버전이 있습니다. 자세한 내용은 Gecko 모델 카드를 참고하세요.
모델 사양은 모델 파일 이름에서 확인할 수 있습니다. 예를 들면 다음과 같습니다.
Gecko_256_fp32.tflite
: 최대 256개 토큰의 시퀀스를 지원하는 부동 소수점 모델입니다.Gecko_1024_quant.tflite
: 최대 1,024개의 토큰 시퀀스를 지원하는 정규화된 모델입니다.
시퀀스 길이는 모델이 삽입할 수 있는 최대 청크 크기입니다. 예를 들어 Gecko_256_fp32.tflite
모델에 시퀀스 길이를 초과하는 청크가 전달되면 모델은 처음 256개 토큰을 삽입하고 나머지 청크를 자릅니다.
토큰화 모델 (sentencepiece.model
)과 Gecko 삽입기를 기기에 푸시합니다.
adb push sentencepiece.model /data/local/tmp/sentencepiece.model
adb push Gecko_256_fp32.tflite /data/local/tmp/gecko.tflite
임베딩 모델은 CPU와 GPU 모두와 호환됩니다. 기본적으로 샘플 앱은 GPU에서 Gecko 모델을 사용하여 임베딩을 추출하도록 구성됩니다.
companion object {
...
private const val USE_GPU_FOR_EMBEDDINGS = true
}
Gemini 삽입 도구로 설정
Gemini Embedder (GeminiEmbedder
)는 Gemini Cloud API를 사용하여 임베딩을 만듭니다. 애플리케이션을 실행하려면 Google Gemini API 키가 필요하며 이 키는 Google Gemini API 설정 페이지에서 가져올 수 있습니다.
Google AI Studio에서 Gemini API 키 받기
Gemini API 키를 추가하고 RagPipeline.kt에서 COMPUTE_EMBEDDINGS_LOCALLY
를 false로 설정합니다.
companion object {
...
private const val COMPUTE_EMBEDDINGS_LOCALLY = false
private const val GEMINI_API_KEY = "<API_KEY>"
}
작동 방식
이 섹션에서는 애플리케이션의 RAG 파이프라인 구성요소에 관해 자세히 설명합니다. 대부분의 코드는 RagPipeline.kt에서 확인할 수 있습니다.
종속 항목
RAG SDK는 com.google.ai.edge.localagents:localagents-rag
라이브러리를 사용합니다.
Android 앱의 build.gradle
파일에 다음 종속 항목을 추가합니다.
dependencies {
...
implementation("com.google.ai.edge.localagents:localagents-rag:0.1.0")
implementation("com.google.mediapipe:tasks-genai:0.10.22")
}
사용자 제공 데이터
애플리케이션의 사용자 제공 데이터는 assets
디렉터리에 저장된 sample_context.txt
라는 텍스트 파일입니다. 애플리케이션은 텍스트 파일의 청크를 가져와 이러한 청크의 임베딩을 생성하고 출력 텍스트를 생성할 때 임베딩을 참조합니다.
다음 코드 스니펫은 MainActivity.kt에서 확인할 수 있습니다.
class MainActivity : ComponentActivity() {
lateinit var chatViewModel: ChatViewModel
...
chatViewModel.memorizeChunks("sample_context.txt")
...
}
청킹
단순성을 위해 sample_context.txt
파일에는 샘플 애플리케이션에서 청크를 만드는 데 사용하는 <chunk_splitter>
태그가 포함되어 있습니다. 그런 다음 각 청크에 대해 임베딩이 생성됩니다. 프로덕션 애플리케이션에서는 청크의 크기가 중요한 고려사항입니다. 청크가 너무 크면 벡터에 유용하기에 충분한 구체성이 포함되지 않으며, 청크가 너무 작으면 컨텍스트가 충분히 포함되지 않습니다.
샘플 애플리케이션은 RagPipeline.kt의 memorizeChunks
함수를 통해 청크 처리를 처리합니다.
임베딩
이 애플리케이션은 텍스트 삽입을 위한 두 가지 경로를 제공합니다.
- Gecko 삽입 도구: Gecko 모델을 사용한 로컬 (기기 내) 텍스트 임베딩 추출
- Gemini Embedder: 생성형 언어 Cloud API를 사용한 클라우드 기반 텍스트 임베딩 추출
샘플 애플리케이션은 사용자가 삽입을 로컬에서 계산할지 아니면 Google Cloud를 통해 계산할지 여부에 따라 삽입자를 선택합니다. 다음 코드 스니펫은 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
)
}
데이터베이스
샘플 애플리케이션은 SQLite (SqliteVectorStore
)를 사용하여 텍스트 임베딩을 저장합니다. 비영구 벡터 저장소에 DefaultVectorStore
데이터베이스를 사용할 수도 있습니다.
다음 코드 스니펫은 RagPipeline.kt에서 확인할 수 있습니다.
private val config = ChainConfig.create(
mediaPipeLanguageModel, PromptBuilder(QA_PROMPT_TEMPLATE1),
DefaultSemanticTextMemory(
SqliteVectorStore(768), embedder
)
)
샘플 앱은 임베딩 측정기준을 768로 설정합니다. 이는 벡터 데이터베이스의 각 벡터 길이를 나타냅니다.
체인
RAG SDK는 여러 RAG 구성요소를 단일 파이프라인으로 결합하는 체인을 제공합니다. 체이닝을 사용하여 검색 및 쿼리 모델을 조정할 수 있습니다. 이 API는 Chain 인터페이스를 기반으로 합니다.
샘플 애플리케이션은 검색 및 추론 체인을 사용합니다. 다음 코드 스니펫은 RagPipeline.kt에서 확인할 수 있습니다.
private val retrievalAndInferenceChain = RetrievalAndInferenceChain(config)
체인은 모델이 응답을 생성할 때 호출됩니다.
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
}