#!/usr/bin/env python3 """영어 텍스트 감정 모델 (DistilRoBERTa) sanity check. hand-crafted 영어 문장으로 모델 로딩, 출력 포맷, 기본 정확도를 검증한다. Usage: python scripts/validate_text_emotion_english.py """ from __future__ import annotations import logging import sys from pathlib import Path PROJECT_ROOT = Path(__file__).parent.parent sys.path.insert(0, str(PROJECT_ROOT)) logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", ) logger = logging.getLogger("validate_text_en") PROJECT_LABELS = ["neutral", "joy", "sadness", "anger", "surprise", "fear", "disgust"] # (text, expected_emotion) — 명확한 감정 표현 문장 TEST_CASES = [ # joy ("I'm so happy today, everything is wonderful!", "joy"), ("This is the best day of my life!", "joy"), ("I'm thrilled about the good news!", "joy"), # anger ("This makes me absolutely furious!", "anger"), ("I can't believe how unfair this is, I'm so angry!", "anger"), ("Stop doing that, it's driving me crazy!", "anger"), # sadness ("I feel so sad and lonely right now.", "sadness"), ("I miss you so much, it hurts.", "sadness"), ("I can't stop crying, everything feels hopeless.", "sadness"), # fear ("I'm really scared, something is wrong.", "fear"), ("I'm terrified of what might happen next.", "fear"), ("Help me, I'm so afraid!", "fear"), # surprise ("Oh my god, I can't believe it!", "surprise"), ("Wow, I never expected that to happen!", "surprise"), ("What?! That's absolutely incredible!", "surprise"), # neutral ("The meeting is scheduled for 3pm.", "neutral"), ("I need to buy groceries on the way home.", "neutral"), ("The temperature today is around 20 degrees.", "neutral"), # disgust ("That's absolutely disgusting, I feel sick.", "disgust"), ("This food tastes terrible, it's revolting.", "disgust"), ("I can't stand the smell, it's nauseating.", "disgust"), ] def validate(): """DistilRoBERTa 모델 검증.""" from src.stage2.text_emotion import predict as text_predict logger.info("=" * 60) logger.info("영어 텍스트 감정 모델 (DistilRoBERTa) 검증 시작") logger.info("=" * 60) passed = 0 failed = 0 results = [] for text, expected in TEST_CASES: result = text_predict(text, language="en") # 출력 포맷 검증 assert "emotion" in result, f"Missing 'emotion' key in result" assert "confidence" in result, f"Missing 'confidence' key in result" assert "scores" in result, f"Missing 'scores' key in result" # 모든 프로젝트 라벨이 scores에 있는지 확인 for label in PROJECT_LABELS: assert label in result["scores"], f"Missing label '{label}' in scores" # scores 합계 ~1.0 확인 score_sum = sum(result["scores"].values()) assert abs(score_sum - 1.0) < 0.01, f"Scores sum={score_sum}, expected ~1.0" predicted = result["emotion"] confidence = result["confidence"] match = predicted == expected if match: passed += 1 status = "PASS" else: failed += 1 status = "FAIL" results.append({ "text": text[:50], "expected": expected, "predicted": predicted, "confidence": confidence, "match": match, }) logger.info( f" [{status}] expected={expected:10s} predicted={predicted:10s} " f"conf={confidence:.3f} | \"{text[:45]}...\"" if len(text) > 45 else f" [{status}] expected={expected:10s} predicted={predicted:10s} " f"conf={confidence:.3f} | \"{text}\"" ) total = passed + failed accuracy = passed / total if total > 0 else 0 logger.info(f"\n{'='*60}") logger.info(f"결과: {passed}/{total} PASS ({accuracy:.1%})") logger.info(f" Passed: {passed}") logger.info(f" Failed: {failed}") if accuracy >= 0.8: logger.info("판정: PASS — 모델이 정상적으로 동작합니다.") elif accuracy >= 0.6: logger.info("판정: WARN — 일부 감정에서 부정확합니다.") else: logger.info("판정: FAIL — 모델에 문제가 있을 수 있습니다.") logger.info(f"{'='*60}") return accuracy >= 0.6 if __name__ == "__main__": success = validate() sys.exit(0 if success else 1)