# 로빙 감정 시스템 현실 적용 5단계 로드맵

**작성자**: happybell80 & Claude  
**목적**: 감정 시스템 설계서를 현실적으로 구현 가능한 단계별 계획으로 구체화

## 핵심 원칙
- **MVP 우선**: 복잡한 기능보다 작동하는 기본 기능
- **측정 가능한 성과**: 각 단계마다 명확한 KPI
- **점진적 복잡도**: 단순 → 복잡으로 진화
- **서비스 분리**: 단일 장애점 방지
- **함수형 프로그래밍 100%**: 하드코딩 0% 목표. 근거없는 하드코딩 값 절대 사용 금지
  - 모든 값은 설정 파일이나 환경변수에서 로드
  - 순수 함수 체인으로 구성
  - 상태 변경 최소화, 불변성 유지

---

## Phase 1: 7개 감정 기본 구현 (모델 준비 완료, 통합 대기)

### 목표
"이미 학습된 7개 한국어 감정 모델을 skill-embedding에 통합"

### 진행 현황 (2025-08-15 기준)
- ✅ 모델 학습 완료 (F1 56.3%)
- ✅ ONNX 변환 완료 (442MB)
- ⏳ skill-embedding 서비스 통합 대기
- ⏳ /emotion 엔드포인트 구현 필요

### 구현 범위
```python
# AI Hub 데이터로 학습 완료된 7개 감정
EMOTIONS = [
    "fear",      # 공포 (기본정서)
    "surprise",  # 놀람 (기본정서)
    "anger",     # 분노 (기본정서)
    "sadness",   # 슬픔
    "neutral",   # 중립
    "happiness", # 행복  
    "disgust"    # 혐오
]
# 모델 성능: F1 56.3%, Temperature Scaling 1.232

# 엔트로피 계산 (7개 감정)
def calculate_entropy(probs: List[float]) -> float:
    """7개 감정 확률값으로 엔트로피 계산"""
    return -sum(p * log(p) for p in probs if p > 0)
```

### 기술 스택
- **감정 모델**: klue/bert-base 기반 → ONNX 변환 완료
- **서비스**: skill-embedding 확장 (포트 8515, /emotion 추가)
- **저장**: 기존 ChromaDB 활용 (메타데이터에 감정 추가)
- **의사결정**: 엔트로피 기반 복잡도 판단
- **기존 코드**: rb10508_micro의 memory/storage.py 재사용
- **설정값**: confidence=0.35, entropy=2.0, temperature=1.232

### 성능 목표
- 응답시간: 500ms 이내
- 정확도: 사용자 평가 3.5/5.0
- 메모리: 200MB 이내

### 데이터 준비 (완료)
- AI Hub 한국어 대화 데이터셋 38,594개 샘플
- 7개 감정 균형 분포
- 학습/검증/테스트 분할 완료
- 클래스 가중치 적용

### 검증 방법
```bash
# 단위 테스트
pytest tests/test_basic_emotions.py

# 부하 테스트  
locust -f tests/load_test.py --users 10

# 응답시간 측정
curl -w "@curl-format.txt" http://localhost:8503/analyze
```

### 산출물
- [x] 7개 감정 모델 학습 완료 (training_emotion) ✅ 2025-08-08
- [x] ONNX 변환 완료 (442MB) ✅ 2025-08-13
- [x] 모델 파일 51124 서버 배치 완료 ✅ 2025-08-13
- [ ] skill-embedding 서비스에 /emotion 엔드포인트 추가 ⏳
- [ ] Temperature Scaling 적용 (1.232) ⏳
- [ ] 엔트로피 계산기 구현 ⏳
- [ ] ChromaDB 메타데이터 통합 ⏳
- [ ] rb10508_micro 연동 ⏳

### 아키텍처 결정 사항 (2025-08-12)
**문제**: 감정 분석을 어디에 구현할 것인가?
- Option A: 별도 skill-emotion 서비스 (아키텍처 원칙)
- Option B: skill-embedding에 통합 (자원 효율성)

