Spaces:
Runtime error
Runtime error
File size: 8,159 Bytes
f0322a6 3233c37 f0322a6 3233c37 eb53885 3233c37 4a7e26d 3233c37 5ae7e5b 3233c37 5ae7e5b eb53885 3233c37 5ae7e5b 3233c37 eb53885 3233c37 5ae7e5b 3233c37 f0322a6 5ae7e5b 3233c37 5ae7e5b 3233c37 5ae7e5b 3233c37 5ae7e5b 3233c37 5ae7e5b 3233c37 5ae7e5b 3233c37 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
"""
FastAPI Application - para.AI v3.0
Endpoint principal para processamento de acórdãos jurisprudenciais
"""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
import time
from datetime import datetime
from api.config import get_settings
from api.utils.logger import api_logger
from api.utils.exceptions import ParaAIException
settings = get_settings()
# Variável global para tracking de uptime
app_start_time = datetime.now()
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Lifecycle events - startup e shutdown."""
# Startup
api_logger.info("=" * 70)
api_logger.info(f"🚀 Starting {settings.APP_NAME} v{settings.APP_VERSION}")
api_logger.info(f"📍 Environment: {settings.APP_ENV}")
api_logger.info(f"🐛 Debug mode: {settings.DEBUG}")
api_logger.info(f"🗄️ Database: {settings.DATABASE_URL.split('@')[-1] if '@' in settings.DATABASE_URL else 'N/A'}")
api_logger.info(f"📂 Files path: {settings.FILES_BASE_PATH}")
api_logger.info(f"🤖 LLM Providers:")
api_logger.info(f" - Groq: {'✅' if settings.GROQ_API_KEY else '❌'}")
api_logger.info(f" - OpenAI: {'✅' if settings.OPENAI_API_KEY else '❌'}")
api_logger.info(f" - Anthropic: {'✅' if settings.ANTHROPIC_API_KEY else '❌'}")
api_logger.info("=" * 70)
yield
# Shutdown
api_logger.info("🛑 Shutting down para.AI API")
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
description="""
# para.AI - Análise Jurisprudencial com IA
Sistema completo para processamento automatizado de acórdãos com 9 especialistas IA.
## Funcionalidades Principais
* 📤 **Upload JSONL**: Envie lotes de acórdãos para processamento
* 🤖 **9 Especialistas**: Análise por múltiplos processadores especializados
* 📦 **Download TAR.GZ**: Receba resultados compactados
* 🔍 **Debug Completo**: Teste cada componente isoladamente
* 📊 **Métricas**: Acompanhe performance e custos
## Endpoints Principais
* `/api/v1/process/upload` - Upload e processamento
* `/api/v1/process/status/{task_id}` - Status da tarefa
* `/api/v1/process/download/{task_id}` - Download de resultados
* `/api/v1/health` - Health check
## Debug e Testes
* `/api/v1/debug/*` - Informações de sistema
* `/api/v1/test/llm/*` - Testar LLMs
* `/api/v1/test/processors/*` - Testar processadores
* `/api/v1/test/database/*` - Testar banco de dados
* `/api/v1/test/files/*` - Testar gestão de arquivos
""",
docs_url="/api/docs",
redoc_url="/api/redoc",
openapi_url="/api/openapi.json",
lifespan=lifespan,
swagger_ui_parameters={"defaultModelsExpandDepth": -1}
)
# ============================================================================
# MIDDLEWARES
# ============================================================================
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""Middleware para logging de todas as requisições."""
start_time = time.time()
# Log request
api_logger.info(f"➡️ {request.method} {request.url.path}")
# Process
response = await call_next(request)
# Log response
process_time = (time.time() - start_time) * 1000
api_logger.info(
f"⬅️ {request.method} {request.url.path} - "
f"Status: {response.status_code} - "
f"Time: {process_time:.2f}ms"
)
# Add headers
response.headers["X-Process-Time"] = f"{process_time:.2f}"
response.headers["X-API-Version"] = settings.APP_VERSION
return response
@app.middleware("http")
async def add_security_headers(request: Request, call_next):
"""Middleware para adicionar headers de segurança."""
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
return response
# ============================================================================
# EXCEPTION HANDLERS
# ============================================================================
@app.exception_handler(ParaAIException)
async def para_ai_exception_handler(request: Request, exc: ParaAIException):
"""Handler para exceções customizadas do para.AI."""
api_logger.error(f"ParaAIException: {exc.message} - Details: {exc.details}")
return JSONResponse(
status_code=500,
content={
"error": exc.message,
"details": exc.details,
"type": exc.__class__.__name__,
"timestamp": datetime.now().isoformat()
}
)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""Handler global para exceções não tratadas."""
api_logger.error(f"Unhandled exception: {str(exc)}", exc_info=True)
return JSONResponse(
status_code=500,
content={
"error": "Internal server error",
"detail": str(exc) if settings.DEBUG else "An unexpected error occurred",
"timestamp": datetime.now().isoformat()
}
)
# ============================================================================
# ROUTERS
# ============================================================================
# Import routers (fazemos lazy import para evitar dependências circulares)
from api.routers import health, processing, debug, llm, database, files, processors
app.include_router(health.router, prefix="/api/v1", tags=["🏥 Health"])
app.include_router(processing.router, prefix="/api/v1", tags=["🚀 Processing"])
app.include_router(debug.router, prefix="/api/v1/debug", tags=["🐛 Debug"])
app.include_router(llm.router, prefix="/api/v1/test/llm", tags=["🤖 LLM Testing"])
app.include_router(database.router, prefix="/api/v1/test/database", tags=["🗄️ Database Testing"])
app.include_router(files.router, prefix="/api/v1/test/files", tags=["📁 Files Testing"])
app.include_router(processors.router, prefix="/api/v1/test/processors", tags=["⚙️ Processors Testing"])
# ============================================================================
# ROOT ENDPOINTS
# ============================================================================
@app.get("/", include_in_schema=False)
async def root():
"""Root endpoint - informações básicas da API."""
uptime = (datetime.now() - app_start_time).total_seconds()
return {
"name": settings.APP_NAME,
"version": settings.APP_VERSION,
"environment": settings.APP_ENV,
"status": "online",
"uptime_seconds": uptime,
"docs": "/api/docs",
"health": "/api/v1/health",
"timestamp": datetime.now().isoformat()
}
@app.get("/api", include_in_schema=False)
async def api_root():
"""API root - redireciona para docs."""
return {
"message": "para.AI API v3.0 - Acesse /api/docs para documentação completa",
"docs": "/api/docs",
"endpoints": {
"health": "/api/v1/health",
"upload": "/api/v1/process/upload",
"debug": "/api/v1/debug/info"
}
}
# ============================================================================
# MAIN (para execução direta)
# ============================================================================
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"api.main:app",
host=settings.HOST,
port=settings.PORT,
reload=settings.DEBUG,
workers=1 if settings.DEBUG else settings.WORKERS,
log_level=settings.LOG_LEVEL.lower(),
access_log=True
) |