11 minute read

HCX·Qwen·MiniCPM 56샘플 × 4 variants 분류 본 배치 완료. RQ3 부분 신호(MiniCPM emotion 운율), HCX 디폴트-답 함정, parse_category 1글자 카테고리 위험까지.


한 줄

비교 모델 3종 본 배치 끝났고, 가설(audio in > text in)에 가장 또렷한 신호는 MiniCPM의 emotion 운율(46.4%, text +9%p). 다만 HCX는 image/audio에서 “중립” 디폴트 답변으로 패턴이 가짜 동률, parse_category가 1글자 카테고리(정/한)에 over-match 가능성 — 결과 신뢰도 검증 필요. 핵심 검증 모델 Kanana는 미진행.


결과 매트릭스

56샘플(기쁨 10·슬픔 10·분노 10·중립 10·정 8·한 8). 4 variants(text-bare / image-bare / audio-neutral / audio-emotion).

모델 text image audio_neutral audio_emotion
HCX-SEED-Omni 8B (한국어 특화) 33.9% 17.9% 17.9% 17.9%
Qwen2.5-Omni 7B 37.5% 30.4% 32.1% 33.9%
MiniCPM-o 2.6 8B 37.5% 21.4% 37.5% 46.4%
Kanana-1.5-o 11.6B (한국어 특화) (미진행)

※ 위 표는 parse_category 우선순위 매칭(아래 “parse 검증 후 정정”)을 거친 최종 수치. 초기 substring 매칭 기준 Qwen은 text 42.9%였음.

MiniCPM만 audio_emotion이 text 능가. 그러나 모델별 패턴 차이가 더 흥미로워서 한 줄 요약으로 안 끝남 — 카테고리별 분해해야 보임.


HCX: image/audio 디폴트-답 함정

variant 기쁨 슬픔 분노 중립
text-bare 1/10 0/10 4/10 0/10 6/8 8/8
image-bare 0/10 0/10 0/10 10/10 0/8 0/8
audio-neutral 0/10 0/10 0/10 10/10 0/8 0/8
audio-emotion 0/10 0/10 0/10 10/10 0/8 0/8

image·audio 모든 변형에서 56/56이 모두 중립으로 답함 — 즉 분류 능력 상실, 디폴트 답으로 도망. text는 한(8/8), 정(6/8) 비례를 보면 1글자 카테고리에 강하게 끌림 (parsed 분포: “한” 36회, “정” 12회). 사실상 한·정 위주의 over-match로 33.9% 정답률을 만들었음 — 진짜 분류 능력이라기보다 substring 매칭의 구조적 산물에 가까움 (아래 “parse_category 함정” 참조).

→ HCX는 본 task에서 사실상 실패. classify에선 안 쓸 모델로 분류해야 할 가능성. 응답 task 결과 보기 전엔 단정 보류.


MiniCPM: 운율이 분류에 기여 — H3 가장 또렷한 신호

variant 기쁨 슬픔 분노 중립
text-bare 6/10 2/10 8/10 2/10 3/8 0/8
image-bare 2/10 0/10 3/10 6/10 1/8 0/8
audio-neutral 4/10 5/10 6/10 3/10 3/8 0/8
audio-emotion 6/10 6/10 7/10 4/10 3/8 0/8

audio_emotion vs text 비교: 기쁨 6=6, 슬픔 2→6 (+4), 분노 8→7 (-1), 중립 2→4 (+2), 정 3=3, 한 0=0.

audio_neutral과 audio_emotion 차이: 기쁨 4→6 (+2), 슬픔 5→6 (+1), 분노 6→7 (+1), 중립 3→4 (+1) — 운율(emotion)이 거의 모든 카테고리에서 +1~2 보탬.

prosody-only signal(audio_neutral → audio_emotion 차이)이 분류에 실질적으로 기여. MiniCPM은 H3 정직한 후보. 슬픔 분류는 text(2/10)에서 audio_emotion(6/10)으로 3배가 됨 — 운율로 슬픔을 잡음.

