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

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

실습 3 — 비전 모델로 그림 설명 만들기

이 PC 의 Ollama 에서 비전 언어 모델 qwen2.5vl:3b 로 상품 그림 24장의 설명 글을 만들고 out_captions.csv 로 저장합니다. 미리 ollama pull qwen2.5vl:3b 로 모델(3.2GB)을 받아 두어야 합니다. 이 PC 에서는 그림 한 장에 20초쯤, 모두 몇 분이 걸립니다.

1단계. 그림 한 장 물어보기

Python
import base64, json, time, urllib.request
import pandas as pd

labels = pd.read_csv("product_labels.csv")
PROMPT = "이 그림 속 물건이 무엇이고 무슨 색인지 한국어 한 문장으로 설명하세요."


def describe(path):
    """그림을 base64 로 바꿔 Ollama 의 /api/chat 에 보내고 설명 글을 받는다"""
    b64 = base64.b64encode(open(path, "rb").read()).decode()
    body = {"model": "qwen2.5vl:3b", "stream": False, "options": {"temperature": 0, "seed": 42},
            "messages": [{"role": "user", "content": PROMPT, "images": [b64]}]}
    req = urllib.request.Request("http://localhost:11434/api/chat", data=json.dumps(body).encode(),
                                 headers={"Content-Type": "application/json"})
    return json.loads(urllib.request.urlopen(req).read())["message"]["content"].strip()


t = time.time()
print(labels.loc[0, "파일"], "→", describe(labels.loc[0, "파일"]), f"({time.time() - t:.0f}초, 모델을 올리는 시간 포함)")
출력
products/P01.png → 그림 속 물건은 컵으로, 노란색입니다. (32초, 모델을 올리는 시간 포함)

2단계. 24장 모두 설명하고 저장하기

Python
t = time.time()
labels["설명"] = [describe(f) for f in labels["파일"]]
print(f"24장: {time.time() - t:.0f}초 · 한 장에 {(time.time() - t) / 24:.1f}초")
labels[["코드", "파일", "설명"]].to_csv("out_captions.csv", index=False, encoding="utf-8-sig")
for _, r in labels.head(6).iterrows():
    print(f"  {r['코드']} {r['이름']}: {r['설명']}")
출력
24장: 487초 · 한 장에 20.3초
  P01 데일리 머그 1호: 그림 속 물건은 컵으로, 노란색입니다.
  P02 데일리 머그 2호: 그림 속 물건은 컵으로, 빨간색입니다.
  P03 데일리 머그 3호: 그림 속 물건은 컵입니다. 컵은 파란색입니다.
  P04 산책 우산 1호: 그림 속 물건은 우산입니다. 그 색상은 빨간색입니다.
  P05 산책 우산 2호: 그림 속 물건은 파란색의 우산입니다.
  P06 산책 우산 3호: 그림 속 물건은 노란색의 우산입니다.

3단계. 설명이 종류와 색을 말했는지 세기

Python
# 정답 종류와 색을 가리키는 낱말들. 설명에 하나라도 있으면 맞힌 것으로 센다
KIND_WORDS = {"머그컵": ["컵", "머그"], "우산": ["우산"], "운동화": ["신발", "운동화", "스니커"], "배낭": ["가방", "배낭", "백팩"],
              "티셔츠": ["티셔츠", "셔츠"], "모자": ["모자", "캡"], "스탠드 조명": ["램프", "조명", "스탠드"],
              "화분": ["화분", "식물", "꽃"]}
COLOR_WORDS = {"빨강": ["빨간", "빨강", "붉은", "레드"], "파랑": ["파란", "파랑", "푸른", "블루"], "노랑": ["노란", "노랑", "옐로"]}
labels["종류 말함"] = [any(w in d for w in KIND_WORDS[k]) for d, k in zip(labels["설명"], labels["종류"])]
labels["색 말함"] = [any(w in d for w in COLOR_WORDS[c]) for d, c in zip(labels["설명"], labels["색"])]
print("종류를 말한 설명:", labels["종류 말함"].sum(), "/ 24 · 색을 말한 설명:", labels["색 말함"].sum(), "/ 24")
miss = labels[~(labels["종류 말함"] & labels["색 말함"])]
for _, r in miss.iterrows():
    print(f"  {r['색']} {r['종류']}: {r['설명']}")
