DOCS/journey/plans/251017_intent_analysis_improvement_plan.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

14 KiB

로빙 의도 파악 개선 플랜

날짜: 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

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 폴백

구현:

intent_descriptions = {
    "time_query": "현재 시각, 날짜, 요일을 묻는 질문",
    "startup_analysis": "스타트업 기업 분석, 유사 기업 검색, 가치평가 요청",
    "context_retrieval": "과거 대화를 참조하는 요청 (아까, 어제, 방금 등)",
    "email": "이메일 확인, 전송, 검색과 관련된 요청"
}

# 임베딩 유사도 → 후보 3개 → 확신도 체크 → LLM 폴백

2.3 시간 인식 주입 (250819 문서)

문제: "오늘 몇일이야?" → "2024년 5월 16일" (실제: 2025년 9월 9일)

해결:

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일)

# 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일)

# 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일)

# 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일)

# app/brain/intent_descriptions.py
INTENT_DESCRIPTIONS = {
    "time_query": "현재 시각, 날짜, 요일을 묻는 질문",
    "email": "이메일 확인, 전송, 검색과 관련된 요청",
    "news": "뉴스 검색, 확인, 요약 요청",
    "startup_analysis": "스타트업 기업 분석, 유사 기업 검색, 가치평가 요청",
    "context_retrieval": "아까, 어제, 방금 등 과거 대화를 참조하는 요청",
    "general_chat": "일반적인 대화, 인사, 잡담"
}

5.3 테스트 케이스

# 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주 스프린트) 검토 필요: 임베딩 모델 선택, 의도 설명 초안