text 응답엔 None(6개) 끼어있음 — parse_category가 매칭 실패한 케이스. 모델이 카테고리 단어를 안 쓰고 풀어 답했을 가능성. 본 결과 정답률은 paserd 50/56 기준.


Qwen: 평탄한 modality 갭

variant 기쁨 슬픔 분노 중립
text-bare 5/10 3/10 9/10 4/10 3/8 0/8
image-bare 3/10 3/10 6/10 5/10 2/8 0/8
audio-neutral 5/10 4/10 6/10 3/10 2/8 0/8
audio-emotion 6/10 6/10 6/10 0/10 3/8 0/8

text 42.9% > audio_emotion 37.5% — text 우위지만 갭 5%p로 좁음. emotion에서 슬픔 +3 향상되지만 중립이 0/10으로 망함 — 운율 강조가 “중립” 같은 비특정 감정 분류를 오히려 방해. trade-off가 있음.

→ Qwen은 modality gap이 좁고, 운율이 카테고리에 따라 도움/방해 양면. RQ3 지지하는 정도가 모호.


두 점수: Parsed (단답·지시 준수) / Extracted (추출·내용 매칭)

분류 정답률을 두 기준으로 분리해 본다.

  • Parsed (단답): 응답 전체 또는 첫 비어있지 않은 줄이 카테고리 단어와 정확히 일치할 때만 정답. 모델이 단답 지시를 그대로 따른 경우만 인정.
  • Extracted (추출): Parsed 조건 + 본문에서 라벨이 식별 가능한 경우(우선순위 매칭). 사람이 응답 전체를 보고 “정답으로 인정 가능”하다고 판단할 모든 경우.

두 점수 차이의 해석:

  • Parsed = Extracted: 모델이 단답 지시를 잘 따르거나, 따르지 않아도 그 응답은 답이 안 맞음
  • Parsed < Extracted: “분류 능력은 있는데 지시 이행은 약함” — 풀어 답해도 의미상 정답을 적은 케이스
  • Extracted ≥ Parsed 항상 성립 (Extracted가 Parsed의 superset)

점수표

모델 text Parsed / Extracted image audio_neutral audio_emotion
HCX 33.9 / 33.9 17.9 / 17.9 17.9 / 17.9 17.9 / 17.9
MiniCPM 37.5 / 37.5 19.6 / 21.4 (+1) 37.5 / 37.5 46.4 / 46.4
Qwen 37.5 / 37.5 30.4 / 30.4 32.1 / 32.1 33.9 / 33.9

Δ가 거의 0. 의미: 단답으로 답하지 않은 응답들이 대체로 답까지 틀렸다. 단답 따른 응답이 분류도 잘했다는 신호. Qwen에서 특히 또렷 — 단답 안 따른 케이스가 audio variants에 4~5개씩 있는데 그 중 정답에 기여한 건 0건.

응답 예시

HCX 기쁨-001 (truth=기쁨, Parsed=기쁨, Extracted=기쁨)
  "기쁨\nassistant\n\n\n\n\n기쁨\nassistant\n\n\n\n\n..."
  → 첫 줄이 정확히 카테고리. assistant 토큰 새는 건 stop token 안 잡혀
    max_new_tokens 채운 결과, 응답 task 갈 때 후처리 필요

MiniCPM 기쁨-001 (truth=기쁨, Parsed=기쁨, Extracted=기쁨)
  "기쁨"
  → 깔끔한 단답

Qwen 정-001 (truth=정, Parsed=None, Extracted=기쁨, 정답 X)
  "감정은 기쁨입니다."
  → 단답 지시 안 따름. 추출은 "기쁨"으로 해석 (모델이 진짜 그렇게 답함, truth는 정).
    옛 substring 매칭은 "감*정*"의 정을 잘못 잡아 정답 처리한 함정 — 새 추출에서 정정.

MiniCPM 기쁨-009 (truth=기쁨, Parsed=None, Extracted=None)
  "感"
  → 카테고리 외 단어. 둘 다 거름. 이런 케이스는 모델이 답을 못 한 거라 오답 처리.

Qwen 한-001 (truth=한, Parsed=중립, Extracted=중립, 오답)
  "중립"
  → 단답이긴 한데 다른 카테고리로 답함. Parsed=Extracted=중립, 둘 다 오답.

