mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 19:36:23 +00:00
주요 변경사항:
[Critical]
- API 엔드포인트 통일: POST /api/minutes/{minutesId}/finalize
- 이벤트 이름 표준화: MinutesFinalized
[Warning]
- API Gateway 라우팅 규칙 문서화 (외부 시퀀스 7개 파일)
- 대시보드 API 경로 통일: GET /api/dashboard
- AI 제안 병합 프로세스 상세 문서화
- 회의록 확정 검증 로직 5단계 상세화
[Minor]
- Redis 캐시 TTL 명시 (7개 파일, TTL 정책 표준화)
- 대시보드 페이지네이션 파라미터 추가
- 에러 응답 포맷 표준화 (14개 에러 응답)
총 31개 파일 수정, 34건의 개선 사항 적용
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
262 lines
5.9 KiB
Plaintext
262 lines
5.9 KiB
Plaintext
@startuml
|
|
!theme mono
|
|
|
|
title AI Service 내부 시퀀스 - 회의록자동작성 (실시간 추천 포함)
|
|
|
|
participant "TranscriptController" as Controller
|
|
participant "TranscriptService" as Service
|
|
participant "SuggestionService" as SuggestService
|
|
participant "LLMClient" as LLM
|
|
participant "VectorService" as Vector
|
|
participant "TranscriptRepository" as Repo
|
|
database "Azure OpenAI" as OpenAI <<external>>
|
|
database "Vector DB" as VectorDB <<external>>
|
|
database "PostgreSQL" as DB <<external>>
|
|
|
|
== TranscriptReady 이벤트 수신 ==
|
|
|
|
note over Controller
|
|
Azure Event Hubs로부터
|
|
TranscriptReady 이벤트 수신
|
|
end note
|
|
|
|
Controller -> Service: processTranscript(meetingId, transcriptText)
|
|
activate Service
|
|
|
|
Service -> Service: 회의 맥락 정보 조회 준비
|
|
|
|
== 병렬 처리: 맥락 정보 수집 ==
|
|
|
|
par 회의 정보 조회
|
|
Service -> Repo: getMeetingContext(meetingId)
|
|
activate Repo
|
|
Repo -> DB: 회의 맥락 정보 조회
|
|
activate DB
|
|
DB --> Repo: 회의 정보 반환
|
|
deactivate DB
|
|
Repo --> Service: 회의 맥락 정보
|
|
deactivate Repo
|
|
else 이전 내용 조회
|
|
Service -> Repo: getPreviousTranscripts(meetingId)
|
|
activate Repo
|
|
Repo -> DB: 이전 회의록 내용 조회
|
|
activate DB
|
|
DB --> Repo: 이전 회의록
|
|
deactivate DB
|
|
Repo --> Service: 이전 내용
|
|
deactivate Repo
|
|
end
|
|
|
|
Service -> Service: 프롬프트 생성
|
|
note right
|
|
시스템 프롬프트 생성
|
|
- 역할 정의
|
|
- 변환 규칙 적용
|
|
end note
|
|
|
|
== LLM 기반 회의록 작성 ==
|
|
|
|
Service -> LLM: generateMinutes(prompt, context)
|
|
activate LLM
|
|
|
|
LLM -> OpenAI: POST /chat/completions
|
|
activate OpenAI
|
|
note right
|
|
model: gpt-4o
|
|
temperature: 0.3
|
|
max_tokens: 2000
|
|
end note
|
|
|
|
OpenAI -> OpenAI: 텍스트 분석 및 정리
|
|
|
|
OpenAI --> LLM: 정리된 회의록 내용
|
|
deactivate OpenAI
|
|
|
|
LLM --> Service: 회의록 초안
|
|
deactivate LLM
|
|
|
|
== 회의록 저장 ==
|
|
|
|
Service -> Service: 회의록 데이터 구조화
|
|
|
|
Service -> Repo: saveTranscriptDraft(meetingId, content)
|
|
activate Repo
|
|
|
|
Repo -> DB: AI 회의록 초안 저장 (상태: DRAFT)
|
|
activate DB
|
|
note right
|
|
저장 데이터:
|
|
- meeting_id
|
|
- content (JSON)
|
|
- status: DRAFT
|
|
end note
|
|
|
|
DB --> Repo: 저장 완료
|
|
deactivate DB
|
|
|
|
Repo --> Service: transcriptId
|
|
deactivate Repo
|
|
|
|
== 벡터 임베딩 생성 ==
|
|
|
|
Service -> Vector: createEmbedding(transcriptId, content)
|
|
activate Vector
|
|
|
|
Vector -> OpenAI: POST /embeddings
|
|
activate OpenAI
|
|
note right
|
|
model: text-embedding-3-large
|
|
end note
|
|
|
|
OpenAI --> Vector: 임베딩 벡터
|
|
deactivate OpenAI
|
|
|
|
Vector -> VectorDB: INSERT embedding
|
|
activate VectorDB
|
|
|
|
VectorDB --> Vector: 저장 완료
|
|
deactivate VectorDB
|
|
|
|
Vector --> Service: 임베딩 생성 완료
|
|
deactivate Vector
|
|
|
|
== 실시간 추천 병렬 처리 ==
|
|
|
|
Service -> SuggestService: generateRealtimeSuggestions(meetingId, transcriptText)
|
|
activate SuggestService
|
|
|
|
par 논의사항 제안 생성
|
|
SuggestService -> LLM: suggestDiscussionTopics(meetingId, transcript)
|
|
activate LLM
|
|
|
|
LLM -> OpenAI: POST /chat/completions
|
|
activate OpenAI
|
|
note right
|
|
프롬프트:
|
|
- 현재 대화 맥락 분석
|
|
- 빠진 논의 항목 찾기
|
|
- 추가하면 좋을 주제 제안
|
|
|
|
응답 형식:
|
|
{
|
|
"suggestions": [
|
|
{
|
|
"topic": "논의 주제",
|
|
"reason": "제안 이유",
|
|
"priority": "HIGH|MEDIUM|LOW"
|
|
}
|
|
]
|
|
}
|
|
end note
|
|
|
|
OpenAI --> LLM: 논의사항 제안 목록
|
|
deactivate OpenAI
|
|
|
|
LLM --> SuggestService: discussionSuggestions
|
|
deactivate LLM
|
|
|
|
SuggestService -> Repo: saveSuggestions(meetingId, "DISCUSSION", suggestions)
|
|
activate Repo
|
|
Repo -> DB: INSERT INTO ai_suggestions
|
|
activate DB
|
|
DB --> Repo: 저장 완료
|
|
deactivate DB
|
|
deactivate Repo
|
|
|
|
else 결정사항 제안 생성
|
|
SuggestService -> LLM: suggestDecisions(meetingId, transcript)
|
|
activate LLM
|
|
|
|
LLM -> OpenAI: POST /chat/completions
|
|
activate OpenAI
|
|
note right
|
|
프롬프트:
|
|
- "~하기로 함" 패턴 감지
|
|
- "~로 결정" 패턴 감지
|
|
- 결정 내용 구조화
|
|
|
|
응답 형식:
|
|
{
|
|
"decisions": [
|
|
{
|
|
"content": "결정 내용",
|
|
"category": "기술|일정|리소스",
|
|
"confidence": 0.0-1.0
|
|
}
|
|
]
|
|
}
|
|
end note
|
|
|
|
OpenAI --> LLM: 결정사항 제안 목록
|
|
deactivate OpenAI
|
|
|
|
LLM --> SuggestService: decisionSuggestions
|
|
deactivate LLM
|
|
|
|
SuggestService -> Repo: saveSuggestions(meetingId, "DECISION", suggestions)
|
|
activate Repo
|
|
Repo -> DB: INSERT INTO ai_suggestions
|
|
activate DB
|
|
DB --> Repo: 저장 완료
|
|
deactivate DB
|
|
deactivate Repo
|
|
|
|
end
|
|
|
|
SuggestService --> Service: 모든 추천사항 생성 완료
|
|
deactivate SuggestService
|
|
|
|
== 이벤트 발행 ==
|
|
|
|
Service -> Controller: 회의록 및 추천사항 생성 완료 응답
|
|
deactivate Service
|
|
|
|
Controller -> Controller: TranscriptSummaryCreated 발행
|
|
note right
|
|
이벤트 데이터:
|
|
- meetingId
|
|
- transcriptId
|
|
- content
|
|
- suggestions:
|
|
* discussionTopics: []
|
|
* decisions: []
|
|
end note
|
|
|
|
note over Controller, DB
|
|
AI 제안 병합 프로세스:
|
|
|
|
1. 자동 병합 (Auto-merge):
|
|
- confidence >= 0.8인 결정사항
|
|
→ 회의록 "결정사항" 섹션에 자동 추가
|
|
- priority: HIGH인 논의사항
|
|
→ "추가 논의 필요" 섹션에 자동 반영
|
|
|
|
2. 사용자 검토 (User Review):
|
|
- 0.5 <= confidence < 0.8
|
|
→ 제안 목록에 표시, 사용자 승인 대기
|
|
- priority: MEDIUM/LOW
|
|
→ 선택적 반영 가능
|
|
|
|
3. 병합 시점:
|
|
- 실시간: 회의 진행 중 자동 반영
|
|
- 최종: 회의록 확정 전 사용자 최종 검토
|
|
|
|
4. 병합 이력:
|
|
- 제안 ID, 병합 여부, 승인자, 시각 기록
|
|
- 감사 추적(Audit Trail) 유지
|
|
end note
|
|
|
|
note over Controller, DB
|
|
처리 시간:
|
|
- 맥락 조회: 100-200ms
|
|
- LLM 회의록 생성: 3-5초
|
|
- 저장: 100-200ms
|
|
- 벡터화: 500ms-1초
|
|
- 실시간 추천 병렬 처리: 4-6초
|
|
* 논의사항 제안: 2-3초
|
|
* 결정사항 제안: 2-3초
|
|
총: 약 8-13초
|
|
end note
|
|
|
|
@enduml
|