caarleexx commited on
Commit
eb53885
·
verified ·
1 Parent(s): 320f736

Update api/main.py

Browse files
Files changed (1) hide show
  1. api/main.py +85 -253
api/main.py CHANGED
@@ -1,275 +1,107 @@
1
- #!/usr/bin/env python3
2
  """
3
- ParaAi - FastAPI Main Application v2.0
4
- Inicializa aplicação FastAPI com integração de TODOS os módulos
5
  """
6
-
7
- import os
 
 
8
  import logging
 
9
  from datetime import datetime
10
- from pathlib import Path
11
- from typing import Dict, List, Optional
12
-
13
- from fastapi import FastAPI, HTTPException, BackgroundTasks
14
- from fastapi.middleware.cors import CORSMiddleware
15
- from fastapi.responses import JSONResponse, FileResponse
16
- from pydantic import BaseModel
17
- import uvicorn
18
-
19
- # ============================================================================
20
- # IMPORTS DO PROJETO (FASE 1 + FASE 2)
21
- # ============================================================================
22
-
23
- # FASE 1: APIs e Database
24
- from api.llm_client import APILLMClient
25
- from data.db.postgres_manager import PostgreSQLManager
26
-
27
- # FASE 2: Context e Files
28
- from data.context.context_engine import ContextEngine
29
- from files_manager.files_manager import FilesManager
30
-
31
- # FASE 2: Workers (refatorado)
32
- from workers.llm_worker_hybrid import LLMWorkerHybrid
33
 
34
- # API Routes (próximos arquivos)
35
- from api.routes import debug_routes, process_routes, status_routes
36
 
37
- # ============================================================================
38
- # CONFIGURAÇÃO E LOGGING
39
- # ============================================================================
40
 
41
  logging.basicConfig(
42
- level=logging.INFO,
43
- format='%(asctime)s [%(levelname)-5s] %(name)s - %(message)s',
44
- datefmt='%Y-%m-%d %H:%M:%S'
45
  )
46
  logger = logging.getLogger(__name__)
47
 
48
- # ============================================================================
49
- # PYDANTIC MODELS (Request/Response)
50
- # ============================================================================
51
-
52
- class ProcessRequest(BaseModel):
53
- """Request para processar um lote de acórdãos"""
54
- jsonl_path: str
55
- batch_id: Optional[str] = None
56
- num_workers: int = 10
57
- timeout_seconds: int = 300
58
- enable_cache: bool = True
59
-
60
- class ProcessResponse(BaseModel):
61
- """Response do processamento"""
62
- status: str # pending, processing, completed, failed
63
- batch_id: str
64
- total_records: int
65
- processed_records: int
66
- failed_records: int
67
- output_path: Optional[str] = None
68
- download_url: Optional[str] = None
69
- timestamp: str
70
-
71
- class StatusResponse(BaseModel):
72
- """Response de status"""
73
- batch_id: str
74
- status: str
75
- progress_percent: float
76
- processed: int
77
- total: int
78
- timestamp: str
79
-
80
- # ============================================================================
81
- # INICIALIZAÇÃO DA APLICAÇÃO
82
- # ============================================================================
83
-
84
- app = FastAPI(
85
- title="ParaAi - Sistema de Análise Jurídica com IA",
86
- description="Pipeline multidisciplinar de processamento de acórdãos",
87
- version="2.0.0"
88
- )
89
-
90
- # CORS
91
- app.add_middleware(
92
- CORSMiddleware,
93
- allow_origins=["*"],
94
- allow_credentials=True,
95
- allow_methods=["*"],
96
- allow_headers=["*"],
97
- )
98
-
99
- # ============================================================================
100
- # COMPONENTES GLOBAIS (Inicializados uma vez)
101
- # ============================================================================
102
-
103
- # FASE 1
104
- llm_client: APILLMClient = None
105
- db_manager: PostgreSQLManager = None
106
-
107
- # FASE 2
108
- context_engine: ContextEngine = None
109
- files_manager: FilesManager = None
110
-
111
- # Workers
112
- workers: List[LLMWorkerHybrid] = []
113
 