단답 지시 안 따른 비율 (Parsed=None인 응답)

모델 text image audio_neutral audio_emotion
HCX 0/56 0/56 0/56 0/56
MiniCPM 6/56 2/56 1/56 1/56
Qwen 6/56 2/56 4/56 5/56

→ HCX가 지시 준수 최고(전부 단답). MiniCPM은 거의 단답. Qwen은 audio 입력에서 단답 이탈이 두드러짐 — 입력 모달리티가 출력 형식 준수에도 영향. 본 task와 직접 무관해도 모델 행태 차이로 기록할 가치.


parse 검증 후 정정: HCX text의 “한”은 substring 함정이 아님

초기 의심: parse_category가 substring 매칭이라 1글자 카테고리(정/한)가 응답 본문에 우연히 박힌 경우 over-match. HCX text가 56중 48을 1글자 카테고리로 답했으니 그게 함정의 결과일 가능성 추정.

검증: parse를 우선순위 매칭으로 교체(정확 일치 > 첫 줄 정확 일치 > 다글자 substring > 1글자는 한글 경계로 격리된 standalone). raw response 그대로 두고 재집계.

재집계 결과 (변경된 sample 수)
  HCX     : 4 variants 모두 0개 변화 (정답률 그대로)
  MiniCPM : 4 variants 모두 0개 변화
  Qwen    : text -3, image -2, audio_neutral -2, audio_emotion -3
            (text 42.9 → 37.5%, audio_emotion 37.5 → 33.9% 등)

HCX의 “한” 폭발은 진짜 모델 행동. 응답에 “한”이 standalone token(한글 경계로 격리)으로 박혀 있어서 새 parse도 동일하게 매칭. HCX는 실제로 “한”이라고 답한 것이지, 본문에 우연히 끼어든 게 아니다.

Qwen만 substring 함정에 약간 영향 (-2~-3개). 이게 실제 정확도 향상.

MiniCPM은 영향 없음 — parse가 제대로 작동했음.

이 결과의 함의가 더 흥미롭다: HCX(한국어 특화)는 한국 고유 정서(정/한)에 강하게 편향되어 있어 다른 카테고리도 “한”으로 흘려보낸다. text에선 한 8/8, 정 6/8 — 한·정 정답률은 압도적이지만 그 대가로 다른 카테고리(기쁨/슬픔/분노/중립)에서 정답률 폭락. 편향된 강점이 정답률 33.9%를 만들었다, 아니라 균형 잡힌 분류기가 아니다. 한국어 특화의 양면성.

반면 image/audio에선 그 편향마저 사라지고 모두 “중립”으로 빠짐 → 한국어 특화 효과는 modality 의존적. text 입력에서만 한·정 인식, 비텍스트 입력에선 능력 상실. 이건 RQ3 흥미로운 갈래 — 한국어 특화는 텍스트에 갇혀 있을 가능성.

(Kanana 결과가 HCX와 비슷한 한국어 편향을 보일지, 아니면 균형 잡힌 분류기일지가 RQ3 한국 가설의 결정적 검증.)


의심점 2: HCX image/audio 56/56 “중립” — 디폴트 답인지 진짜 분류인지

본 결과만 보면 “HCX는 image/audio에서 모든 샘플을 중립으로 답한다”인데, 56샘플 중 중립 정답이 10개라 정답률 17.9%(=10/56)가 그 결과. 진짜 분류 의도는 0, 그냥 한 답으로 모은 거. 응답 본문 들춰보면 모델이 정말 “중립이라 판단”했는지 vs “답을 못 만들어 디폴트로 빠짐”인지 분간 가능. 후자라면 HCX는 image/audio task에 부적합으로 결론.


한 카테고리는 전 모델 약함 — 데이터 노출 부족 의심

모델 한 정답률 (4 variants 평균)
HCX 8/32 (text 8/8, image/audio 0)
MiniCPM 0/32
Qwen 0/32

