@startuml !theme mono title AI Service 내부 시퀀스 - Todo자동추출 participant "TodoController" as Controller participant "TodoExtractionService" as Service participant "LLMClient" as LLM participant "TodoRepository" as Repo participant "MeetingServiceClient<>" as MeetingClient database "Azure OpenAI<>" as OpenAI database "PostgreSQL<>" as DB == API 요청 수신 == note over Controller POST /todos/extract Request Body: - meetingId - userId - minutesContent (회의록 전체 내용) end note Controller -> Service: extractTodos(request) activate Service note right Request 데이터: - meetingId - userId - minutesContent end note == 입력 데이터 검증 == Service -> Service: 회의록 내용 검증 note right 검증 항목: - minutesContent 필수 확인 - 최소 길이 검증 (50자 이상) - meetingId 형식 검증 (UUID) end note alt 검증 실패 Service --> Controller: 400 Bad Request note right 에러 메시지: - "회의록 내용이 필요합니다" - "회의록이 너무 짧습니다" end note end == 회의록 내용 파싱 == Service -> Service: 회의록에서 참석자 추출 note right Markdown 파싱: - "## 참석자" 섹션 파싱 - 참석자 목록 추출 - 담당자 매칭에 활용 end note == LLM 기반 Todo 추출 == Service -> Service: Todo 추출 프롬프트 생성 note right 시스템 프롬프트: - 역할: Todo 추출 전문가 - 지시사항: 액션 아이템 식별, 담당자 및 마감일 추출 사용자 프롬프트: - 회의록 전체 내용 - 참석자 목록 - 추출 기준: * "~하기로 함", "~까지 완료" * "~담당", "제가 하겠습니다" * 명령형 문장 end note Service -> LLM: extractActionItems(prompt, minutesContent, participants) activate LLM LLM -> OpenAI: POST /chat/completions activate OpenAI note right 요청 파라미터: - model: gpt-4o - temperature: 0.2 - response_format: json_object 응답 형식: { "todos": [ { "content": "Todo 내용", "assignee": "담당자명", "dueDate": "YYYY-MM-DD", "priority": "HIGH|MEDIUM|LOW", "section": "관련 섹션" } ] } end note OpenAI -> OpenAI: 회의록 분석 note right 1. 액션 아이템 키워드 탐지 2. 명령형 문장 분석 3. 담당자 식별 - 발언 내용 기반 - 직책/역할 기반 4. 마감일 추출 5. 우선순위 판단 end note OpenAI --> LLM: Todo 목록 (JSON) deactivate OpenAI LLM --> Service: extractedTodos deactivate LLM == Todo 데이터 저장 및 검증 == Service -> Service: Todo 데이터 검증 note right 검증 항목: - content 필수 - assignee가 참석자 목록에 있는지 - dueDate 형식 검증 - priority 유효성 검증 end note loop 각 Todo 항목마다 Service -> Repo: saveTodo(meetingId, todoData) activate Repo Repo -> DB: Todo 정보 저장 activate DB note right 저장 데이터: - meeting_id - content - assignee - due_date - priority - section_reference - status: PENDING - extracted_at end note DB --> Repo: todoId deactivate DB Repo --> Service: todoId deactivate Repo end == Meeting Service에 Todo 전송 == Service -> Service: Todo 목록 준비 note right 전송 데이터 구성: - Todo 내용 - 담당자 정보 - 마감일 - 우선순위 - 관련 회의록 섹션 링크 end note Service -> MeetingClient: POST /meetings/{meetingId}/todos activate MeetingClient note right 요청 바디: { "meetingId": "{meetingId}", "todos": [ { "content": "Todo 내용", "assignee": "담당자", "dueDate": "2025-01-30", "priority": "HIGH", "sectionReference": "결정사항 #3" } ] } end note MeetingClient -> MeetingClient: Todo 생성 및 할당 처리 note right Meeting Service 내부 처리: - Todo 테이블에 저장 - 회의록 섹션 링크 연결 - TodoCreated 이벤트 발행 - 담당자에게 알림 발송 end note MeetingClient --> Service: 200 OK (Todo 생성 완료) deactivate MeetingClient == 처리 상태 업데이트 == Service -> Repo: updateExtractionStatus(meetingId, "COMPLETED") activate Repo Repo -> DB: 추출 상태 업데이트 activate DB DB --> Repo: 업데이트 완료 deactivate DB Repo --> Service: 완료 deactivate Repo Service --> Controller: Todo 추출 완료 deactivate Service Controller -> Controller: TodoExtractionCompleted 이벤트 발행 (내부 로깅) note over Controller, DB 처리 시간: - 입력 검증: 10-50ms - 회의록 파싱: 50-100ms - LLM Todo 추출: 3-5초 - 저장 처리: 200-500ms - Meeting Service 전송: 500ms-1초 총 처리 시간: 약 4-7초 (외부 API 호출 제거로 500ms 단축) end note @enduml