3 minute read

감정 실험의 변형(modality × context × prosody) 전체셋을 마감하고, 응답 task의 paradigm·평가축까지 확정. log-15에서 톤 매핑·TTS 96/112를 만들어 두었고, 본 글은 그 위에서 설계를 닫는 단계.


변형 정의 (3축)

대화의 전달 매체(modality), 상황 설명(context) 포함 여부, 그리고 task용 입력 컨텍스트 크기 — 세 축으로 변형을 나눈다.

modality text / image / audio
context (text·image만) bare(상황 제외) / ctx(상황 포함)
prosody (audio만) neutral / emotion
task 컨텍스트 classify(전체 대화) / respond(turns[:-1])

비용 비대칭이 설계를 결정했다. text·image는 생성 비용 0이라 ctx와 task 두 축 모두 두 버전을 다 만들고 실험은 bare부터 시작. audio는 ctx축은 만들지 않고(상황은 프롬프트 텍스트로 공통 제공), task 축은 만들어야 한다 — paradigm A를 살리려면 turns[:-1] 음성이 필요하기 때문(아래 §Paradigm 참조).

prosody 축(neutral/emotion)은 audio 안에서 운율 정보가 분류·응답에 영향을 주는지 보려고 유지. neutral은 “다음 대화를 자연스럽게 읽어줘”, emotion은 log-15 톤 매핑 테이블의 감정 톤 지시.


파일 컨벤션 (task별 서브폴더)

data/exp_c/artifacts/
  classify/                ← 전체 대화 (분류 task)
    {id}-text.txt          : 대화만
    {id}-text-ctx.txt      : [상황] + 대화
    {id}-image.png         : 대화만 PNG
    {id}-image-ctx.png     : [상황] + 대화 PNG
    {id}-neutral.wav       : 대화만 평이 TTS
    {id}-emotion.wav       : 대화만 감정 톤 TTS
  respond/                 ← turns[:-1] (응답 생성 task)
    {id}-text.txt
    {id}-text-ctx.txt
    {id}-image.png
    {id}-image-ctx.png
    {id}-neutral.wav       (※ 신규 TTS 콜 필요)
    {id}-emotion.wav       (※ 동상)

같은 파일명을 task 폴더로만 분리. 세 generator 모두 sample_pool.json을 읽고 두 task에 대해 각각 생성, 기존 파일은 skip. 변형 추가는 image/text는 VARIANTS dict에 한 줄, audio는 _generate_tts의 분기 추가.


데이터 현황 (4-27 시점)

카테고리 샘플 classify (전체 대화) respond (turns[:-1])
기쁨 10 text·ctx·image·image-ctx·neutral·emotion 6×10 ✓ text·ctx·image·image-ctx 4×10 ✓ / wav 0 ❌
슬픔 10 동상 ✓ 동상
분노 10 동상 ✓ 동상
중립 10 동상 ✓ 동상
8 동상 ✓ 동상
8 동상 ✓ 동상
56 336/336 ✓ 224/336 (text/image 224 ✓, audio 112 미생성)

audio respond 112개는 다음 세션에서 TTS 콜로 생성 예정.


Paradigm: turns[:-1] 입력 + 마지막 발화 생성 (A)

응답 생성 task에서 두 paradigm을 두고 흔들렸다.

Paradigm 입력 모델 출력 사람 응답 reference 추가 비용
A: turns[:-1] 입력 마지막 발화 제외 마지막 발화 생성 turns[-1] = 데이터셋 사람 응답 audio respond 신규 TTS 56×2=112콜
B: 전체 turns 입력 N턴 전체 N+1번째 발화 생성 없음(N+1 발화는 데이터셋에 없음) 0

처음에는 비용을 우선해 B로 결정했다. 그러나 A의 큰 장점 — 사람의 turn[-1]을 LaaJ에 후보로 추가할 수 있음 — 이 연구의 핵심을 살린다는 판단으로 뒤집었다. 모델 응답들끼리만 비교하면 “어떤 모달리티 입력이 더 좋은 응답을 만드는가”는 답할 수 있지만, “한국어 정서 응답에서 모델이 사람을 이기는가/사람과 비슷한가” 라는 흥미로운 질문이 빠진다. paradigm A는 그 anchor를 무료로 제공한다.

비용 측면: 마지막 발화까지 포함된 음성을 새로 만드는 게 아니라(=B에 필요), 오히려 마지막 발화를 빼고 TTS해야 한다(=A 입력). 56샘플 × neutral/emotion 2종 = 112 wav, ≈2일 콜 분량. text·image의 turns[:-1] 변형은 비용 0이라 이미 만들어 둠.

A로 결정. audio respond TTS는 다음 세션에서 진행.


Tasks

분류 (classify)

6지선다(기쁨/슬픔/분노/중립/정/한)를 골라내는 단답 task. 출력은 text only.

  • 평가: 정답률(accuracy) — sample_pool의 category 필드와 비교
  • 4 variants 사용: text-bare / image-bare / audio_neutral / audio_emotion
  • Kanana 콜 예산: 4콜/샘플 × 56샘플 = 224콜 (≈4일 분량)

응답 생성 (respond)

artifacts/respond/ 입력(turns[:-1])을 받아 데이터셋의 마지막 발화 자리(turn[-1])에 들어갈 응답을 자유 텍스트로 생성. 출력은 text + audio.

  • 입력: turns[:-1] (modality별로 text·image·audio 형태)
  • 모델 출력: text 응답 + audio 응답 (HCX는 text only)
  • 평가: LLM-as-a-judge pairwise — 후보군에 사람 응답(turn[-1])도 포함해서 모델 vs 사람 vs 모델 간 비교
  • 4 variants 사용
  • HCX의 audio 차원은 결측 처리

분리 vs 통합

분류와 응답 생성을 한 콜에 묶어 출력할 수도 있지만(콜 절반), 평가가 섞여서 깔끔하지 않다. 분리해서 각각의 정답률과 응답 품질을 독립적으로 측정한다.


모델 라인업

모델 파라미터 한국어 특화 adapter audio in audio out
Kanana-1.5-o 11.6B kanana_client.py (REST)
HCX-SEED-Omni 8B experiments/exp_c/adapters/hcx.py ✗ (디코더 미공개)
Qwen2.5-Omni 7B .../qwen.py
MiniCPM-o 2.6 8B .../minicpm.py

비교 모델은 모두 4×RTX3090 local에서 돌고, exp_a 어댑터를 상속해 INSTRUCTION만 감정 task용으로 교체. parallel_runner로 4-GPU 분산 실행 패턴은 exp_a와 동일하게 가져갈 예정.


다음

  1. 분류 풀 배치 — 13~17샘플/일, 4일 안에 56샘플 완주
  2. audio respond TTS 112개 — paradigm A 입력 (turns[:-1] 음성), 2일 분량 콜
  3. 응답 생성 runnerRESPOND_INSTRUCTION 가다듬기, audio output 받기, 사람 응답 후보 결과 JSON에 같이 저장
  4. LaaJ 프롬프트 설계 — pairwise 비교 기준(공감 정도, 자연스러움, 한국어 운율 적합성 등). 후보군: Kanana / HCX / Qwen / MiniCPM / 사람
  5. 비교 모델 어댑터 확장 — exp_c용 Kanana 어댑터 추가, parallel_runner 패턴 도입

분류 결과부터 모이는 대로 patterns 보면서 RQ1·RQ3에 대한 예비 신호를 본다.