MiniCPM·Qwen은 text·image·audio 모든 변형에서 한 카테고리를 0/8로 못 잡음. 한국 고유 정서라 학습 데이터 노출이 적은 결과로 보임. HCX는 text에서만 8/8인데, 위에서 짚은 substring over-match 함정과 겹침 — 진짜로 잘 한 건지 의심.

→ 한 카테고리에서 모델 간 진짜 차이는 parse 함정 잡고 다시 봐야 함. 또 Kanana(한국어 특화)가 어떻게 답할지가 본 가설의 핵심.


큰 그림 해석

본 결과가 RQ3/H3 검증에서 갖는 의미·sub-hypothesis 정리는 별도 글로 분리: log-19.


감정별 오답 패턴 (어떤 감정을 어떤 감정으로 틀리는가)

정답률만 보면 어떤 감정이 어디로 흘러가는지 안 보임. truth → 잘못 예측한 카테고리 분포를 모델·variant별로 분해.

HCX text-bare — “한” substring 함정 검증됨

truth 정답 가장 흔한 오답들
기쁨 1/10 한 5, 정 4
슬픔 0/10 한 8, 정 2
분노 4/10 한 6
중립 0/10 한 8, 기쁨 2
6/8 한 1, 슬픔 1
8/8 (전부 정답)

기쁨·슬픔·분노·중립 truth에서 무려 5~8개씩 “한”으로 매칭됨. 응답 본문에 “한”이 우연히 substring으로 등장해서 parse가 그걸 첫 매칭으로 골랐을 가능성 매우 높음. HCX text 33.9%는 1글자 카테고리 over-match가 만든 거짓 정답률일 가능성. parse 함수 수정 후 재집계 필수.

HCX image/audio — 단조 디폴트 답

3 variants 모두 동일 패턴: 56샘플 중 46개(=중립이 아닌 모든 truth 46개)를 모두 “중립”으로 답함. 분류 신호 0, 디폴트 답으로 도망. 응답 raw 떠봐서 진짜 “중립으로 판단” vs “답을 못 만들어 디폴트 빠짐” 분간 필요.

MiniCPM — 한→슬픔 함정 + 운율의 실질 효과

text-bare 오답 패턴:

  • 한 0/8: 슬픔=5, None=2, 기쁨=1 — 한국 고유 정서가 모델 임베딩에서 “슬픔” 근처에 위치
  • 중립 2/10: 기쁨=4, 분노=2 — 중립 대화를 기쁨으로 오인
  • 정 3/8: 기쁨=2, None=2, 슬픔=1

audio-emotion에서 은 여전히 슬픔=6으로 못 잡음 (한국어 모델 노출 부족 가설 재확인). 다만 슬픔 truth는 text 2/10 → audio-emotion 6/10으로 3배 — 운율 정보가 슬픔 분류에 결정적. 이게 MiniCPM의 H3 신호의 실체.

text→audio_emotion 변형 효과 카테고리별:

  • 슬픔: 2 → 6 (+4) 운율 결정적
  • 중립: 2 → 4 (+2)
  • 기쁨: 6 = 6
  • 분노: 8 → 7 (-1) text가 더 나음
  • 정: 3 = 3
  • 한: 0 = 0

Qwen — emotion 강화시 중립 0/10 폭락

text vs audio-emotion 비교:

  • 슬픔: 3 → 6 (+3)
  • 기쁨: 5 → 6 (+1)
  • 분노: 9 → 6 (-3) 운율이 분노 분류 방해
  • 중립: 4 → 0 (-4) 운율 강조하면 무조건 감정 라벨 고름
  • 정: 3 = 3
  • 한: 0 = 0

audio-emotion 중립 truth 분포: 분노=5, 기쁨=4, 한=1 — 운율이 들리면 모델이 어떤 감정이든 골라야 한다고 학습된 듯. 이게 Qwen이 H3에 또렷하게 반응 안 하는 이유.

