mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 09:06:24 +00:00
- AI 서비스와 Meeting 서비스 통합 개선 - AgendaSummaryDTO에 decisions 필드 추가 (안건별 결정사항 배열) - EndMeetingService에서 AI 서비스 타임아웃 처리 개선 - AIServiceClient에 상세한 에러 로깅 추가 - 회의록 consolidate 프롬프트 개선 - Todo 추출 로직 강화 (자연스러운 표현 인식) - 안건별 decisions 필드 추가 (대시보드 표시용) - 담당자 패턴 인식 개선 - Kubernetes 배포 설정 개선 - meeting-service.yaml에 AI_SERVICE_URL 환경변수 추가 - AI_SERVICE_TIMEOUT 설정 추가 - 데이터베이스 관리 SQL 스크립트 추가 - check-agenda-sections.sql: 안건 섹션 확인 - cleanup-test-data.sql: 테스트 데이터 정리 - insert-test-data-final.sql: 최종 테스트 데이터 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
124 lines
4.1 KiB
Python
124 lines
4.1 KiB
Python
"""Transcript Service - 회의록 통합 처리"""
|
|
import logging
|
|
from datetime import datetime
|
|
from app.models.transcript import (
|
|
ConsolidateRequest,
|
|
ConsolidateResponse,
|
|
AgendaSummary,
|
|
ExtractedTodo
|
|
)
|
|
from app.services.claude_service import claude_service
|
|
from app.prompts.consolidate_prompt import get_consolidate_prompt
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TranscriptService:
|
|
"""회의록 통합 서비스"""
|
|
|
|
async def consolidate_minutes(
|
|
self,
|
|
request: ConsolidateRequest
|
|
) -> ConsolidateResponse:
|
|
"""
|
|
참석자별 회의록을 통합하여 AI 요약 생성
|
|
"""
|
|
logger.info(f"회의록 통합 시작 - Meeting ID: {request.meeting_id}")
|
|
logger.info(f"참석자 수: {len(request.participant_minutes)}")
|
|
|
|
try:
|
|
# 1. 프롬프트 생성
|
|
participant_data = [
|
|
{
|
|
"user_name": pm.user_name,
|
|
"content": pm.content
|
|
}
|
|
for pm in request.participant_minutes
|
|
]
|
|
|
|
prompt = get_consolidate_prompt(
|
|
participant_minutes=participant_data,
|
|
agendas=request.agendas
|
|
)
|
|
|
|
# 입력 데이터 로깅
|
|
logger.info("=" * 80)
|
|
logger.info("INPUT - 참석자별 회의록:")
|
|
for pm in participant_data:
|
|
logger.info(f"\n[{pm['user_name']}]")
|
|
logger.info(f"{pm['content'][:500]}..." if len(pm['content']) > 500 else pm['content'])
|
|
logger.info("=" * 80)
|
|
|
|
# 2. Claude API 호출
|
|
start_time = datetime.utcnow()
|
|
ai_result = await claude_service.generate_completion(prompt)
|
|
processing_time = (datetime.utcnow() - start_time).total_seconds() * 1000
|
|
|
|
logger.info(f"AI 처리 완료 - {processing_time:.0f}ms")
|
|
|
|
# 3. 응답 구성
|
|
response = self._build_response(
|
|
meeting_id=request.meeting_id,
|
|
ai_result=ai_result,
|
|
participants_count=len(request.participant_minutes),
|
|
duration_minutes=request.duration_minutes
|
|
)
|
|
|
|
logger.info(f"통합 요약 완료 - 안건 수: {len(response.agenda_summaries)}, Todo 수: {response.statistics['todos_count']}")
|
|
|
|
return response
|
|
|
|
except Exception as e:
|
|
logger.error(f"회의록 통합 실패: {e}", exc_info=True)
|
|
raise
|
|
|
|
def _build_response(
|
|
self,
|
|
meeting_id: str,
|
|
ai_result: dict,
|
|
participants_count: int,
|
|
duration_minutes: int = None
|
|
) -> ConsolidateResponse:
|
|
"""AI 응답을 ConsolidateResponse로 변환"""
|
|
|
|
# 안건별 요약 변환
|
|
agenda_summaries = []
|
|
for agenda_data in ai_result.get("agenda_summaries", []):
|
|
# Todo 변환 (제목만)
|
|
todos = [
|
|
ExtractedTodo(title=todo.get("title", ""))
|
|
for todo in agenda_data.get("todos", [])
|
|
]
|
|
|
|
agenda_summaries.append(
|
|
AgendaSummary(
|
|
agenda_number=agenda_data.get("agenda_number", 0),
|
|
agenda_title=agenda_data.get("agenda_title", ""),
|
|
summary_short=agenda_data.get("summary_short", ""),
|
|
summary=agenda_data.get("summary", ""),
|
|
decisions=agenda_data.get("decisions", []),
|
|
pending=agenda_data.get("pending", []),
|
|
todos=todos
|
|
)
|
|
)
|
|
|
|
# 통계 정보
|
|
statistics = ai_result.get("statistics", {})
|
|
statistics["participants_count"] = participants_count
|
|
if duration_minutes:
|
|
statistics["duration_minutes"] = duration_minutes
|
|
|
|
# 응답 생성
|
|
return ConsolidateResponse(
|
|
meeting_id=meeting_id,
|
|
keywords=ai_result.get("keywords", []),
|
|
statistics=statistics,
|
|
decisions=ai_result.get("decisions", ""),
|
|
agenda_summaries=agenda_summaries,
|
|
generated_at=datetime.utcnow()
|
|
)
|
|
|
|
|
|
# 싱글톤 인스턴스
|
|
transcript_service = TranscriptService()
|