merithalle-ai / app.py
Cyril Dupland
First Commit
bd44418
"""
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__)
@asynccontextmanager
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
@app.exception_handler(RequestValidationError)
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
}
)
@app.exception_handler(Exception)
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
@app.get("/", tags=["Root"])
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
)