# 짧은 후속 질문 컨텍스트 유지 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 프롬프트에 명시적으로 포함하여 "새 대화로 오인" 방지 --- ## 후속 작업 (제안) 1. **Redis 마이그레이션**: 메모리 기반 SessionManager를 Redis로 전환하여 서버 재시작 시에도 세션 유지 2. **슬롯 추출 개선**: 현재는 간단한 정규식 휴리스틱 사용, LLM 기반 엔티티 추출로 정확도 향상 3. **프론트엔드 통합 테스트**: happybell80 (UUID: 53529291-5050-4daa-89fb-008b546feb63) 사용자로 실제 시나리오 테스트 4. **Human-in-the-loop 연동**: CONTEXT_FOLLOWUP Intent도 리뷰 큐에 포함하여 자주 틀리는 패턴 보완 --- **작성일**: 2025-11-17 **상태**: ✅ 3단계 구현 완료, 프론트엔드 테스트 대기 중