114
- # ============================================================================
115
- # STARTUP / SHUTDOWN
116
- # ============================================================================
117
-
118
- @app.on_event("startup")
119
- async def startup_event():
120
- """Inicializa todos os componentes"""
121
- global llm_client, db_manager, context_engine, files_manager, workers
122
-
123
- logger.info("=" * 80)
124
- logger.info("🚀 ParaAi Starting Up...")
125
- logger.info("=" * 80)
126
-
127
- try:
128
- # FASE 1: Inicializar APIs
129
- logger.info("📡 Inicializando APILLMClient...")
130
- llm_client = APILLMClient(
131
- configpath=".apiLLMst2t/configllms.yaml"
132
- )
133
- logger.info("✅ APILLMClient inicializado")
134
-
135
- # FASE 1: Inicializar Database
136
- logger.info("🗄️ Inicializando PostgreSQL...")
137
- db_manager = PostgreSQLManager(
138
- dbname=os.getenv("PGDB", "paraai"),
139
- user=os.getenv("PGUSER", "postgres"),
140
- password=os.getenv("PGPASSWORD", ""),
141
- host=os.getenv("PGHOST", "localhost"),
142
- port=int(os.getenv("PGPORT", 5432))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  )
144
-
145
- # Criar tabelas
146
- if db_manager.criar_tabelas():
147
- logger.info("✅ Banco de dados pronto")
148
- else:
149
- logger.warning("⚠️ Erro ao criar tabelas, continuando...")
150
-
151
- # FASE 2: Inicializar Context Engine
152
- logger.info("🔗 Inicializando ContextEngine...")
153
- context_engine = ContextEngine()
154
- logger.info("✅ ContextEngine inicializado")
155
-
156
- # FASE 2: Inicializar Files Manager
157
- logger.info("📦 Inicializando FilesManager...")
158
- files_manager = FilesManager(
159
- basedir=os.path.expanduser(os.getenv("WORKDIR", "../trabalho")),
160
- ano="2024"
161
- )
162
- logger.info("✅ FilesManager inicializado")
163
-
164
- # Inicializar workers
165
- num_workers = int(os.getenv("NUMWORKERS", 10))
166
- logger.info(f"👷 Criando {num_workers} workers...")
167
- for i in range(num_workers):
168
- worker = LLMWorkerHybrid(
169
- worker_id=i,
170
- configpath=".apiLLMst2t/configllms.yaml"
171
- )
172
- workers.append(worker)
173
- logger.info(f"✅ {num_workers} workers criados")
174
-
175
- logger.info("=" * 80)
176
- logger.info("✅ ParaAi iniciada com sucesso!")
177
- logger.info("=" * 80)
178
-
179
- except Exception as e:
180
- logger.error(f"❌ Erro na inicialização: {e}")
181
- raise
182
-
183
- @app.on_event("shutdown")
184
- async def shutdown_event():
185
- """Limpa recursos"""
186
- logger.info("🛑 ParaAi Shutting Down...")
187
- if db_manager:
188
- db_manager.fechar()
189
- logger.info("✅ Shutdown completo")
190
 
191
- # ============================================================================
192
- # ROTAS RAIZ
193
- # ============================================================================
194
-
195
- @app.get("/")
196
- async def root():
197
- """Rota raiz - informações da API"""
198
- return {
199
- "status": "running",
200
- "name": "ParaAi",
201
- "version": "2.0.0",
202
- "endpoints": {
203
- "health": "/health",
204
- "process": "/process (POST)",
205
- "status": "/status/{batch_id} (GET)",
206
- "debug": "/debug/* (GET)",
207
- "docs": "/docs"
208
- }
209
- }
210
-
211
- @app.get("/health")
212
- async def health_check():
213
- """Health check de todos os componentes"""
214
- health_status = {
215
- "status": "healthy",
216
- "timestamp": datetime.now().isoformat(),
217
- "components": {
218
- "llm_client": "OK" if llm_client else "FAIL",
219
- "db_manager": "OK" if db_manager else "FAIL",
220
- "context_engine": "OK" if context_engine else "FAIL",
221
- "files_manager": "OK" if files_manager else "FAIL",
222
- "workers": f"{len(workers)}/OK" if workers else "FAIL"
223
  }
224
- }
225
- return health_status
226
 
227
- # ============================================================================
228
- # INCLUIR ROUTERS
229
- # ============================================================================
230
 
231
- # Rotas de Debug
232
- debug_router = debug_routes.create_debug_router(
233
- llm_client=llm_client,
234
- db_manager=db_manager,
235
- context_engine=context_engine,
236
- files_manager=files_manager,
237
- workers=workers
238
- )
239
- app.include_router(debug_router, prefix="/debug", tags=["debug"])
240
 
241
- # Rotas de Processamento
242
- process_router = process_routes.create_process_router(
243
- llm_client=llm_client,
244
- db_manager=db_manager,
245
- context_engine=context_engine,
246
- files_manager=files_manager,
247
- workers=workers
248
- )
249
- app.include_router(process_router, prefix="/process", tags=["processing"])
250
-
251
- # Rotas de Status
252
- status_router = status_routes.create_status_router(
253
- context_engine=context_engine,
254
- files_manager=files_manager
255
- )
256
- app.include_router(status_router, prefix="/status", tags=["status"])
257
 
