MiniCPM-o 4.5 한국어 성능도 잘 나올까?

MiniCPM-o 4.5 한국어 성능도 잘 나올까?
MiniCPM-o 4.5는 영어와 중국어에 최적화된 옴니 모델입니다. 그렇다면 한국어는 얼마나 될까요?
동일한 이미지에 한국어와 영어로 같은 질문을 던지고, 출력을 나란히 비교했습니다. 이미지 설명, OCR, 문서 추출, 파인튜닝까지 실제로 돌려본 결과를 정리합니다.
결론부터 말하면: 한국어는 됩니다. 하지만 흥미로운 문제들이 있고, 그 원인은 프롬프트가 아니라 더 깊은 곳에 있습니다.
테스트 환경
시스템 프롬프트는 각 언어별로 다음과 같이 설정했습니다:
system_prompts = {
"ko": "당신은 한국어 전문 어시스턴트입니다. 반드시 한국어로만 답변하세요. 중국어, 영어, 러시아어 등 다른 언어를 섞지 마세요.",
"en": "You are a helpful assistant. Respond only in English.",
}잘 되는 것들
이미지 설명: 에펠탑
파리 에펠탑 사진을 보여주고 "자세히 설명해달라"고 요청했습니다.
한국어 출력(발췌):
이 사진은 프랑스 파리의 상징적인 루즈벨트 광장에 위치한 에펠탑을 보여줍니다. 풍성한 밝은 파란 하늘 아래 에펠탑이 풍경의 중심에 우뚝선 모습을 담고 있습니다. (...) 전경에는 푸른 잔디밭이 넓게 펼쳐져 있으며, 몇몇 사람들이 산책하는 것을 볼 수 있습니다.
영어 출력(발췌):
This is a vibrant, sunlit daytime photograph of the Eiffel Tower in Paris, France. The iconic iron lattice tower stands majestically in the center of the frame, reaching toward a brilliant, deep blue sky streaked with wispy white cirrus clouds and faint contrails from aircraft.
한국어도 상당히 자연스럽습니다. 구조적 설명(아치형 구조, 대칭적 나무 배열), 분위기 묘사(고요하고 아름다운 날씨), 문화적 맥락(프랑스 정원의 전통적 디자인)까지 영어와 대등한 수준으로 다루고 있습니다.
음식 비교 분석: 비빔밥 vs 바베큐
두 장의 음식 사진(한국식 비빔밥, 서양식 바베큐 립)을 동시에 보여주고 공통점과 차이점을 분석하게 했습니다.
한국어 출력은 공통점 3가지, 차이점 5가지를 체계적으로 분류하고, "첫 번째는 아시아식 볶음밥 스타일의 다채로운 요리, 두 번째는 서구식 바베큐 메인 요리"라고 정확히 정리했습니다. 영어와 분석 깊이에서 차이가 없었습니다.
영수증 JSON 추출
한국어 영수증 이미지를 주고 "상호명, 날짜, 품목, 총액을 JSON으로 추출해달라"고 요청했습니다.
{
"상호명": "네이어-김유나-음영가인",
"날짜": "2022-06-17",
"품목목록": [
{"품명": "코코라떼", "수량": 1, "가격": 2500},
{"품명": "리얼하리라떼", "수량": 1, "가격": 2500}
],
"총액": 5000
}품목명, 가격, 총액 모두 정확합니다. 상호명은 약간 부정확하지만, 구조화된 추출 자체는 잘 작동합니다.
여기까지만 보면 "한국어 완벽하네?"라고 생각할 수 있습니다. 하지만 더 까다로운 태스크에서 균열이 보이기 시작합니다.
무너지는 지점들
1. 중국어 토큰 유출 (Chinese Token Leakage)
에펠탑의 역사적 배경을 설명해달라고 했을 때, 한국어 출력에서 이런 부분이 발견됩니다:
하늘에는 얇고 길게 뻗어 있는 **천空痕**(비행기 흔적)이 보이며
몇몇 사람들이 산책하는 것을 볼 수 있습니다. 이는 이 장소가 관광객과 **시민们** 모두가 즐기는 공공 공간임을 암시합니다.
1889년 프랑스-republic(프랑스 공화국)이 옛 **프랑스-republique**(프랑스 왕국) 시대를 기념하기 위해
이 이미지는 한국의 현대적인 상업 문화와 브랜드 정체성을 잘 보여주는 시각적 요약입니다 (**招牌**를 모아놓은 콜라주)
천空痕, 시민们, 招牌 — 한국어 문장 한가운데에 중국어 문자가 끼어듭니다. "반드시 한국어로만 답변하세요"라고 시스템 프롬프트에 명시했는데도 말입니다.
2. 반복 루프 (Repetition Loop)
한국 거리 간판 사진에서 텍스트를 읽어달라고 했을 때:
스킨푸드, SKINFOOD, 파리크라상, PARIS CROISSANT, 이니스프리, TONY MOLY, 토니모리, 올리브영, 아리따움, **에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나, 에나...** (수백 번 반복)
처음 몇 개 간판은 정확히 읽었지만, 어느 순간 "에나"라는 토큰에 빠져서 최대 토큰 길이까지 반복합니다.
같은 이미지를 영어로 요청하면? 완벽하지는 않지만, 반복 루프 없이 다양한 간판명을 읽어냅니다.
3. 언어 혼재 (Code-switching)
한국어로 OCR을 요청했는데 출력의 첫 줄이 이렇습니다:
**Sure Here's** all the text from the image, exactly as it appears:
"반드시 한국어로만"이라고 했는데 영어로 시작합니다. 이후에는 한국어로 전환되지만, 첫 토큰부터 영어 패턴을 따르고 있습니다.
원인 분석: 프롬프트가 아니라 아키텍처다
이 문제들의 원인을 "프롬프트를 잘못 쓴 것"이라고 보기 쉽습니다. 하지만 실제 원인은 더 깊은 곳에 있습니다.
토크나이저의 CJK 공유 공간
MiniCPM-o 4.5의 언어 백본은 Qwen3-8B입니다. Qwen3의 토크나이저는 CJK(Chinese, Japanese, Korean) 유니코드 영역에서 토큰을 공유합니다.
문제는 학습 데이터의 비중입니다. Qwen3의 학습 데이터에서:
- 영어: 약 40-50%
- 중국어: 약 30-40%
- 한국어: 약 2-5% (추정)
"에펠탑의 역사"라는 지식이 모델에 저장될 때, 대부분의 연관 토큰이 중국어/영어 컨텍스트에 묶여 있습니다. 한국어로 생성하라고 해도, 내부적으로 중국어 토큰이 더 높은 확률을 가지는 순간이 생깁니다. "비행기 흔적"을 생성하다가 "天空痕"으로 빠지는 건 이 때문입니다.
시스템 프롬프트는 high-level instruction입니다. "한국어로 답변하라"는 지시는 디코딩 전략에 영향을 주지만, 개별 토큰의 logit 분포를 직접 제어하지는 못합니다.
한국어 토큰의 편향된 확률 분포
반복 루프 문제는 더 근본적입니다. 영어의 경우, 어휘가 풍부하고 학습 데이터도 다양하기 때문에 다음 토큰 예측 시 여러 후보에 확률이 분산됩니다. 하지만 한국어는 학습 데이터가 적어서 소수의 토큰에 확률이 집중되는 경향이 있습니다.
특히 OCR처럼 반복 패턴이 있는 입력에서, 하나의 토큰이 높은 확률을 얻으면 positive feedback loop가 발생합니다. "에나"를 한 번 생성하면 다음 토큰으로 "에나"가 다시 높은 확률을 얻고, 이것이 연쇄적으로 반복됩니다.
repetition_penalty=1.2로 완화할 수 있지만, 한국어에서는 이 값이 충분하지 않을 수 있습니다. 너무 높이면 정상적인 반복(조사, 어미)까지 억제됩니다.
Instruction Following의 영어 편향
"Sure Here's..."로 응답이 시작되는 문제는 Qwen3의 instruction tuning이 주로 영어 데이터로 이루어졌기 때문입니다. 모델의 "응답 시작 패턴"이 영어에 맞춰져 있어서, 한국어 시스템 프롬프트를 줘도 첫 몇 토큰은 영어 패턴을 따르려는 경향이 있습니다.
해결 방법: 3단계 접근
1단계: 즉시 적용 가능한 완화책
# 강화된 시스템 프롬프트
system_prompt = "당신은 한국어 전문 어시스턴트입니다. 반드시 한국어로만 답변하세요. 중국어, 영어, 러시아어 등 다른 언어를 섞지 마세요."
# 디코딩 파라미터 조정
model.chat(
msgs=msgs,
tokenizer=tokenizer,
sampling=True,
temperature=0.7, # 다양성 확보
repetition_penalty=1.2, # 반복 억제
)이것만으로도 대부분의 이미지 설명, 분석 태스크에서 쓸만한 한국어 출력을 얻을 수 있습니다. 하지만 OCR이나 긴 생성에서는 여전히 문제가 발생합니다.
2단계: LoRA 파인튜닝 (반나절)
NCSOFT의 K-DTCBench 데이터셋(한국어 문서/표/차트 VQA, 240샘플)으로 LoRA 파인튜닝을 시도했습니다.
from peft import LoraConfig, get_peft_model, TaskType
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
task_type=TaskType.CAUSAL_LM,
)
peft_model = get_peft_model(model.llm, lora_config)
# trainable params: 7,667,712 (0.09%)240샘플, 3에폭만으로도 loss가 71% 감소했습니다. 한국어 도메인 데이터가 모델의 한국어 토큰 분포를 빠르게 교정한다는 의미입니다.
프로덕션 적용 시에는 수천~수만 샘플의 도메인 특화 데이터(의료 문서, 법률 텍스트, 한국어 간판 등)로 파인튜닝하면 중국어 유출과 반복 루프를 크게 줄일 수 있습니다.
3단계: 본격 한국어 파이프라인 구축
음성까지 포함한 완전한 한국어 서비스를 만들려면:
- 한국어 ASR: 파인튜닝된 한국어 Whisper (CER ~3% 달성 가능)
- 텍스트+비전: MiniCPM-o (한국어 LoRA 적용)
- 한국어 TTS: CosyVoice2 (한국어 공식 지원)
이 세 컴포넌트를 조합하면, MiniCPM-o의 옴니 파이프라인을 우회하면서도 한국어 음성 대화 시스템을 구축할 수 있습니다.
결론
MiniCPM-o 4.5의 한국어 성능을 정리하면:
중국어 토큰 유출, 반복 루프, 언어 혼재는 프롬프트 엔지니어링으로 해결할 수 없습니다. 학습 데이터 비중과 토크나이저 구조에서 오는 문제입니다. 오픈소스이기 때문에 직접 원인을 분석하고 LoRA로 교정할 수 있고, 240샘플만으로도 loss가 71% 감소합니다.
관련 링크
- 원본 소개글: 온디바이스 GPT-4o의 등장? MiniCPM-o 4.5 완벽 분석
- 실습 노트북: Can MiniCPM-o 4.5 Handle Korean?
- MiniCPM-o: GitHub | HuggingFace
- K-DTCBench: NCSOFT/K-DTCBench
- Qwen3: Qwen/Qwen3-8B