**최종 결정**: skill-embedding에 통합
- 이유: ONNX Runtime 공유, 메모리 200MB 절약, 레이턴시 감소
- 트레이드오프: 서비스 역할 혼재 vs 실용성
- 향후: 서비스명 변경 고려 (skill-embedding → skill-ai)

### 현재 보유 모델 (2025-08-15)
1. **aihub-7emotions** (메인 모델)
   - 크기: 442MB (ONNX)
   - 감정: fear, surprise, anger, sadness, neutral, happiness, disgust
   - 성능: F1 56.3%, ECE 0.090
   - 위치: /home/admin/ivada_project/onnx_models/aihub-7emotions/

2. **korean-sentiment-kcelectra** (보조 모델)
   - 크기: 511MB (ONNX)
   - 감정: 11개 한국어 세분화 감정
   - 성능: F1 70.72%
   - 위치: /home/admin/ivada_project/onnx_models/korean-sentiment-kcelectra/

---

## Phase 2: 서비스 통합 및 최적화

### 목표
"skill-embedding 서비스 통합, 캐싱 구현, rb10508_micro 연동"

### 우선 작업 (로컬 개발자)
1. skill-embedding에 /emotion 엔드포인트 추가
2. ONNX 모델 로딩 및 추론 코드 구현
3. Temperature Scaling (T=1.232) 적용
4. rb10508_micro에서 감정 API 호출 통합

### 최적화 전략
```python
# LRU 캐시 적용
from functools import lru_cache

@lru_cache(maxsize=1000)
def get_emotion_embedding(text: str) -> np.ndarray:
    """자주 사용되는 텍스트의 임베딩 캐싱"""
    return model.encode(text)

# 배치 처리
async def batch_analyze(texts: List[str]):
    """여러 텍스트 동시 처리"""
    embeddings = model.encode(texts, batch_size=32)
    return [analyze_emotion(emb) for emb in embeddings]
```

### ChromaDB 튜닝
- 인덱스 최적화: HNSW 파라미터 조정
- 쿼리 최적화: top-k를 10으로 제한
- 연결 풀링: 커넥션 재사용

### 프로파일링
```python
# 병목 지점 찾기
import cProfile
import pstats

cProfile.run('analyze_emotion(text)', 'profile_stats')
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative').print_stats(10)
```

### 성능 목표
- 응답시간: 200ms (60% 개선)
- 동시 처리: 50 req/s
- 캐시 적중률: 30%

### 산출물
- [x] ONNX 모델 변환 완료 (442MB) ✅
- [ ] skill-embedding /emotion 엔드포인트 구현 ⏳
- [ ] LRU 캐시 시스템 (5분 TTL)
- [ ] 배치 처리 API
- [ ] ChromaDB 감정 메타데이터 인덱싱
- [ ] 성능 모니터링 (Grafana)
- [ ] rb10508_micro 감정 기반 응답 톤 조정

---

## Phase 3: 감정 패턴 분석 및 개인화

### 목표
"장기 감정 패턴 추적, 사용자별 감정 프로파일 구축"

### 감정 패턴 분석
```python
# 시간별 감정 추적
class EmotionTracker:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.history = []  # 시계열 감정 데이터
    
    def track(self, emotion_result: dict):
        """감정 결과를 시계열로 저장"""
        self.history.append({
            "timestamp": datetime.now(),
            "emotions": emotion_result["emotions"],
            "dominant": emotion_result["dominant"],
            "entropy": emotion_result["entropy"]
        })
    
    def get_pattern(self, period: str = "day"):
        """일/주/월 단위 감정 패턴 분석"""
        # 시간대별 주요 감정
        # 감정 변화 추이
        # 엔트로피 패턴
        return analyze_temporal_pattern(self.history, period)
```

