Spaces:
Sleeping
Sleeping
| """ | |
| CAPL Routeur IA API | |
| Main FastAPI application with AI agent routing. | |
| """ | |
| from dotenv import load_dotenv | |
| load_dotenv() # charge .env pour tout le process | |
| from fastapi import FastAPI, Request, status | |
| from fastapi.responses import JSONResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.exceptions import RequestValidationError | |
| from contextlib import asynccontextmanager | |
| import logging | |
| from config import settings | |
| from api.routes import auth, completion, transcription, models, realtime | |
| # Configure logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" | |
| ) | |
| logger = logging.getLogger(__name__) | |
| async def lifespan(app: FastAPI): | |
| """Lifespan event handler for startup and shutdown.""" | |
| # Startup | |
| logger.info(f"Starting {settings.api_title} v{settings.api_version}") | |
| logger.info(f"Environment: {settings.environment}") | |
| yield | |
| # Shutdown | |
| logger.info("Shutting down API") | |
| # Create FastAPI app | |
| app = FastAPI( | |
| title=settings.api_title, | |
| version=settings.api_version, | |
| description=""" | |
| # CAPL Routeur IA API | |
| API sécurisée pour l'interaction avec des agents IA basés sur LangGraph. | |
| ## Fonctionnalités principales: | |
| - **Authentification JWT** pour sécuriser l'accès | |
| - **Completion texte** avec support du streaming (SSE) | |
| - **Multi-modèles**: OpenAI (GPT-4, GPT-3.5) et Mistral AI | |
| - **Multi-agents**: Architecture extensible pour différents types d'agents | |
| - **Transcription audio**: Conversion audio vers texte avec Whisper | |
| - **Temps réel**: Support WebRTC (à venir) | |
| ## Authentification | |
| 1. Obtenez un token JWT via `POST /auth/token` | |
| 2. Incluez le token dans le header: `Authorization: Bearer <token>` | |
| 3. Utilisez le token pour toutes les requêtes protégées | |
| ## Architecture | |
| - **Clean Architecture** avec séparation domain/services/api | |
| - **SOLID principles** pour une extensibilité maximale | |
| - **LangGraph** pour l'orchestration des agents IA | |
| """, | |
| lifespan=lifespan, | |
| docs_url="/docs", | |
| redoc_url="/redoc" | |
| ) | |
| # CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # À restreindre en production | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Exception handlers | |
| async def validation_exception_handler(request: Request, exc: RequestValidationError): | |
| """Handle validation errors with detailed messages.""" | |
| return JSONResponse( | |
| status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, | |
| content={ | |
| "error": "Validation Error", | |
| "detail": exc.errors(), | |
| "body": exc.body | |
| } | |
| ) | |
| async def general_exception_handler(request: Request, exc: Exception): | |
| """Handle unexpected exceptions.""" | |
| logger.error(f"Unexpected error: {str(exc)}", exc_info=True) | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content={ | |
| "error": "Internal Server Error", | |
| "detail": str(exc) if settings.environment == "development" else "An unexpected error occurred" | |
| } | |
| ) | |
| # Root endpoint | |
| async def root(): | |
| """Root endpoint with API information.""" | |
| return { | |
| "name": settings.api_title, | |
| "version": settings.api_version, | |
| "status": "running", | |
| "environment": settings.environment, | |
| "docs": "/docs", | |
| "health": "/health" | |
| } | |
| # Include routers | |
| app.include_router(auth.router) | |
| app.include_router(models.router) | |
| app.include_router(completion.router) | |
| app.include_router(transcription.router) | |
| app.include_router(realtime.router) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run( | |
| "app:app", | |
| host="0.0.0.0", | |
| port=7860, | |
| reload=True if settings.environment == "development" else False | |
| ) | |