RSS

멀티모달 RAG의 현실: 모달을 섞지 않고 텍스트로 환원하는 이유

멀티모달 RAG라는 말을 처음 들었을 때, 이미지를 임베딩해서 문서 텍스트와 같은 벡터 공간에 올리는 걸 상상했습니다. CLIP 같은 모델로 그림과 글을 하나의 공간에 두면, "이런 느낌의 다이어그램 찾아줘" 같은 질문도 답이 나올 것 같았죠.

그런데 막상 시스템을 짜고 보니, 제가 실제로 쓰는 멀티모달은 전혀 다른 모양이었습니다. 이미지를 벡터로 올리지 않습니다. 이미지를 먼저 텍스트로 환원하고, 그 텍스트를 기존 텍스트 RAG에 넣습니다. 이 글은 왜 그렇게 됐는지를 적은 겁니다.

RAG는 왜 텍스트뿐인가

지금 색인 테이블(doc_chunk)을 보면 content 컬럼이 text입니다. 임베딩 벡터는 별도 컬럼에 들어있고, 그 벡터를 만든 입력은 텍스트뿐입니다. 이미지, 오디오, 표의 시각적 구조는 어디에도 직접 들어가지 않습니다.

이건 게으름이 아니라 임베딩 모델의 한계입니다. 제가 쓰는 bge-m3는 텍스트 전용입니다. 이미지를 넣을 수도 없고, 넣더라도 의미가 없습니다. 멀티모달 임베딩 모델을 따로 두면 되지만, 그러면 차원이 다른 벡터가 두 종류 생겨서 검색 시점에 어떤 공간에서 찾을지 매번 결정해야 합니다. 혼자 쓰는 시스템에 그 복잡도는 과했습니다.

그래서 택한 길은, 이미지가 섞인 데이터를 다룰 때 비전 모델로 먼저 텍스트를 뽑아내고, 그 텍스트만 색인에 넣는 것입니다. 모달을 섞지 않고 하나의 모달(텍스트)로 환원합니다.

비전 모델로 모달을 텍스트로 환원하기

이 패턴은 원래 리드 추출에서 먼저 썼습니다. 영업 리드를 입력할 때 명함 이미지나 홈페이지 스크린샷을 올리면, 비전 모델이 그 이미지에서 글자를 읽어 회사명, 담당자, 전화번호, 주소 같은 정형 필드로 쪼개 줍니다.

여기서 중요한 건 프롬프트의 태도입니다. 모델에게 "이미지에서 실제로 보이는 글자를 위에서 아래 순서로 줄바꿈해 그대로 옮긴다. 요약하거나 주소를 검색·보완·황하지 않는다"고 시킵니다. 보이는 것만 쓰고, 보이지 않으면 빈 문자열로 둡니다.

이 원칙이 RAG로 그대로 옮겨갑니다. 이미지가 든 문서를 색인할 때, 비전 모델로 그 이미지의 텍스트를 먼저 뽑습니다. 다이어그램이면 그 안의 라벨과 화살표 설명을 텍스트로 풀고, 표가 찍힌 이미지면 행과 열을 텍스트 표로 옮깁니다. 그런 다음 그 텍스트를 문서 본문에 이어 붙이고, 통째로 텍스트 RAG에 넣습니다.

즉 멀티모달 RAG가 아니라, 텍스트를 뽑아내는 전처리 단계에서 비전 모델을 쓰는 겁니다. 뽑히고 나면 뒤는 전부 텍스트 RAG와 같습니다.

표는 어떻게 색인에 들어가나

마크다운 표는 애초에 텍스트입니다. 그래서 비전 모델을 거칠 필요 없이 그대로 색인에 들어갑니다. 다만 자를 때 주의가 필요합니다. 표를 청크 경계로 쪼개면 한 행만 떨어져 나가서 의미가 사라집니다.

그래서 청킹 코드는 코드 펜스()로 감싼 블록을 하나로 묶어 보존합니다. 표시가 나오면 닫힐 때까지 한 블록으로 취급하고, 그 안에서는 제목 변화나 빈 줄로 자르지 않습니다. 표를 코드 블록으로 감싸두면 청크가 쪼개지는 일을 막을 수 있습니다.

다만 이건 표가 마크다운 텍스트로 있을 때의 이야기입니다. 표가 이미지(스캔 PDF, 스크린샷)로 들어있으면, 비전 모델로 먼저 텍스트 표로 바꿔야 합니다. 이 단계가 빠지면 이미지 속 표는 검색에 한 번도 걸리지 않습니다. 이걸 몰랐을 때, 스캔해둔 영수증 이미지가 색인엔 들어있는데 절대 검색이 안 되는 일이 있었습니다. 텍스트가 없으니 임베딩이 빈 것과 같았죠.

모달을 섞지 않는 이유

멀티모달 임베딩을 안 쓰는 결정적인 이유는 단순함입니다. 텍스트 하나만 다루면 임베딩 모델도 하나, 벡터 차원도 하나, 검색 경로도 하나입니다. 이미지 벡터를 추가하면 이 셋이 전부 둘이 됩니다. 혼자 쓰는 시스템에서 그 비용을 감당할 만큼, 이미지를 그대로 벡터로 올려야만 답이 되는 질문이 많지 않았습니다.

실제로 제가 묻는 질문을 돌아보면, "이런 느낌의 이미지 찾아줘" 같은 시각적 유사도 질문은 거의 없었습니다. 대부분 "명함에 적힌 이름이 뭐였지", "다이어그램에서 이 라벨이 어디 붙었지" 같은, 결국 텍스트로 답이 되는 질문이었습니다. 그런 질문에는 텍스트 환원이 더 정확합니다. 비전 모델이 라벨을 정확히 읽어내면, 그 텍스트는 키워드 검색에도, 벡터 검색에도 다 잡힙니다.

물론 단점도 있습니다. 비전 모델이 이미지의 시각적 뉘앙스(색, 배치, 분위기)를 버린다는 겁니다. 제품 사진의 색상이 중요한 카탈로그라면 텍스트 환원만으로는 부족합니다. 하지만 제 데이터에서 그런 시각적 뉘앙스가 검색의 핵심인 경우는 거의 없었습니다. 손해보다 단순함이 더 컸습니다.

남은 문제

지금은 이미지를 올리는 시점에 비전 모델을 한 번 돌려 텍스트를 뽑아 저장합니다. 즉 "전처리 환원" 방식입니다. 이미지가 바뀌면 텍스트도 다시 뽑아야 하고, 비전 모델을 바꾸면 과거 이미지의 텍스트는 옛 모델 결과로 남습니다.

나중에 이미지를 그대로 색인에 두고, 검색 시점에 비전 모델을 실시간으로 돌리는 구조도 생각해볼 수 있습니다. 하지만 그러면 질문 한 번에 비전 모델이 매번 돌아가서 느려집니다. 혼자 쓰는 시스템에서 전처리 한 번으로 끝내는 쪽이, 검색마다 비전 모델을 부르는 것보다 훨씬 쌉니다.

멀티모달 RAG를 "여러 모달을 섞는 기술"로만 보면, 혼자 쓰기엔 너무 무거운 걸 떠맡게 됩니다. 하지만 "모달을 텍스트로 환원한 뒤 텍스트 RAG에 넣는 전략"으로 보면, 오늘 당장 쓸 수 있고 이미 리드 추출에서 검증된 패턴입니다. 화려하지는 않지만, 답이 정확하고 운영이 단순합니다. 저한테는 그쪽이 맞았습니다.