# 로빙 감정 분석 시스템 구현 계획

> 사용자의 사양(7개 감정, klue/bert-base, Temperature Scaling, ONNX 추론)을 전제로, 로빙이 감정 그래프를 생성하고 제공하기 위한 구현 순서와 운영 항목을 정리한 문서입니다.

---

## 1. 목표와 범위

로빙은 한국어 텍스트 입력을 받아 7개 감정(fear, surprise, anger, sadness, neutral, happiness, disgust) 확률을 산출하고, 보정된 확률 기반의 시계열 그래프와 요약 리포트를 제공합니다. 실시간 대화형(배치 1)과 비동기 배치(8–32) 처리를 모두 지원합니다.

**[현재 프로젝트 상태]** app/core/emotion/base.py에 9개 감정 임시 균등값만 존재. EMOTION_TEMPERATURE 변수 있으나 스케일링 미적용. ONNX 추론 미통합. emotion_readings 테이블 없음. /v1/emotion/* API 엔드포인트 미구현 (test_endpoint.py의 /emotion만 존재).

## 2. 모델 파이프라인

*   **입력 전처리:** `klue/bert-base` 토크나이저 사용, 최대 길이 128로 고정, 잘림 규칙 명시.
*   **추론 모델:** 7개 클래스 단일 라벨 분류기. 원시 로짓(logits)을 산출.
*   **확률 보정:** Temperature Scaling `Softmax(z/T)`으로 확률 보정.
*   **후처리:**
    *   최댓값 확률과 엔트로피 계산.
    *   임계값(기본 τ=0.45) 미만은 `unknown`으로 강등.
*   **버저닝:** `model_version`과 `temperature` 값을 쌍으로 관리. 모델 교체 시 T를 반드시 재추정.

## 3. Temperature Scaling 운용

*   **학습:** 검증 세트(validation set)로만 T 값을 추정 (L-BFGS-B 알고리즘, 목적 함수 NLL, 보조 지표 ECE).
*   **관리:** 배포 구성 파일에 모델 버전별 T 값을 기록. 모델 교체 시 재보정 필수.
*   **품질 기준:** 보정 전 대비 NLL 및 ECE 감소를 최소 기준으로 삼음.

## 4. ONNX 변환 및 추론 최적화

*   **변환:** `transformers optimum` 또는 `onnx export` 사용 (opset 17, 동적 축 지정).
*   **실행:** ONNX Runtime, 그래프 최적화 `ORT_ENABLE_ALL`, 스레드 수 고정.
*   **양자화 (선택):** 동적 양자화 적용 후 정밀도, 지연, ECE 재점검.
*   **지연 관리:** 실시간 p95 지연 목표 수립 (예: 40–80ms on CPU, 10–20ms on GPU).

## 5. 저장 스키마

`emotion_readings` 테이블에 다음 항목을 저장합니다.

*   `user_id`, `source`, `ts`, `text_hash`
*   `model_version`, `temperature`
*   `logits[7]`, `probs[7]`
*   `top_label`, `top_p`, `entropy`, `meta`

**주요 인덱스:**
*   `(user_id, ts)` 복합 인덱스
*   `meta` GIN 인덱스

> **참고:** 원문 텍스트는 별도 저장소에 암호화하여 저장하고, 본 테이블에는 해시값만 유지합니다.

## 6. 서비스 API

*   `POST /v1/emotion/infer`: 단건 추론. 보정 확률, 라벨, 엔트로피, `top_p`, `model_version`, `temperature`, `ts` 반환.
*   `POST /v1/emotion/infer:batch`: 최대 128건 배치 처리. 서버 내부에서 마이크로배칭 및 캐시 적용.
*   `GET /v1/emotion/timeseries`: 기간 및 빈도(`bin=1h` 등)별 평균 확률, 지배 라벨, 평균 엔트로피 반환.

## 7. 시각화 설계

*   **지배 라벨 타임라인:** 시간축에 최댓값 라벨을 색상 구간으로 표시. EMA(α=0.2) 또는 이동평균을 적용하여 진동 완화.
*   **확률 시계열:** 7개 라벨의 확률을 선 그래프로 표시. 기본적으로 상위 2–3개만 강조하고 나머지는 토글로 제어.
*   **분포 그래프:** 일/시간대별 스택 영역 차트로 감정 비중 요약.
*   **불확실성 표현:** 엔트로피가 높을수록 그래프의 음영 또는 투명도를 조절하여 시각적으로 표현.
*   **Slack 연동:** 최근 24시간 요약 텍스트(상위 라벨, 평균 엔트로피 등)와 함께 정적 PNG 그래프 또는 대시보드 링크를 제공.

## 8. 운영 및 모니터링

*   **모델 건전성:** 주간 혼동 행렬, 라벨별 평균 확률, ECE, NLL 트래킹.
*   **데이터 분포:** 사용자별 라벨 분포가 전체 대비 과도하게 치우치면 점검 알림.
*   **성능:** p95 추론 지연, 큐 대기 시간, 배치 처리량 모니터링.
*   **알림 정책:** 부정 라벨 비중이 지속적으로 상승하거나 엔트로피가 급증하는 구간을 탐지. 단, 알림은 사용자 동의 범위 내에서만 제안형으로 표시.

## 9. 보안과 프라이버시

*   **원문 보호:** 원문은 암호화하여 저장하거나 비식별화 처리 후 해시만 유지.
*   **삭제 권리:** 사용자가 기간을 지정하여 데이터를 삭제할 수 있는 API 지원.
*   **접근 제어:** 본인과 관리자만 열람 가능하도록 스코프 분리. 감사 로그는 최소한으로 기록.

## 10. 배포 체크리스트

- [ ] 검증 세트 분리 및 T 추정 완료
- [ ] ONNX와 PyTorch 결과의 최대 오차 검증
- [ ] 보정 전후 NLL·ECE 비교 리포트 산출
- [ ] 지연 시간 목표(p95) 만족 여부 확인
- [ ] Slack 메시지 규격 및 이미지 렌더러 동작 확인
- [ ] 모델 버전, T, 임계값 τ 설정이 구성 서버에 반영되었는지 점검

## 11. 1주 구현 순서 (예시)

*   **1일차:** 모델 가중치 확정, 검증 세트 준비, T 추정.
*   **2일차:** ONNX 변환 및 추론 엔진 래퍼, 단건 API 구현.
*   **3일차:** 배치 API, 저장 스키마 및 리포지토리 구현.
*   **4일차:** 시계열 집계 로직, EMA 적용, 그래프 렌더러 구현.
*   **5일차:** Slack 요약 카드, PNG 업로드, 권한 및 로깅 적용.
*   **6일차:** 품질 대시보드 구축 (ECE, NLL, 혼동 행렬).
*   **7일차:** 부하/지연 테스트, 문서화 및 운영 기준 수립.