### 개인화 전략
- 사용자별 감정 프로파일 생성
- 감정 응답 히스토리 학습
- 개인별 감정 임계값 조정
- 엔트로피 특이점 활용 (창발적 응답)

### 엔트로피 기반 의사결정
```python
class EntropyBasedDecision:
    def __init__(self):
        self.entropy_threshold = 2.5  # 특이점 임계값
    
    def should_be_creative(self, entropy: float) -> bool:
        """높은 엔트로피일 때 창의적 응답"""
        return entropy > self.entropy_threshold
    
    def adjust_response(self, response: str, emotion_result: dict):
        """감정에 따른 응답 톤 조정"""
        if emotion_result["dominant"] == "sadness":
            return make_empathetic(response)
        elif emotion_result["dominant"] == "anger":
            return make_calm(response)
        elif self.should_be_creative(emotion_result["entropy"]):
            return make_creative(response)
        return response
```

### 성능 목표
- 패턴 분석: 일 1회 배치 처리
- 프로파일 업데이트: 실시간
- 감정 히스토리: 30일 보관
- 개인화 정확도: 70% 이상

### 산출물
- [ ] 감정 패턴 분석기
- [ ] 사용자 감정 프로파일 DB
- [ ] 엔트로피 기반 의사결정 모듈
- [ ] 시계열 감정 시각화
- [ ] 개인화 응답 전략

---

## Phase 4: 베이지안 학습 시스템

### 목표
"실시간 학습과 개인화된 감정 모델 구축"

### 베이지안 파라미터
```python
class BayesianEmotionModel:
    def __init__(self):
        # Dirichlet 사전분포 (9개 감정)
        self.emotion_prior = np.ones(9)
        
        # Beta 분포 (저장 결정)
        self.save_alpha = 1
        self.save_beta = 1
        
        # Gamma 분포 (응답 길이)
        self.length_k = 2
        self.length_theta = 50
    
    def update_posterior(self, observation):
        """관측값으로 사후분포 업데이트"""
        self.emotion_prior += observation['emotion_counts']
        
        if observation['saved']:
            self.save_alpha += 1
        else:
            self.save_beta += 1
            
        # Gamma 업데이트 (moment matching)
        self.length_k, self.length_theta = \
            self.update_gamma(observation['response_length'])
```

### 예측-평가 루프
```python
async def prediction_evaluation_loop(user_input):
    # 1. 예측
    prediction = model.predict_user_response(user_input)
    
    # 2. 실제 응답 생성
    actual_response = await generate_response(user_input)
    
    # 3. 사용자 반응 수집
    user_reaction = await collect_feedback()
    
    # 4. 오차 계산 (3종)
    kl_div = calculate_kl(prediction, user_reaction)
    brier = calculate_brier(prediction, user_reaction)
    ece = calculate_ece(prediction, user_reaction)
    
    # 5. 모델 업데이트
    if max(kl_div, brier, ece) > threshold:
        model.update_posterior(user_reaction)
    
    return actual_response
```

### 개인화
- 사용자별 베이지안 파라미터 저장
- 조직/팀/개인 3단계 계층 구조
- Cold start: 조직 평균값 사용

### 성능 목표
- ECE: ≤ 0.08
- Brier Score: ≤ 0.20
- 학습 수렴: 50회 상호작용
- 개인화 효과: +15% 만족도

### 산출물
- [ ] 베이지안 모델 클래스
- [ ] 예측-평가 파이프라인
- [ ] 3종 오차 메트릭
- [ ] 사용자별 파라미터 저장소
- [ ] 학습 곡선 분석

---

## Phase 5: 프로덕션 및 확장

### 목표
"안정적인 프로덕션 배포와 고급 기능 추가"

