This commit is contained in:
happybell80 2025-12-04 16:52:48 +09:00
commit 800508f9eb
5 changed files with 281 additions and 3 deletions

View File

@ -48,6 +48,7 @@
{ {
"nickname": "joann", "nickname": "joann",
"position": "CEO", "position": "CEO",
"short_name": "고은",
"department": "경영", "department": "경영",
"preferences": { "preferences": {
"communication": "direct", "communication": "direct",

View File

@ -0,0 +1,95 @@
# 감정 기반 호칭 시스템 테스트 결과
**작성일**: 2025-12-04
**작성자**: happybell80
**테스트 대상**: 김종태 (UUID: 1a7ebe8c-1cfd-4acf-a821-2cc526313706, position: CTO)
---
## 테스트 결과: 6/7 성공 (85.7%)
### 성공한 시나리오
| 번호 | 메시지 | 감정 | 예상 호칭 | 실제 응답 | 결과 |
|------|--------|------|-----------|-----------|------|
| 2 | "너무 힘들어요... 스트레스 받아요" | sadness | CTO님 | "CTO님, 얼마나 힘드신지..." | ✅ |
| 3 | "오늘 날씨 어때요?" | neutral | CTO님 | "CTO님, 오늘 날씨는..." | ✅ |
| 4 | "감사합니다!" | happiness | CTO님 | "CTO님, 제가 조금이라도..." | ✅ |
| 5 | "화가 나요..." | anger | CTO님 | "CTO님, 얼마나 힘든지..." | ✅ |
| 6 | "불안하고 걱정돼요..." | fear | CTO님 | "CTO님, 얼마나 불안하고..." | ✅ |
| 7 | "좋은 아침이에요!" | happiness | CTO님 | "CTO님, 좋은 아침입니다!" | ✅ |
### 실패한 시나리오
| 번호 | 메시지 | 감정 | 예상 호칭 | 실제 응답 | 결과 |
|------|--------|------|-----------|-----------|------|
| 1 | "고마워요! 오늘 일정 알려주세요" | happiness | CTO님 | "12월 04일에 등록된 일정이 없습니다." | ❌ |
**실패 원인**: 일정 조회 의도로 분류되어 calendar 스킬로 라우팅, 해당 스킬에서 호칭 미사용
---
## 구현 완료 사항
### 신규 파일
- `app/services/addressing_service.py` (95줄): 호칭 결정 비즈니스 로직
### 수정 파일
- `app/state/database.py`: user 조회, 감정 평균 함수 추가 (108줄)
- `app/router/router.py`: 감정 분석 후 호칭 결정 로직 통합 (4줄)
- `app/services/llm/llm_service.py`: system_instruction에 호칭 지시 추가 (4줄)
- `DOCS/book/300_architecture/database/tables.md`: short_name 필드 추가 (1줄)
**총 코드 변경**: 약 212줄
### Git 커밋
- `a26e7b6`: Add emotion-based addressing system
- `c8052f7`: Fix SQL query: INTERVAL parameter binding
---
## 로그 검증
```
Emotion detected: happiness (confidence: 0.99)
Preferred name: CTO님
```
✅ 호칭 결정 로직 정상 작동
✅ LLM에 호칭 전달 확인
✅ 응답에 호칭 포함 확인
---
## 계층 분리 원칙 준수
```
router.py (HTTP)
addressing_service.py (비즈니스 로직)
database.py (DB CRUD)
```
✅ 311_FastAPI_구조_원칙.md 준수
✅ 계층 간 책임 명확히 분리
✅ 순환 참조 없음
---
## 향후 개선 사항
1. **calendar 스킬 통합**: 일정 조회 응답에도 호칭 포함
2. **nickname 테스트**: metadata에 nickname 설정 후 테스트
3. **감정 변화 테스트**: 연속 대화에서 감정에 따른 호칭 변화 확인
4. **A/B 테스트**: 사용자 만족도 비교 (호칭 on/off)
---
## 교훈
1. **API 응답 구조 확인 필수**: 테스트 스크립트 작성 시 실제 응답 필드명 확인 필요
2. **SQL 파라미터 바인딩**: INTERVAL 같은 SQL 키워드는 f-string으로 처리
3. **로그 기반 디버깅**: docker logs로 실제 동작 확인 (Preferred name 로그)
4. **TDD 효과**: 시나리오 먼저 작성 → 코드 구현 → 테스트 → 버그 수정 흐름 효과적

View File

@ -0,0 +1,78 @@
# 감정 기반 호칭 시스템 UX 시나리오
**작성일**: 2025-12-04
**테스트 대상**: 김종태 (UUID: 1a7ebe8c-1cfd-4acf-a821-2cc526313706)
---
## 시나리오 1: 긍정 감정 + 직책 있음
**입력**: "고마워요! 오늘 일정 알려주세요"
**감정**: happiness
**예상 호칭**: "CTO님"
**검증**: 응답에 "CTO님" 포함
## 시나리오 2: 부정 감정 + 직책 있음
**입력**: "너무 힘들어요... 스트레스 받아요"
**감정**: sadness
**예상 호칭**: "CTO님" (직책 우선)
**검증**: 응답에 "CTO님" 포함
## 시나리오 3: 중립 감정 + 직책 있음
**입력**: "오늘 날씨 어때요?"
**감정**: neutral
**예상 호칭**: "CTO님"
**검증**: 응답에 "CTO님" 포함
## 시나리오 4: 긍정 감정 + nickname 설정
**설정**: metadata에 nickname="JT" 추가, position 제거
**입력**: "좋은 아침이에요!"
**감정**: happiness
**예상 호칭**: "JT님"
**검증**: 응답에 "JT님" 포함
## 시나리오 5: 부정 감정 + nickname 설정
**설정**: metadata에 nickname="JT", position 없음
**입력**: "힘들어요... 도와주세요"
**감정**: sadness
**예상 호칭**: "김종태님" (정식 이름)
**검증**: 응답에 "김종태님" 포함
## 시나리오 6: metadata 없음 + 긍정 감정
**설정**: metadata={}
**입력**: "감사합니다!"
**감정**: happiness
**예상 호칭**: "종태님" (성 제외)
**검증**: 응답에 "종태님" 포함
## 시나리오 7: metadata 없음 + 부정 감정
**설정**: metadata={}
**입력**: "화가 나요..."
**감정**: anger
**예상 호칭**: "김종태님" (정식 이름)
**검증**: 응답에 "김종태님" 포함
## 시나리오 8: 복합 감정 (fear + sadness)
**입력**: "불안하고 걱정돼요..."
**감정**: fear
**예상 호칭**: "CTO님" (직책 우선)
**검증**: 응답에 "CTO님" 포함, 위로 톤
## 시나리오 9: 연속 대화 (감정 변화)
**1단계**: "힘들어요" (sadness) → "CTO님"
**2단계**: "고마워요!" (happiness) → "CTO님"
**검증**: 감정 변화에도 직책 호칭 유지
## 시나리오 10: 감정 분석 실패 케이스
**설정**: USE_EMOTION_ANALYSIS=false
**입력**: "안녕하세요"
**예상 호칭**: "CTO님" (기본값)
**검증**: 에러 없이 정상 응답
---
## 검증 방법
1. 웹 UI 직접 테스트 (http://localhost:8000)
2. API 엔드포인트 테스트 (curl)
3. Docker 로그 확인 (Preferred name)
4. emotion_readings 테이블 확인

View File

@ -0,0 +1,72 @@
# 감정 기반 호칭 v2 UX 시나리오
**작성일**: 2025-12-04
**테스트 대상**: 김종태 (UUID: 53529291-5050-4daa-89fb-008b546feb63, position: 이사)
---
## 시나리오 1: 매우 부정 (fear+sadness)
**입력**: "너무 힘들고 불안해요... 실패할까봐 두려워요"
**예상 감정**: fear(0.5) + sadness(0.3), entropy 낮음
**예상 호칭**: "김종태 이사님" (최대 존중 + 위로)
**검증**: 응답에 "김종태 이사님" 포함, 위로 톤
## 시나리오 2: 부정 (anger 단독)
**입력**: "정말 화나네요!"
**예상 감정**: anger(0.8), 단독 높음
**예상 호칭**: "이사님" (격식 유지)
**검증**: 응답에 "이사님" 포함, 공감 톤
## 시나리오 3: 부정 (disgust)
**입력**: "이건 정말 별로네요"
**예상 감정**: disgust(0.7)
**예상 호칭**: "이사님"
**검증**: 응답에 "이사님" 포함
## 시나리오 4: 중립 (애매한 감정)
**입력**: "좋긴 한데 걱정도 되고..."
**예상 감정**: happiness(0.4) + fear(0.3), entropy 높음
**예상 호칭**: "이사님" (안전 선택)
**검증**: 응답에 "이사님" 포함
## 시나리오 5: 중립 (neutral 단독)
**입력**: "오늘 날씨 어때요?"
**예상 감정**: neutral(0.7)
**예상 호칭**: "이사님"
**검증**: 응답에 "이사님" 포함
## 시나리오 6: 긍정 (happiness 0.5-0.9)
**입력**: "좋아요! 잘 됐네요"
**예상 감정**: happiness(0.75)
**예상 호칭**: "종태 이사님" (친근 + 존중)
**검증**: 응답에 "종태 이사님" 포함
## 시나리오 7: 긍정 (happiness + surprise)
**입력**: "완전 좋아요! 최고예요!"
**예상 감정**: happiness(0.6) + surprise(0.25)
**예상 호칭**: "종태 이사님"
**검증**: 응답에 "종태 이사님" 포함
## 시나리오 8: 매우 긍정 (happiness 0.9+)
**입력**: "정말 감사합니다! 너무 좋아요!"
**예상 감정**: happiness(0.95)
**예상 호칭**: "종태님" (친밀, 직책 생략)
**검증**: 응답에 "종태님" 포함
## 시나리오 9: 연속 대화 (부정→긍정)
**1단계**: "힘들어요..." (sadness) → "이사님"
**2단계**: "고마워요!" (happiness 0.9+) → "종태님"
**검증**: 감정 변화에 따른 호칭 전환
## 시나리오 10: 호칭 남발 방지
**입력**: "오늘 일정 알려주세요"
**예상 호칭**: "이사님" (1회만)
**검증**: 응답에 "이사님"이 1-2회만 등장 (남발 X)
---
## 성공 기준
- 8/10 이상 정확한 호칭 사용
- 호칭 남발 없음 (응답당 1-2회)
- 감정 변화 시 자연스러운 전환

View File

@ -1,8 +1,9 @@
# 감정 기반 호칭 시스템 구현 # 감정 기반 호칭 시스템 구현
**작성일**: 2025-12-04 **작성일**: 2025-12-04
**수정일**: 2025-12-04 (복합 감정 기반 개선안 추가)
**작성자**: happybell80 **작성자**: happybell80
**상태**: 계획 **상태**: v1 구현 완료, v2 계획
--- ---
@ -32,11 +33,11 @@
이유: 일관성, 속도, 예측 가능성, 제어 용이 이유: 일관성, 속도, 예측 가능성, 제어 용이
LLM 역할: 결정된 호칭 자연스럽게 사용만 LLM 역할: 결정된 호칭 자연스럽게 사용만
### 호칭 결정 규칙 ### 호칭 결정 규칙 (v1 - 구현 완료)
| 조건 | 호칭 | | 조건 | 호칭 |
|------|------| |------|------|
| `metadata->>'position'` 있음 | "대표님", "이사님" (감정 무관) | | `metadata->>'position'` 있음 | "대표님", "이사님" |
| 긍정 감정 + position 없음 | `metadata->>'nickname'` → "joann님" | | 긍정 감정 + position 없음 | `metadata->>'nickname'` → "joann님" |
| 부정 감정 + position 없음 | `user.name` → "이고은님" | | 부정 감정 + position 없음 | `user.name` → "이고은님" |
| nickname 없음 | `user.name` 성 제외 → "고은님" | | nickname 없음 | `user.name` 성 제외 → "고은님" |
@ -45,6 +46,8 @@ LLM 역할: 결정된 호칭 자연스럽게 사용만
**부정 감정**: fear, anger, sadness, disgust **부정 감정**: fear, anger, sadness, disgust
**감정 소스**: emotion_readings 최근 10분 평균 (현재 메시지 가중치 2배) **감정 소스**: emotion_readings 최근 10분 평균 (현재 메시지 가중치 2배)
**v1 문제점**: 직책 있으면 감정 무관 → 상황별 미묘한 차이 표현 불가
## 구현 (계층 분리 원칙 준수) ## 구현 (계층 분리 원칙 준수)
### 계층 구조 ### 계층 구조
@ -122,4 +125,33 @@ curl -X POST http://192.168.219.52:8001/api/message \
- [[tables.md]](../book/300_architecture/database/tables.md) - [[tables.md]](../book/300_architecture/database/tables.md)
- [[230_감정윤리_필터]](../book/200_core_design/230_감정윤리_필터_LLM후처리와_정체성.md) - [[230_감정윤리_필터]](../book/200_core_design/230_감정윤리_필터_LLM후처리와_정체성.md)
- [[311_FastAPI_구조_원칙]](../book/300_architecture/311_FastAPI_구조_원칙.md) - [[311_FastAPI_구조_원칙]](../book/300_architecture/311_FastAPI_구조_원칙.md)
- [[251204_addressing_test_report]](251204_addressing_test_report.md)
---
## 개선 계획 (v2) - 복합 감정 기반
### 배경
v1에서 직책 있으면 감정 무관 → 상황별 미묘한 차이 표현 불가
### 복합 감정 5단계 호칭 (직책 + 감정 조합)
| 감정 상태 | 호칭 | 예시 |
|----------|------|------|
| 매우 부정 (fear+sadness, entropy 낮음) | **김종태 이사님** | "힘들고 불안해요" |
| 부정 (anger/disgust 단독) | **이사님** | "화나요" |
| 중립 (neutral 또는 entropy 높음) | **이사님** | "좋긴 한데..." |
| 긍정 (happiness 단독 0.5-0.9) | **종태 이사님** | "완전 좋아요!" |
| 매우 긍정 (happiness 0.9+, 누적 긍정) | **종태님** | "최고예요!" (10회차) |
### 구현 변경
- `addressing_service.py`: top_emotions + entropy + 누적 감정 활용 (약 30-40줄 수정)
- `llm_service.py`: system_instruction에 "호칭은 첫 문장 1회만" 추가 (호칭 남발 방지)
### 기대 효과
1. 감정 미묘함 반영 (복합 감정 패턴)
2. 호칭 변동 완화 (entropy로 확신도 반영)
3. 상황별 거리감 조절 (스트레스/갈등/협업/잡담)
4. 관계 진화 표현 (시간 경과 시 친밀화)
5. 오판 보완 (top-p 70% 안정성)