bini / app.py
ObinnaOkpolu's picture
Initial commit of Bini API state
ba7290b
Raw
History Blame Contribute Delete
3.69 kB
"""Main app file for the translation service"""
from contextlib import asynccontextmanager
from typing import List, Tuple
import asyncio
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from translate import translate_batch_async
class TranslateRequest(BaseModel):
sourceLangCode: str
targetLangCode: str
textArray: List[str]
active_translation_requests: List[Tuple[str, str, List[str], asyncio.Future]] = [
] # a list to store translation requests
async def process_translation(
src_lang: str, tgt_lang: str, textArr: List[str]
) -> List[str]:
future = asyncio.get_running_loop().create_future()
active_translation_requests.append(
(src_lang, tgt_lang, textArr, future))
result = await future
return result
async def batch_translate():
"""Background task that processes queued translation requests."""
global active_translation_requests
while True:
if active_translation_requests:
requestsProcessingNow = len(active_translation_requests)
results = await translate_batch_async(
[src for src, _, _, _ in active_translation_requests],
[tgt for _, tgt, _, _ in active_translation_requests],
[text for _, _, text, _ in active_translation_requests]
)
for i, (_, _, _, future) in enumerate(active_translation_requests[:requestsProcessingNow]):
future.set_result(results[i])
# remove the processed tasks:
active_translation_requests = active_translation_requests[requestsProcessingNow:]
else:
await asyncio.sleep(0.1)
@asynccontextmanager
async def lifespan(app_instance: FastAPI):
"""Lifespan context manager for startup and shutdown events."""
# Startup: Launch the batch translation background task
asyncio.create_task(batch_translate())
yield
# Shutdown: Clean up (if needed in the future)
# Define a FastAPI app with lifespan
app = FastAPI(lifespan=lifespan)
@app.exception_handler(Exception)
async def exception_handler(request, exc):
"""Handle exceptions"""
error_data = {
'status': 'failure',
'error': 'An unexpected error occurred'
}
return JSONResponse(content=error_data, status_code=500)
# # Serve static files
# app.mount("/static", StaticFiles(directory="static"), name="static")
# @app.get("/")
# def index():
# """Serve UI page"""
# return FileResponse("templates/index.html")
# @app.get("/favicon.svg")
# def favicon():
# "Serve favicon"
# return FileResponse("static/favicon.svg", media_type="image/svg+xml")
@app.post("/api/translate")
async def api_translate(data: TranslateRequest):
"""
Endpoint to handle batch translation requests.
Args:
data (TranslateRequest): The request payload containing:
- sourceLangCode: FLORES code for the source language.
- targetLangCode: FLORES code for the target language.
- textArray: List of strings to translate.
Returns:
dict: A dictionary containing the translation status and the translated array.
"""
try:
task = asyncio.create_task(process_translation(
data.sourceLangCode, data.targetLangCode, data.textArray))
await task
translation_array = task.result()
return { 'status': 'success',
'data': {'translationArray': translation_array}}
except Exception as e:
raise HTTPException(status_code=500, detail="An error occurred during translation") from e