Files
llm-gateway-sub-backup/workspace/routers/stt_router.py
2025-08-11 18:56:38 +09:00

145 lines
5.6 KiB
Python

# 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())