Add intent analysis improvement plan

현재 상태:
- 정규식 기반만 사용 (255줄)
- 시간 질문 오류 ("오늘 몇일이야?" → UNKNOWN)
- 복잡한 질문 미지원 (유사 기업 검색 + 가치평가)
- 멀티턴 대화 불가

제안 방법:
- Phase 1: 시간 인식 + 임베딩 후보 축소 (2주, +300줄)
  - 시간 질문 오류율 100% → 1%
  - LLM 호출 100% → 30% (-70% 비용)
  - ROI: 매우 높음, 리스크: 낮음

- Phase 2: 멀티턴 대화 (1개월, +800줄)
  - 슬롯 필링, Redis 세션 관리
  - 작업 완성률 60% → 90%
  - 단점: LLM 비용 20배

- Phase 3: 도메인 특화 (1개월, +1,200줄)
  - 스타트업 분석 의도
  - LangGraph 워크플로우 연동

권장: Phase 1 즉시 시작 (2주 스프린트)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude-51124 2025-10-17 01:17:03 +09:00
parent fea024b7d4
commit 02e6e5df4c

View File

@ -0,0 +1,458 @@
# 로빙 의도 파악 개선 플랜
**날짜**: 2025-10-17
**작성자**: Claude Code
**관련 문서**:
- `/home/admin/ivada_project/DOCS/ideas/250920_happybell80_로빙_의도분석_전략.md`
- `/home/admin/ivada_project/DOCS/ideas/250819_대화형_점진적_의도_구축_시스템.md`
- `/home/admin/ivada_project/DOCS/ideas/250819_시간인식_제로샷_의도분류_시스템.md`
**현재 구현**: `/home/admin/ivada_project/rb8001/app/brain/decision_engine.py` (255줄)
---
## 1. 현재 상태 분석
### 1.1 현재 구현 (DecisionEngine)
**방식**: 정규식 패턴 매칭 ONLY
```python
def analyze_intent(self, message: str) -> Tuple[IntentType, float]:
for intent_type, patterns in self.intent_patterns.items():
for pattern in patterns:
if re.search(pattern, message_lower):
return intent_type, confidence
return IntentType.UNKNOWN, 0.3
```
**장점**:
- ✅ 빠름 (< 10ms)
- ✅ 비용 없음 (LLM 호출 불필요)
- ✅ 예측 가능
**단점**:
- ❌ 복잡한 질문 처리 불가
- ❌ 시간 인식 없음 ("오늘 몇일이야?" → UNKNOWN)
- ❌ 맥락 이해 없음
- ❌ 멀티턴 대화 불가
- ❌ 확신도 낮을 때 대응 없음
### 1.2 실제 문제 사례
| 사용자 질문 | 현재 처리 | 문제점 |
|------------|----------|--------|
| "오늘 몇일이야?" | UNKNOWN | 시간 질문 패턴 없음 |
| "리버스마운틴 유사 기업 찾아서 가치평가해줘" | UNKNOWN | 복잡한 멀티스텝 질문 |
| "아까 말한 그 기업 투자 단계는?" | UNKNOWN | 맥락 참조 불가 |
| "협업툴 시장 seed 평균은?" | UNKNOWN | 도메인 특화 질문 |
**결론**: 현재는 **단순 명령만 처리 가능**. 종합적 질문은 처리 불가.
---
## 2. 문서에서 제안한 방법론
### 2.1 하이브리드 시스템 (250920 문서)
**아키텍처**:
```
사용자 메시지
┌─────────────────────────┐
│ 1단계: 정규식 FastPath │ → 명확한 패턴 (이메일, 뉴스 등)
└─────────────────────────┘
↓ (매칭 실패)
┌─────────────────────────┐
│ 2단계: 임베딩 후보 축소 │ → 제로샷 분류 (상위 3개)
└─────────────────────────┘
↓ (확신도 < 0.7)
┌─────────────────────────┐
│ 3단계: LLM 확인 │ → 최종 의도 결정
└─────────────────────────┘
```
**장점**:
- 단순 명령: 정규식으로 빠르게 처리 (기존 유지)
- 복잡한 질문: LLM 활용
- LLM 호출 최소화 (비용 절감 70%)
### 2.2 제로샷 의도 분류 (250819 문서)
**핵심**:
1. 의도 설명(description)만으로 분류 (학습 데이터 불필요)
2. 임베딩 유사도로 후보 축소 (20ms)
3. 확신도 낮으면 LLM 폴백
**구현**:
```python
intent_descriptions = {
"time_query": "현재 시각, 날짜, 요일을 묻는 질문",
"startup_analysis": "스타트업 기업 분석, 유사 기업 검색, 가치평가 요청",
"context_retrieval": "과거 대화를 참조하는 요청 (아까, 어제, 방금 등)",
"email": "이메일 확인, 전송, 검색과 관련된 요청"
}
# 임베딩 유사도 → 후보 3개 → 확신도 체크 → LLM 폴백
```
### 2.3 시간 인식 주입 (250819 문서)
**문제**: "오늘 몇일이야?" → "2024년 5월 16일" (실제: 2025년 9월 9일)
**해결**:
```python
TIME_PATTERNS = ["오늘", "내일", "어제", "몇일", "몇시", "요일"]
if any(p in message for p in TIME_PATTERNS):
context["current_time"] = datetime.now(KST).strftime("%Y년 %m월 %d일 %H:%M")
context["needs_time"] = True
```
### 2.4 멀티턴 대화 시스템 (250819 문서)
**현재**: 단일 턴만 처리
**목표**: 3-5턴 대화 지원 (Phase 2)
**슬롯 필링 예시**:
```
User: "이메일 보낼건데..."
Robeing: "누구에게 보내실까요?"
User: "happybell 지메일로"
Robeing: "어떤 내용을 보내실까요?"
User: "감사 인사"
Robeing: "공손한 톤으로 작성하겠습니다. 발송할까요?"
User: "응"
Robeing: "전송했습니다."
```
**필요 컴포넌트**:
- Redis 세션 관리
- 슬롯 스키마 정의
- 컨텍스트 상태 추적
---
## 3. 개선 플랜 (단계별 구현)
### Phase 1: 시간 인식 + 임베딩 후보 축소 (2주)
**목표**: 시간 질문 오류 해결, 복잡한 질문 기본 대응
**구현 내용**:
1. **시간 컨텍스트 주입** (app/brain/decision_engine.py)
- TIME_PATTERNS 정의
- 시간 관련 질문 시 KST 자동 주입
2. **임베딩 기반 후보 축소** (app/brain/intent_classifier.py 신규)
- SentenceTransformer 임베딩
- 의도 설명(description) 정의
- 코사인 유사도 → 상위 3개 후보
3. **확신도 기반 LLM 폴백**
- confidence < 0.7 LLM 호출
- 의도 설명 포함 프롬프트
**예상 효과**:
- 시간 질문 오류율: 100% → 1%
- 복잡한 질문 대응률: 0% → 60%
- LLM 호출 비율: 100% → 30% (단순 명령은 정규식)
**코드 증가**: +300줄
### Phase 2: 멀티턴 대화 (1개월)
**목표**: 3-5턴 대화 지원, 슬롯 필링
**구현 내용**:
1. **컨텍스트 관리 시스템** (app/context/ 신규)
- Redis 세션 저장
- WorkContext 스키마
- 타임아웃 관리 (30분)
2. **슬롯 필링 시스템**
- 스킬별 슬롯 정의 (required/optional)
- 자동 질문 생성
- 충돌 해결
3. **대화 상태 추적**
- Idle → Collecting → Confirming → Executing
**예상 효과**:
- 작업 완성률: 60% → 90%
- 사용자 만족도 증가
**코드 증가**: +800줄
**단점**:
- LLM 비용 20배 증가 (7턴 대화 기준)
- 응답 시간: 500ms → 2,600ms
### Phase 3: 도메인 특화 (추가 1개월)
**목표**: 스타트업 분석 등 도메인 특화 의도 처리
**구현 내용**:
1. **스타트업 분석 의도** (app/brain/decision_engine.py)
- STARTUP_ANALYSIS 의도 추가
- LangGraph 워크플로우 연동
2. **Neo4j/TF-IDF 검색 통합**
- 유사 기업 검색 스킬
- 베이지안 평가 스킬
3. **도메인 지식 주입**
- 스타트업 용어 사전
- 산업 분류 체계
**예상 효과**:
- "리버스마운틴 유사 기업 찾아서 가치평가해줘" → 처리 가능
- "협업툴 시장 seed 평균은?" → 처리 가능
**코드 증가**: +1,200줄
---
## 4. 우선순위 결정
### 4.1 시급도 평가
| 문제 | 시급도 | 영향도 | Phase |
|------|--------|--------|-------|
| 시간 질문 오류 | 🔴 HIGH | 일상 대화 | Phase 1 |
| 복잡한 질문 미지원 | 🟡 MEDIUM | 고급 기능 | Phase 1 |
| 멀티턴 대화 부재 | 🟡 MEDIUM | UX | Phase 2 |
| 도메인 특화 미지원 | 🟢 LOW | 특수 기능 | Phase 3 |
### 4.2 권장 순서
**즉시 구현 (1-2주)**:
1. Phase 1 - 시간 인식 + 임베딩 후보 축소
- ROI: 매우 높음 (적은 코드로 큰 효과)
- 리스크: 낮음 (기존 코드 영향 최소)
**중기 구현 (1-2개월)**:
2. Phase 2 - 멀티턴 대화
- ROI: 중간 (복잡도 증가, 비용 증가)
- 리스크: 중간 (컨텍스트 관리 복잡)
**장기 구현 (3-4개월)**:
3. Phase 3 - 도메인 특화
- ROI: 높음 (특정 사용 사례에만 적용)
- 리스크: 낮음 (독립적 기능)
---
## 5. Phase 1 상세 구현 계획
### 5.1 파일 구조
```
rb8001/
├── app/
│ ├── brain/
│ │ ├── decision_engine.py # 기존 (수정)
│ │ ├── intent_classifier.py # 신규 (임베딩 분류)
│ │ ├── intent_descriptions.py # 신규 (의도 설명)
│ │ └── time_aware_helper.py # 신규 (시간 컨텍스트)
│ └── tests/
│ └── test_intent_classifier.py # 신규
```
### 5.2 구현 순서
#### Step 1: 시간 인식 (3일)
```python
# app/brain/time_aware_helper.py
TIME_PATTERNS = {
"absolute_time": ["오늘", "내일", "어제", "몇일", "몇시", "요일"],
"relative_time": ["아까", "방금", "조금전"],
"time_reference": ["그때", "언제", "며칠"]
}
def inject_time_context(message: str, context: Dict) -> Dict:
if any(p in message for patterns in TIME_PATTERNS.values() for p in patterns):
context["current_time"] = datetime.now(KST).strftime("%Y년 %m월 %d일 %H:%M")
context["needs_time"] = True
return context
```
#### Step 2: 임베딩 분류 (5일)
```python
# app/brain/intent_classifier.py
class ZeroShotIntentClassifier:
def __init__(self):
self.embedder = SentenceTransformer('paraphrase-multilingual-mpnet-base-v2')
self.intent_descriptions = load_intent_descriptions()
def classify(self, text: str) -> Tuple[str, float, List]:
# 임베딩
text_emb = self.embedder.encode(text)
# 후보 축소
scores = {}
for intent, desc in self.intent_descriptions.items():
desc_emb = self.embedder.encode(desc)
scores[intent] = cosine_similarity(text_emb, desc_emb)
# 상위 3개
top_3 = sorted(scores.items(), key=lambda x: x[1], reverse=True)[:3]
return top_3[0][0], top_3[0][1], top_3
```
#### Step 3: DecisionEngine 통합 (3일)
```python
# app/brain/decision_engine.py (수정)
def analyze_intent(self, message: str, context: Dict) -> Tuple[IntentType, float]:
# 1. 시간 컨텍스트 주입
context = inject_time_context(message, context)
# 2. 정규식 FastPath (기존)
for intent_type, patterns in self.intent_patterns.items():
for pattern in patterns:
if re.search(pattern, message):
return intent_type, 0.9
# 3. 임베딩 분류 (신규)
intent_str, confidence, candidates = self.intent_classifier.classify(message)
# 4. 확신도 체크
if confidence < 0.7:
# LLM 폴백
intent_str = await self.llm_fallback(message, candidates, context)
return IntentType(intent_str), confidence
```
#### Step 4: 의도 설명 정의 (2일)
```python
# app/brain/intent_descriptions.py
INTENT_DESCRIPTIONS = {
"time_query": "현재 시각, 날짜, 요일을 묻는 질문",
"email": "이메일 확인, 전송, 검색과 관련된 요청",
"news": "뉴스 검색, 확인, 요약 요청",
"startup_analysis": "스타트업 기업 분석, 유사 기업 검색, 가치평가 요청",
"context_retrieval": "아까, 어제, 방금 등 과거 대화를 참조하는 요청",
"general_chat": "일반적인 대화, 인사, 잡담"
}
```
### 5.3 테스트 케이스
```python
# app/tests/test_intent_classifier.py
test_cases = [
# 시간 질문
("오늘 몇일이야?", "time_query", 0.9),
("지금 몇시야?", "time_query", 0.9),
# 복잡한 질문
("리버스마운틴 유사 기업 찾아줘", "startup_analysis", 0.8),
("협업툴 시장 seed 평균은?", "startup_analysis", 0.7),
# 맥락 참조
("아까 말한 그 기업", "context_retrieval", 0.85),
# 기존 패턴 (정규식)
("이메일 보내줘", "email", 0.9),
("뉴스 찾아봐", "news", 0.9)
]
```
---
## 6. 성능 및 비용 분석
### 6.1 Phase 1 예상 성능
| 지표 | 현재 | Phase 1 | 개선 |
|------|------|---------|------|
| 단순 명령 응답 시간 | 10ms | 10ms | 0% |
| 복잡 질문 응답 시간 | - | 150ms | 신규 |
| LLM 호출 비율 | 100% | 30% | -70% |
| 시간 질문 정확도 | 0% | 99% | +99% |
| 복잡 질문 대응률 | 0% | 60% | +60% |
### 6.2 비용 분석
**현재 (복잡한 질문 시)**:
- 모두 LLM으로 폴백 → 100% LLM 호출
**Phase 1 후**:
- 정규식 매칭: 60% (비용 0원)
- 임베딩 분류: 25% (비용 < 1원/1000건)
- LLM 폴백: 15% (기존 대비 -85%)
**월간 비용 (10만건 기준)**:
- 현재: $300
- Phase 1: $50 (-83%)
---
## 7. 리스크 및 대응
### 7.1 리스크 요인
| 리스크 | 확률 | 영향 | 대응 |
|--------|------|------|------|
| 임베딩 모델 용량 큼 | 중 | 중 | 경량 모델 선택 (miniLM) |
| 확신도 임계값 조정 어려움 | 중 | 중 | A/B 테스트로 최적값 탐색 |
| 기존 코드 영향 | 낮 | 중 | 기존 로직 보존 (정규식 우선) |
### 7.2 롤백 계획
- Phase 1은 기존 코드에 추가만 하므로 롤백 용이
- `USE_INTENT_CLASSIFIER=false` 환경변수로 비활성화 가능
---
## 8. 다음 단계
### 8.1 즉시 실행
1. **Phase 1 구현 시작** (추천)
- 2주 소요
- ROI 매우 높음
- 리스크 낮음
2. **임베딩 모델 선택**
- `paraphrase-multilingual-mpnet-base-v2` (420MB) vs
- `paraphrase-multilingual-MiniLM-L12-v2` (120MB)
3. **의도 설명 초안 작성**
- 현재 IntentType 15개에 대한 설명
### 8.2 의사 결정 필요
1. Phase 2 (멀티턴 대화) 진행 여부
- 장점: UX 대폭 개선
- 단점: LLM 비용 20배, 복잡도 증가
2. Phase 3 (도메인 특화) 우선순위
- 스타트업 분석 외 다른 도메인?
---
## 9. 참고 자료
### 9.1 관련 문서
- 로빙 의도분석 전략: `DOCS/ideas/250920_happybell80_로빙_의도분석_전략.md`
- 대화형 시스템: `DOCS/ideas/250819_대화형_점진적_의도_구축_시스템.md`
- 제로샷 분류: `DOCS/ideas/250819_시간인식_제로샷_의도분류_시스템.md`
### 9.2 연구 논문
- Hong et al. (2024): Zero-shot Intent Classification (SIGDIAL)
- 핵심: 고품질 의도 설명 + 임베딩 후보 축소
### 9.3 기술 스택
- SentenceTransformer (임베딩)
- Redis (세션 관리, Phase 2)
- PostgreSQL (대화 로그)
---
**작성 완료**: 2025-10-17
**권장 다음 액션**: Phase 1 구현 시작 (2주 스프린트)
**검토 필요**: 임베딩 모델 선택, 의도 설명 초안