DOCS/journey/troubleshooting/251209_rb8001_calendar_intent_overlap_fastpath_fix.md

3.9 KiB

rb8001 캘린더 조회/생성 의도 경계 FastPath 수정

날짜: 2025-12-09 작성자: Claude 관련 파일: rb8001/app/services/brain/decision_engine.py:380-470


문제 상황

  • 사용자 발화가 조회·생성을 함께 암시하는 경우에도 FastPath 정규식이 한쪽 intent로 강하게 고정되면서 UX가 어색했다.
    • 예: "로빙아 내 구글 캘린더에 내일 12시 교육 일정 추가해줘."calendar_query로 분류되거나,
      "이번 주 일정 정리해서 보여주고, 안 잡힌 시간에 회의 하나 넣어줘."가 단일 intent로만 처리됨.
  • 상위 설계(3단계 의도 아키텍처, 하이브리드 의도 분석, HITL 리뷰 큐)는 존재하지만, 캘린더 FastPath(DecisionEngine) 레벨에서 조회/생성/삭제 경계가 충분히 정제되어 있지 않았다.

해결 방안

  • FastPath에서 캘린더 관련 intent(CALENDAR_DELETE, CALENDAR_QUERY, CALENDAR_EVENT)를 별도 분기 처리하도록 수정.
    • 삭제 패턴(CALENDAR_DELETE)은 항상 최우선으로 처리.
    • 조회/생성 패턴이 둘 다 매칭되는 혼합 문장은 추가 규칙으로 분기.
  • 조회/생성 혼합 문장에 대한 UX 기준을 명시:
    • "없으면", "필요하면"이 포함된 경우: 먼저 조회(intent=calendar_query) 후 필요 시 생성하는 흐름으로 간주.
    • "등록해줘", "추가해줘", "넣어줘", "잡아줘" 등 명령형 생성 표현만 있는 경우: 생성(intent=calendar_event) 우선.
    • 그 밖의 혼합 문장은 기본적으로 조회(intent=calendar_query)로 처리.
  • 캘린더 외 intent는 기존 intent_patterns 순서를 그대로 유지하되, 캘린더 세 가지 intent는 공통 분기 후 다른 intent와 독립적으로 처리.

수정 위치

  • 의도 판정 로직 확장: rb8001/app/services/brain/decision_engine.py:399-470
    • 기존 priority_intents = [CALENDAR_DELETE, CALENDAR_QUERY] 루프 제거.
    • calendar_delete_match, calendar_query_match, calendar_event_match를 별도로 계산하고, 혼합 케이스에서 조건부/생성 키워드를 기준으로 분기.
    • 이후 일반 intent 패턴 루프에서는 캘린더 intent 세 종류를 건너뛰도록 변경.

구현 결과

  • UX 시나리오 20개를 기준으로 한 TDD 테스트 추가 (로컬 전용):
    • 파일: rb8001/tests/test_calendar_intent_overlap_tdd.py (gitignore로 인해 리포지토리에는 포함하지 않음)
    • 검증 범위:
      • 순수 조회 문장: calendar_query
      • 명시적 생성 문장: calendar_event
      • "없으면 잡아줘", "필요하면 등록해줘" 형태 혼합 문장: 기본 calendar_query (조회 우선)
      • 삭제/정리 문장: calendar_delete
  • 위 20개 케이스는 모두 DecisionEngine FastPath에서 기대 intent로 분류됨을 확인.
  • rb8001 리포지토리에 변경 사항 커밋/푸시 후, Gitea Actions 자동 배포를 통해 51124 서버의 rb8001 컨테이너가 재시작되었음을 docker ps | grep rb8001로 검증.

교훈

  • 상위 설계(3단계 의도 파이프라인, 하이브리드 의도 분석, HITL 리뷰 큐)만으로는 FastPath 정규식이 만드는 UX 문제를 막기 어렵다. 캘린더처럼 사용자 기대가 명확한 도메인에 대해서는 FastPath 레벨에서도 조회/생성/삭제 경계를 명시적으로 설계해야 한다.
  • 계획 문서에는 ActionPlanner/SkillSelector·clarify·HITL까지 포함된 전체 작업이 적혀 있었지만, 실제 1차 배포에서는 FastPath 캘린더 분기만 안전하게 적용하는 식으로 단계를 나누는 것이 리스크 관리에 도움이 된다.
  • TDD 방식으로 “문장 → 기대 intent”를 먼저 고정해 두면, 이후 ActionPlanner/SkillSelector·clarify·HITL를 추가로 도입하더라도 기존 캘린더 UX를 깨지 않고 개선 여부를 안정적으로 검증할 수 있다.