From 50b52ae4aca59c93936431c39d4a2118e3edd41d Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Mon, 17 Nov 2025 23:29:44 +0900 Subject: [PATCH] docs: add 3-phase context followup implementation documentation --- ..._followup_context_3phase_implementation.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 journey/troubleshooting/251117_short_followup_context_3phase_implementation.md diff --git a/journey/troubleshooting/251117_short_followup_context_3phase_implementation.md b/journey/troubleshooting/251117_short_followup_context_3phase_implementation.md new file mode 100644 index 0000000..b52d398 --- /dev/null +++ b/journey/troubleshooting/251117_short_followup_context_3phase_implementation.md @@ -0,0 +1,98 @@ +# 짧은 후속 질문 컨텍스트 유지 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단계 구현 완료, 프론트엔드 테스트 대기 중 +