공통 발견

  1. 한 카테고리는 거의 모든 모델·variant에서 슬픔으로 오답 — 한국 고유 정서가 외국 모델(MiniCPM/Qwen)뿐 아니라 한국어 특화 HCX에서도 image/audio에선 안 잡힘. 임베딩 공간에서 슬픔 근처. Kanana 결과 봐야 한국어 특화 효과 확정.
  2. HCX text의 “한” 폭발은 parse 함정 의심 — 다른 모델은 한이 정답일 때 슬픔으로 가는데 HCX만 모든 카테고리가 한으로 흘러가는 이상 패턴 → 모델 출력보다 parse 로직 문제일 가능성.
  3. 운율(emotion)의 효과는 카테고리 비대칭 — 슬픔에선 모든 모델에서 +효과, 분노에선 종종 -효과(분노는 text가 더 명확), 중립에선 Qwen에서 폭락. 단순히 “운율이 좋다/나쁘다”가 아니라 카테고리에 따라 운율 정보가 도움 또는 방해.
  4. MiniCPM image의 “분노” 폭주 — image-bare에서 기쁨 truth → 분노=7, 슬픔 truth → 분노=4. 텍스트 렌더링 PNG의 시각적 특징(글자 색·배치)이 분노로 인식되는 듯. 이미지 렌더링 정책 검토 후보.

다음

진행 상태·서버별 actionable·큰 덩어리 #1-10은 별도 문서: docs/misc/exp_c_status.md.

log-16 “다음” 회수만 짧게:

  1. 스모크 테스트 — ✅ (HCX 1샘플, log-16 부록)
  2. 분류 풀 배치 — 🔄 비교 모델 3종 ✅, Kanana 미진행
  3. audio respond TTS 112개 — ✅ (4-28 마무리)
  4. 응답 생성 runner 작성 — ✅ (4-28 다듬기까지)
  5. LaaJ 프롬프트 설계 — ✅ (log-18)
  6. 비교 모델 어댑터 확장 — ✅ (parallel_runner, log-16 부록)

결정 메모

  • (보류) HCX 본 가설 검증에서 빼기: image/audio 56/56 디폴트 답으로 보면 빼는 게 깔끔. 그러나 응답 task 결과 보면 다른 양상일 수 있어 단정은 respond 단계 후로.
  • (채택) parse 함수 수정 후 재집계: 본 결과 신뢰도가 함수 정확성에 크게 의존. 수정 비용 작고 raw 다 보유 — 안 할 이유 없음.
  • (폐기) 1샘플 smoke가 분류 정답률 의미 있다는 가정: HCX 기쁨-001 1샘플 33.9%·17.9% 패턴이 본 배치 56샘플 분포와 비슷 — smoke의 운빨이라기보다 진짜 패턴. 운빨 X.

API 서버 sweep — TTS 마무리 + audio 60초 한계 대응

