Day 11: 멀티모달 모델
멀티모달(Multimodal) 모델은 텍스트뿐만 아니라 이미지, 음성, 영상 등 여러 형태의 입력을 동시에 처리합니다. 2024년 이후 대부분의 최신 LLM은 멀티모달을 지원합니다.
멀티모달 모델 비교 (모델군 기준)
| 모델군 | 입력 | 출력 | 특징 |
|---|---|---|---|
| OpenAI 멀티모달 계열 | 텍스트+이미지(+음성) | 텍스트(+음성) | 범용 API, 생태계 풍부 |
| Claude 멀티모달 계열 | 텍스트+이미지 | 텍스트 | 문서/차트 해석에 강점 |
| Gemini 멀티모달 계열 | 텍스트+이미지(+영상) | 텍스트 | 긴 컨텍스트/영상 활용 |
| LLaVA/Qwen-VL 계열 | 텍스트+이미지 | 텍스트 | 오픈소스, 로컬 실행 용이 |
버전/모델 ID는 자주 변경되므로 사용 전에 각 제공사의 모델 목록 문서를 먼저 확인하세요.
OpenAI Vision API (Chat Completions 호환 예시)
from openai import OpenAI
import base64
client = OpenAI()
# 방법 1: URL로 이미지 전달
response = client.chat.completions.create(
model="gpt-4o", # 프로젝트에서 사용 가능한 최신 멀티모달 모델로 교체 가능
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 이미지에 무엇이 보이나요? 한국어로 설명해주세요."},
{
"type": "image_url",
"image_url": {"url": "https://example.com/sample.jpg"},
},
],
}
],
max_tokens=500,
)
print(response.choices[0].message.content)
# 방법 2: 로컬 이미지를 base64로 전달
def encode_image(image_path):
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
image_base64 = encode_image("screenshot.png")
response = client.chat.completions.create(
model="gpt-4o", # 프로젝트에서 사용 가능한 최신 멀티모달 모델로 교체 가능
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 스크린샷의 에러를 분석해주세요."},
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_base64}"},
},
],
}
],
)
print(response.choices[0].message.content)
Claude Vision API
import anthropic
import base64
client = anthropic.Anthropic()
def encode_image(path):
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
image_data = encode_image("chart.png")
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data,
},
},
{
"type": "text",
"text": "이 차트의 데이터를 분석하고 주요 트렌드를 설명해주세요.",
},
],
}
],
)
print(message.content[0].text)
LLaVA 로컬 실행 (오픈소스)
# Ollama로 LLaVA 실행 (로컬, 무료)
# ollama pull llava:13b
import ollama
response = ollama.chat(
model="llava:13b",
messages=[
{
"role": "user",
"content": "이 이미지를 설명해주세요.",
"images": ["./photo.jpg"], # 로컬 이미지 경로
}
],
)
print(response["message"]["content"])
# 여러 이미지 비교도 가능
response = ollama.chat(
model="llava:13b",
messages=[
{
"role": "user",
"content": "두 이미지의 차이점을 찾아주세요.",
"images": ["./before.jpg", "./after.jpg"],
}
],
)
print(response["message"]["content"])
멀티모달 활용 사례
| 활용 분야 | 설명 | 적합한 모델 |
|---|---|---|
| 문서 OCR + 분석 | 스캔된 문서를 읽고 내용 요약 | OpenAI/Claude/Gemini 멀티모달 |
| 코드 스크린샷 디버깅 | 에러 화면을 보고 원인 분석 | OpenAI/Claude 멀티모달 |
| 차트/그래프 해석 | 시각화된 데이터를 텍스트로 설명 | Claude/Gemini 멀티모달 |
| 제품 이미지 분류 | 상품 사진을 카테고리별 분류 | LLaVA (로컬, 비용 절감) |
| UI/UX 리뷰 | 앱 스크린샷을 분석하여 개선점 제안 | OpenAI/Claude/Gemini 멀티모달 |
| 의료 영상 보조 | X-ray, CT 이미지 1차 분석 | 전문 모델 필요 |
멀티모달 모델의 핵심은 이미지를 “이해”하는 것이 아니라, 이미지를 토큰 시퀀스로 변환하여 텍스트와 함께 처리한다는 점입니다. 이미지 인코더(보통 ViT 기반)가 이미지를 벡터로 변환하고, 이를 언어 모델의 입력과 합칩니다.
오늘의 연습문제
- 상용 멀티모달 API 하나(OpenAI/Claude/Gemini 중 선택)로 본인의 스크린샷을 분석해보세요. 텍스트 인식, 레이아웃 이해, 의미 파악 중 어떤 것을 가장 잘 하나요?
- LLaVA를 Ollama로 로컬에서 실행하고, 상용 멀티모달 API와 같은 이미지에 대한 응답 품질을 비교해보세요.
- 멀티모달 모델에서 이미지 해상도와 토큰 수의 관계를 조사해보세요. 고해상도 이미지를 보내면 비용이 얼마나 증가하나요?