출력
종류를 말한 설명: 23 / 24 · 색을 말한 설명: 24 / 24
  노랑 운동화: 그림 속 물건은 노란색의 스포츠화입니다.

이 실습이 뜻하는 것

이 실습은 그림을 보고 말로 풀어 주는 해설사에게 상품 사진을 한 장씩 보여 주는 일과 같습니다. 사진 한 장을 보여 주며 "무엇이고 무슨 색인지 한 문장으로" 물어보고(1단계), 24장을 모두 물어 답을 공책에 적어 둔 뒤(2단계), 답마다 종류와 색을 말했는지 낱말로 셉니다(3단계). 여기서 해설사가 비전 언어 모델 qwen2.5vl:3b, 사진을 보여 주는 일이 그림을 base64 글자로 바꿔 보내는 것, 공책이 out_captions.csv 입니다. 비유와 다른 점은, 3단계 채점이 낱말 목록에 있는 말만 알아보므로 해설사가 맞는 말을 다른 낱말로 하면 못 맞힌 것으로 센다는 것입니다.

단계출력뜻
1. 한 장그림 속 물건은 컵으로, 노란색입니다. (32초, …)첫 그림(노란 머그컵)을 "노란 컵"으로 바르게 말했습니다. 32초에는 모델을 GPU(Graphics Processing Unit, 그래픽 처리 장치)에 올리는 시간이 들어 있습니다
2. 24장24장: 487초 · 한 장에 20.3초24장 설명에 8분쯤 걸렸습니다. 그래서 한 번 만들어 저장해 두고 실습 4가 읽습니다
2. 설명 예P05 산책 우산 2호: 그림 속 물건은 파란색의 우산입니다.상품 이름에는 색이 없지만, 설명 글에는 그림에서 본 색이 들어갑니다
3. 세기종류를 말한 설명: 23 / 24 · 색을 말한 설명: 24 / 24설명 24개가 모두 색을 말했고, 23개가 종류를 목록에 있는 낱말로 말했습니다
3. 걸린 것노랑 운동화: 그림 속 물건은 노란색의 스포츠화입니다.남은 하나는 운동화를 "스포츠화"라고 한 것입니다. 틀린 답이라기보다 낱말 목록에 없던 말입니다

한 줄로 줄이면, 비전 모델이 그림 24장을 "무엇이고 무슨 색인지"를 담은 한국어 문장으로 바꿔 주었다는 실습입니다. 이 문장을 안내서의 표에 붙여 글로 찾는 것이 실습 4입니다. 걸린 시간은 이 PC(4GB GPU)에서 잰 것이라 다른 PC 에서는 다르고, 낱말이 들어 있는지만 센 채점이라 설명이 얼마나 자세하고 정확한지는 눈으로 함께 봐야 합니다.

코드 설명

  • describe() 는 그림 파일을 base64 글자로 바꿔 메시지의 images 에 넣고 Ollama 고유 주소(/api/chat)로 보냅니다. temperature 0 과 seed 로 다시 돌려도 같은 설명이 나오게 했습니다.
  • 첫 그림은 모델을 올리는 시간까지 32초, 24장은 487초(한 장에 20.3초)가 걸렸습니다. 4GB GPU 에 3.2GB 모델이 다 올라가지 않아 일부를 CPU 에서 돌렸기 때문입니다. 그래서 설명은 한 번 만들어 out_captions.csv 로 저장해 두고 실습 4가 읽습니다.
  • 설명 24개 모두 색을 말했고("노란색입니다"), 23개가 종류를 말했습니다. 머그컵은 "컵", 배낭은 "가방", 스탠드 조명은 "램프"처럼 다른 낱말로 말한 것이 많아, 낱말 목록을 넉넉히 두고 셌습니다.
  • 종류를 못 맞힌 하나는 노란 운동화를 "스포츠화"라고 한 것으로, 틀렸다기보다 우리 낱말 목록에 없던 말입니다. 설명 글로 찾을 때는 이런 다른 이름도 검색이 받아 주는지가 관건입니다(실습 4).
← 이전 절12장 · 실습 2 — 그림으로 찾고 이름 붙이기다음 절 →12장 · 실습 4 — 그림과 표가 섞인 안내서로 답하기