DOCS/journey/plans/251117_short_followup_context_3phase_plan.md

5.9 KiB

짧은 후속 질문 컨텍스트 유실 개선 3단계 계획

날짜: 2025-11-17
작성자: Claude Code
관련 파일:

  • rb8001/app/brain/decision_engine.py
  • rb8001/tests/test_intent_entity_skill_comprehensive.py
  • DOCS/journey/plans/251017_intent_analysis_improvement_plan.md
  • DOCS/journey/troubleshooting/251117_human_in_the_loop_intent_learning.md

1. 문제 요약

  • 사용자: "11월 18일 오전 6시 40분에 검진이 있습니다" → RoBeing 응답 OK
  • 이어서 사용자: "어디서?"
  • 실제 동작: 짧은 질문이 UNKNOWN → understand 액션으로 전달 → LLM이 "오늘 일정 정리해 드릴까요?"처럼 새 대화로 오인
  • 근본 원인: 짧은 후속 질문에 대한 별도 Intent/처리 경로가 없어서, 직전 발화/대화 맥락을 강제 참조하지 못하는 구조

2. 목표

  1. "어디서?", "언제?", "누구랑?" 같은 짧은 후속 질문이 항상 직전 발화/대화 맥락과 연결되도록 한다.
  2. 비용 제약 없이, 정규식 FastPath → 임베딩 기반 의도 분류 → 멀티턴/슬롯필링까지 단계적으로 설계한다.
  3. 기존 DecisionEngine/테스트 구조를 유지하면서, 점진적으로 확장 가능한 형태로 설계한다.

3. 1단계: 짧은 후속 질문 전용 Intent 추가 (FastPath)

3.1 설계

  • 새 IntentType 추가: CONTEXT_FOLLOWUP (이름은 구현 시 팀 합의)
  • intent_patterns에 짧은 후속 질문 패턴 추가 (예시):
    • r"^어디서[요]?$"
    • r"^언제[요]?$"
    • r"^누구(랑|하고)?[요]?$"
    • r"^뭐[야|였어]?$"
  • 규칙:
    • 이 패턴이 매칭되면 무조건 CONTEXT_FOLLOWUP 으로 분류 (UNKNOWN으로 보내지 않음).
    • 현재 발화만으로 판단하지 않고, 직전 1~3턴의 메시지를 강제 참조하도록 DecisionEngine에 후속 처리 경로 추가.

3.2 처리 흐름

  1. DecisionEngine에서 CONTEXT_FOLLOWUP 감지.
  2. 대화 로그/메모리에서 가장 최근의 "장소/시간/대상"이 포함된 발화를 검색.
  3. LLM 프롬프트에 아래 정보를 함께 전달:
    • 현재 질문: "어디서?"
    • 직전 발화: "11월 18일 오전 6시 40분에 검진이 있습니다"
    • 관련 메모리(예: 병원명, 의료기관 기록 등)
  4. LLM에게 "후속 질문으로, 위 직전 발화를 기준으로 답하라" 는 제약을 명시.

3.3 테스트 전략

  • rb8001/tests/test_intent_entity_skill_comprehensive.py 또는 별도 테스트 파일에 케이스 추가:
    • 대화 시나리오: ["내일 아침에 건강검진 있어", "어디서?"] → 장소가 포함된 응답 기대.
    • ["내일 오전 10시에 미팅 있어", "언제?"] → 시간 재응답.
  • 기대 행동:
    • Intent: CONTEXT_FOLLOWUP
    • UNKNOWN 비율 감소, understand 액션 호출 없이도 적절한 핸들링 가능.

4. 2단계: 임베딩 기반 의도/맥락 분류 + LLM 폴백

4.1 설계

  • 251017 문서에서 제안한 정규식 FastPath + 임베딩 + LLM 3단계 구조를, CONTEXT_FOLLOWUP에도 확장.
  • 핵심 아이디어:
    • "어디서?" 자체만 보면 모호하지만,
    • 직전/과거 발화와의 임베딩 유사도로 "장소 관련 후속 질문"임을 더 강하게 판단.

4.2 처리 흐름 (의사 단계)

  1. 정규식 FastPath에서 패턴 매칭 실패 또는 확신도 낮음.
  2. 임베딩 엔진으로 현재 발화 + 최근 N턴 발화를 임베딩.
  3. 후보 의도들(예: calendar_query, context_followup, general_chat 등)의 description 임베딩과 유사도 비교.
  4. 상위 3개 의도 + 유사도 스코어를 계산:
    • 확신도 ≥ 0.8 → 해당 의도로 결정.
    • 0.5 ≤ 확신도 < 0.8 → LLM에게 top-3 후보와 함께 전달, 최종 선택 요청.
    • 확신도 < 0.5 → LLM general understand로 폴백.

4.3 기대 효과

  • 짧은 질문이라도, 직전 발화와의 관계를 임베딩 수준에서 반영.
  • DecisionEngine의 UNKNOWN 경로 유입을 줄이고, LLM 호출도 불필요하게 늘리지 않도록 제어.
  • 향후 Human/LLM-in-the-loop 라벨링과 결합 시, 의도 prototype 업데이트로 정밀도 향상.

5. 3단계: 멀티턴/슬롯필링 기반 대화 관리

5.1 설계

  • Redis 등 외부 스토리지를 사용해 세션 단위로 3~5턴 대화 상태를 유지.
  • 각 세션에 대해 슬롯 구조를 정의:
    • 예: calendar_event → {날짜, 시간, 장소, 대상, 목적}
  • 사용자의 후속 질문은, 이 슬롯 구조를 기반으로 해석:
    • "어디서?" → 장소 슬롯 재질문/확인
    • "언제?" → 시간 슬롯 재질문/확인

5.2 처리 흐름

  1. 사용자가 "검진 일정 잡아줘" → Phase 1/2의 의도 분석을 거쳐 calendar_event로 분류.
  2. 시스템이 슬롯 채우기 진행 (날짜, 시간, 장소 등).
  3. 후속 질문 발생 시, 현재 세션의 슬롯 상태를 조회:
    • 이미 채워진 값이 있으면, 그 값을 기준으로 답변.
    • 값이 없으면, LLM이 추가 질문 또는 기본값 제안.

5.3 비용 및 운영 관점

  • LLM 호출 횟수는 증가하지만, 세션/슬롯 상태 관리를 통해 재질문/중복 호출을 줄일 수 있음.
  • Redis 세션 TTL, 슬롯 수 제한 등을 통해 메모리/비용 관리 가능.
  • 사람 개입(Human-in-the-loop) 또는 LLM-in-the-loop 리뷰 큐와 결합해, 자주 틀리는 패턴을 우선적으로 보완.

6. 정리

  1. 1단계: CONTEXT_FOLLOWUP Intent + 패턴 추가로, 짧은 후속 질문을 UNKNOWN에서 분리.
  2. 2단계: 임베딩 기반 의도/맥락 분류와 LLM 폴백으로, "어디서?" 같은 질문도 직전 발화와 안정적으로 연결.
  3. 3단계: 멀티턴/슬롯필링 구조를 도입해, 일정/검진/회의 등 복합 작업 흐름에서 자연스러운 후속 질문 처리를 지원.