Feat: AI 서비스 및 STT 서비스 기능 개선

- AI 서비스: Redis 캐싱 및 EventHub 통합 개선
- STT 서비스: 오디오 버퍼링 및 변환 기능 추가
- 설정 파일 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Minseo-Jo
2025-10-30 15:23:30 +09:00
parent ad287de176
commit 032842cf53
13 changed files with 1096 additions and 156 deletions
+23 -5
View File
@@ -2,6 +2,7 @@
import asyncio
import logging
import json
from datetime import datetime
from azure.eventhub.aio import EventHubConsumerClient
from app.config import get_settings
@@ -63,12 +64,30 @@ class EventHubService:
}
"""
try:
# 이벤트 원본 데이터 로깅
raw_body = event.body_as_str()
logger.info(f"수신한 이벤트 원본 (처음 300자): {raw_body[:300]}")
# 이벤트 원본 데이터 추출
try:
# Event Hub 데이터는 bytes 또는 str일 수 있음
if hasattr(event, 'body_as_str'):
raw_body = event.body_as_str()
elif hasattr(event, 'body'):
raw_body = event.body.decode('utf-8') if isinstance(event.body, bytes) else str(event.body)
else:
logger.error(f"이벤트 타입 미지원: {type(event)}")
return
logger.info(f"수신한 이벤트 원본 (처음 300자): {raw_body[:300]}")
logger.debug(f"이벤트 전체 길이: {len(raw_body)}")
except Exception as extract_error:
logger.error(f"이벤트 데이터 추출 실패: {extract_error}", exc_info=True)
return
# 이벤트 데이터 파싱
event_data = json.loads(raw_body)
try:
event_data = json.loads(raw_body)
except json.JSONDecodeError as json_error:
logger.error(f"JSON 파싱 실패 - 전체 데이터: {raw_body}")
logger.error(f"파싱 에러: {json_error}")
return
event_type = event_data.get("eventType")
meeting_id = event_data.get("meetingId")
@@ -78,7 +97,6 @@ class EventHubService:
# timestamp 변환: LocalDateTime 배열 → Unix timestamp (ms)
# Java LocalDateTime은 [year, month, day, hour, minute, second, nano] 형식
if isinstance(timestamp_raw, list) and len(timestamp_raw) >= 3:
from datetime import datetime
year, month, day = timestamp_raw[0:3]
hour = timestamp_raw[3] if len(timestamp_raw) > 3 else 0
minute = timestamp_raw[4] if len(timestamp_raw) > 4 else 0
+34 -2
View File
@@ -105,6 +105,34 @@ class RedisService:
count = await self.redis_client.zcard(key)
return count if count else 0
async def add_generated_suggestion(self, meeting_id: str, suggestion_content: str):
"""
생성된 제안사항 저장 (중복 방지용)
Args:
meeting_id: 회의 ID
suggestion_content: 제안사항 내용
"""
key = f"meeting:{meeting_id}:suggestions"
await self.redis_client.sadd(key, suggestion_content)
# TTL 설정 (1시간)
await self.redis_client.expire(key, 3600)
logger.debug(f"제안사항 저장 - meetingId: {meeting_id}")
async def get_generated_suggestions(self, meeting_id: str) -> set:
"""
이미 생성된 제안사항 목록 조회
Args:
meeting_id: 회의 ID
Returns:
제안사항 set
"""
key = f"meeting:{meeting_id}:suggestions"
suggestions = await self.redis_client.smembers(key)
return suggestions if suggestions else set()
async def cleanup_meeting_data(self, meeting_id: str):
"""
회의 종료 시 데이터 정리
@@ -112,6 +140,10 @@ class RedisService:
Args:
meeting_id: 회의 ID
"""
key = f"meeting:{meeting_id}:transcript"
await self.redis_client.delete(key)
transcript_key = f"meeting:{meeting_id}:transcript"
suggestions_key = f"meeting:{meeting_id}:suggestions"
await self.redis_client.delete(transcript_key)
await self.redis_client.delete(suggestions_key)
logger.info(f"회의 데이터 정리 완료 - meetingId: {meeting_id}")