# 감정 시스템 Phase 1 실행 계획 작성일: 2025년 8월 12일 작성자: Claude (51123 서버) 상태: 실행 준비 완료 ## 0. 개발 철학 (절대 준수) ### 함수형 프로그래밍 100% 원칙 - **하드코딩 0% 목표**: 근거없는 하드코딩 값 절대 사용 금지 - **모든 설정값은 외부화**: - 환경변수 (.env) - 설정 파일 (config.yaml) - DB에서 동적 로드 - **순수 함수 체인**: 부작용 없는 함수 조합 - **불변성 유지**: 상태 변경 대신 새 객체 생성 ### 예시 ```python # ❌ 잘못된 예 (하드코딩) def analyze_emotion(text): if len(text) > 100: # 하드코딩된 값 return "neutral" threshold = 0.3 # 하드코딩된 임계값 # ✅ 올바른 예 (함수형) def analyze_emotion(text: str, config: Dict) -> Dict: max_length = config.get("max_text_length", 512) threshold = config.get("confidence_threshold", 0.3) # 순수 함수로 처리 ``` ## 1. 현황 분석 결과 ### 1.1 기존 자산 - **학습 완료 모델**: training_emotion에 7개 감정 모델 (klue/bert-base) - **모델 성능**: F1 56.3%, Temperature Scaling 1.232 - **인프라**: skill-embedding 서비스 운영 중 (FastAPI, ONNX Runtime) - **여유 자원**: CPU 0.05%, 메모리 873MB/2GB ### 1.2 기술 스택 확인 ``` ✅ transformers 4.45.2 설치됨 ✅ FastAPI 구조 확립 ✅ ONNX Runtime 지원 ✅ ChromaDB 메타데이터 저장 가능 ``` ## 2. 감정 모델 상세 ### 2.1 7개 감정 체계 ```python emotions = [ 'fear', # 공포 (즉발적 기본정서) 'surprise', # 놀람 (즉발적 기본정서) 'anger', # 분노 (즉발적 기본정서) 'sadness', # 슬픔 (감정적 반응) 'happiness', # 행복 (감정적 반응) 'disgust', # 혐오 (감정적 반응) 'neutral' # 중립 (균형 상태) ] ``` ### 2.2 로빙 철학과의 연결 - **기본정서 (100ms)**: fear, surprise, anger → 즉발 반응 - **사회기능 (500ms)**: sadness, happiness, disgust → 숙고된 반응 - **엔트로피 특이점**: 높은 엔트로피 시 창발적 응답 ## 3. 구현 아키텍처 ### 3.1 서비스 확장 (Option A - 선택) ``` skill-embedding (포트 8515) ├── /embed (기존) └── /analyze_emotion (신규) ├── 입력: text, user_id (optional) ├── 처리: 7개 감정 분석 └── 출력: emotions, dominant, entropy, confidence ``` ### 3.2 API 설계 ```json // Request POST /analyze_emotion { "text": "오늘 프로젝트가 실패했어요", "user_id": "optional_for_caching" } // Response { "emotions": { "fear": 0.15, "surprise": 0.05, "anger": 0.25, "sadness": 0.35, "neutral": 0.10, "happiness": 0.05, "disgust": 0.05 }, "dominant": "sadness", "entropy": 2.31, "confidence": 0.35, "processing_time_ms": 87 } ``` ## 4. 실행 계획 ### Phase 1-A: 기본 통합 (Day 1-2) #### 51123 서버 작업 ```bash # 1. 모델 준비 sudo mkdir -p /opt/models/emotion sudo cp -r /path/to/training_emotion/outputs/aihub-7emotions-complete/* \ /opt/models/emotion/ sudo chown -R admin:admin /opt/models/emotion ``` #### 로컬 개발자 작업 ```python # 2. emotion_analyzer.py 작성 from transformers import AutoModelForSequenceClassification, AutoTokenizer import torch import numpy as np class EmotionAnalyzer: def __init__(self, config: Dict): # 하드코딩 없음 - 모든 값은 config에서 self.model_path = config["model_path"] self.model = AutoModelForSequenceClassification.from_pretrained(self.model_path) self.tokenizer = AutoTokenizer.from_pretrained(self.model_path) self.temperature = config["temperature_scaling"] # from calibration.json self.emotions = config["emotion_labels"] # from config async def analyze(self, text: str) -> dict: inputs = self.tokenizer(text, return_tensors="pt", max_length=512, truncation=True) with torch.no_grad(): logits = self.model(**inputs).logits probs = torch.softmax(logits / self.temperature, dim=-1) emotion_scores = { emotion: float(probs[0][i]) for i, emotion in enumerate(self.emotions) } dominant = max(emotion_scores, key=emotion_scores.get) entropy = self._calculate_entropy(list(emotion_scores.values())) return { "emotions": emotion_scores, "dominant": dominant, "entropy": entropy, "confidence": emotion_scores[dominant] } def _calculate_entropy(self, probs): probs = np.array(probs) probs = probs[probs > 0] return -np.sum(probs * np.log(probs)) ``` #### 51124 서버 작업 ```yaml # 3. docker-compose.yml 수정 services: skill-embedding: volumes: - /opt/models:/opt/models:ro environment: - EMOTION_MODEL_PATH=/opt/models/emotion ``` ### Phase 1-B: 최적화 (Day 3-4) #### ONNX 변환 ```bash # 로컬 개발자 python convert_to_onnx.py \ --model_path /opt/models/emotion \ --output_path /opt/models/emotion-onnx \ --optimize ``` #### 캐싱 구현 (설정 기반) ```python from functools import lru_cache import hashlib class CachedEmotionAnalyzer(EmotionAnalyzer): def __init__(self, config: Dict): super().__init__(config) self.cache_size = config.get("cache_size", 1000) self.cache_ttl = config.get("cache_ttl_seconds", 300) @lru_cache(maxsize=None) # maxsize는 동적으로 관리 def _analyze_cached(self, text_hash: str): # 실제 분석 로직 pass async def analyze(self, text: str, user_id: str = None): text_hash = hashlib.md5(text.encode()).hexdigest() cache_key = f"{user_id}:{text_hash}" if user_id else text_hash return self._analyze_cached(cache_key) ``` ### Phase 1-C: 통합 (Day 5) #### rb10508_micro 연동 ```python # Slack 메시지 처리 시 async def process_slack_message(text: str, user_id: str): # 1. 감정 분석 emotion_result = await call_emotion_api(text, user_id) # 2. ChromaDB 메타데이터 추가 metadata = { "user_id": user_id, "timestamp": datetime.now().isoformat(), "emotions": emotion_result["emotions"], "dominant_emotion": emotion_result["dominant"], "emotional_entropy": emotion_result["entropy"] } # 3. 응답 톤 조정 response_tone = adjust_tone_by_emotion(emotion_result["dominant"]) return generate_response(text, tone=response_tone) ``` ## 5. 성능 목표 및 측정 ### 5.1 목표 지표 - **응답시간**: < 200ms (캐시 미스), < 50ms (캐시 히트) - **정확도**: 체감 정확도 > 70% - **메모리**: < 1.5GB 총 사용량 - **처리량**: > 10,000 요청/일 ### 5.2 측정 방법 ```bash # 성능 테스트 curl -w "@curl-format.txt" \ -X POST http://localhost:8515/analyze_emotion \ -H "Content-Type: application/json" \ -d '{"text":"테스트 메시지"}' # 부하 테스트 locust -f tests/load_test.py --users 10 --spawn-rate 2 ``` ## 6. 리스크 관리 ### 6.1 잠재 위험 | 위험 요소 | 영향도 | 대응 방안 | |---------|-------|----------| | 모델 크기 (442MB) | 중 | ONNX 변환으로 150MB로 축소 | | 메모리 부족 | 중 | 모델 공유, 캐싱 최적화 | | 낮은 정확도 (56.3%) | 낮 | confidence 임계값 설정 | | Cold start | 낮 | 서비스 시작 시 프리로드 | ### 6.2 폴백 전략 (설정 기반) ```yaml # config.yaml fallback: confidence_threshold: 0.3 # DB나 실험으로 결정된 값 entropy_threshold: 2.8 # 데이터 분석으로 도출된 값 default_emotion: "neutral" # 기본값 skip_on_error: true # 오류 시 동작 ``` - confidence < threshold일 때 neutral로 분류 - 엔트로피 > threshold일 때 "복잡한 감정" 표시 - 오류 시 감정 분석 스킵하고 진행 ## 7. 작업 분담 ### 51123 서버 (시스템 관리) - [ ] 모델 파일 /opt/models 배치 - [ ] 배포 파이프라인 설정 - [ ] 시스템 모니터링 - [ ] 문서화 ### 로컬 개발자 (코드 구현) - [ ] emotion_analyzer.py 작성 - [ ] FastAPI 엔드포인트 추가 - [ ] ONNX 변환 스크립트 - [ ] rb10508_micro 연동 ### 51124 서버 (서비스 운영) - [ ] Docker 이미지 빌드 - [ ] 서비스 배포 - [ ] 로그 모니터링 - [ ] 성능 측정 ## 8. 검증 계획 ### 8.1 단위 테스트 ```python def test_emotion_analysis(): analyzer = EmotionAnalyzer() result = analyzer.analyze("정말 기쁜 하루였어요!") assert result["dominant"] == "happiness" assert result["confidence"] > 0.5 ``` ### 8.2 통합 테스트 - Slack 메시지 → 감정 분석 → ChromaDB 저장 - 다양한 감정 텍스트 100개 테스트 - 응답 시간 측정 ## 9. 다음 단계 (Phase 2 준비) - 감정 기반 대화 전략 수립 - 장기 감정 패턴 분석 - 사용자별 감정 프로파일 - 멀티모달 감정 분석 (이미지, 음성) ## 10. 성공 기준 ✅ Phase 1 완료 조건: 1. 7개 감정 분석 API 정상 작동 2. 평균 응답시간 < 200ms 3. rb10508_micro 통합 완료 4. ChromaDB 메타데이터 저장 확인 5. 100개 테스트 케이스 통과 --- **시작일**: 2025년 8월 13일 (예정) **완료일**: 2025년 8월 17일 (목표)