한 일

  • Audio respond TTS 마무리: 어제 53/112 → 오늘 59 추가 → 112/112 ✓
  • Kanana classify 2샘플 smoke:
    • 기쁨-001 4 variants 모두 정답 또는 합리적 응답
    • 기쁨-002 audio 두 종 모두 Max audio length 60s API 거절 → Kanana API audio 60초 한계 발견
  • audio variant 재설계 — 처음 fast(atempo 가속) + cut(앞 자름) 둘 다 도입했다가 fast는 prosody 왜곡으로 폐기. cut만 유지:
    • process_audio.py 신설, ffmpeg로 60s 초과 wav 처리, ≤60s 원본은 복사
    • 안전 마진 0.5s (실제 ≤59.83s)
    • 224개 -cut.wav 생성 (classify 112 + respond 112)
  • VARIANTS 4종 확정: text-bare, image-bare, audio-neutral-cut, audio-emotion-cut
  • runner.py 통합: common.parse_category 사용으로 1글자(정/한) substring 함정 회피 (위 의심점 #1과 동일 함수 통일)
  • runner 버그 수정: 4 variants 전부 ok일 때만 done_classify 마킹
  • kanana_client.py call_log 정합성: API가 응답한 모든 에러(400/429/5xx) 발생 시 로컬도 카운트 차감. 네트워크 미도달은 차감 안 함
  • pool 리셋: 기쁨-001 done_classify=False, 2026-04-28.json 삭제 — paradigm A + cut variant로 다시 시작

오늘 못 끝낸 것

  • Kanana classify 본 배치 0/56 — 콜 부족
  • 60s-안전 wav 실측 검증 — 처리된 wav(>60s 원본 → ffmpeg 출력)가 진짜 API 통과하는지 미확인. 검증한 기쁨-001은 원본이 ≤60s라 cut이 그냥 복사

부록 (4-28 후반): -cut 재실행 — audio 입력 길이 견고성 검증

API 서버 sweep에서 audio variant를 audio-{neutral,emotion} (full-length) → audio-{neutral,emotion}-cut (마지막 60초)로 재정의한 뒤, GPU 서버에서 비교 모델 3종 classify를 새 -cut variants로 재실행. 4-27 옛 audio 결과({model}/classify/2026-04-27.json)와 4-28 새 -cut 결과({model}/classify/2026-04-28.json)를 비교.

모델 text image audio_neutral 4-27 → -cut 4-28 audio_emotion 4-27 → -cut 4-28
HCX 33.9 → 33.9 17.9 → 17.9 17.9 → 17.9 17.9 → 17.9
MiniCPM 37.5 → 37.5 21.4 → 21.4 37.5 → 37.5 46.4 → 44.6 (-1.8)
Qwen 37.5 → 37.5 30.4 → 30.4 32.1 → 30.4 (-1.7) 33.9 → 37.5 (+3.6)

해석:

  • HCX 패턴 100% 강건 — 모든 variant 동일. image/audio 디폴트-답 결론(한국어 특화의 modality 종속성) 굳건
  • MiniCPM H3 신호 유지 — emotion 44.6% > text 37.5% (+7%p, 옛 +9%p에서 약화되지만 또렷)
  • Qwen audio_emotion +3.6%p 흥미로운 신호 — cut으로 마지막 60초(정서 절정)만 보니 운율 정보가 더 강하게 잡힘. text와 동률(37.5%)
  • 평균적으로 audio 입력 길이는 결과를 거의 안 흔듦. 41/112(=37%) 샘플만 60초 초과로 cut 실제 발생 → 63%는 입력 동일이라 변화 없는 게 정상

→ 본 분석의 RQ3 패턴(MiniCPM 운율 신호, HCX modality 종속성, Qwen baseline)이 audio 입력 길이에 강건. 신뢰 한 단계 더 확보. 본 단계의 의미는 log-19 “다음 단계가 결정할 것” 3번에 회수.


부록 (4-28): HCX classify raw response inspection

의심점 #1·#2 검증 위해 HCX classify all.json의 raw 응답 본문 샘플링.

text-bare — 응답이 한 / assistant / ... / 한 / assistant ... 식으로 첫 단어가 분류 라벨이고 stop token 없이 max_new_tokens 채움. parsed 분포: 한 36 / 정 12 / 분노 4 / 기쁨 3 / 슬픔 1.

parse 함정 아님. 모델이 진짜 그 라벨을 답으로 출력. 다만 1글자 카테고리(정/한)에 모델 자체 over-bias.

image-bare / audio-neutral / audio-emotion — 56/56 모두 첫 단어가 “중립”. audio 응답엔 instruction의 "감정 보기: 기쁨 / 슬픔 / 분노 / 중립 / 정 / 한" 부분이 echo되고 <|audio0978|>·<|audio6486|> 같은 audio token이 텍스트 stream에 새어나옴. HCX는 audio_output_supported=False인데도 audio 토큰을 텍스트로 뱉음.

분류 의도 아니고 디폴트 도주 확정.

결론

  • 의심점 #1 (parse 함정): 폐기. parse_category가 1글자 over-match 시킨 게 아니라 모델 자체가 한·정 단어를 답으로 출력. parse_category 수정 후에도 HCX text는 한·정 over-bias 유지될 것.
  • 의심점 #2 (디폴트 도주): 채택. HCX는 image/audio classify 본 가설 검증에서 빼는 게 깔끔.

→ 결정 메모의 “(보류) HCX 본 가설 검증에서 빼기”는 image/audio에 한해 채택으로 갱신. text-bare는 over-bias 분포를 별도 분석 대상으로 남김.