LLM 엔지니어링12장 · 멀티모달 RAG 와 데이터셋 자동 생성3 / 22← 이전목차다음 →MetaContents

12장. 멀티모달 RAG 와 데이터셋 자동 생성

멀티모달이란

가구점 카탈로그를 넘기면 사진 한 장, 소개 글 한 줄, 치수와 값이 적힌 표가 함께 나옵니다. 사진만 있으면 값을 모르고, 표만 있으면 어떻게 생겼는지 모릅니다. 사람이 정보를 찾는 자료는 대개 여러 종류가 섞여 있습니다. 이렇게 종류가 다른 자료를 함께 다루는 것이 멀티모달입니다.

글, 그림, 표의 세 가지 자료와 각각을 컴퓨터가 읽는 방법을 견준 세 카드

세 카드는 이 장에서 다루는 자료의 종류입니다. 글은 지금까지처럼 임베딩으로 찾고, 그림은 그림 임베딩으로 찾거나 설명 글로 바꾸고, 표는 행마다 문장으로 바꿔 글처럼 다룹니다. 여기서 카탈로그의 사진, 소개 글, 표가 각각 그림, 글, 표 모달리티입니다.

자료마다 어려운 점

자료그대로 쓰면이 장에서 하는 일
글글 임베딩으로 찾는다(7장)그대로 쓴다
그림글 임베딩으로는 찾을 수 없다. 그림에만 있는 정보(색, 모양)가 있다CLIP 임베딩으로 찾거나, 비전 모델로 설명 글을 만든다
표칸이 흩어지면 무엇의 값인지 잃는다행마다 "이름, 가격 9,900원, 용량 350ml" 같은 문장으로 바꾼다

안내서에 든 것 세어 보기

실습에 쓰는 상품 안내서(product_guide.md)에는 그림 줄과 표 줄이 섞여 있습니다.

Python
from pathlib import Path

lines = Path("product_guide.md").read_text(encoding="utf-8").split("\n")

# 그림 줄(![...](...)), 표 줄(| 로 시작), 나머지 글 줄을 센다
images = [l for l in lines if l.startswith("![")]
tables = [l for l in lines if l.startswith("|")]
texts = [l for l in lines if l.strip() and not l.startswith(("![", "|", "#"))]
print("그림", len(images), "· 표 줄", len(tables), "· 글 줄", len(texts))
print(images[0])

코드에 나오는 함수

코드쉬운 뜻
Path("product_guide.md")pathlib(path library, 경로 도구)의 Path 다. 파일 이름을 경로 객체로 만든다
.read_text(encoding="utf-8")파일 전체를 글 하나로 읽는다. encoding(부호화)은 글자를 바이트로 바꾸는 방식이고, utf-8 은 한글도 담는 표준 방식이다
.split("\n")줄바꿈 글자(\n, new line)마다 잘라 줄의 목록으로 만든다
l.startswith("![")줄이 ![ 로 시작하면 True 다. 마크다운에서 그림 줄은 이렇게 시작한다
startswith(( ... ))시작 글자 여러 개를 튜플로 묶어 주면, 그 가운데 하나로만 시작해도 True 다
l.strip()줄의 앞뒤 빈칸을 지운다. 빈 줄은 빈 글이 되어 거짓으로 친다

이 코드가 뜻하는 것

우체국에서 우편물을 봉투 생김새만 보고 편지 상자, 소포 상자, 나머지 상자로 나누는 일과 같습니다. 여기서 우편물 한 통이 안내서의 줄 하나이고, 봉투 생김새가 줄의 첫 글자입니다. 다만 사람과 달리 이 코드는 첫 글자만 보므로, 글 줄이 우연히 세로 막대로 시작하면 표 줄로 잘못 셉니다.

줄하는 일쉽게 말하면
lines = ...split("\n")안내서를 줄의 목록으로 만든다우편물 더미를 한 통씩 펼친다
images = [...]![ 로 시작하는 줄만 모은다그림 상자
tables = [...]세로 막대로 시작하는 줄만 모은다표 상자
texts = [...]비어 있지 않고, 그림·표·제목(#)도 아닌 줄을 모은다나머지 글 상자
print(images[0])첫 그림 줄을 보인다그림 상자의 맨 위 한 통

이 PC 에서 실행하면 그림 24 · 표 줄 40 · 글 줄 9 와 ![데일리 머그 1호](products/P01.png) 가 나옵니다. 표 줄 40 은 상품 행만이 아니라 표의 머리글 줄과 구분 줄(---)까지 센 수입니다.

작게 줄여서 눈으로 보기

설명을 위해 지어낸 여섯 줄로 세 가지 검사가 줄마다 무엇을 돌려주는지 봅니다.

Python
lines = ["# 머그컵", "![머그 1호](P01.png)", "| 이름 | 가격 |", "| 머그 1호 | 9,900원 |", "", "모든 머그는 식기세척기에 넣을 수 있습니다."]

print([l.startswith("![") for l in lines])
print([l.startswith(("![", "|", "#")) for l in lines])
print([bool(l.strip()) for l in lines])
출력
[False, True, False, False, False, False]
[True, True, True, True, False, False]
[True, True, True, True, False, True]
결과읽는 법
첫 줄둘째 줄(그림)만 ![ 로 시작한다
둘째 줄제목, 그림, 표 머리글, 표 행의 네 줄이 묶음 가운데 하나로 시작한다. 이 넷은 글 줄에서 빠진다
셋째 줄다섯째의 빈 줄만 False 다. 빈 줄을 글 줄로 세지 않는 까닭이다

두 검사를 함께 보면 글 줄로 남는 것은 여섯째 줄 하나입니다. 원래 코드의 texts 가 고르는 방법이 이것입니다.

주의할 점

  • 안내서의 그림 대체 글은 "데일리 머그 1호"처럼 상품 이름뿐입니다. 색은 그림에만 있습니다. 그래서 "빨간 머그컵"을 글만으로 찾으면 1~3호 가운데 하나를 짐작하게 됩니다(실습 4).
  • 실습의 그림은 단순한 그림이라 실제 상품 사진보다 알아보기 쉽습니다. 실제 사진은 배경, 조명, 각도가 섞여 결과가 더 흔들립니다.
← 이전 절12장 · 용어 짚고 가기다음 절 →12장 · 멀티모달 임베딩