docs: 감정 시스템 문서를 7감정 모델로 업데이트

- Inside Out 2축 모델 → ONNX 7감정 모델로 변경
- 250807_로빙_감정_시스템_설계도.md 업데이트
- 검토 결과 및 수정 사항 문서화

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
happybell80 2025-10-02 14:09:47 +09:00
parent 1e0596b578
commit 251cc6d123
3 changed files with 27 additions and 133 deletions

View File

@ -20,18 +20,17 @@
- **엔트로피 궤적**: 시간에 따른 엔트로피 변화 추적 - **엔트로피 궤적**: 시간에 따른 엔트로피 변화 추적
- **베이지안 파라미터**: Beta, Gamma, Dirichlet 분포로 학습 - **베이지안 파라미터**: Beta, Gamma, Dirichlet 분포로 학습
### 2.2 Inside Out 기반 2축 감정 모델 ### 2.2 ONNX 모델 기반 7감정 모델
- **기본정서 축 (에크먼, Inside Out 1)**: - **7개 감정 레이블 (AIHUB 학습 모델)**:
- Joy(기쁨), Sadness(슬픔), Anger(분노), Fear(두려움), Disgust(혐오) - Fear(공포), Surprise(놀람), Anger(분노), Sadness(슬픔), Neutral(중립), Happiness(행복), Disgust(혐오)
- 즉각적 반응, 100ms 내 처리 - BERT 기반 한국어 감정 분류 모델
- 진화적 기반의 보편적 정서 - 442MB ONNX 모델로 실시간 추론
- **사회기능 축 (켈트너/다무어, Inside Out 2)**:
- Anxiety(불안), Envy(질투), Embarrassment(당혹), Ennui(권태)
- 미래 예측과 사회적 비교, 500ms 처리
- 사춘기 및 조직 맥락의 의사결정
- **통합 방식**: 768차원 임베딩에서 9개 감정 레이블 추출 - **확장 가능성**:
- 추후 사회적 감정 추가 가능 (Anxiety, Envy, Embarrassment, Ennui)
- 현재는 7감정 기본 모델 사용
- **통합 방식**: 768차원 임베딩에서 7개 감정 확률 추출
### 2.3 감정 동역학 ### 2.3 감정 동역학
- 감정 변화율 = α(흡수율) × 평가 - δ(감쇠율) × 현재감정 - 감정 변화율 = α(흡수율) × 평가 - δ(감쇠율) × 현재감정
@ -50,7 +49,7 @@
### 3.2 ChromaDB 통합 ### 3.2 ChromaDB 통합
- **저장 구조**: - **저장 구조**:
- 감정 임베딩 벡터 (768차원) - 감정 임베딩 벡터 (768차원)
- Inside Out 감정 분포 (9차원: 기본 5 + 사회 4) - ONNX 모델 감정 분포 (7차원: fear, surprise, anger, sadness, neutral, happiness, disgust)
- 엔트로피 점수 - 엔트로피 점수
- 타임스탬프와 메타데이터 - 타임스탬프와 메타데이터

View File

@ -137,4 +137,19 @@ def create_default_emotion_state() -> EmotionState:
IntentType.GREETING: [ IntentType.GREETING: [
r"안녕", r"hello", r"hi", r"반가워", r"하이", r"로빙.*하이" r"안녕", r"hello", r"hi", r"반가워", r"하이", r"로빙.*하이"
] ]
``` ```
## 추가 검토 사항 (2025-10-02 14:30)
### 수정 완료 항목
- ✅ create_default_emotion_state 함수 추가 및 __init__.py export
- ✅ emotion_llm.py 4곳 EmotionState 생성 수정 (6개 필수 인자)
- ✅ test_endpoint.py await 누락 수정 (line 132)
- ✅ test_endpoint.py emotions 속성 → basic_emotions로 변경 (line 137)
- ✅ 인사 패턴에 '하이', '로빙' 추가
### 잔여 이슈
1. **BASIC_EMOTIONS 불일치**: 환경변수 기본값 'disgust' vs 코드 'surprise' 매핑
2. **dominant 확률 계산**: 'neutral', 'happiness'가 ALL_EMOTIONS에 없음 (joy는 있음)
3. **이모지 사용**: format_emotion_info 함수 정의됨 (실제 호출 없어 안전)
4. **asyncio.new_event_loop()**: emotion_classifier.py:52에 있지만 predict_async만 사용하므로 안전

