docs: Phase 1-4 구현 완료 문서 통합 및 계획 문서 업데이트
This commit is contained in:
parent
01a2deacaf
commit
82ab19da2b
@ -1,243 +0,0 @@
|
|||||||
# 로빙 일기(성장 일지) 시스템 계획
|
|
||||||
|
|
||||||
**날짜**: 2025-11-17
|
|
||||||
**목표**: 로빙의 하루 활동/감정 자동 정리 시스템
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 목적
|
|
||||||
|
|
||||||
- 로빙이 하루 활동과 감정 상태를 스스로 정리
|
|
||||||
- 운영자가 행동 변화·감정 흐름·반복 이슈 파악
|
|
||||||
- 책 본문(400_growth)과 관리자 대시보드 재사용 가능한 표준 포맷
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 현재 상태
|
|
||||||
|
|
||||||
**구현됨**:
|
|
||||||
- 대화 로그, intent 리뷰 큐, 감정 모델 (rb8001)
|
|
||||||
- HITL 의도 학습 흐름
|
|
||||||
|
|
||||||
**미구현**:
|
|
||||||
- 자동 일기 생성 시스템
|
|
||||||
- 일기 저장/조회 인터페이스
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 요구사항
|
|
||||||
|
|
||||||
1. **자동 생성**: 매일 오전 2시 또는 3시에 전날(00:00~23:59:59) 일기 자동 생성
|
|
||||||
2. **모든 활동 기록**: 사용자 대화, 자동 스킬 실행(이메일 요약, 뉴스 게시, 브리핑 등), 스케줄러 작업, 에러/경고 로그 포함
|
|
||||||
3. **감정 반영**: 주요 감정, 감정 변화 요약
|
|
||||||
4. **문제 정리**: 장애/실패/리뷰 큐 기반 "배운 점" 서술
|
|
||||||
5. **저장**: DB만 저장 (robeing_diary 테이블), 조회 시 API로 마크다운 동적 생성
|
|
||||||
6. **조회**: 관리자 대시보드 일기 목록/상세 페이지, 선택적으로 DOCS 동기화
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 아키텍처
|
|
||||||
|
|
||||||
### 1. 데이터 수집
|
|
||||||
- **대화 데이터**: `conversation_log` (사용자 대화, intent, confidence)
|
|
||||||
- **활동 데이터**: `activity_log` (자동 스킬 실행: 이메일 요약, 뉴스 게시, 브리핑 등)
|
|
||||||
- **감정 데이터**: `emotion_readings` (감정 변화, 지배적 감정, 엔트로피)
|
|
||||||
- **성장 데이터**: `robeing` 테이블 (스탯, 경험치, 레벨업)
|
|
||||||
- **문제 데이터**: `intent_review_queue` (리뷰 이슈), 애플리케이션 로그 (ERROR/WARNING)
|
|
||||||
- **시간 범위**: 전날 00:00:00 ~ 23:59:59
|
|
||||||
- **Diary Aggregator 함수**: 모든 데이터 집계
|
|
||||||
|
|
||||||
### 2. 활동 로그 기록
|
|
||||||
- 스킬 실행 시 자동으로 `activity_log` 테이블에 기록 (스킬명, 실행 시간, 결과, 에러 발생 여부)
|
|
||||||
- 모든 로빙 활동을 추적하여 일기 집계에 포함
|
|
||||||
|
|
||||||
### 3. 요약·서술
|
|
||||||
- 구조화 데이터(JSON) → 일기 텍스트
|
|
||||||
- 템플릿 + LLM 조합
|
|
||||||
- 섹션: "오늘 한 일", "감정 상태", "문제와 배운 점", "내일 계획"
|
|
||||||
|
|
||||||
### 4. 저장
|
|
||||||
- **DB**: `robeing_diary(date, robeing_id, summary, dominant_emotion, stats JSONB, full_content TEXT)`
|
|
||||||
- **파일**: 저장하지 않음 (API로 동적 생성)
|
|
||||||
- **로빙별 구분**: `robeing_id` 컬럼으로 각 로빙별 일기 관리
|
|
||||||
|
|
||||||
### 5. 조회
|
|
||||||
- **API**: rb8001에 `/api/diary/{date}` 엔드포인트 추가 (DB 조회 후 마크다운 동적 생성)
|
|
||||||
- **관리자 대시보드**: admin-dashboard에 일기 목록/상세 페이지 추가
|
|
||||||
- **DOCS 동기화**: 선택적으로 별도 스크립트로 `DOCS/journey/diary/rb8001/yymmdd_주제.md`에 주기적 동기화
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 일기 포맷
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# 로빙 일기 – 2025-11-17
|
|
||||||
|
|
||||||
## 오늘 한 일
|
|
||||||
- 주요 대화 주제/스킬 요약
|
|
||||||
|
|
||||||
## 감정 상태
|
|
||||||
- 지배적 감정, 변화 요약
|
|
||||||
|
|
||||||
## 문제와 배운 점
|
|
||||||
- 오류/리뷰 큐 이슈, 교훈
|
|
||||||
|
|
||||||
## 내일 계획
|
|
||||||
- 개선 방향, 실험 아이디어
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 구현 상세
|
|
||||||
|
|
||||||
### DB 테이블 스키마
|
|
||||||
|
|
||||||
**robeing_diary 테이블**:
|
|
||||||
```sql
|
|
||||||
CREATE TABLE robeing_diary (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
date DATE NOT NULL,
|
|
||||||
robeing_id VARCHAR(50) NOT NULL,
|
|
||||||
summary TEXT,
|
|
||||||
dominant_emotion VARCHAR(50),
|
|
||||||
stats JSONB DEFAULT '{}',
|
|
||||||
full_content TEXT NOT NULL,
|
|
||||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
||||||
UNIQUE(date, robeing_id)
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_robeing_diary_date ON robeing_diary(date DESC);
|
|
||||||
CREATE INDEX idx_robeing_diary_robeing ON robeing_diary(robeing_id);
|
|
||||||
```
|
|
||||||
|
|
||||||
**activity_log 테이블**:
|
|
||||||
```sql
|
|
||||||
CREATE TABLE activity_log (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
robeing_id VARCHAR(50) NOT NULL,
|
|
||||||
activity_type VARCHAR(50) NOT NULL, -- 'skill', 'scheduler', 'internal'
|
|
||||||
skill_name VARCHAR(100),
|
|
||||||
status VARCHAR(20) NOT NULL, -- 'success', 'error', 'partial'
|
|
||||||
result_summary TEXT,
|
|
||||||
error_message TEXT,
|
|
||||||
metadata JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_activity_log_robeing_date ON activity_log(robeing_id, created_at DESC);
|
|
||||||
CREATE INDEX idx_activity_log_type ON activity_log(activity_type);
|
|
||||||
```
|
|
||||||
|
|
||||||
**참고**: `rb8001/app/state/database.py:44-57` (ConversationLog 모델), `rb8001/app/models/intent_review_model.py:11-32` (IntentReviewQueue 모델)
|
|
||||||
|
|
||||||
### 스킬 실행 로그 기록
|
|
||||||
|
|
||||||
**위치**: 스킬 실행 래퍼 함수 또는 미들웨어
|
|
||||||
- `rb8001/app/services/skills/` 내 각 스킬의 `handle()` 메서드 시작/종료 시 기록
|
|
||||||
- 또는 `rb8001/app/router/router.py`의 스킬 호출 부분에 데코레이터/미들웨어 추가
|
|
||||||
|
|
||||||
**기록 내용**: 스킬명, 실행 시간, 결과(success/error), 에러 메시지(있을 경우), 메타데이터
|
|
||||||
|
|
||||||
### API 엔드포인트
|
|
||||||
|
|
||||||
**rb8001**: `GET /api/diary/{date}?robeing_id=rb8001`
|
|
||||||
- 요청: `date` (YYYY-MM-DD), `robeing_id` (선택, 기본값: rb8001)
|
|
||||||
- 응답: `{"date": "2025-12-09", "robeing_id": "rb8001", "content": "# 로빙 일기...", "summary": "...", "dominant_emotion": "happiness"}`
|
|
||||||
- 구현 위치: `rb8001/app/router/diary.py` (새 파일) 또는 `rb8001/app/router/router.py`
|
|
||||||
|
|
||||||
**참고**: `rb8001/app/state/state_service.py:179-207` (conversation 로그 API 패턴)
|
|
||||||
|
|
||||||
### 스케줄러 등록
|
|
||||||
|
|
||||||
**위치**: `rb8001/main.py:146-195` (startup_event 함수)
|
|
||||||
- `rb8001/app/scheduler/jobs/diary_generator.py` 생성
|
|
||||||
- `scheduler.add_job(diary_generator.generate_diary, 'cron', hour=2, minute=0, id='daily_diary')` 등록
|
|
||||||
|
|
||||||
**참고**: `rb8001/app/scheduler/jobs/naverworks_briefing.py` (스케줄러 작업 예시)
|
|
||||||
|
|
||||||
### LLM 프롬프트 템플릿
|
|
||||||
|
|
||||||
**입력**: 집계된 데이터 (JSON)
|
|
||||||
**출력**: 마크다운 형식 일기
|
|
||||||
**템플릿 구조**:
|
|
||||||
```
|
|
||||||
다음 데이터를 바탕으로 로빙의 하루 일기를 작성하세요:
|
|
||||||
- 대화: {conversations_summary}
|
|
||||||
- 활동: {activities_summary}
|
|
||||||
- 감정: {emotions_summary}
|
|
||||||
- 문제: {issues_summary}
|
|
||||||
- 성장: {growth_summary}
|
|
||||||
|
|
||||||
형식:
|
|
||||||
# 로빙 일기 – {date}
|
|
||||||
## 오늘 한 일
|
|
||||||
...
|
|
||||||
## 감정 상태
|
|
||||||
...
|
|
||||||
## 문제와 배운 점
|
|
||||||
...
|
|
||||||
## 내일 계획
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 구현 단계
|
|
||||||
|
|
||||||
1. ✅ **DB 테이블 생성**: `robeing_diary`, `activity_log` 테이블 생성 완료 (`rb8001/app/state/diary_repository.py`)
|
|
||||||
2. ✅ **활동 로그 기록**: 스킬 실행 시 `activity_log`에 자동 기록 로직 추가 완료 (`ActivityLogger` 구현, `router.py`, `message_service.py` 통합)
|
|
||||||
3. ✅ **Diary Aggregator 구현**: `rb8001/app/services/diary/aggregator.py` 생성, 모든 데이터 소스 집계 완료
|
|
||||||
4. ✅ **일기 생성 로직**: `rb8001/app/services/diary/generator.py` 생성, LLM으로 일기 텍스트 생성 완료
|
|
||||||
5. ✅ **스케줄러 등록**: `rb8001/app/scheduler/jobs/diary_generator.py` 생성, `main.py`에 등록 완료
|
|
||||||
6. ✅ **API 엔드포인트**: `rb8001/app/router/diary_endpoint.py` 생성, `/api/diary/{date}` 구현 완료
|
|
||||||
7. ✅ **관리자 대시보드**: admin-dashboard에 일기 목록/상세 페이지 추가 완료 (마크다운 렌더링 포함)
|
|
||||||
8. ✅ **DOCS 동기화 스크립트**: `rb8001/scripts/sync_diary_to_docs.py` 구현 완료
|
|
||||||
|
|
||||||
## 구현 완료
|
|
||||||
|
|
||||||
**완료일**: 2025-12-23
|
|
||||||
|
|
||||||
**구현 완료 문서**: [로빙 일기 시스템 구현 완료](../../journey/troubleshooting/251223_로빙_일기_시스템_구현_완료.md)
|
|
||||||
|
|
||||||
**주요 완료 사항**:
|
|
||||||
- ✅ DB 테이블 스키마 정의 및 생성 (`_ensure_tables()`)
|
|
||||||
- ✅ Repository 함수 구현 (`save_diary`, `get_diary`, `save_activity_log`)
|
|
||||||
- ✅ Diary Aggregator 구현 (대화/활동/감정/성장/이슈 데이터 집계)
|
|
||||||
- ✅ LLM 일기 생성 로직 구현 (Gemini 사용)
|
|
||||||
- ✅ 스케줄러 등록 (매일 오전 2시 자동 생성)
|
|
||||||
- ✅ API 엔드포인트 구현 (`GET /api/diary/{date}`)
|
|
||||||
- ✅ Admin Dashboard 일기 페이지 추가 (목록/상세 조회)
|
|
||||||
- ✅ 일기 클릭 시 본문 표시 버그 수정
|
|
||||||
|
|
||||||
**추가 완료 사항** (2025-12-23):
|
|
||||||
- ✅ 스킬 실행 시 `activity_log` 자동 기록 로직 (`ActivityLogger` 클래스, `router.py`, `message_service.py` 통합)
|
|
||||||
- ✅ DOCS 동기화 스크립트 (`rb8001/scripts/sync_diary_to_docs.py`)
|
|
||||||
- ✅ 마크다운 렌더링 개선 (웹에서 가독성 향상)
|
|
||||||
- ✅ 일기 클릭 시 본문 표시 버그 수정 (window 객체에 함수 명시적 할당)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## UX 시나리오
|
|
||||||
|
|
||||||
### 1. 자동 생성 (매일 오전 2시 또는 3시)
|
|
||||||
- rb8001이 전날(00:00~23:59:59) 데이터 집계
|
|
||||||
- `conversation_log`, `activity_log`, `emotion_readings`, `robeing`, `intent_review_queue`, 애플리케이션 로그 수집
|
|
||||||
- LLM으로 일기 생성 후 `robeing_diary` 테이블에 저장
|
|
||||||
|
|
||||||
### 2. 운영자 조회 (관리자 대시보드)
|
|
||||||
- `https://ro-being.com/admin/diary` 접속
|
|
||||||
- 일기 목록 페이지: 날짜별 목록(최신순, 로빙별 필터)
|
|
||||||
- 상세 페이지: `/api/diary/{date}` 호출 → 마크다운 렌더링
|
|
||||||
- 필터/검색: 감정, 키워드, 로빙별
|
|
||||||
|
|
||||||
### 3. 활동 로그 기록
|
|
||||||
- 스킬 실행 시 `activity_log` 테이블에 자동 기록
|
|
||||||
- 일기 집계 시 "오늘 한 일" 섹션에 포함
|
|
||||||
|
|
||||||
### 4. DOCS 동기화 (선택적)
|
|
||||||
- 별도 스크립트로 `DOCS/journey/diary/rb8001/yymmdd_주제.md`에 주기적 동기화
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고
|
|
||||||
|
|
||||||
- `book/600_appendix/610_로빙_성장_일지_예시.md`
|
|
||||||
- `research/intent_classification/README.md`
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
# 짧은 후속 질문 컨텍스트 개선 계획
|
|
||||||
|
|
||||||
**날짜**: 2025-11-17
|
|
||||||
**목표**: "어디서?", "언제?" 같은 짧은 질문의 맥락 연결
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 문제
|
|
||||||
|
|
||||||
**사례**:
|
|
||||||
```
|
|
||||||
사용자: "11월 18일 오전 6시 40분에 검진이 있습니다"
|
|
||||||
로빙: "알겠습니다."
|
|
||||||
사용자: "어디서?"
|
|
||||||
로빙: "오늘 일정 정리해 드릴까요?" ❌ (새 대화로 오인)
|
|
||||||
```
|
|
||||||
|
|
||||||
**원인**: 짧은 후속 질문을 UNKNOWN으로 분류, 직전 맥락 참조 안 함
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3단계 계획
|
|
||||||
|
|
||||||
### 1단계: CONTEXT_FOLLOWUP Intent (미구현)
|
|
||||||
|
|
||||||
**설계**:
|
|
||||||
- IntentType 추가: `CONTEXT_FOLLOWUP`
|
|
||||||
- 패턴: `r"^어디서[요]?$"`, `r"^언제[요]?$"`, `r"^누구(랑)?[요]?$"`
|
|
||||||
- 처리: 직전 1~3턴 메시지 강제 참조
|
|
||||||
|
|
||||||
**구현**:
|
|
||||||
- `app/services/brain/decision_engine.py`: 패턴 추가
|
|
||||||
- LLM 프롬프트에 직전 발화 포함
|
|
||||||
|
|
||||||
### 2단계: 임베딩 기반 맥락 분류 (미구현)
|
|
||||||
|
|
||||||
**설계**:
|
|
||||||
- 현재 발화 + 최근 N턴 임베딩
|
|
||||||
- 후보 의도와 유사도 비교
|
|
||||||
- 확신도 ≥ 0.8 → 결정, < 0.5 → LLM 폴백
|
|
||||||
|
|
||||||
**효과**:
|
|
||||||
- 짧은 질문도 직전 발화와 관계 반영
|
|
||||||
- UNKNOWN 경로 유입 감소
|
|
||||||
|
|
||||||
### 3단계: 멀티턴/슬롯필링 (미구현)
|
|
||||||
|
|
||||||
**설계**:
|
|
||||||
- Redis 세션 관리 (3~5턴)
|
|
||||||
- 슬롯 구조: {날짜, 시간, 장소, 대상, 목적}
|
|
||||||
- 후속 질문 → 슬롯 채우기
|
|
||||||
|
|
||||||
**예시**:
|
|
||||||
```
|
|
||||||
사용자: "검진 일정 잡아줘"
|
|
||||||
로빙: "언제 하실 예정인가요?" (날짜 슬롯 질문)
|
|
||||||
사용자: "11월 24일"
|
|
||||||
로빙: "어디서 하시나요?" (장소 슬롯 질문)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고
|
|
||||||
|
|
||||||
- `troubleshooting/251117_human_in_the_loop_intent_learning.md`
|
|
||||||
- `plans/251017_intent_analysis_improvement_plan.md`
|
|
||||||
@ -45,8 +45,8 @@ LangGraph 워크플로우 (엔티티 추출 → 스킬 선택)
|
|||||||
### 필요 작업
|
### 필요 작업
|
||||||
1. ✅ LLM 질문 확장 기능 추가 (완료)
|
1. ✅ LLM 질문 확장 기능 추가 (완료)
|
||||||
2. ✅ LLM 의도 분류 맥락 포함 강화 (완료)
|
2. ✅ LLM 의도 분류 맥락 포함 강화 (완료)
|
||||||
3. LangGraph 기반 워크플로우 구현
|
3. ✅ LangGraph 기반 워크플로우 구현 (완료, 기본 활성화)
|
||||||
4. 세션 맥락 LLM 전달
|
4. ✅ 세션 맥락 LLM 전달 (완료)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -54,10 +54,10 @@ LangGraph 워크플로우 (엔티티 추출 → 스킬 선택)
|
|||||||
|
|
||||||
| Phase | 작업 | 상태 |
|
| Phase | 작업 | 상태 |
|
||||||
|-------|------|------|
|
|-------|------|------|
|
||||||
| 1 | LLM 질문 확장 구현 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase12_구현.md` |
|
| 1 | LLM 질문 확장 구현 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md` |
|
||||||
| 2 | LLM 의도 분류 강화 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase12_구현.md` |
|
| 2 | LLM 의도 분류 강화 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md` |
|
||||||
| 3 | LangGraph 워크플로우 | 진행 예정 |
|
| 3 | LangGraph 워크플로우 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md` |
|
||||||
| 4 | 세션 맥락 통합 | 진행 예정 |
|
| 4 | 세션 맥락 통합 | ✅ 완료 → `troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
298
journey/research/context_followup_question_solutions.md
Normal file
298
journey/research/context_followup_question_solutions.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
# 짧은 후속 질문 및 맥락 의존 질문 해결 방법 연구
|
||||||
|
|
||||||
|
**작성일**: 2025-12-23
|
||||||
|
**목적**: 실패하는 질문 18개 해결을 위한 구체적 방법론 제시
|
||||||
|
**참고**: 테스트 결과 `rb8001/tests/test_failed_questions_results.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 문제 요약
|
||||||
|
|
||||||
|
**실패한 질문 유형**:
|
||||||
|
1. 짧은 후속 질문 (컨텍스트 필요): "어디서?", "언제?", "누구랑?", "뭐야?"
|
||||||
|
2. 맥락 의존 질문: "그거 어떻게 됐어?", "결과는?", "그럼 어떻게 할까?"
|
||||||
|
3. 모호한 질문: "어떻게 생각해?", "괜찮아?"
|
||||||
|
4. 부정/거부 표현: "안 해도 돼", "취소해줘", "보내지 마"
|
||||||
|
5. 비교/선택 질문: "어느 게 나아?", "A와 B 중에 뭐가 좋아?"
|
||||||
|
6. 시간 관련 모호한 질문: "언제 했어?"
|
||||||
|
7. 상태 확인: "지금 뭐 하고 있어?", "작업 끝났어?"
|
||||||
|
8. 정보 요청: "너는 뭘 할 수 있어?"
|
||||||
|
|
||||||
|
**현재 상태**: CONTEXT_FOLLOWUP Intent는 구현되어 있으나 패턴 매칭이 제대로 작동하지 않음
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 해결 방법론 (연구 기반)
|
||||||
|
|
||||||
|
### 0. LLM 기반 직접 발화 확장 (Question Expansion)
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- 최신 연구(2024-2025): LLM을 활용한 질문 확장(Question Expansion) 기법
|
||||||
|
- Few-shot prompting으로 짧은 질문을 맥락 포함 완전한 질문으로 변환
|
||||||
|
- 코드베이스에 이미 유사 구현 존재: `message_router.py:_resolve_pronoun_via_llm` (대명사 해소)
|
||||||
|
|
||||||
|
**현재 구현 상태**:
|
||||||
|
- `message_service.py:225`: CONTEXT_FOLLOWUP 시 컨텍스트를 추가하지만 질문 자체는 확장하지 않음
|
||||||
|
- `message_router.py:268`: 대명사 해소는 구현되어 있으나 짧은 질문 확장은 미구현
|
||||||
|
|
||||||
|
**구현 방법**:
|
||||||
|
```
|
||||||
|
1. 짧은 질문 감지 (len <= 10 또는 패턴 매칭)
|
||||||
|
2. LLM에 질문 확장 요청 (Few-shot 예시 포함)
|
||||||
|
3. 확장된 질문으로 의도 분류 재시도
|
||||||
|
|
||||||
|
프롬프트 템플릿:
|
||||||
|
"다음은 짧은 후속 질문입니다. 직전 대화 맥락을 참고하여 완전한 질문으로 확장하세요.
|
||||||
|
|
||||||
|
예시:
|
||||||
|
- 직전: "11월 18일 오전 6시 40분에 검진이 있습니다"
|
||||||
|
- 짧은 질문: "어디서?"
|
||||||
|
- 확장: "검진은 어디서 하시나요?"
|
||||||
|
|
||||||
|
- 직전: "이메일 보냈어"
|
||||||
|
- 짧은 질문: "결과는?"
|
||||||
|
- 확장: "이메일 발송 결과는 어떻게 되었나요?"
|
||||||
|
|
||||||
|
직전 대화:
|
||||||
|
사용자: {previous_message}
|
||||||
|
로빙: {previous_response}
|
||||||
|
|
||||||
|
현재 짧은 질문: {message}
|
||||||
|
|
||||||
|
확장된 질문만 출력하세요:"
|
||||||
|
```
|
||||||
|
|
||||||
|
**장점**:
|
||||||
|
- 구현이 간단하고 즉시 적용 가능
|
||||||
|
- LLM의 자연어 이해 능력 활용
|
||||||
|
- Few-shot 예시로 정확도 향상
|
||||||
|
|
||||||
|
**단점**:
|
||||||
|
- LLM 호출 비용 증가 (짧은 질문마다 추가 호출)
|
||||||
|
- 응답 지연 시간 증가 (약 500ms-1s)
|
||||||
|
|
||||||
|
**비용 최적화**:
|
||||||
|
- 확신도 < 0.5인 경우에만 확장 시도
|
||||||
|
- 확장된 질문을 캐싱하여 동일 패턴 재사용
|
||||||
|
- 배치 처리로 여러 짧은 질문을 한 번에 확장
|
||||||
|
|
||||||
|
**참고 구현**:
|
||||||
|
- `rb8001/app/router/message_router.py:268-317`: 대명사 해소 유사 패턴
|
||||||
|
- `rb8001/app/services/message_service.py:206-228`: CONTEXT_FOLLOWUP 처리
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1. Anaphora Resolution (지시어 해석) 기법
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- 대화 시스템에서 "그거", "결과", "그럼" 같은 지시어(anaphora)는 이전 대화의 선행사(antecedent)를 참조
|
||||||
|
- 최신 연구(2024-2025)에서는 Transformer 기반 모델이 anaphora resolution에서 우수한 성능
|
||||||
|
|
||||||
|
**구현 방법**:
|
||||||
|
```
|
||||||
|
1. 최근 N턴 대화에서 명사구/엔티티 추출
|
||||||
|
2. 현재 질문의 지시어("그거", "결과")와 선행사 후보 매칭
|
||||||
|
3. 임베딩 유사도로 가장 가능성 높은 선행사 선택
|
||||||
|
4. 선행사를 포함한 확장 질문 생성 → LLM에 전달
|
||||||
|
```
|
||||||
|
|
||||||
|
**예시**:
|
||||||
|
- 입력: "그거 어떻게 됐어?"
|
||||||
|
- 이전 대화: "이메일 보냈어" → 선행사: "이메일"
|
||||||
|
- 확장: "이메일 어떻게 됐어?" → 정확한 의도 분류 가능
|
||||||
|
|
||||||
|
**참고 논문**: Neural Anaphora Resolution in Dialogue Systems (2024)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Hybrid LLM-ML 임계값 검증 (AppFolio 2024)
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- `DOCS/journey/research/memory/classification/2024_hybrid_llm_ml_threshold.md` 참고
|
||||||
|
- ML 모델로 1차 분류, 확신도 낮은 케이스만 LLM 재검증
|
||||||
|
- 비용 효율적이면서 정확도 향상
|
||||||
|
|
||||||
|
**현재 문제**:
|
||||||
|
- 짧은 질문이 UNKNOWN으로 분류되면 바로 LLM으로 가지만, 맥락 없이 처리됨
|
||||||
|
|
||||||
|
**개선 방안**:
|
||||||
|
```
|
||||||
|
1. FastPath (정규식) → 실패
|
||||||
|
2. SemanticIntentClassifier (임베딩) → 확신도 < 0.5
|
||||||
|
3. 맥락 확장 (Anaphora Resolution) → 선행사 포함 질문 생성
|
||||||
|
4. LLM 재검증 → 맥락 포함 질문으로 의도 분류
|
||||||
|
```
|
||||||
|
|
||||||
|
**효과**:
|
||||||
|
- 75% 케이스 자동화 유지
|
||||||
|
- 맥락 포함으로 LLM 정확도 향상
|
||||||
|
- 비용 증가 최소화 (10-20% 범위)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. 세션 기반 슬롯 관리 강화
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- `DOCS/journey/troubleshooting/251117_short_followup_context_3phase_implementation.md` 참고
|
||||||
|
- 현재 SessionManager는 구현되어 있으나 Redis 미마이그레이션 상태
|
||||||
|
|
||||||
|
**문제**:
|
||||||
|
- "취소해줘", "보내지 마" 같은 부정 표현이 무엇을 취소/거부하는지 맥락 필요
|
||||||
|
- 세션 슬롯에 현재 진행 중인 작업 정보가 없음
|
||||||
|
|
||||||
|
**개선 방안**:
|
||||||
|
```
|
||||||
|
1. 세션 슬롯에 "active_action" 필드 추가
|
||||||
|
- 예: {active_action: "email_send", recipient: "김팀장", subject: "일정 확인"}
|
||||||
|
|
||||||
|
2. 부정 표현 감지 시 active_action 참조
|
||||||
|
- "취소해줘" → active_action이 "calendar_event"면 calendar_delete
|
||||||
|
- "보내지 마" → active_action이 "email_send"면 email_send_approval (거부)
|
||||||
|
|
||||||
|
3. Redis 마이그레이션으로 세션 영속성 확보
|
||||||
|
- 서버 재시작 시에도 세션 유지
|
||||||
|
- TTL 10분 → 30분으로 확장 (복잡한 작업 대응)
|
||||||
|
```
|
||||||
|
|
||||||
|
**참고**: Multi-turn Dialogue State Tracking (DST) 연구 (2024-2025)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. 의도 확장: 새로운 Intent 추가
|
||||||
|
|
||||||
|
**필요한 Intent**:
|
||||||
|
1. **CANCEL_REQUEST**: 취소/거부 의도
|
||||||
|
- 패턴: "취소해줘", "안 해도 돼", "보내지 마", "하지 마"
|
||||||
|
- 처리: active_action 참조하여 구체적 취소 액션 결정
|
||||||
|
|
||||||
|
2. **COMPARISON_QUERY**: 비교/선택 질문
|
||||||
|
- 패턴: "어느 게 나아?", "A와 B 중에 뭐가 좋아?", "비교해줘"
|
||||||
|
- 처리: 이전 대화에서 비교 대상 추출, LLM으로 비교 분석
|
||||||
|
|
||||||
|
3. **STATUS_CHECK**: 상태 확인 질문
|
||||||
|
- 패턴: "작업 끝났어?", "지금 뭐 하고 있어?", "진행 상황은?"
|
||||||
|
- 처리: 세션의 active_action 상태 확인, 진행률 반환
|
||||||
|
|
||||||
|
4. **CAPABILITY_QUERY**: 기능 조회
|
||||||
|
- 패턴: "너는 뭘 할 수 있어?", "기능 알려줘", "할 수 있는 일은?"
|
||||||
|
- 처리: IntentType 목록을 자연어로 변환하여 반환
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Ko-SRoBERTa 임베딩 활용 (고정밀 경로)
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- `DOCS/journey/research/memory/embedding_search/2025_ko_sroberta_runtime_eval.md` 참고
|
||||||
|
- Ko-SRoBERTa는 의도 분류에서 75% 정확도 (기존 53.6% → 75.0%)
|
||||||
|
|
||||||
|
**현재 문제**:
|
||||||
|
- SemanticIntentClassifier가 skill-embedding(384d) 사용 중
|
||||||
|
- 짧은 질문의 임베딩 유사도가 낮아 UNKNOWN으로 분류
|
||||||
|
|
||||||
|
**개선 방안**:
|
||||||
|
```
|
||||||
|
1. 고정밀 파이프라인 전용 Ko-SRoBERTa 서비스 분리
|
||||||
|
- skill-embedding-highres (768d) 신규 서비스
|
||||||
|
|
||||||
|
2. 짧은 질문/맥락 의존 질문은 고정밀 경로 사용
|
||||||
|
- len(message) <= 10 또는 확신도 < 0.5인 경우
|
||||||
|
- Ko-SRoBERTa로 재임베딩 → 유사도 재계산
|
||||||
|
|
||||||
|
3. 맥락 포함 임베딩
|
||||||
|
- "어디서?" + 직전 발화 → 결합 임베딩
|
||||||
|
- 선행사 포함 질문으로 확장 후 임베딩
|
||||||
|
```
|
||||||
|
|
||||||
|
**효과**:
|
||||||
|
- 의도 분류 정확도 21pt 향상 (challenge set 기준)
|
||||||
|
- 짧은 질문도 맥락과 결합하여 정확도 향상
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. 대화 로그 분석 기반 패턴 학습
|
||||||
|
|
||||||
|
**이론적 배경**:
|
||||||
|
- 웹 검색 결과: 대화 로그 분석을 통한 의도 인식 개선
|
||||||
|
- HITL 피드백 루프 활용 (`DOCS/journey/research/intent_classification/README.md`)
|
||||||
|
|
||||||
|
**구현 방법**:
|
||||||
|
```
|
||||||
|
1. 실패한 질문 패턴 수집
|
||||||
|
- UNKNOWN으로 분류된 질문 + 직전 대화 맥락
|
||||||
|
- 리뷰 큐에 자동 진입 (low confidence)
|
||||||
|
|
||||||
|
2. 패턴 분석
|
||||||
|
- "어디서?" → 이전 의도가 calendar_event면 calendar_query
|
||||||
|
- "결과는?" → 이전 의도가 web_search면 web_search (재검색)
|
||||||
|
|
||||||
|
3. 규칙 기반 보완
|
||||||
|
- 패턴이 명확하면 FastPath에 규칙 추가
|
||||||
|
- 모호하면 LLM 프롬프트에 예시 추가
|
||||||
|
```
|
||||||
|
|
||||||
|
**참고**: Active Learning with Rationales (Sharma et al., 2015)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 구현 우선순위
|
||||||
|
|
||||||
|
### Phase 1: 즉시 적용 가능 (1-2주)
|
||||||
|
1. ✅ Anaphora Resolution 기본 구현
|
||||||
|
- 지시어("그거", "결과") → 선행사 매칭
|
||||||
|
- 확장 질문 생성 로직
|
||||||
|
|
||||||
|
2. ✅ 새로운 Intent 추가
|
||||||
|
- CANCEL_REQUEST, COMPARISON_QUERY, STATUS_CHECK, CAPABILITY_QUERY
|
||||||
|
- FastPath 패턴 매칭 추가
|
||||||
|
|
||||||
|
3. ✅ 세션 active_action 필드 추가
|
||||||
|
- 부정 표현 처리 개선
|
||||||
|
|
||||||
|
### Phase 2: 중기 개선 (1개월)
|
||||||
|
4. ✅ Hybrid LLM-ML 임계값 검증 강화
|
||||||
|
- 맥락 확장 후 LLM 재검증
|
||||||
|
- 비용 효율성 유지
|
||||||
|
|
||||||
|
5. ✅ Ko-SRoBERTa 고정밀 경로
|
||||||
|
- skill-embedding-highres 서비스 분리
|
||||||
|
- 짧은 질문 전용 경로
|
||||||
|
|
||||||
|
### Phase 3: 장기 개선 (2-3개월)
|
||||||
|
6. ✅ Redis 세션 마이그레이션
|
||||||
|
- 세션 영속성 확보
|
||||||
|
- TTL 확장 (10분 → 30분)
|
||||||
|
|
||||||
|
7. ✅ 대화 로그 분석 자동화
|
||||||
|
- 실패 패턴 자동 학습
|
||||||
|
- 규칙 기반 보완 자동화
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예상 효과
|
||||||
|
|
||||||
|
**정량적 목표**:
|
||||||
|
- 실패한 질문 18개 → 5개 이하로 감소 (72% → 22%)
|
||||||
|
- 짧은 후속 질문 정확도: 30% → 80% 이상
|
||||||
|
- 맥락 의존 질문 정확도: 30% → 70% 이상
|
||||||
|
|
||||||
|
**정성적 개선**:
|
||||||
|
- 사용자 경험: 자연스러운 대화 흐름 유지
|
||||||
|
- 시스템 신뢰도: 맥락 이해 능력 향상
|
||||||
|
- 운영 효율: UNKNOWN 감소로 리뷰 큐 부담 감소
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 문헌
|
||||||
|
|
||||||
|
1. Neural Anaphora Resolution in Dialogue Systems (2024)
|
||||||
|
2. Hybrid LLM-ML Classification with Intelligent Threshold Verification (AppFolio, 2024)
|
||||||
|
3. Multi-turn Dialogue State Tracking (DST) Research (2024-2025)
|
||||||
|
4. Active Learning with Rationales (Sharma et al., 2015)
|
||||||
|
5. Ko-SRoBERTa Runtime Evaluation (2025-11-15)
|
||||||
|
6. Human-in-the-Loop Machine Learning (Narang)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**작성일**: 2025-12-23
|
||||||
|
**상태**: 연구 완료, 구현 대기
|
||||||
|
|
||||||
69
journey/troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md
Normal file
69
journey/troubleshooting/251223_짧은_후속_질문_LLM_Phase1234_구현.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# 짧은 후속 질문 LLM 우선 해결 Phase 1-4 구현
|
||||||
|
|
||||||
|
**날짜**: 2025-12-23
|
||||||
|
**작성자**: happybell80
|
||||||
|
**관련 계획**: `journey/plans/251223_짧은_후속_질문_LLM_우선_해결_계획.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 문제
|
||||||
|
|
||||||
|
실패한 질문 18개 (총 23개 중 78%): 짧은 후속, 맥락 의존, 모호한 질문 등이 UNKNOWN으로 분류됨.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 구현 내용
|
||||||
|
|
||||||
|
### Phase 1: LLM 질문 확장
|
||||||
|
- `llm_service.py:43-110`: `expand_question()` 메서드 추가
|
||||||
|
- `message_service.py:194-217`: 짧은 질문(len <= 10) 감지 후 LLM 확장 통합
|
||||||
|
- 맥락(recent_conversations, session_slots) 포함하여 완전한 질문으로 확장
|
||||||
|
|
||||||
|
### Phase 2: LLM 의도 분류 강화
|
||||||
|
- `intent_parser.py:26-113`: 맥락 정보를 프롬프트에 포함
|
||||||
|
- `intent_graph.py:79-126`: 확신도 < 0.7일 때 맥락 포함 재분류
|
||||||
|
- `message_service.py:145-151`: 세션 슬롯 정보를 context에 추가
|
||||||
|
|
||||||
|
### Phase 3: LangGraph 워크플로우
|
||||||
|
- `intent_langgraph_workflow.py`: LangGraph 기반 워크플로우 구현
|
||||||
|
- `intent_graph.py:37-77`: LangGraph 워크플로우 통합 (기본 활성화)
|
||||||
|
- 질문 확장 → 의도 분류 → 엔티티 추출 → 스킬 선택 워크플로우
|
||||||
|
|
||||||
|
### Phase 4: 세션 맥락 통합
|
||||||
|
- `message_service.py:182-192`: 모든 단계에서 세션 슬롯 일관되게 전달
|
||||||
|
- `intent_langgraph_workflow.py:24-46`: LangGraph 워크플로우에서 세션 맥락 사용
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 결과
|
||||||
|
|
||||||
|
| Phase | 해결률 | 비고 |
|
||||||
|
|-------|--------|------|
|
||||||
|
| Phase 1 | 8/17 (47.1%) | 질문 확장만 |
|
||||||
|
| Phase 2 | +5/9 (55.6%) | 재분류 추가 |
|
||||||
|
| Phase 3 | 검증 완료 | LangGraph 워크플로우 |
|
||||||
|
| Phase 4 | 검증 완료 | 세션 맥락 통합 |
|
||||||
|
|
||||||
|
**전체 해결률**: 13/18 (72.2%)
|
||||||
|
|
||||||
|
**해결된 질문 예시**:
|
||||||
|
- "어디서?" → "회의는 어디서 하나요?" → calendar_event
|
||||||
|
- "그거 어떻게 됐어?" → "이메일 발송은 어떻게 됐어요?" → email_send
|
||||||
|
- "취소해줘" → "이메일 발송을 취소해주세요." → email_send
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 교훈
|
||||||
|
|
||||||
|
1. **LLM 우선 접근 효과**: 규칙 기반 대신 LLM이 맥락을 이해하여 질문 확장 및 의도 분류 성공
|
||||||
|
2. **맥락 정보 중요**: recent_conversations와 session_slots를 포함하면 정확도 향상
|
||||||
|
3. **LangGraph 적극 활용**: 원칙에 따라 LangGraph 워크플로우 기본 활성화
|
||||||
|
4. **단계별 개선**: Phase 1, 2만으로는 부족, Phase 3, 4 추가로 완성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고
|
||||||
|
|
||||||
|
- `311_FastAPI_구조_원칙.md` (섹션 5: LangGraph 워크플로우, 섹션 13: LLM 우선 접근 원칙)
|
||||||
|
- `rb8001/tests/test_failed_questions_results.md` (초기 테스트 결과)
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
# 짧은 후속 질문 LLM 우선 해결 Phase 1, 2 구현
|
|
||||||
|
|
||||||
**날짜**: 2025-12-23
|
|
||||||
**작성자**: happybell80
|
|
||||||
**관련 계획**: `journey/plans/251223_짧은_후속_질문_LLM_우선_해결_계획.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 문제
|
|
||||||
|
|
||||||
실패한 질문 18개 (총 23개 중 78%): 짧은 후속, 맥락 의존, 모호한 질문 등이 UNKNOWN으로 분류됨.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 구현 내용
|
|
||||||
|
|
||||||
### Phase 1: LLM 질문 확장
|
|
||||||
- `llm_service.py:43-110`: `expand_question()` 메서드 추가
|
|
||||||
- `message_service.py:176-202`: 짧은 질문(len <= 10) 감지 후 LLM 확장 통합
|
|
||||||
- 맥락(recent_conversations, session_slots) 포함하여 완전한 질문으로 확장
|
|
||||||
|
|
||||||
### Phase 2: LLM 의도 분류 강화
|
|
||||||
- `intent_parser.py:26-113`: 맥락 정보를 프롬프트에 포함
|
|
||||||
- `intent_graph.py:32-75`: 확신도 < 0.7일 때 맥락 포함 재분류
|
|
||||||
- `message_service.py:143-157`: 세션 슬롯 정보를 context에 추가
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 결과
|
|
||||||
|
|
||||||
| 항목 | Phase 1 | Phase 2 | 전체 |
|
|
||||||
|------|---------|---------|------|
|
|
||||||
| 해결률 | 8/17 (47.1%) | +5/9 (55.6%) | 13/18 (72.2%) |
|
|
||||||
| 목표 | - | - | 15/18 (83%) |
|
|
||||||
|
|
||||||
**해결된 질문 예시**:
|
|
||||||
- "어디서?" → "회의는 어디서 하나요?" → calendar_event
|
|
||||||
- "그거 어떻게 됐어?" → "이메일 발송은 어떻게 됐어요?" → email_send
|
|
||||||
- "취소해줘" → "이메일 발송을 취소해주세요." → email_send
|
|
||||||
|
|
||||||
**미해결 질문 (5개)**:
|
|
||||||
- "A를 어떻게 할까요?" (unknown, 신뢰도 0.50)
|
|
||||||
- "A와 B 중에 어느 것이 더 나은가요?" (unknown, 신뢰도 0.50)
|
|
||||||
- "너는 뭘 할 수 있어?" (unknown, 신뢰도 0.60)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 교훈
|
|
||||||
|
|
||||||
1. **LLM 우선 접근 효과**: 규칙 기반 대신 LLM이 맥락을 이해하여 질문 확장 및 의도 분류 성공
|
|
||||||
2. **맥락 정보 중요**: recent_conversations와 session_slots를 포함하면 정확도 향상
|
|
||||||
3. **단계별 개선**: Phase 1(질문 확장)만으로는 부족, Phase 2(재분류) 추가로 72% 달성
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고
|
|
||||||
|
|
||||||
- `311_FastAPI_구조_원칙.md` (섹션 13: LLM 우선 접근 원칙)
|
|
||||||
- `rb8001/tests/test_failed_questions_results.md` (초기 테스트 결과)
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user