### 프라이버시 게이트
```python
class PrivacyGate:
    def __init__(self):
        self.pii_patterns = load_pii_patterns()
        self.sensitive_topics = load_sensitive_topics()
    
    def filter(self, text, metadata):
        # PII 감지
        if self.detect_pii(text):
            return self.anonymize(text)
        
        # 민감 주제 필터
        if self.is_sensitive(text):
            return {"summary": self.summarize(text), 
                   "original": None}
        
        # 24시간 옵트아웃
        if metadata.get('opt_out_requested'):
            return None
            
        return text
```

### 모니터링 시스템
```yaml
# prometheus metrics
metrics:
  - emotion_analysis_duration_seconds
  - emotion_cache_hit_ratio
  - bayesian_update_count
  - prediction_error_rate
  - privacy_filter_triggers

alerts:
  - name: HighECE
    expr: emotion_ece > 0.1
    for: 5m
    
  - name: SlowResponse  
    expr: emotion_p95_latency > 500
    for: 10m
```

### 고급 기능
- HDBSCAN 클러스터링 도입
- 감정 전환 패턴 학습
- 멀티모달 확장 준비 (음성/표정)
- 설명가능 AI (LIME/SHAP)

### 확장성
```python
# 수평 확장 준비
class EmotionAnalyzerCluster:
    def __init__(self, workers=4):
        self.workers = workers
        self.load_balancer = ConsistentHash()
    
    async def analyze(self, text, user_id):
        # 사용자별로 일관된 워커 할당
        worker = self.load_balancer.get_worker(user_id)
        return await worker.analyze(text)
```

### 최종 KPI
- ECE: ≤ 0.05
- Brier Score: ≤ 0.18
- NDCG@10: ≥ 0.6
- 응답시간 P95: ≤ 300ms
- 가용성: 99.9%

### 산출물
- [ ] 프라이버시 게이트 시스템
- [ ] Prometheus/Grafana 대시보드
- [ ] 수평 확장 아키텍처
- [ ] HDBSCAN 클러스터링
- [ ] 프로덕션 배포 (Docker/K8s)
- [ ] 운영 문서 및 Runbook

---

## 리스크 및 완화 방안

### 기술적 리스크
1. **ChromaDB 성능 한계**
   - 완화: Redis 캐시 레이어 추가
   - 대안: Pinecone/Weaviate 검토

2. **모델 추론 속도**
   - 완화: ONNX 변환, 양자화
   - 대안: DistilBERT 기반 경량 모델

3. **베이지안 계산 복잡도**
   - 완화: 근사 알고리즘 사용
   - 대안: 단순 EMA로 대체

### 데이터 리스크
1. **라벨 품질**
   - 완화: 다중 라벨러, 합의 메커니즘
   - 대안: 약지도 학습

2. **개인정보 유출**
   - 완화: 로컬 처리, 암호화
   - 대안: 연합 학습

### 운영 리스크
1. **서비스 장애**
   - 완화: Circuit breaker, 폴백
   - 대안: 기본 감정만 제공

2. **비용 증가**
   - 완화: 사용량 기반 스케일링
   - 대안: 엣지 디바이스 처리

---

## 성공 기준

### Phase별 체크포인트
- **Phase 1**: 5개 감정 인식 작동 확인
- **Phase 2**: 200ms 응답시간 달성
- **Phase 3**: 9개 감정 정확도 80%
- **Phase 4**: 개인화 효과 측정 가능
- **Phase 5**: 프로덕션 안정성 99.9%

### 전체 프로젝트 성공 지표
1. **사용자 만족도**: NPS 40 이상
2. **기술 성능**: 모든 KPI 목표치 달성
3. **비즈니스 가치**: 사용자 이탈률 20% 감소
4. **확장 가능성**: 일 100만 요청 처리

---

---

*이 로드맵은 이상적인 설계를 현실적으로 구현 가능한 단계로 나눈 실행 계획입니다. 각 Phase는 독립적으로 가치를 제공하며, 상황에 따라 중단하거나 방향을 전환할 수 있습니다.*