# 의도 파악 3단계 아키텍처 전환 계획 **작성일**: 2025-11-26 **작성자**: Auto (Claude) **상태**: 구현 완료 (2025-11-26) **관련 문서**: - `251017_intent_analysis_improvement_plan.md` - 의도 분석 개선 플랜 - `251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md` - 의도 런타임 설계 - `311_FastAPI_구조_원칙.md` - 코드 작성 원칙 --- ## 1. 문제 발견 ### 1.1 현재 구조의 근본적 문제 **발견된 문제**: - IntentType이 스킬/액션과 직접 1:1 매핑되어 있음 - 의도 파악이 곧 스킬 선택으로 이어지는 구조 - 진정한 "의도 파악(무엇을 원하는가)" → "행동 계획(어떻게 할 것인가)" → "스킬 선택(어떤 도구를 쓸 것인가)"의 단계적 분리가 없음 **실제 문제 사례**: ``` 사용자: "12월 10일 11시 종합운동장에서 뵙겠습니다. 준비물: 노트북,휴대폰 일정등록" 로빙: "네, 종합운동장 미팅 일정을 12월 10일 11시에 등록해 드릴게요. 구글 캘린더에 등록해드릴까요?" 사용자: "그래" 로빙: "안녕하세요! 무엇을 도와드릴까요? 😊" # ❌ 일반 인사로 돌아감 ``` **원인 분석**: - "구글 캘린더에 등록해드릴까요?" 응답이 `calendar_event` intent로 저장됨 - "그래" 같은 동의 메시지가 `_confirm`으로 끝나는 intent를 찾지 못함 - `calendar_event`는 approval 대상이 아니어서 `calendar_approval`로 변환되지 않음 ### 1.2 아키텍처 구조적 문제 **현재 구조**: ``` IntentType (스킬/액션과 직접 매핑) ↓ decide_skill_sequence() → 스킬 선택 ``` **문제점**: - 의도 파악이 스킬 선택에 가까움 - 새로운 의도 추가 시 스킬도 함께 정의해야 함 - 의도와 구현이 강하게 결합됨 --- ## 2. 개선 방향 ### 2.1 3단계 구조 설계 **목표**: 의도 파악 → 행동 계획 → 스킬 선택의 단계적 접근 ``` 1단계: 의도 파악 (IntentAnalyzer) - 추상적 목표 파악 (일정 관리, 정보 검색, 커뮤니케이션 등) - LLM 기반 제로샷 의도 분석 (무한한 의도 처리 가능) - 사용자가 무엇을 원하는지 추상적 수준에서 이해 2단계: 행동 계획 (ActionPlanner) - 구체적 행동 결정 (등록/조회/삭제/수정 등) - 의도를 달성하기 위한 구체적 행동 계획 - 여러 행동이 필요한 경우 순서 및 우선순위 결정 3단계: 스킬 선택 (SkillSelector) - 적절한 도구 선택 (calendar_skill.create_event 등) - 행동을 수행할 적절한 스킬 선택 - 스킬 실행 가능 여부 확인 ``` ### 2.2 3단계 구조의 장점 - **의도와 구현의 분리**: 같은 의도라도 다른 행동/스킬로 구현 가능 - **확장성**: 새로운 스킬 추가 시 기존 의도 재사용 가능 - **유연성**: 행동 계획 단계에서 여러 대안 고려 가능 - **명확성**: 각 단계의 책임이 명확히 분리됨 - **무한한 의도 처리**: LLM 기반으로 아직 구현되지 않은 의도도 파악 가능 --- ## 3. 구현 계획 ### 3.1 폴더 구조 ``` app/services/brain/ ├── intent/ # 신규 폴더 │ ├── __init__.py │ ├── schemas.py # IntentGoal, ActionPlan, SkillSequence │ ├── intent_analyzer.py # 1단계: 의도 파악 │ ├── action_planner.py # 2단계: 행동 계획 │ ├── skill_selector.py # 3단계: 스킬 선택 │ ├── intent_graph.py # 기존 파일 이동 │ └── semantic_classifier.py # 기존 파일 이동 ├── decision_engine.py # 래퍼로 유지 (하위 호환성) ├── brain_service.py # 3단계 파이프라인 호출 └── ... ``` ### 3.2 데이터 구조 정의 **Pydantic 모델** (`app/services/brain/intent/schemas.py`): ```python from pydantic import BaseModel from typing import Optional, List, Dict, Any from enum import Enum class IntentCategory(str, Enum): """추상적 의도 카테고리""" SCHEDULE_MANAGEMENT = "schedule_management" # 일정 관리 INFORMATION_RETRIEVAL = "information_retrieval" # 정보 검색 COMMUNICATION = "communication" # 커뮤니케이션 DOCUMENT_PROCESSING = "document_processing" # 문서 처리 TASK_EXECUTION = "task_execution" # 작업 실행 GENERAL_INQUIRY = "general_inquiry" # 일반 질의 UNKNOWN = "unknown" class IntentGoal(BaseModel): """1단계: 의도 파악 결과""" category: IntentCategory # 추상적 카테고리 description: str # LLM이 파악한 의도 설명 confidence: float # 신뢰도 (0.0 ~ 1.0) raw_intent: Optional[str] = None # LLM 원본 출력 (디버깅용) context_hints: Dict[str, Any] = {} # 컨텍스트 힌트 class ActionType(str, Enum): """구체적 행동 타입""" CREATE_EVENT = "create_event" QUERY_EVENTS = "query_events" DELETE_EVENT = "delete_event" UPDATE_EVENT = "update_event" SEARCH_WEB = "search_web" SEARCH_MEMORY = "search_memory" SEND_EMAIL = "send_email" READ_EMAIL = "read_email" ANALYZE_DOCUMENT = "analyze_document" CLARIFY = "clarify" CHAT = "chat" class ActionPlan(BaseModel): """2단계: 행동 계획 결과""" actions: List[Dict[str, Any]] # 행동 목록 requires_clarification: bool = False clarification_message: Optional[str] = None class SkillSequence(BaseModel): """3단계: 스킬 선택 결과 (기존 execution_plan과 호환)""" skills: List[Dict[str, Any]] # 스킬 목록 intent: Dict[str, Any] # 원본 의도 정보 (하위 호환성) ``` ### 3.3 데이터 흐름 ``` IntentAnalyzer.analyze() → IntentGoal ↓ ActionPlanner.plan(IntentGoal) → ActionPlan ↓ SkillSelector.select(ActionPlan) → SkillSequence ↓ 기존 execution_plan 형식으로 변환 (하위 호환성) ``` ### 3.4 하위 호환성 유지 **기존 DecisionEngine 클래스는 래퍼로 유지**: - 내부적으로 3단계 파이프라인 호출 - 기존 API 인터페이스 유지 - 점진적 마이그레이션 가능 --- ## 4. TDD 시나리오 ### 시나리오 1: 일정 등록 동의 처리 (현재 문제 해결) ``` 사용자: "12월 10일 11시 종합운동장에서 뵙겠습니다. 준비물: 노트북,휴대폰 일정등록" 로빙: "네, 종합운동장 미팅 일정을 12월 10일 11시에 등록해 드릴게요. 구글 캘린더에 등록해드릴까요?" 사용자: "그래" → IntentGoal: {category: SCHEDULE_MANAGEMENT, description: "일정 등록 승인"} → ActionPlan: {actions: [{type: CREATE_EVENT, goal: "구글 캘린더에 일정 등록"}]} → SkillSequence: {skills: [{skill: "CALENDAR", action: "create_event"}]} → 성공: 일정 등록 완료 ``` ### 시나리오 2: 아직 구현되지 않은 의도 처리 ``` 사용자: "내일 오후 2시 회의실 예약해줘" → IntentGoal: {category: SCHEDULE_MANAGEMENT, description: "회의실 예약 요청"} → ActionPlan: {actions: [{type: CREATE_EVENT, goal: "회의실 예약"}]} → SkillSelector: 회의실 예약 스킬 없음 감지 → 로빙: "죄송합니다. 회의실 예약 기능은 아직 준비 중입니다. 구글 캘린더에 일정만 등록해드릴까요?" ``` ### 시나리오 3: 복합 의도 처리 ``` 사용자: "리버스마운틴 유사 기업 찾아서 가치평가 보고서 이메일로 보내줘" → IntentGoal: {category: INFORMATION_RETRIEVAL, description: "기업 검색 및 분석 후 이메일 발송"} → ActionPlan: {actions: [ {type: SEARCH_WEB, goal: "리버스마운틴 유사 기업 검색", priority: 1}, {type: ANALYZE_DOCUMENT, goal: "가치평가 분석", priority: 2}, {type: SEND_EMAIL, goal: "보고서 이메일 발송", priority: 3} ]} → SkillSequence: {skills: [ {skill: "TOOL", action: "web_search"}, {skill: "LLM", action: "analyze"}, {skill: "EMAIL", action: "compose"} ]} ``` ### 시나리오 4: 맥락 기반 의도 파악 ``` 사용자: "아까 말한 그 기업 투자 단계는?" → IntentGoal: {category: INFORMATION_RETRIEVAL, description: "이전 대화에서 언급된 기업의 투자 단계 조회", context_hints: {reference: "previous_conversation"}} → ActionPlan: {actions: [{type: SEARCH_MEMORY, goal: "이전 대화에서 기업 정보 검색"}]} → SkillSequence: {skills: [{skill: "LLM", action: "search_memory"}]} → 성공: ChromaDB에서 관련 대화 검색 후 답변 ``` ### 시나리오 5: 모호한 의도 명확화 ``` 사용자: "이메일 보내줘" → IntentGoal: {category: COMMUNICATION, description: "이메일 발송 요청", confidence: 0.6} → ActionPlan: { requires_clarification: True, clarification_message: "누구에게 보내실까요? 어떤 내용을 보내실까요?" } → SkillSequence: {skills: []} → 로빙: "누구에게 보내실까요? 어떤 내용을 보내실까요?" ``` --- ## 5. 수정 범위 ### 5.1 수정 필요한 부분 **백엔드 (rb8001)**: - `app/services/brain/decision_engine.py` → 3단계 파이프라인으로 재구성 - `app/services/brain/intent/` 폴더 신규 생성 - `app/services/brain/brain_service.py` → 3단계 파이프라인 호출 ### 5.2 수정 불필요한 부분 - **Gateway (robeing-gateway)**: 변경 불필요, JWT 검증/프록시 역할 유지 - **프론트엔드**: 변경 불필요, API 인터페이스 동일 - **DB 스키마**: 변경 불필요, 의도/행동 계획은 런타임 처리 --- ## 6. 구현 순서 ### Phase 1: 구조 설계 및 스키마 정의 (1일) 1. `app/services/brain/intent/` 폴더 생성 2. `schemas.py` 작성 (IntentGoal, ActionPlan, SkillSequence) 3. 기존 파일 이동 (intent_graph.py, semantic_classifier.py) ### Phase 2: IntentAnalyzer 구현 (2일) 1. LLM 기반 제로샷 의도 분석 2. IntentCategory 분류 3. TDD 테스트 작성 ### Phase 3: ActionPlanner 구현 (2일) 1. IntentGoal → ActionPlan 변환 로직 2. 복합 행동 처리 3. Clarify 로직 ### Phase 4: SkillSelector 구현 (2일) 1. ActionPlan → SkillSequence 변환 2. 기존 execution_plan 형식으로 변환 3. 하위 호환성 유지 ### Phase 5: 통합 및 테스트 (2일) 1. DecisionEngine 래퍼 구현 2. 기존 테스트 통과 확인 3. TDD 시나리오 검증 --- ## 7. 참고 사항 ### 7.1 코드 작성 원칙 준수 - 계층 분리: router → services → state - 파일 크기: 한 파일 최대 300줄 - 의존성 방향: 단방향 흐름 ### 7.2 하위 호환성 - 기존 DecisionEngine API 유지 - 기존 execution_plan 형식 유지 - 점진적 마이그레이션 가능 --- **작성 완료**: 2025-11-26 **다음 단계**: Phase 1 구현 시작 --- ## 8. 구현 완료 (2025-11-26) ### 8.1 구현 내용 **완료된 작업**: 1. ✅ IntentAnalyzer 구현 (`app/services/brain/intent/intent_analyzer.py`) - LLM 기반 제로샷 의도 분석 (async) - 키워드 기반 폴백 분석 (sync) - IntentCategory 분류 지원 2. ✅ ActionPlanner 확장 (`app/services/brain/intent/action_planner.py`) - 모든 IntentCategory에 대한 ActionType 매핑 - SCHEDULE_MANAGEMENT: CREATE_EVENT, QUERY_EVENTS, DELETE_EVENT, UPDATE_EVENT - INFORMATION_RETRIEVAL: SEARCH_WEB, SEARCH_MEMORY - COMMUNICATION: SEND_EMAIL, READ_EMAIL - DOCUMENT_PROCESSING: ANALYZE_DOCUMENT - TASK_EXECUTION, GENERAL_INQUIRY: CHAT - UNKNOWN: CLARIFY 3. ✅ SkillSelector 확장 (`app/services/brain/intent/skill_selector.py`) - 모든 ActionType에 대한 스킬 매핑 - CALENDAR, EMAIL, TOOL, LLM 스킬 지원 4. ✅ DecisionEngine 통합 (`app/services/brain/decision_engine.py`) - `_build_intent_pipeline_sync`: 동기 버전 (폴백 분석) - `_build_intent_pipeline`: 비동기 버전 (LLM 기반) - `create_execution_plan`에 `intent_pipeline` 메타데이터 추가 5. ✅ 테스트 통과 - ActionPlanner 테스트 통과 - SkillSelector 테스트 통과 - DecisionEngine 통합 테스트 통과 ### 8.2 배포 상태 - **커밋**: `1b57c86` - "feat: 3단계 의도 파악 아키텍처 구현" - **배포 완료**: 2025-11-26 19:17 - **컨테이너 상태**: 정상 (healthy) ### 8.3 하위 호환성 - 기존 `decide_skill_sequence` 메서드 유지 (하위 호환성) - 새로운 3단계 파이프라인은 `execution_plan["intent_pipeline"]` 메타데이터로 제공 - 점진적 마이그레이션을 위해 두 시스템 병행 ### 8.4 중복 코드 확인 - `decide_skill_sequence`와 `SkillSelector` 모두 IntentType/ActionType → Skill 매핑 포함 - 의도적 중복: 하위 호환성 및 점진적 마이그레이션을 위해 병행 유지 - 주석 추가로 의도 명확화 --- ## 9. DB/베이지안 방법 통합 방안 ### 9.1 문제 5가지 TDD 시나리오 테스트 결과 시나리오 2~5가 미비: - 시나리오 2: 미구현 의도 처리 - clarify 없음 - 시나리오 3: 복합 의도 처리 - 단일 액션만 생성 - 시나리오 4: 맥락 기반 의도 파악 - UNKNOWN 분류 - 시나리오 5: 모호한 의도 명확화 - clarify 없음 ### 9.2 해결 방안 기존 DB/베이지안 방법(`intent_prototypes`, `intent_thresholds`, `intent_path_stats`)을 3단계 아키텍처에 통합: - **IntentAnalyzer**: `SemanticIntentClassifier` 재사용, 임베딩 기반 후보 축소 - **ActionPlanner**: `intent_path_stats`의 Beta(α,β)로 액션 우선순위 조정, 복합 의도 파싱 - **SkillSelector**: 스킬별 실행 성공률 추적, 미구현 스킬 감지 **상세 내용**: `251126_intent_3step_db_bayesian_integration.md` 참고 --- ## 10. 리스크 및 추가 고려사항 - **회귀 및 승인/컨펌 흐름 붕괴 리스크** - 기존 DecisionEngine이 암묵적으로 처리하던 승인/취소/컨펌, 예외 케이스들이 IntentGoal → ActionPlan → SkillSequence 분리 과정에서 깨질 수 있음 (예: 같은 입력인데 캘린더/이메일 오작동). - 실제 서비스 대화 로그를 기반으로 한 리플레이 테스트 세트, A/B 플래그(구 구조/신 구조 토글), 빠른 롤백 전략을 설계한 뒤 단계적으로 트래픽을 전환해야 함. - **LLM 기반 1단계 도입에 따른 비용/레이턴시/안정성 이슈** - 모든 발화가 최소 1회 LLM을 타면 레이턴시·비용·비결정성이 커지므로, 고빈도·단순 패턴(“그래”, “응”, 일정 단문 등)은 규칙/통계 모델로 단축 경로를 두고, 각 단계별 confidence 기준과 실패 시 폴백 전략(UNKNOWN → 안전한 일반 대화/질문 재확인)을 명시적으로 정의해야 함. - LLM 프롬프트/파라미터 변경에 따른 드리프트를 감시할 수 있도록, IntentAnalyzer 입력/출력(카테고리, 설명, confidence)을 구조화된 로그로 남기고 모니터링 지표(오탐/미탐 비율, 평균 응답 시간 등)를 운영 레벨에서 관리해야 함. - **학습·개선 루프까지 포함한 설계** - 3단계 분리는 파일 구조 정리가 아니라, 각 단계에서 생성되는 신호를 intent_review/active_learning과 연결해 시간이 지날수록 의도→행동→스킬 품질이 자동 개선되도록 만드는 것이 핵심. - IntentGoal/ActionPlan/SkillSequence 및 실제 실행 결과(성공/실패, 사용자 피드백)를 표준 스키마로 저장하고, 이를 기반으로 한 오프라인 평가·액티브 러닝·온라인 튜닝 루프를 설계해야 함.