DOCS/journey/troubleshooting/251118_happybell80_rb8001_의도분석_UNKNOWN_및_웹검색.md

9.4 KiB

rb8001 의도분석 UNKNOWN 및 웹 검색 처리 문제

날짜: 2025-11-18 작성자: happybell80 관련 파일: rb8001/app/brain/decision_engine.py, rb8001/app/brain/intent_graph.py, rb8001/app/router/router.py, DOCS/book/300_architecture/database/tables.md


문제 상황

  • Docker 로그와 OpenSearch dataprepper-static 인덱스를 기준으로 rb8001 최근 대화 로그를 분석한 결과, 웹 검색 의도로 보이는 문장들이 UNKNOWN 의도로 분류되는 사례가 반복적으로 관찰됨.
  • 예시: "엠에스 바이오 인터케어 관련 검", "인터케어.. 오토테크는 뭐야?"와 같은 질의가 의도 분석 단계에서 UNKNOWN으로 떨어져 이후 웹 검색/뉴스 조회 워크플로우로 연결되지 않음.
  • 동일한 로그 분석 과정에서 Web Search Workflow의 SQLite 체크포인트 unable to open database file 에러, Gemini/Mistral API 429, coldmail 파일 404, asyncio 콜백 예외 등도 함께 확인되었으나, 본 문서는 의도분석 UNKNOWN 및 웹 검색 경로 문제에 초점을 맞춤.

원인 분석

  • 현재 의도 분석 플로우는 INTENT_ENGINE 설정에 따라 FastPath(DecisionEngine 정규식+Naive Bayes) → Semantic(임베딩 top-k) → LLM Parser → Clarify 순으로 진행되며, FastPath와 Semantic 단계에서 확신도가 충분하지 않으면 UNKNOWN으로 처리됨.
  • rb8001/app/brain/decision_engine.py:360-370: FastPath에서 패턴 매칭 실패 후 _semantic_fallback()이 적절한 의도를 반환하지 못하는 경우, 로그에 "[DecisionEngine] 의도 매칭 실패 - UNKNOWN으로 처리"가 남고 IntentType.UNKNOWN가 반환됨.
  • DOCS/book/300_architecture/database/tables.md:162-170: SemanticIntentClassifier는 intents, intent_prototypes, intent_thresholds, intent_path_stats 테이블을 사용해 제로샷 의도 분류 및 경로별 임계값/통계를 관리하도록 설계되어 있으나, 웹 검색 계열 질의에 대해 프로토타입/임계값이 충분히 정의되어 있지 않아 Semantic 단계의 커버리지가 제한된 상태로 동작하고 있음.

해결 방안

  • 웹 검색 의도로 보이는 UNKNOWN 사례를 주기적으로 수집하여, WEB_SEARCH(또는 실제 사용 중인 웹 검색 intent)용 프로토타입을 intent_prototypes에 추가하고, intent_thresholds에서 semantic/LLM 경로 임계값을 조정해 SemanticIntentClassifier가 검색 계열 발화를 더 잘 흡수하도록 개선.
  • rb8001/app/brain/decision_engine.py:385-407: _semantic_fallback()이 반환하는 상위 intent 중 검색 계열 intent에 대해서는, 유사도/마진이 일정 수준 이상이면 UNKNOWN 대신 검색 intent로 반환하도록 기준을 명확히 정의하고, 관련 동작을 테스트로 고정.
  • DOCS/journey/ideas/250920_happybell80_로빙_의도분석_전략.md에서 정의한 하이브리드 전략(FastPath + Semantic + LLM + Clarify)을 기준으로, 웹/정보 탐색 전용 intent 레이어를 추가하여 FastPath에서 키워드 매칭에 실패하더라도 Semantic/LLM 경로를 통해 검색 워크플로우로 안전하게 연결되도록 실행 계획을 정리하고, 추후 구현 시 본 문서를 참고하도록 함.

향후 개선 사항 (2025-11-18 추가)

Chain-of-Thought (CoT) 적용

  • DOCS/journey/plans/251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md의 5.2 섹션에 정의된 CoT 적용 방안을 LLM Parser 단계에 적용하면, "엠에스 바이오 인터케어 관련 검"처럼 불완전하거나 복잡한 웹 검색 질문의 의도 분류 정확도가 개선될 것으로 예상됨.
  • CoT를 통해 LLM이 단계별로 추론(키워드 추출 → 의도 후보 검토 → 최종 결정)하도록 하면, FastPath/Semantic 단계에서 놓친 복잡한 질문도 LLM Parser 단계에서 더 정확히 분류 가능.
  • 환경변수 INTENT_USE_COT=true로 조건부 활성화하여, 확신도 낮은 경우나 복잡한 질문에만 CoT를 적용해 비용/지연 최소화.

컨텍스트 의존적 질문 처리

  • "이 기업 대표 누구야?" 같은 대명사 포함 질문은 대명사 해소(message_router.py_resolve_pronoun_via_llm)가 선행되어야 웹 검색 의도로 정확히 분류됨.
  • 대명사 해소 실패 시 컨텍스트 정보 부족으로 UNKNOWN으로 분류되거나, 잘못된 엔티티로 웹 검색이 실행되어 여러 회사 정보를 섞어서 답변하는 문제 발생 가능.
  • CONTEXT_FOLLOWUP Intent와 대명사 해소 로직을 웹 검색 경로와 더 긴밀하게 통합하여, 컨텍스트 의존적 질문이 웹 검색 워크플로우로 자연스럽게 연결되도록 개선 필요.

