from typing import Callable from fastapi import Request from fastapi.responses import JSONResponse from slowapi import Limiter from slowapi.util import get_remote_address # Configure slowapi.Limiter with key_func=get_remote_address. limiter = Limiter(key_func=get_remote_address) # Custom handler that returns {"error": "Rate limit exceeded. Try again shortly."} # with HTTP 429 (not the default slowapi response format). async def custom_rate_limit_handler(request: Request, exc: Exception) -> JSONResponse: return JSONResponse( status_code=429, content={"error": "Rate limit exceeded. Try again shortly."} ) # Decorator factory chat_rate_limit that applies 20/minute limit. def chat_rate_limit() -> Callable: return limiter.limit("20/minute")