""" FastAPI OpenAI Compatible API """ import sys from contextlib import asynccontextmanager import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from loguru import logger from .core.config import settings from .routers.development import router as dev_router from .routers.openai_compatible import router as openai_router from .services.tts_service import TTSService def setup_logger(): """Configure loguru logger with custom formatting""" config = { "handlers": [ { "sink": sys.stdout, "format": "{time:hh:mm:ss A} | " "{level: <8} | " "{message}", "colorize": True, "level": "INFO", }, ], } logger.remove() logger.configure(**config) logger.level("ERROR", color="") # Configure logger setup_logger() @asynccontextmanager async def lifespan(app: FastAPI): """Lifespan context manager for model initialization""" logger.info("Loading TTS model and voice packs...") # Initialize service service = TTSService() await service.ensure_initialized() # Get available voices voices = await service.list_voices() voicepack_count = len(voices) # Get device info from model manager device = "GPU" if settings.use_gpu else "CPU" model = "ONNX" if settings.use_onnx else "PyTorch" boundary = "░" * 2*12 startup_msg = f""" {boundary} ╔═╗┌─┐┌─┐┌┬┐ ╠╣ ├─┤└─┐ │ ╚ ┴ ┴└─┘ ┴ ╦╔═┌─┐┬┌─┌─┐ ╠╩╗│ │├┴┐│ │ ╩ ╩└─┘┴ ┴└─┘ {boundary} """ startup_msg += f"\nModel warmed up on {device}: {model}" startup_msg += f"\n{voicepack_count} voice packs loaded\n" startup_msg += f"\n{boundary}\n" logger.info(startup_msg) yield # Initialize FastAPI app app = FastAPI( title=settings.api_title, description=settings.api_description, version=settings.api_version, lifespan=lifespan, openapi_url="/openapi.json", # Explicitly enable OpenAPI schema ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(openai_router, prefix="/v1") app.include_router(dev_router) # New development endpoints # app.include_router(text_router) # Deprecated but still live for backwards compatibility # Health check endpoint @app.get("/health") async def health_check(): """Health check endpoint""" return {"status": "healthy"} @app.get("/v1/test") async def test_endpoint(): """Test endpoint to verify routing""" return {"status": "ok"} if __name__ == "__main__": uvicorn.run("api.src.main:app", host=settings.host, port=settings.port, reload=True)