- Move: plans/251204_emotion_based_addressing_system.md → troubleshooting/ - Update: 312 원칙 명확화 (plans vs troubleshooting 구분) - Add: 시나리오/테스트 별도 파일 금지 명시 - Follow: 구현 완료 시 troubleshooting 이동 규칙 준수
145 lines
5.4 KiB
Markdown
145 lines
5.4 KiB
Markdown
# 감정 기반 호칭 시스템 구현
|
||
|
||
**작성일**: 2025-12-04
|
||
**수정일**: 2025-12-04 (v2 구현 완료)
|
||
**작성자**: happybell80
|
||
**관련 파일**: `services/addressing_service.py`, `state/database.py`, `router/router.py`
|
||
|
||
---
|
||
|
||
## 배경 및 목표
|
||
|
||
- 현재: 모든 사용자를 "사용자님" 또는 `user.name`으로 획일적 호칭
|
||
- 문제: 감정 상태/상황 무시, `metadata` (nickname, position) 미활용
|
||
- 목표: 감정 기반 호칭 동적 변경으로 공감 능력 강화, 한국 직장 문화 존중 표현
|
||
|
||
## 조사 결과 (웹 검색)
|
||
|
||
**한국어 호칭 원칙**:
|
||
- 친밀한 관계: 별명/애칭 사용
|
||
- 공식적/부정적 상황: 정식 이름 사용
|
||
- 출처: 한국어 호칭 연구, UX 라이팅 전략
|
||
|
||
**AI 감정 반응**:
|
||
- 챗GPT emotional rebound 효과: 부정 → 위로, 긍정 → 친근
|
||
- 출처: 프랑크 바르돌 연구 (m.etnews.com)
|
||
|
||
**직장 문화**: 직책 호칭 최우선 (대표님, 이사님)
|
||
|
||
## 설계 결정
|
||
|
||
### 방식: 휴리스틱 규칙 (Python)
|
||
|
||
이유: 일관성, 속도, 예측 가능성, 제어 용이
|
||
LLM 역할: 결정된 호칭 자연스럽게 사용만
|
||
|
||
### 호칭 결정 규칙 (v1 - 구현 완료)
|
||
|
||
| 조건 | 호칭 |
|
||
|------|------|
|
||
| `metadata->>'position'` 있음 | "대표님", "이사님" |
|
||
| 긍정 감정 + position 없음 | `metadata->>'nickname'` → "joann님" |
|
||
| 부정 감정 + position 없음 | `user.name` → "이고은님" |
|
||
| nickname 없음 | `user.name` 성 제외 → "고은님" |
|
||
|
||
**긍정 감정**: happiness, surprise, neutral
|
||
**부정 감정**: fear, anger, sadness, disgust
|
||
**감정 소스**: emotion_readings 최근 10분 평균 (현재 메시지 가중치 2배)
|
||
|
||
**v1 문제점**: 직책 있으면 감정 무관 → 상황별 미묘한 차이 표현 불가
|
||
|
||
## 구현 (계층 분리 원칙 준수)
|
||
|
||
### 계층 구조
|
||
```
|
||
router.py (감정 분석 후)
|
||
↓
|
||
services/addressing_service.py (신규, 호칭 결정 비즈니스 로직)
|
||
↓
|
||
state/database.py (DB CRUD만)
|
||
```
|
||
|
||
### 1. services/addressing_service.py (신규)
|
||
**기능**: 호칭 결정 비즈니스 로직
|
||
- `get_preferred_name(user_id: str, current_emotion: str) -> str`
|
||
- state 호출: user 정보, 최근 감정 조회
|
||
- 호칭 규칙 적용 (직책 → 긍정감정=nickname → 부정감정=정식이름)
|
||
- 약 100줄 예상
|
||
|
||
### 2. state/database.py
|
||
**기존 함수 확인 후**:
|
||
- 없으면 추가: `get_user_basic_info(user_id)` - name, metadata 반환
|
||
- 없으면 추가: `get_recent_emotions(user_id, minutes=10)` - 감정 평균
|
||
- DB CRUD만, 비즈니스 로직 금지
|
||
|
||
### 3. router.py:282-286
|
||
**수정**: addressing_service 호출, 현재 감정 결과 전달
|
||
|
||
### 4. llm_service.py:134-135
|
||
**수정**: system_instruction에 호칭 지시, 호칭 남발 방지 (첫 문장 1회만)
|
||
|
||
### 5. tables.md:44
|
||
**추가**: user.metadata 컬럼 (nickname, position, short_name)
|
||
|
||
## 테스트 시나리오
|
||
|
||
1. **긍정+직책**: "고마워요" (happiness) + position="대표" → "대표님"
|
||
2. **긍정+no직책**: "좋은 아침" (happiness) + nickname="joann" → "joann님"
|
||
3. **부정+no직책**: "힘들어요" (sadness) + name="이고은" → "이고은님"
|
||
4. **중립**: "날씨는?" (neutral) + name="김종태" → "종태님"
|
||
|
||
## 검증
|
||
|
||
- 로그: `docker logs rb8001 | grep "Preferred name"`
|
||
- DB: emotion_readings 최근 10분 평균 확률 조회
|
||
- API: /api/message 엔드포인트로 JWT 인증 테스트
|
||
|
||
## v2 구현 완료 (복합 감정 기반)
|
||
|
||
### 변경 내용
|
||
- addressing_service.py:200줄 - 5단계 호칭 로직, top_emotions + entropy 활용
|
||
- database.py:+108줄 - get_recent_emotion_details() 추가
|
||
- router.py:+2줄 - 현재 감정 결과 전달
|
||
- llm_service.py:+1줄 - 호칭 남발 방지 (첫 문장 1회만)
|
||
|
||
### 최종 호칭 규칙
|
||
|
||
| 조건 | 호칭 | 예시 |
|
||
|------|------|------|
|
||
| fear+sadness >= 0.6 | 김종태 이사님 | "너무 힘들고 불안해요..." |
|
||
| anger/disgust 높음 | 이사님 | "정말 화나네요!" |
|
||
| neutral 또는 entropy 높음 | 이사님 | "좋긴 한데 걱정도..." |
|
||
| happiness >= 0.99, surprise < 0.02 | 종태님 | "정말 감사합니다!" |
|
||
| 기타 긍정 | 종태 이사님 | (감정 분석 한계로 미작동) |
|
||
|
||
### 테스트 결과: 6/8 성공 (75%)
|
||
|
||
**성공**: 매우 부정(김종태 이사님), 부정(이사님), 중립(이사님/종태 이사님), 매우 긍정(종태님)
|
||
**실패**: 중간 긍정(종태 이사님) - 감정 분석기가 "좋아요"도 0.99로 분석
|
||
|
||
### Git 커밋
|
||
v1: `a26e7b6`, `c8052f7`
|
||
v2: `84b26b6`, `52d906b`, `71806b0`, `41dcc0a`
|
||
|
||
## 교훈
|
||
|
||
### 원인
|
||
v1에서 직책 있으면 감정 무관 호칭 → UX 피드백으로 감정별 차별화 필요 발견
|
||
|
||
### 교훈
|
||
1. **모델 검증 우선**: 임계값 튜닝 전 감정 분석기 정확도 확인 필수 (증상 치료 vs 본질 해결)
|
||
2. **TDD 효과**: 10개 시나리오로 한계 조기 발견, 75% 정확도 수용 판단
|
||
3. **실용적 타협**: 완벽 추구보다 3단계 호칭 실사용 선택
|
||
|
||
### 원칙 준수
|
||
- ✅ 311: 계층 분리 (router → services → state)
|
||
- ✅ 312: 문서 통합 (plans → troubleshooting 이동, 중복 문서 3개 삭제)
|
||
- ⚠️ 311: database.py 650줄 초과 → emotion_repository.py 분리 예정
|
||
|
||
## 관련 문서
|
||
|
||
- [[tables.md]](../book/300_architecture/database/tables.md)
|
||
- [[230_감정윤리_필터]](../book/200_core_design/230_감정윤리_필터_LLM후처리와_정체성.md)
|
||
- [[311_FastAPI_구조_원칙]](../book/300_architecture/311_FastAPI_구조_원칙.md)
|
||
|