4.5 KiB
4.5 KiB
짧은 후속 질문 컨텍스트 유지 3단계 구현 완료
날짜: 2025-11-17
작성자: Claude Code
관련 파일:
- rb8001/app/brain/decision_engine.py:264-316 (CONTEXT_FOLLOWUP Intent 추가 및 패턴 매칭)
- rb8001/app/brain/decision_engine.py:437-439 (CONTEXT_FOLLOWUP 스킬 시퀀스)
- rb8001/app/router/router.py:218-263 (CONTEXT_FOLLOWUP 처리 및 세션 슬롯 관리)
- rb8001/app/brain/session_manager.py (3단계: 멀티턴/슬롯필링 세션 관리)
- rb8001/tests/test_intent_entity_skill_comprehensive.py:83-253 (3단계 테스트)
문제 상황
- 사용자: "11월 18일 오전 6시 40분에 검진이 있습니다" → RoBeing 응답 OK
- 이어서 사용자: "어디서?"
- 실제 동작: 짧은 질문이 UNKNOWN → understand 액션으로 전달 → LLM이 "오늘 일정 정리해 드릴까요?"처럼 새 대화로 오인
- 근본 원인: 짧은 후속 질문에 대한 별도 Intent/처리 경로가 없어서, 직전 발화/대화 맥락을 강제 참조하지 못하는 구조
해결 방안 (3단계 TDD 구현)
1단계: CONTEXT_FOLLOWUP Intent 추가 (FastPath)
구현 내용:
IntentType.CONTEXT_FOLLOWUP추가 (decision_engine.py:67-68)- 정규식 패턴 매칭: "어디서?", "언제?", "누구랑?", "뭐야?" 등 (decision_engine.py:271-277)
- 컨텍스트가 있을 때만 CONTEXT_FOLLOWUP으로 분류 (decision_engine.py:266-291)
- router에서 CONTEXT_FOLLOWUP 감지 시 직전 발화를 LLM 프롬프트에 포함 (router.py:218-240)
테스트: test_context_followup_intent_detection, test_context_followup_without_context_falls_back, test_context_followup_retrieves_previous_message
2단계: 임베딩 기반 의도/맥락 분류
구현 내용:
- 정규식 패턴 매칭 실패 시 임베딩 기반 분류 시도 (decision_engine.py:293-316)
- 직전 발화와 현재 메시지를 결합하여 임베딩 유사도 계산
- 확신도 ≥0.5이면 CONTEXT_FOLLOWUP으로 분류
- SemanticIntentClassifier 활용 (기존 인프라 재사용)
테스트: test_embedding_based_context_followup_detection, test_embedding_fallback_when_pattern_mismatch
3단계: 멀티턴/슬롯필링 기반 대화 관리
구현 내용:
SessionManager클래스 추가 (session_manager.py)- 사용자별 세션 상태 유지 (3~5턴, 10분 TTL)
- 슬롯 구조: 날짜, 시간, 장소 등 (calendar_event Intent 기준)
- router에서 calendar_event Intent 감지 시 슬롯 자동 추출 (router.py:242-263)
- CONTEXT_FOLLOWUP 처리 시 슬롯 정보도 LLM에 전달 (router.py:226-234)
테스트: test_slot_filling_for_calendar_event, test_multi_turn_conversation_state_persistence (TODO: Redis 마이그레이션 후 완전 구현)
구현 완료 (커밋 해시)
- feat: add CONTEXT_FOLLOWUP Intent for short followup questions (1단계)
- feat: add embedding-based context followup detection (2단계)
- feat: add session manager for multi-turn slot filling (3단계)
교훈
1. TDD 원칙 준수
- 테스트 먼저 작성 (Red) → 구현 (Green) → 리팩터 순서로 진행
- 각 단계별로 독립적인 테스트 작성으로 점진적 확장 가능
2. 기존 인프라 재사용
- SemanticIntentClassifier를 2단계에서 재사용하여 추가 의존성 없이 구현
- 기존 router 구조를 최소한으로 수정하여 안정성 유지
3. 점진적 확장 설계
- 1단계: 정규식 FastPath (즉시 적용 가능)
- 2단계: 임베딩 폴백 (패턴 매칭 실패 시)
- 3단계: 세션/슬롯 관리 (향후 Redis 마이그레이션 가능하도록 설계)
4. 컨텍스트 강제 참조
- CONTEXT_FOLLOWUP Intent는 컨텍스트가 필수이므로, 컨텍스트 없이는 다른 Intent로 폴백
- router에서 직전 발화를 LLM 프롬프트에 명시적으로 포함하여 "새 대화로 오인" 방지
후속 작업 (제안)
- Redis 마이그레이션: 메모리 기반 SessionManager를 Redis로 전환하여 서버 재시작 시에도 세션 유지
- 슬롯 추출 개선: 현재는 간단한 정규식 휴리스틱 사용, LLM 기반 엔티티 추출로 정확도 향상
- 프론트엔드 통합 테스트: happybell80 (UUID: 53529291-5050-4daa-89fb-008b546feb63) 사용자로 실제 시나리오 테스트
- Human-in-the-loop 연동: CONTEXT_FOLLOWUP Intent도 리뷰 큐에 포함하여 자주 틀리는 패턴 보완
작성일: 2025-11-17
상태: ✅ 3단계 구현 완료, 프론트엔드 테스트 대기 중