DOCS/journey/troubleshooting/251117_short_followup_context_3phase_implementation.md

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 프롬프트에 명시적으로 포함하여 "새 대화로 오인" 방지

후속 작업 (제안)

  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단계 구현 완료, 프론트엔드 테스트 대기 중