145 lines
5.6 KiB
Python
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())
|