# llmgateway/routers/stt_proxy.py import logging import httpx from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile from fastapi.responses import JSONResponse from utils.checking_keys import create_key from utils.logging_utils import EndpointLogger from utils.minio_utils import upload_file_to_minio_v2 router = APIRouter(tags=["STT Gateway"]) STT_API_BASE_URL = "http://stt_fastapi:8899/ccp" # docker-compose 내 서비스명 기반 MULTI_STT_API_BASE_URL = ( "http://stt_fastapi:8899/dialog" # docker-compose 내 서비스명 기반 ) logger = logging.getLogger(__name__) # 파일 업로드 → stt_api에 Presigned URL 전달 @router.post("/audio") async def proxy_audio( audio_file: UploadFile = File(...), endpoint_logger: EndpointLogger = Depends(EndpointLogger), ): request_id = create_key() bucket_name = "stt-gateway" object_name = f"{request_id}/{audio_file.filename}" try: # upload_file_to_minio_v2는 presigned URL을 반환합니다. presigned_url = upload_file_to_minio_v2( file=audio_file, bucket_name=bucket_name, object_name=object_name, ) except Exception as e: logger.error(f"MinIO upload failed: {e}") raise HTTPException(status_code=500, detail="File upload to storage failed.") # 로깅 endpoint_logger.log(model="N/A", input_filename=audio_file.filename) # stt_fastapi에 Presigned URL 정보 전달 try: async with httpx.AsyncClient() as client: payload = { "file_url": presigned_url, "language": "ko", } response = await client.post(f"{STT_API_BASE_URL}/audio", json=payload) return JSONResponse(content=response.json(), status_code=response.status_code) except Exception as e: raise HTTPException(status_code=500, detail=f"STT API 호출 실패: {str(e)}") # 상태 조회 → stt_api에 중계 및 오류 로깅 @router.get("/progress/{request_id}") async def proxy_progress(request_id: str): try: async with httpx.AsyncClient() as client: response = await client.get(f"{STT_API_BASE_URL}/progress/{request_id}") response.raise_for_status() # HTTP 오류 발생 시 예외 처리 # 응답 데이터 확인 및 로깅 data = response.json() if data.get("celery_status") == "FAILURE": # 상세 오류 정보를 포함하여 에러 로그 기록 error_details = data.get("progress_logs", []) logger.error(f"[ERROR] STT task failed for request_id {request_id}. Details: {error_details}") return JSONResponse(content=data, status_code=response.status_code) except httpx.HTTPStatusError as e: logger.error(f"STT progress check failed with status {e.response.status_code} for request_id {request_id}: {e.response.text}") raise HTTPException(status_code=e.response.status_code, detail=f"STT 상태 조회 실패: {e.response.text}") except Exception as e: logger.error(f"An unexpected error occurred while checking STT progress for request_id {request_id}: {e}") raise HTTPException(status_code=500, detail=f"STT 상태 조회 실패: {str(e)}") # 다중 입력 회의 → stt_api에 Presigned URL 전달 @router.post("/dialog_processing") async def proxy_dialog_processing( audio_file: UploadFile = File(...), meeting_tag: str = Form(...), endpoint_logger: EndpointLogger = Depends(EndpointLogger), ): bucket_name = "stt-gateway" request_id = create_key() object_name = f"{meeting_tag}_{request_id}/{audio_file.filename}" try: presigned_url = upload_file_to_minio_v2( file=audio_file, bucket_name=bucket_name, object_name=object_name, ) except Exception as e: logger.error(f"MinIO upload failed for dialog_processing: {e}") raise HTTPException(status_code=500, detail="File upload to storage failed.") # 로깅 endpoint_logger.log(model="N/A", input_filename=audio_file.filename) # stt_fastapi에 Presigned URL 정보 전달 try: async with httpx.AsyncClient() as client: payload = { "file_url": presigned_url, "meeting_tag": meeting_tag, } resp = await client.post( f"{MULTI_STT_API_BASE_URL}/dialog_processing", json=payload ) return JSONResponse(status_code=resp.status_code, content=resp.json()) except httpx.RequestError as e: raise HTTPException(status_code=500, detail=f"내부 서버 요청 실패: {e}") @router.get("/start_parallel_stt/{meeting_tag}") async def proxy_start_parallel_stt(meeting_tag: str): async with httpx.AsyncClient() as client: try: resp = await client.get( f"{MULTI_STT_API_BASE_URL}/start_parallel_stt/{meeting_tag}" ) except httpx.RequestError as e: raise HTTPException(status_code=500, detail=f"내부 서버 요청 실패: {e}") return JSONResponse(status_code=resp.status_code, content=resp.json()) @router.get("/dialog_result/{task_id}") async def proxy_get_progress(task_id: str): async with httpx.AsyncClient() as client: try: resp = await client.get( f"{MULTI_STT_API_BASE_URL}/result/parallel/{task_id}" ) except httpx.RequestError as e: raise HTTPException(status_code=500, detail=f"내부 서버 요청 실패: {e}") return JSONResponse(status_code=resp.status_code, content=resp.json())