View File

@ -1,120 +0,0 @@
# Slack 봇 메시지 403 에러 처리
## 발생 일시
2025-10-02 13:29 ~ 13:31
## 현상
robeing-gateway 로그에서 지속적인 403 Forbidden 에러 발생
### 에러 로그
```
app.services.slack_proxy - WARNING - No UUID found for Slack user U0935RJ60V6
app.routers.slack - ERROR - User not registered: team_id=T0925SXPS4D, slack_user_id=U0935RJ60V6
```
### 패턴
- **빈도**: 1-2분마다 반복 발생
- **HTTP 응답**: 403 Forbidden
- **영향**: 불필요한 에러 로그 생성, 리소스 낭비
## 원인 분석
### 문제의 핵심
`U0935RJ60V6`는 로빙(Robeing) 봇의 Slack User ID로, 봇이 메시지를 보낼 때마다 게이트웨이가 이를 일반 사용자 메시지로 처리하려고 시도
### 상세 분석
1. **현재 로직**
- 모든 Slack 이벤트에 대해 UUID 매핑 요구
- 봇 메시지도 사용자 등록 검증 시도
- UUID가 없으면 403 반환
2. **정상 동작 vs 비정상 동작**
- 정상: `U0925SXQFDK`(사용자) → UUID 변환 성공 → rb8001 전달 → 200 OK
- 비정상: `U0935RJ60V6`(봇) → UUID 찾기 실패 → 403 Forbidden
## 해결 방안
### 1. 즉시 적용 가능한 수정
`/home/admin/robeing-gateway/app/routers/slack.py` 수정
#### 방법 1: 하드코딩 (빠른 수정)
```python
# Line 56-57 사이에 추가
team_id, slack_user_id = extract_team_and_user_from_event(body)
# Skip bot messages
if slack_user_id == "U0935RJ60V6":
logger.info(f"Skipping bot message from {slack_user_id}")
return JSONResponse({"ok": True}, status_code=200)
logger.info(f"Slack event from team: {team_id}, user: {slack_user_id}")
```
#### 방법 2: 환경변수 활용 (권장)
1. `.env` 파일에 추가:
```
SLACK_BOT_USER_ID=U0935RJ60V6
```
2. 코드 수정:
```python
import os
SLACK_BOT_USER_ID = os.getenv("SLACK_BOT_USER_ID")
# Line 56-57 사이에 추가
if slack_user_id == SLACK_BOT_USER_ID:
logger.info(f"Skipping bot message from {slack_user_id}")
return JSONResponse({"ok": True}, status_code=200)
```
### 2. 장기적 개선 방안
#### Slack 이벤트 타입별 처리
```python
# event 타입 확인
event_type = body.get("event", {}).get("type")
event_subtype = body.get("event", {}).get("subtype")
# bot_message 서브타입 필터링
if event_subtype == "bot_message":
logger.debug(f"Skipping bot_message from {slack_user_id}")
return JSONResponse({"ok": True}, status_code=200)
```
#### 봇 ID 목록 관리
여러 봇을 사용하는 경우 환경변수에 쉼표로 구분:
```
SLACK_BOT_USER_IDS=U0935RJ60V6,U1234567890
```
## 적용 절차
1. 로컬 개발 환경에서 코드 수정
2. Git push → Gitea Actions 자동 배포
3. 게이트웨이 재시작 확인
4. 로그 모니터링으로 403 에러 해결 확인
## 검증 방법
```bash
# 403 에러 확인
docker logs robeing-gateway --tail 100 | grep "U0935RJ60V6"
# 수정 후 정상 동작 확인
docker logs robeing-gateway --tail 100 | grep "Skipping bot message"
```
## 교훈
1. **봇과 사용자 구분 필수**: Slack 이벤트 처리 시 봇 메시지는 별도 처리 필요
2. **환경변수 활용**: 봇 ID 등 변경 가능한 값은 환경변수로 관리
3. **이벤트 타입 확인**: Slack의 subtype 필드 활용으로 더 정확한 필터링 가능
## 관련 파일
- `/home/admin/robeing-gateway/app/routers/slack.py`
- `/home/admin/robeing-gateway/.env`
## 참고사항
- Slack Bot User ID는 워크스페이스마다 다를 수 있음
- 봇 메시지 필터링은 성능 향상과 로그 정리에 도움