Multimodal RAG
Multimodal RAG는 텍스트뿐만 아니라 이미지, 오디오, 비디오 등 다양한 모달리티의 데이터를 검색하고 활용하여 답변을 생성하는 RAG 아키텍처입니다. 기존 텍스트 전용 RAG로는 처리할 수 없는 시각적 정보, 도표, 다이어그램 등을 검색 대상에 포함합니다.
핵심 아이디어
실제 문서에는 텍스트만 있는 것이 아닙니다. 기술 문서의 아키텍처 다이어그램, 논문의 실험 결과 그래프, 매뉴얼의 제품 사진 등 텍스트만으로는 전달할 수 없는 정보가 포함되어 있습니다. Multimodal RAG는 이러한 비텍스트 데이터까지 검색하고 활용합니다.
텍스트 RAG의 한계
Multimodal RAG가 해결하는 것
- 이미지에 담긴 정보(다이어그램, 차트, 사진)를 검색할 수 없음
- PDF의 표, 그래프를 텍스트 추출 시 구조가 손실됨
- 동영상, 오디오 콘텐츠를 활용할 수 없음
- 멀티모달 질문(“이 그래프에서 가장 높은 값은?”)에 답변 불가
- 이미지를 직접 임베딩하여 시각적 유사도로 검색
- 비전 LLM으로 이미지 내용을 이해하고 답변에 활용
- 텍스트와 이미지를 동일한 벡터 공간에 매핑하여 크로스모달 검색
- 다양한 모달리티의 정보를 종합하여 정확한 답변 생성
구현 전략
Multimodal RAG를 구현하는 주요 접근법은 세 가지입니다.
전략 1: 멀티모달 임베딩
텍스트와 이미지를 동일한 벡터 공간에 매핑하여, 텍스트 질문으로 이미지를 검색하거나 이미지 질문으로 텍스트를 검색합니다.
대표적인 멀티모달 임베딩 모델:
- CLIP (OpenAI): 텍스트-이미지 공동 임베딩의 기반 모델
- OpenCLIP: CLIP의 오픈소스 구현
- Nomic Embed Vision: 텍스트와 이미지를 통합 임베딩
전략 2: 이미지를 텍스트로 변환
비전 LLM으로 이미지를 텍스트 설명으로 변환한 뒤, 기존 텍스트 RAG 파이프라인에 통합합니다.
- 기존 텍스트 RAG 인프라를 그대로 활용할 수 있는 장점
- 이미지에서 텍스트로 변환 시 시각적 구조 정보 손실 발생 가능
전략 3: 비전 LLM 직접 활용
검색된 이미지를 비전 LLM(GPT-4o, Claude 등)에 직접 전달하여 이미지 내용을 이해하고 답변합니다.
- 이미지의 시각적 정보를 직접 해석하므로 변환 손실이 적음 (모델의 시각 이해 능력에 의존)
- 비전 LLM의 API 비용이 텍스트 전용 대비 높음
전략 비교
| 항목 | 멀티모달 임베딩 | 이미지→텍스트 변환 | 비전 LLM 직접 활용 |
|---|
| 검색 정확도 | 높음 (시각적 유사도) | 보통 (변환 품질 의존) | 높음 |
| 정보 손실 | 적음 (임베딩 차원 제약) | 있음 (변환 시 구조/시각 정보 손실) | 적음 (모델 해석 능력 의존) |
| 인프라 복잡도 | 높음 (멀티모달 DB) | 낮음 (기존 텍스트 DB) | 보통 |
| 비용 | 임베딩 모델 비용 | 변환 LLM 비용 | 비전 LLM API 비용 |
| 지원 모달리티 | 텍스트, 이미지 | 이미지 → 텍스트 | 텍스트, 이미지 |
LangGraph 구현
비전 LLM 직접 활용 방식을 기반으로 구현합니다.
상태 정의
from typing import TypedDict, List
import base64
class MultimodalState(TypedDict):
question: str
text_documents: List[dict]
image_documents: List[dict] # {"path": str, "base64": str, "description": str}
generation: str
노드 함수
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
embeddings = OpenAIEmbeddings()
text_store = Chroma(collection_name="texts", embedding_function=embeddings)
text_retriever = text_store.as_retriever(search_kwargs={"k": 4})
# 이미지 메타데이터에서 관련 이미지 검색 (텍스트 설명 기반)
image_store = Chroma(collection_name="image_descriptions", embedding_function=embeddings)
image_retriever = image_store.as_retriever(search_kwargs={"k": 2})
def retrieve_multimodal(state: MultimodalState) -> MultimodalState:
"""텍스트와 이미지를 동시에 검색합니다."""
question = state["question"]
# 텍스트 검색
text_docs = text_retriever.invoke(question)
text_results = [{"content": doc.page_content, "metadata": doc.metadata} for doc in text_docs]
# 이미지 검색 (텍스트 설명 기반)
image_docs = image_retriever.invoke(question)
image_results = []
for doc in image_docs:
image_path = doc.metadata.get("image_path", "")
if image_path:
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode()
image_results.append({
"path": image_path,
"base64": b64,
"description": doc.page_content,
})
return {"text_documents": text_results, "image_documents": image_results}
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage
vision_llm = init_chat_model("gpt-4o", temperature=0)
def generate_multimodal(state: MultimodalState) -> MultimodalState:
"""텍스트와 이미지를 모두 참고하여 답변을 생성합니다."""
question = state["question"]
text_docs = state["text_documents"]
image_docs = state["image_documents"]
# 텍스트 컨텍스트 구성
text_context = "\n\n".join(doc["content"] for doc in text_docs)
# 메시지 구성 (텍스트 + 이미지)
content = [
{"type": "text", "text": f"컨텍스트:\n{text_context}\n\n질문: {question}"},
]
# 이미지 추가
for img in image_docs:
content.append({
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{img['base64']}"},
})
content.append({
"type": "text",
"text": f"[이미지 설명: {img['description']}]",
})
message = HumanMessage(content=content)
response = vision_llm.invoke([message])
return {"generation": response.content}
그래프 구성
from langgraph.graph import StateGraph, START, END
workflow = StateGraph(MultimodalState)
workflow.add_node("retrieve", retrieve_multimodal)
workflow.add_node("generate", generate_multimodal)
workflow.add_edge(START, "retrieve")
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", END)
app = workflow.compile()
result = app.invoke({"question": "아키텍처 다이어그램에서 데이터 흐름을 설명해주세요"})
print(result["generation"])
비전 LLM(GPT-4o, Claude 등)에 이미지를 전달할 때는 이미지 크기에 따라 토큰 비용이 크게 증가합니다. 이미지를 적절한 해상도로 리사이징하여 비용을 관리하세요.
인덱싱 파이프라인
Multimodal RAG의 인덱싱은 모달리티에 따라 다른 처리가 필요합니다.
문서 파싱
PDF, PPTX, 웹 페이지 등에서 텍스트와 이미지를 분리 추출합니다. unstructured, PyMuPDF 등의 라이브러리를 사용합니다.
이미지 설명 생성
추출된 이미지에 대해 비전 LLM으로 텍스트 설명(캡션)을 생성합니다. 이 설명은 텍스트 기반 검색에 사용됩니다.
임베딩 및 저장
텍스트 청크는 텍스트 임베딩으로, 이미지 설명도 텍스트 임베딩으로 변환하여 벡터 데이터베이스에 저장합니다. 이미지 원본은 별도 스토리지에 보관합니다.
메타데이터 연결
각 임베딩에 원본 파일 경로, 페이지 번호, 이미지 경로 등의 메타데이터를 연결하여 검색 시 원본 데이터에 접근할 수 있게 합니다.
적용 시나리오
아키텍처 다이어그램, 시퀀스 다이어그램, 설정 스크린샷 등이 포함된 기술 문서에서 시각적 정보를 참고한 질의응답을 수행합니다.
X-ray, MRI 등 의료 영상과 판독 보고서를 함께 검색하여, 유사 사례 기반의 진단 보조 정보를 제공합니다.
제품 이미지와 사양 텍스트를 동시에 검색하여, “빨간색 운동화 추천해줘”와 같은 멀티모달 질문에 답변합니다.
강의 슬라이드의 도표, 그래프, 수식 이미지를 검색하여, 시각적 자료를 참고한 학습 질문에 답변합니다.
참고 논문
| 논문 | 학회 | 링크 |
|---|
| Ask in Any Modality: A Comprehensive Survey on Multimodal Retrieval-Augmented Generation (Abootorabi et al., 2025) | - | arXiv 2502.08826 |
| A Survey of Multimodal Retrieval-Augmented Generation (2025) | - | arXiv 2504.08748 |