IntentGraph 활성화 상태 확인

  • INTENT_ENGINE=graph 설정 시 IntentGraph 경로가 활성화되어 LLM Parser 단계가 더 자주 사용되므로, UNKNOWN 비율이 달라질 수 있음.
  • 현재 운영 환경의 INTENT_ENGINE 설정 상태를 확인하고, IntentGraph 활성화 여부에 따른 UNKNOWN 비율 차이를 모니터링하여 최적 경로 결정 필요.

구현 완료 (2025-11-18)

1차 개선: Clarify 응답 및 대명사 해소 보완

  • rb8001/app/router/message_router.py:25-114: _resolve_search_query()에서 기업 후보 스캔 시 숫자/날짜 전용 토큰(예: 11월, 10시, 2025)을 엔티티 후보에서 제외하도록 필터 추가, 날짜·시간 표현이 "기업명"으로 잘못 인식되는 문제 완화.
  • rb8001/app/router/router.py:180-205: Clarify 응답 여부(is_clarify_response) 계산 시 세션의 직전 intent(session.intent)를 함께 보관하여, 후속 발화 처리에 활용.
  • rb8001/app/router/router.py:247-283:
    • Clarify 응답이면서 직전 세션 intent가 web_search이고, DecisionEngine이 현재 발화를 UNKNOWN으로 분류한 경우, intent를 WEB_SEARCH로 보정하고 웹 검색용 스킬 시퀀스를 재구성하도록 수정.
    • 이를 통해 "어떤 회사를 말씀하시나요?"에 대한 답변으로 aidol_company처럼 단일 엔티티만 입력된 경우에도, 일반 LLM 대화가 아니라 웹 검색 플로우로 다시 연결되도록 보장.
  • rb8001/app/router/router.py:286-323: Clarify 응답인 경우 원본 메시지(message)를 엔티티로 사용하여 검색어/엔티티 슬롯을 채우는 기존 로직과 결합해, "원래 질문 + 새 엔티티" 조합 검색이 안정적으로 동작하도록 정렬.

의도 관점 테스트 시나리오 고정 (TDD)

  • rb8001/tests/test_web_search_clarify_flow.py:
    • 시나리오: "aidol_company 대표이사는 누구야?"WEB_SEARCH, 이후 Clarify 응답 "어떤 회사를 말씀하시나요?""aidol_company" 단독 입력.
    • 기대 행동: Clarify 응답 이후에도 세션 intent는 web_search로 유지되고, 엔티티/검색어 슬롯이 "aidol_company"로 채워져야 함.
  • rb8001/tests/test_intent_scenarios_from_logs.py::test_web_search_followup_uses_latest_entity:
    • 시나리오: "엠에스 바이오 인터케어 관련 검색""이 기업 대표이사가 누구야?".
    • 기대 행동: 후속 질문에서도 세션 intent가 web_search로 유지되며, 과거 캘린더/오토테크 컨텍스트가 아닌 최신 검색 대상 회사 컨텍스트를 유지해야 함.
  • rb8001/tests/test_intent_scenarios_from_logs.py::test_calendar_all_day_flow_from_logs:
    • 시나리오: "12월 25일 크리스마스 일정 등록해줘.""시간은 하루종일""ㅇㅇ".
    • 기대 행동: 첫 턴에서 CALENDAR_EVENT intent로 날짜/제목이 잡히고, "시간은 하루종일" 후속 입력으로 all-day 시간 정보가 반영된 뒤, "ㅇㅇ" 승인 시 CalendarSkill.create_event가 호출되어 하루종일 일정 생성 플로우가 실행되어야 함.

교훈

원인

  • FastPath(정규식/Naive Bayes) 중심으로 설계된 DecisionEngine 패턴이 실제 사용자 발화의 다양성을 충분히 반영하지 못해, 웹 검색 계열 자연어 질의가 커버리지 밖으로 빠져 UNKNOWN으로 분류되는 사례가 발생함.
  • SemanticIntentClassifier와 intent_* 테이블 구조가 이미 설계되어 있음에도, 웹 검색 계열 intent에 대한 프로토타입/임계값 정의가 부족해 Semantic 경로가 의도적으로 활용되지 못하고 있음.

교훈

  • 의도분석에서 UNKNOWN 비율이 특정 패턴(예: 웹 검색/정보 탐색 질문)에 집중될 경우, 정규식/키워드 추가만으로 해결하기보다 SemanticIntentClassifier 및 intent_* 레지스트리를 활용해 데이터 기반으로 커버리지를 확장해야 함.
  • 로그 분석 결과를 주기적으로 intent_prototypes, intent_thresholds, intent_path_stats에 반영하여, 의도 유형별로 FastPath·Semantic·LLM·Clarify 경로 비중을 조정하는 피드백 루프를 유지해야 함.

원칙

  • DOCS/book/300_architecture/database/tables.md:162-170에 정의된 동적 의도 레지스트리 설계 원칙(제로샷 의도 분류, DB 기반 업데이트, 재시작 없는 반영)을 실제 rb8001 의도 엔진 운영에도 일관되게 적용해야 함.
  • 트래픽에서 관찰된 실제 사용자 발화는 DecisionEngine 정규식 패턴뿐 아니라 SemanticIntentClassifier 프로토타입과 임계값 설계에까지 반영하여, UNKNOWN을 줄이고 웹 검색/업무 스킬로 자연스럽게 이어지는 경로를 유지해야 함.