"""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", ""), 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()