DOCS/troubleshooting/250914_happybell80_IntentAnalyzer_미사용_문제.md

104 lines
5.1 KiB
Markdown

# 트러블슈팅: IntentAnalyzer 미사용 및 Slack UX 문제
## 발생 시간
- 2025년 9월 14일
## 문제 상황
1. **멘션 필수 문제**: 채널에서 항상 `@robeing /search` 형태로 멘션 필요
2. **자연어 인식 실패**: "검색해줘", "찾아봐" 같은 자연어 명령 무시
3. **마크다운 포맷 깨짐**: `**굵게**` 형식이 Slack에서 깨짐 (Slack은 `*굵게*` 사용)
## 원인 분석
### 1. IntentAnalyzer 고아 코드 상태
```python
# app/llm/intent_analyzer.py 존재하지만 미사용
- "검색해줘" "/search" 변환 기능 구현됨
- 어디서도 import/호출하지 않음
- slack_handler.py:81에서 router.route_message() 직접 호출
- DecisionEngine(정규식 기반) 사용 , IntentAnalyzer(LLM 기반) 미사용
- 2025-08-11 같은 시스템 모두 개발, DecisionEngine만 채택됨
```
### 2. Slack 이벤트 처리 로직
```python
# slack_handler.py:209
if event_type == "app_mention" or (event_type == "message" and is_dm):
# 채널 메시지는 멘션 필수, DM만 멘션 없이 가능
```
### 3. 응답 포맷 문제
- LLM이 `**굵게**` 마크다운 생성
- Slack mrkdwn은 `*굵게*` 형식만 지원
## 해결 방법
### 1. IntentAnalyzer 연결 (두 가지 방안)
#### 방안 A: slack_handler.py 수정 (문제: handler 객체 없음)
```python
# slack_handler.py Line 78-81 사이
# 문제: handler 객체 접근 불가로 구현 어려움
```
#### 방안 B: router.route_message() 수정 (권장)
```python
# router.py의 route_message() 시작부
async def route_message(self, text: str, user_id: str, ...):
# IntentAnalyzer로 전처리
analyzer = IntentAnalyzer()
text = await analyzer.analyze_user_intent(text, self.llm_handler)
# 기존 처리 로직 계속...
```
### 2. 채널 메시지 키워드 감지
```python
# slack_handler.py:209 수정
search_keywords = ["검색", "찾아", "알아봐", "서치"]
is_search_request = any(kw in text for kw in search_keywords)
if event_type == "app_mention" or (event_type == "message" and is_dm) or is_search_request:
# 검색 키워드 포함 시 멘션 없이도 처리
```
### 3. 응답 포맷 변환 ✅ (해결됨)
```python
# slack_handler.py:100-101 (적용 완료)
response_text = response_text.replace("**", "*") # Slack 포맷 변환
```
## 교훈
1. **기능 구현 != 기능 활성화**: 코드 작성 후 연결 확인 필수
2. **고아 코드 점검**: 미사용 모듈 정기적 확인
3. **플랫폼별 포맷**: Slack mrkdwn ≠ Markdown
## 메시지 처리 전체 흐름
**Slack**: `/api/slack/events` → slack_handler → router.route_message() → Brain(DecisionEngine) → 스킬/LLM → Slack 응답
**Frontend**: Gateway(JWT) → `/api/message` → router.route_message() → 동일 처리 → HTTP 응답
**채널 구분**: channel 파라미터 (Slack: "C0123ABCD", Frontend: "frontend")
**응답 반환**: router는 데이터만 생성, 실제 전송은 각 handler가 처리
## 영향 범위
- router 레벨 통합 시 Slack뿐 아니라 모든 인터페이스(frontend 등)에 자연어 지원
- DecisionEngine(정규식)과 IntentAnalyzer(LLM) 병행 사용으로 성능/정확도 균형 필요
- 포맷 깨짐 문제 해결로 가독성 개선 ✅
## 제로샷 의도 시나리오(추가)
- 시나리오 1: "AI 뉴스 뭐 있어?" → 프리필터 [news, digest, 기타] → LLM 점수 {news:0.86,…} → news 선택 → skill-news /search 호출 → 요약 포함 응답
- 시나리오 1 실패: news 스킬 다운 → "현재 뉴스 기능 불가" 안내 + 에러 로그 + 대체 제안(/digest)
- 시나리오 2: "할 일 뽑아줘"(스레드) → 프리필터 [actions, digest, 기타] → actions ≥ 임계치 → 스레드 메시지 수집 → 액션 추출 → 체크리스트 반환
- 시나리오 2 불명확: 임계치 미달 → "범위 선택(이 스레드/지난 24시간)?" 재질문 → 사용자 선택 후 실행
- 시나리오 3: "정리해줘"(모호) → 프리필터 [digest, actions, news, 기타] → 최고 점수<0.6 옵션 제시 선택 실행
- 멘션 없이도 처리: 채널 자연어에서 키워드(뉴스/요약/ ) 감지 IntentAnalyzer 경로 진입
- 출력 스키마: JSON {intent, score, reason} 강제, 파싱 실패 원문 메시지로 폴백
- 실행 가드: 헬스체크/권한 실패 "지금은 불가" 응답, execution_plan 함께 로그 저장
- 레지스트리 연동: 의도 후보·키워드·엔드포인트를 YAML/JSON으로 관리하여 시나리오 자동 반영
- 모니터링: 점수 분포·임계치 미달률·폴백율을 대시보드로 추적해 프리필터/프롬프트 개선
- 실패 대화(요약): "vla 검색"→"다른 내용"→"/search"→"기술용어"에도 미실행
- 기대 처리: thread_focus='vla' 유지, intent=search 지속, query 자동보완
- 보조 슬롯: "기술용어"→domain='tech' 적용, 즉시 실행
- 응답 예: "VLA는 Variable Length Array/ Vision-Language-Action , 어떤 쪽인가요? 기본은 C언어 VLA로 검색합니다."
- 폴백: 스킬 불가 "지금은 검색 불가" + 대체 제안(/digest), 로그 기록