@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 == MeetingEnded 이벤트 수신 == note over Controller Azure Event Hubs로부터 MeetingEnded 이벤트 수신 (meetingId, userId, endTime) end note Controller -> Service: extractTodos(meetingId) activate Service == 최종 회의록 조회 == Service -> Repo: getFinalTranscript(meetingId) activate Repo Repo -> DB: 최종 회의록 조회 activate DB DB --> Repo: 최종 회의록 내용 deactivate DB Repo --> Service: transcriptContent deactivate Repo Service -> Service: 참석자 정보 조회 준비 Service -> Repo: getMeetingParticipants(meetingId) activate Repo Repo -> DB: 참석자 정보 조회 activate DB DB --> Repo: 참석자 목록 deactivate DB Repo --> Service: participants deactivate Repo == LLM 기반 Todo 추출 == Service -> Service: Todo 추출 프롬프트 생성 note right 시스템 프롬프트: - 역할: Todo 추출 전문가 - 지시사항: 액션 아이템 식별, 담당자 및 마감일 추출 사용자 프롬프트: - 회의록 전체 내용 - 참석자 목록 - 추출 기준: * "~하기로 함", "~까지 완료" * "~담당", "제가 하겠습니다" * 명령형 문장 end note Service -> LLM: extractActionItems(prompt, transcript, 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 처리 시간: - 회의록 조회: 100-200ms - LLM Todo 추출: 3-5초 - 저장 처리: 200-500ms - Meeting Service 전송: 500ms-1초 총 처리 시간: 약 4-7초 end note @enduml