From 8565e039385b2d155b279c8563b9bdce3962d0a5 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Tue, 12 Aug 2025 23:13:59 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=B8=EB=B6=80=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=20=EB=AC=B8=EC=84=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?-=20=ED=98=BC=EB=9E=80=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...812_감정시스템_Phase1_실행계획.md | 332 ------------------ 1 file changed, 332 deletions(-) delete mode 100644 plans/250812_감정시스템_Phase1_실행계획.md diff --git a/plans/250812_감정시스템_Phase1_실행계획.md b/plans/250812_감정시스템_Phase1_실행계획.md deleted file mode 100644 index 28850b5..0000000 --- a/plans/250812_감정시스템_Phase1_실행계획.md +++ /dev/null @@ -1,332 +0,0 @@ -# 감정 시스템 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일 (목표) \ No newline at end of file