258
- # ============================================================================
259
- # EXECUÇÃO
260
- # ============================================================================
261
 
262
  if __name__ == "__main__":
263
- host = os.getenv("FASTAPIHOST", "0.0.0.0")
264
- port = int(os.getenv("FASTAPIPORT", 7860)
265
- reload = os.getenv("FASTAPIreload", "true").lower() == "true"
266
-
267
- logger.info(f"🌐 Iniciando servidor em http://{host}:{port}")
268
-
269
  uvicorn.run(
270
- "main:app",
271
- host=host,
272
- port=port,
273
- reload=reload,
274
- log_level=os.getenv("LOGLEVEL", "debug").lower()
275
- )
 
 
1
  """
2
+ FastAPI Application Factory
3
+ Main entry point for para.AI API
4
  """
5
+ from fastapi import FastAPI, Request
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from fastapi.responses import JSONResponse
8
+ from contextlib import asynccontextmanager
9
  import logging
10
+ import time
11
  from datetime import datetime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ from api.config import settings
14
+ from api.routes import debug_routes, process_routes, status_routes, health_routes
15
 
 
 
 
16
 
17
  logging.basicConfig(
18
+ level=settings.LOG_LEVEL,
19
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
 
20
  )
21
  logger = logging.getLogger(__name__)
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
+ @asynccontextmanager
25
+ async def lifespan(app: FastAPI):
26
+ """Lifespan events"""
27
+ logger.info(f"🚀 Starting {settings.APP_NAME} v{settings.APP_VERSION}")
28
+ logger.info(f"📊 Environment: {'DEBUG' if settings.DEBUG else 'PRODUCTION'}")
29
+ logger.info(f"🤖 LLM Model: {settings.LLM_MODEL}")
30
+
31
+ yield
32
+
33
+ logger.info("🛑 Shutting down API")
34
+
35
+
36
+ def create_app() -> FastAPI:
37
+ """Factory function to create FastAPI app"""
38
+
39
+ app = FastAPI(
40
+ title=settings.APP_NAME,
41
+ version=settings.APP_VERSION,
42
+ description="API para análise jurisprudencial com LLMs - Sistema de 9 Especialistas",
43
+ lifespan=lifespan,
44
+ docs_url="/docs" if settings.DEBUG else None,
45
+ redoc_url="/redoc" if settings.DEBUG else None,
46
+ )
47
+
48
+ app.add_middleware(
49
+ CORSMiddleware,
50
+ allow_origins=settings.CORS_ORIGINS,
51
+ allow_credentials=True,
52
+ allow_methods=["*"],
53
+ allow_headers=["*"],
54
+ )
55
+
56
+ @app.middleware("http")
57
+ async def add_process_time_header(request: Request, call_next):
58
+ start_time = time.time()
59
+ response = await call_next(request)
60
+ process_time = time.time() - start_time
61
+ response.headers["X-Process-Time"] = str(process_time)
62
+ return response
63
+
64
+ @app.exception_handler(Exception)
65
+ async def global_exception_handler(request: Request, exc: Exception):
66
+ logger.error(f"Global exception: {exc}", exc_info=True)
67
+ return JSONResponse(
68
+ status_code=500,
69
+ content={
70
+ "error": "Internal Server Error",
71
+ "detail": str(exc) if settings.DEBUG else "An error occurred",
72
+ "timestamp": datetime.now().isoformat(),
73
+ "path": str(request.url)
74
+ }
75
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ app.include_router(health_routes.router, prefix="/health", tags=["Health"])
78
+ app.include_router(process_routes.router, prefix="/process", tags=["Process"])
79
+ app.include_router(status_routes.router, prefix="/status", tags=["Status"])
80
+
81
+ if settings.DEBUG:
82
+ app.include_router(debug_routes.router, prefix="/debug", tags=["Debug"])
83
+
84
+ @app.get("/")
85
+ async def root():
86
+ return {
87
+ "app": settings.APP_NAME,
88
+ "version": settings.APP_VERSION,
89
+ "status": "running",
90
+ "timestamp": datetime.now().isoformat(),
91
+ "docs": "/docs" if settings.DEBUG else "disabled"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
 
 
93
 
94
+ return app
 
 
95
 
 
 
 
 
 
 
 
 
 
96
 
97
+ app = create_app()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
 
 
99
 
100
  if __name__ == "__main__":
101
+ import uvicorn
 
 
 
 
 
102
  uvicorn.run(
103
+ "api.main:app",
104
+ host=settings.API_HOST,
105
+ port=settings.API_PORT,
106
+ reload=settings.DEBUG
107
+ )