멀티모달 RAG 구축을 위한 3가지 핵심 패턴: 종합 가이드
대규모 언어 모델(LLMs)은 개인화된 챗봇, 문서 요약, 문서 질의응답, 문서 분류 등 수많은 AI 애플리케이션에서 사용할 수 있기 때문에 그 다재다능함으로 높은 평가를 받고 있습니다.
하지만 LLM을 사용할 때 한 가지 핵심 문제는 환각의 위험입니다. 환각은 LLM이 우리의 질의에 대해 매우 그럴듯하지만 사실이 아닌 응답을 생성하는 현상을 말합니다. 특히 우리가 잘 알지 못하는 주제에 대해 질문할 경우, LLM의 환각을 알아차리기는 꽤 까다롭습니다.
여러 다른 방법들 중에서도, 검색 증강 생성(Retrieval Augmented Generation, RAG)은 LLM의 환각 위험을 완화하는 데 도움이 될 수 있는 접근 방식입니다. 초기 구현에서 RAG는 텍스트 입력에만 더 일반적으로 사용되었습니다. AI 기술의 발전으로 이제는 이미지, 오디오, 비디오 등 다양한 데이터 모달리티와 함께 RAG를 사용할 수 있으며, 이를 멀티모달 RAG라고 합니다.
이 글에서는 AI 애플리케이션에서 멀티모달 RAG를 구현할 수 있는 다양한 접근 방식에 대해 논의하겠습니다. 멀티모달 RAG를 자세히 살펴보기 전에, 먼저 RAG의 기본 개념을 다시 살펴보겠습니다.
RAG의 기본 개념
RAG는 프롬프트에서 사용자 질의에 관련 컨텍스트를 제공함으로써 LLM 환각의 위험을 완화하는 데 도움이 되는 새로운 접근 방식입니다. 사용자 질의에 응답하기 전에 LLM은 이 관련 컨텍스트를 응답의 기반으로 사용할 수 있으며, 그 결과 더 문맥화된 답변을 생성합니다.
이름에서 알 수 있듯이, RAG에는 검색, 증강, 생성이라는 세 가지 주요 구성 요소가 있습니다.
검색: 이 구성 요소에서는 사용자 질의에 가장 관련 있는 컨텍스트를 가져옵니다. 이 구성 요소에는 후보 검색과 재순위화라는 두 단계가 있습니다. 후보 검색 단계에서는 가장 유망한 상위 n개의 컨텍스트를 가져옵니다. 반면 재순위화 단계에서는 이러한 컨텍스트를 코사인 유사도나 유클리드 거리와 같은 유사도 지표에 따라 순위화하거나 정렬합니다.
증강: 이 구성 요소에서는 가장 유망한 컨텍스트를 원래 사용자 질의와 통합하여 하나의 최종적인 일관된 프롬프트를 형성합니다. 이 최종 프롬프트는 이후 LLM의 입력으로 사용됩니다.
생성: 이 구성 요소에서는 LLM이 사용자 질의에 답하기 위한 유망한 컨텍스트를 포함하는 입력 프롬프트를 기반으로 응답을 생성합니다. 그런 다음 응답은 사용자에게 다시 전달됩니다.
그림: RAG의 전체 워크플로.
하지만 애플리케이션에서 RAG를 구현하기 전에 몇 가지를 설정해야 합니다.
예를 들어, 컨텍스트를 가져오기 전에 가능한 모든 컨텍스트를 저장할 효율적이고 확장 가능한 저장 시스템이 필요합니다. RAG에 일반적으로 유용한 컨텍스트는 비정형 데이터(텍스트, 이미지 등)이므로, 벡터 데이터베이스는 RAG 애플리케이션에서 가장 흔히 사용되는 저장 시스템입니다.
벡터 데이터베이스에서는 일반적으로 원시 컨텍스트 대신 컨텍스트의 임베딩 표현을 저장합니다. 임베딩을 사용하면 주어진 질의에 대해 가장 유망한 컨텍스트를 찾기 위해 유사도 검색을 수행할 수 있습니다. 따라서 원시 컨텍스트를 임베딩으로 변환하기 위한 딥러닝 모델(임베딩 모델)도 필요합니다.
2차원 벡터 공간에서 유사한 단어의 임베딩.
그렇다면 처음부터 RAG 파이프라인의 워크플로는 다음과 같습니다:
임베딩 모델의 도움을 받아 원시 컨텍스트를 임베딩으로 변환합니다.
이러한 임베딩을 벡터 데이터베이스에 저장하고 인덱싱합니다.
주어진 모든 쿼리에 대해, 원시 컨텍스트에 사용했던 동일한 임베딩 모델을 사용하여 쿼리를 임베딩으로 변환합니다.
벡터 데이터베이스 내부에서 쿼리 임베딩과 컨텍스트 임베딩 간의 유사도 검색을 수행합니다.
가장 관련성이 높은 상위 n개의 컨텍스트를 가져와 해당 컨텍스트들을 원래 쿼리와 통합하여 LLM의 입력으로 사용할 하나의 일관된 프롬프트로 만듭니다.
LLM은 제공된 관련 컨텍스트를 사용하여 쿼리에 대한 응답을 생성함으로써 더 정확한 결과를 제공합니다.
멀티모달 RAG의 기본 원리
이전 섹션에서 논의한 RAG의 구현은 LLM 환각의 위험을 완화하고 LLM 응답의 전반적인 품질을 향상시키는 데 매우 유용한 것으로 입증되었습니다. 그러나 RAG에서 컨텍스트를 이야기할 때, 우리는 일반적으로 컨텍스트를 텍스트로 지칭합니다. 한편, 실제 애플리케이션에서는 단순히 텍스트뿐만 아니라 다른 모달리티를 컨텍스트로 제공하고 싶을 수 있다는 것을 알고 있습니다.
내부 챗봇 애플리케이션의 컨텍스트로 문서 모음을 사용하고 싶다고 가정해 보겠습니다. 이미 알고 있듯이, 문서는 일반적으로 텍스트뿐만 아니라 이미지, 차트, 표로도 구성되며, 여기에는 사용자의 쿼리에 답하는 데 유용한 많은 정보가 포함되어 있습니다. 텍스트 기반 RAG로는 이러한 이미지, 차트, 표에 포함된 정보를 컨텍스트로 저장할 수 없습니다.
멀티모달 RAG는 이 문제에 대한 해결책입니다. 이 RAG 방법을 사용하면 다양한 정보 소스의 모든 컨텍스트를 저장할 수 있으며, 따라서 LLM 응답의 전반적인 정확도도 향상시킬 수 있습니다.
그림: 멀티모달 RAG 파이프라인.
멀티모달 임베딩과 멀티모달 LLM의 등장과 성장 덕분에 이제 멀티모달 RAG를 구현하는 것이 가능해졌습니다. 멀티모달 RAG의 아이디어는 일반적인 RAG와 정확히 동일하지만, 이제 이미지, 오디오, 비디오와 같은 다양한 데이터 모달리티의 임베딩을 저장할 수 있습니다. 다만 멀티모달 RAG를 구현하려면 멀티모달 임베딩 모델뿐만 아니라 멀티모달 LLM도 사용하고 있는지 확인해야 합니다.
일반적으로 멀티모달 RAG는 다양한 방식으로 구현할 수 있습니다. 구체적으로, 이 글에서 자세히 다룰 세 가지 패턴이 있습니다:
모든 모달리티를 하나의 기본 모달리티에 맞춥니다.
모든 모달리티를 동일한 벡터 공간에 임베딩합니다.
원시 이미지 접근을 포함한 하이브리드 검색.
이러한 패턴들을 하나씩 살펴보겠습니다.
패턴 1: 모든 모달리티를 하나의 기본 모달리티에 맞추기(멀티미디어에서 텍스트로)
첫 번째 패턴은 모든 모달리티를 하나의 기본 모달리티로 변환하는 것입니다. 어떤 모달리티든 기본 모달리티로 선택할 수 있지만, 멀티모달 RAG에서는 텍스트가 가장 일반적으로 사용됩니다. 따라서 이 섹션 전체에서 텍스트를 기본 모달리티로 사용하겠습니다.
서로 다른 모달리티를 텍스트로 변환하는 요령은 멀티모달 LLM을 사용하여 데이터의 텍스트 요약을 생성하는 것입니다. 예를 들어, 텍스트와 이미지가 많이 포함된 문서가 있다고 가정해 보겠습니다. 텍스트가 우리의 기본 모달리티이므로 문서의 텍스트에 대해서는 아무것도 할 필요가 없습니다. 한편, LLAVA, Gemini, Claude Sonnet, Qwen-VL, Pixtral 등과 같이 이미지와 텍스트를 모두 입력으로 받아 이미지의 텍스트 요약을 생성하는 Vision Language Model (VLM)을 사용할 수 있습니다.
이미지의 텍스트 요약이 준비되면, 이 텍스트를 문서의 다른 텍스트와 함께 텍스트 기반 임베딩 모델을 사용해 임베딩으로 변환할 수 있습니다. SentenceTransformers, OpenAI, VoyageAI 등의 모델처럼 선택할 수 있는 텍스트 기반 임베딩 모델은 많습니다. 그런 다음 이러한 텍스트의 임베딩은 벡터 데이터베이스에 저장되고 인덱싱됩니다.
그림: 패턴 1 워크플로.
이제 주어진 어떤 쿼리든, 이전에 사용했던 동일한 텍스트 기반 임베딩 모델을 사용해 임베딩으로 변환할 수 있습니다. 그 후 유사도 검색을 수행하여 가장 관련성 높은 컨텍스트를 찾고, 그런 다음 텍스트 기반 컨텍스트를 텍스트 기반 또는 멀티모달 LLM의 프롬프트 일부로 사용할 수 있습니다.
이 패턴의 구현 세부 사항에 대해 더 알아보고 싶다면, 이 패턴으로 멀티모달 RAG를 구축하는 단계를 안내하는 전용 글이 있습니다.
이 패턴은 사용 사례에서 원시 비텍스트 데이터에 접근할 필요가 없다면 사용하기에 완벽합니다. 애플리케이션은 이미지를 입력으로 받을 수 있지만, 출력은 항상 텍스트 기반일 수 있습니다. 예를 들어, 내부 문서에 있는 이미지의 내용을 설명하는 기능을 가진 애플리케이션을 구축할 수 있습니다.
그러나 이 패턴에서는 일반적인 RAG 시스템과 마찬가지로 여전히 텍스트 기반 컨텍스트에 의존합니다. 실제 애플리케이션에서는 이미지나 다른 모달리티를 컨텍스트로 사용하고 싶을 수 있습니다. 따라서 두 번째 패턴에 대해 이야기해 보겠습니다.
패턴 2: 모든 모달리티를 동일한 벡터 공간에 임베딩하기
두 번째 패턴은 모든 모달리티의 데이터를 동일한 벡터 공간의 임베딩으로 변환하는 것입니다. 이 접근 방식의 비결은 CLIP 및 ALIGN과 같은 멀티모달 임베딩 모델의 구현에 있습니다. CLIP을 예로 들어 보겠습니다.
CLIP은 OpenAI가 개발한 모델로, 텍스트와 이미지를 입력 쌍으로 받아들이며, 텍스트와 이미지 사이의 유사도를 판단하도록 훈련되었습니다. 그 결과 텍스트가 이미지와 잘 맞으면 CLIP은 높은 유사도 점수를 제공하며, 그 반대도 마찬가지입니다.
그림: 3차원 벡터 공간에서 CLIP을 사용한 서로 다른 모달리티 데이터의 임베딩.
위에서 볼 수 있듯이, "웃고 있는 개"라는 문장과 웃고 있는 개의 이미지가 있다고 해보겠습니다. CLIP은 먼저 텍스트와 이미지를 비슷한 차원의 임베딩으로 변환하며, 벡터 공간을 확인하면 두 임베딩은 서로 가까운 곳에 배치될 가능성이 높습니다.
멀티모달 임베딩 모델이 있으므로, 이 패턴의 첫 번째 단계는 서로 다른 모달리티의 데이터를 이 멀티모달 임베딩 모델로 임베딩으로 변환하는 것입니다. 다음으로, 이러한 임베딩을 Milvus 또는 Zilliz Cloud와 같은 벡터 데이터베이스 안에 저장하고 인덱싱합니다. 사용자 쿼리가 있으면, 동일한 멀티모달 임베딩 모델을 사용해 이를 변환한 다음 유사도 검색을 수행하여 가장 관련성 높은 컨텍스트를 찾을 수 있습니다.
그림: 패턴 2 워크플로.
이 패턴을 적용할 때 검색된 컨텍스트는 이미지와 텍스트처럼 다양한 모달리티의 데이터일 수 있습니다. 따라서 이러한 컨텍스트를 고려하고 최종 응답을 생성하려면 멀티모달 LLM을 사용해야 합니다. 데이터가 이미지와 텍스트로 구성되어 있다면 LLAVA, Gemini, Claude Sonnet, Qwen-VL, Pixtral 등과 같은 Vision Language Model (VLM)을 사용할 수 있습니다.
이 패턴의 구현 세부 사항에 대해 더 알아보고 싶다면, 이 패턴으로 멀티모달 RAG를 구축하는 단계를 안내하는 a 전용 글이 있습니다. 다만 해당 글에서는 원본 이미지가 벡터 데이터베이스 내부에 직접 저장되는 것이 아니라 로컬 메모리에 저장된다는 점을 유의하세요.
이 패턴의 주요 장점은 다용성과 단순성입니다. 멀티모달 임베딩 모델을 구현한다는 것은 첫 번째 패턴에서 했던 것처럼 모든 모달리티의 콘텐츠를 텍스트와 같은 주요 모달리티로 변환하는 추가 단계가 필요 없다는 의미입니다. 또한 유사도 검색 후 검색된 컨텍스트는 특정 하나의 모달리티에만 국한되지 않고 어떤 모달리티의 데이터든 될 수 있습니다.
하지만 멀티모달 LLM의 관련 컨텍스트로 어떤 모달리티의 데이터든 사용할 수 있기 때문에, 이 패턴을 구현할 때 원본 데이터도 저장해야 합니다. 문제는 이미지와 같은 비텍스트 데이터의 메모리 크기가 크며, 이를 벡터 데이터베이스에 직접 저장하면 리소스를 비효율적으로 사용하게 될 수 있다는 점입니다. 이는 결국 쿼리 시간이 느려지고 저장 비용이 증가하는 결과로도 이어집니다.
따라서 서로 다른 모달리티의 데이터를 컨텍스트로 사용해야 하지만, 사용 사례에서 확장성이 우려 사항이 아니라면 이 패턴을 사용하는 것을 권장합니다.
패턴 3: 원본 이미지 접근을 포함한 하이브리드 검색.
다양한 모달리티의 데이터를 컨텍스트로 사용해야 하고 확장성도 우려 사항이라면, 이 패턴을 구현할 수 있습니다. 이 패턴의 핵심 아이디어는 관심사의 분리입니다. 즉, 관련 컨텍스트를 찾기 위해 빠르고 효율적인 유사도 검색을 수행하는 데는 벡터 데이터베이스를 사용하고, 원본 데이터 저장에는 AWS S3 또는 Google Cloud Storage와 같은 전용 객체 스토리지 시스템을 사용합니다.
이 패턴을 구현하는 동안 두 가지 서로 다른 단계를 수행해야 합니다. 첫째, 실제 원본 데이터를 AWS S3 또는 Google Cloud Storage와 같은 전용 객체 스토리지 시스템에 저장합니다. 둘째, 전용 객체 스토리지 시스템에 있는 이미지의 URL과 같은 원본 데이터의 메타데이터를 벡터 데이터베이스 내부에 저장합니다.
그림: 패턴 3 워크플로.
원본 데이터를 저장하기 위해 별도의 시스템을 사용하므로, RAG를 수행하는 방식은 첫 번째 패턴과 거의 유사합니다. 텍스트가 주요 모달리티라고 가정해 보겠습니다. 가장 먼저 해야 할 일은 멀티모달 LLM을 사용해 원본 데이터의 텍스트 요약을 생성하는 것입니다. 다음으로 텍스트 기반 임베딩 모델을 사용해 텍스트 요약을 임베딩으로 변환할 수 있습니다. 그런 다음 임베딩과 원본 데이터의 메타데이터(전용 스토리지 시스템에 있는 원본 데이터의 URL)를 벡터 데이터베이스에 저장합니다.
주어진 쿼리에 대해 동일한 멀티모달 LLM을 사용해 텍스트 요약을 생성한 다음, 동일한 텍스트 기반 임베딩 모델을 사용해 쿼리의 요약을 임베딩으로 변환합니다. 다음으로 유사도 검색을 수행하고 관련 컨텍스트의 텍스트 요약과 URL을 가져올 수 있습니다. 마지막으로 검색된 URL을 통해 원본 데이터를 멀티모달 LLM에 전달할 수 있습니다.
다시 말하지만, 이 패턴으로 멀티모달 RAG를 구축하는 단계를 안내하는 이 글을 참조할 수 있습니다. 다만 해당 글에서는 원본 이미지가 AWS나 GCP와 같은 일반적인 프로덕션 준비형 스토리지 시스템에 저장되는 것이 아니라 로컬 메모리에 저장된다는 점을 유의하세요.
세 가지 옵션 중에서 이 패턴은 원시 데이터 저장소의 분리로 인해 가장 확장성이 뛰어난 패턴입니다. 이미 알고 있을 수 있듯이, 벡터 데이터베이스는 이미지와 같은 대용량 바이너리 객체를 저장하고 제공하는 것이 아니라 비정형 데이터를 쿼리하는 데 최적화되어 있습니다. 실제로 벡터 데이터베이스에서 바이너리 객체를 검색하는 것은 전용 객체 저장 시스템에서 검색하는 것보다 더 느린 경우가 많습니다.
따라서 다양한 모달리티의 데이터를 컨텍스트로 사용하고 확장성이 사용 사례에서 큰 우려 사항이라면 이 패턴을 사용하는 것을 권장합니다.
Milvus Vector Database가 멀티모달 RAG를 지원하는 방법
이전 섹션에서 언급했듯이, vector databases는 Retrieval Augmented Generation(RAG)의 적용에서 중요한 역할을 합니다. Milvus는 고급 기능으로 인해 RAG 시스템이나 기타 AI 애플리케이션에서 사용하기에 완벽한 벡터 데이터베이스입니다.
Milvus는 가장 단순한 것부터 IVFFLAT, HNSW, SCANN과 같은 더 고급 방식에 이르기까지 다양한 인덱싱 방법을 제공하여, 방대한 데이터 컬렉션을 빠르고 효율적으로 저장할 수 있게 합니다. 이러한 고급 인덱싱 방법의 구현은 RAG 구현에서 관련 컨텍스트를 찾기 위한 유사도 검색 프로세스도 가속화합니다.
멀티모달 RAG를 위한 인기 도구들과 Milvus의 쉬운 통합.
Milvus는 또한 이전 섹션에서 논의한 embedding models, LLM, orchestration tools와 같은 모든 RAG 구성 요소와 쉽게 통합할 수 있습니다. 임베딩 모델 측면에서는 pymilvus라고 하는 Milvus의 Python SDK를 사용하여 OpenAI, Cohere, SentenceTransformers, HuggingFace, VoyageAI 등의 인기 옵션을 직접 사용할 수 있습니다. 간단한 pip 명령으로 pymilvus를 설치할 수 있습니다:
pip install -U pymilvus
이제 SentenceTransformers의 임베딩 모델을 사용하고 싶다고 가정하면, 다음과 같이 pymilvus로 쉽게 수행할 수 있습니다:
pip install "pymilvus[model]"
from pymilvus import model
sentence_transformer_ef = model.dense.SentenceTransformerEmbeddingFunction(
model_name='all-MiniLM-L6-v2', # Specify the model name
device='cpu' # Specify the device to use, e.g., 'cpu' or 'cuda:0'
)
doc = [
"Artificial intelligence was founded as an academic discipline in 1956."]
doc_embedding = sentence_transformer_ef.encode_documents(doc)
Pymilvus가 지원하는 다양한 종류의 임베딩 모델에 대해 더 알아보려면 이 통합 페이지를 참조할 수 있습니다.
LLM 및 오케스트레이션 도구 측면에서 Milvus는 vLLM, Ollama, Gemini, LlamaIndex, Langchain과 같은 인기 프레임워크와 쉽게 통합될 수 있습니다. Milvus와 이러한 모든 도구의 통합에 대해 더 알아보고 싶다면, 이 페이지에서 확인할 수 있는 튜토리얼 모음이 있습니다. 또한 Milvus로 간단한 멀티모달 RAG를 구축하는 방법을 배울 수 있는 간단한 튜토리얼도 이 문서 페이지에 있습니다.
결론
멀티모달 RAG는 LLM 응답의 정확도를 향상시키기 위해 다양한 데이터 모달리티를 활용하는 데 있어 중요한 발전을 의미합니다. 이 글에서는 멀티모달 RAG를 구현하기 위한 세 가지 핵심 패턴을 논의했습니다: 모든 모달리티를 기본 모달리티에 그라운딩하는 것, 이를 통합 벡터 공간에 임베딩하는 것, 또는 원시 데이터 접근을 통한 하이브리드 검색을 사용하는 것입니다. 적합한 패턴의 선택은 AI 애플리케이션의 구체적인 요구 사항에 따라 달라집니다.
고급 인덱싱 방법과 임베딩 모델, LLM 및 오케스트레이션 도구와의 쉬운 통합을 통해 Milvus 벡터 데이터베이스는 멀티모달 RAG 시스템을 구현하는 데 적합한 시스템을 제공합니다. AI 애플리케이션의 범위와 복잡성이 확대됨에 따라 Milvus와 같은 확장 가능한 벡터 데이터베이스 시스템을 활용하는 것이 점점 더 중요해지고 있습니다.
계속 읽기

3 Easiest Ways to Use Claude Code on Your Mobile Phone
Run Claude Code from your phone with Remote Control, Happy Coder, or SSH + Tailscale. Comparison table, setup steps, and tools for typing, memory, and parallel tasks.

How to Improve Retrieval Quality for Japanese Text with Sudachi, Milvus/Zilliz, and AWS Bedrock
Learn how Sudachi normalization and Milvus/Zilliz hybrid search improve Japanese RAG accuracy with BM25 + vector fusion, AWS Bedrock embeddings, and practical code examples.

Introducing DeepSearcher: A Local Open Source Deep Research
In contrast to OpenAI’s Deep Research, this example ran locally, using only open-source models and tools like Milvus and LangChain.


