GiusMagi commited on
Commit
5d0c39f
Β·
verified Β·
1 Parent(s): 8480c7c

Delete server.py

Browse files
Files changed (1) hide show
  1. server.py +0 -277
server.py DELETED
@@ -1,277 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import numpy as np
3
- import pandas as pd
4
- import cloudpickle as cp
5
- from fastapi import FastAPI, HTTPException
6
- from fastapi.middleware.cors import CORSMiddleware
7
- from pydantic import BaseModel
8
- import traceback
9
- import logging
10
- import sys
11
- import os
12
-
13
- # Setup logging
14
- logging.basicConfig(
15
- level=logging.INFO,
16
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
17
- handlers=[logging.StreamHandler(sys.stdout)]
18
- )
19
- logger = logging.getLogger(__name__)
20
-
21
- app = FastAPI(
22
- title="Incassi API - Working Version",
23
- description="API per predire incassi - Versione funzionante",
24
- version="v1.0-stable"
25
- )
26
-
27
- app.add_middleware(
28
- CORSMiddleware,
29
- allow_origins=["*"],
30
- allow_credentials=True,
31
- allow_methods=["*"],
32
- allow_headers=["*"],
33
- )
34
-
35
- # Variabile globale per il modello
36
- mdl = None
37
-
38
- def load_model():
39
- global mdl
40
- try:
41
- logger.info("πŸ”§ Caricamento modello...")
42
-
43
- if not os.path.exists("incassi_model.pkl"):
44
- logger.error("❌ File incassi_model.pkl non trovato")
45
- return False
46
-
47
- file_size = os.path.getsize("incassi_model.pkl")
48
- logger.info(f"πŸ“ File trovato - Dimensione: {file_size} bytes")
49
-
50
- with open("incassi_model.pkl", "rb") as f:
51
- mdl = cp.load(f)
52
-
53
- logger.info(f"βœ… Modello caricato: {type(mdl)}")
54
-
55
- # Controlla se ha i metodi necessari
56
- if hasattr(mdl, 'predict'):
57
- logger.info("βœ… Metodo predict trovato")
58
- else:
59
- logger.error("❌ Metodo predict non trovato")
60
- return False
61
-
62
- if hasattr(mdl, 'model_version'):
63
- logger.info(f"πŸ“‹ Versione modello: {mdl.model_version}")
64
-
65
- return True
66
-
67
- except Exception as e:
68
- logger.error(f"❌ Errore nel caricamento modello: {e}")
69
- logger.error(f"❌ Traceback:\n{traceback.format_exc()}")
70
- return False
71
-
72
- # Carica modello all'avvio
73
- logger.info("πŸš€ Caricamento modello all'avvio...")
74
- model_loaded = load_model()
75
-
76
- if not model_loaded:
77
- logger.error("❌ FATALE: Impossibile caricare il modello")
78
- else:
79
- logger.info("βœ… Modello caricato con successo")
80
-
81
- # Pydantic models
82
- class PredictIn(BaseModel):
83
- Debitore_cluster: str | None = None
84
- Stato_Giudizio: str | None = None
85
- Cedente: str | None = None
86
- Importo_iniziale_outstanding: float | None = None
87
- Decreto_sospeso: str | None = None
88
- Notifica_Decreto: str | None = None
89
- Opposizione_al_decreto_ingiuntivo: str | None = None
90
- Ricorso_al_TAR: str | None = None
91
- Sentenza_TAR: str | None = None
92
- Atto_di_Precetto: str | None = None
93
- Decreto_Ingiuntivo: str | None = None
94
- Sentenza_giudizio_opposizione: str | None = None
95
- giorni_da_iscrizione: int | None = None
96
- giorni_da_cessione: int | None = None
97
- Zona: str | None = None
98
-
99
- class CurveIn(PredictIn):
100
- iscr_start: int = 0
101
- iscr_end: int = 1500
102
- step: int = 50
103
-
104
- def to_model_format(d: dict) -> pd.DataFrame:
105
- """Conversione input API -> formato modello"""
106
- logger.info("πŸ”„ Conversione input...")
107
-
108
- # Mapping esplicito
109
- row = {
110
- "Debitore_cluster": d.get("Debitore_cluster"),
111
- "Stato_Giudizio": d.get("Stato_Giudizio"),
112
- "Cedente": d.get("Cedente"),
113
- "Importo iniziale outstanding": d.get("Importo_iniziale_outstanding"), # Nota: spazio vs underscore
114
- "Decreto sospeso": d.get("Decreto_sospeso"),
115
- "Notifica Decreto": d.get("Notifica_Decreto"),
116
- "Opposizione al decreto ingiuntivo": d.get("Opposizione_al_decreto_ingiuntivo"),
117
- "Ricorso al TAR": d.get("Ricorso_al_TAR"),
118
- "Sentenza TAR": d.get("Sentenza_TAR"),
119
- "Atto di Precetto": d.get("Atto_di_Precetto"),
120
- "Decreto Ingiuntivo": d.get("Decreto_Ingiuntivo"),
121
- "Sentenza giudizio opposizione": d.get("Sentenza_giudizio_opposizione"),
122
- "giorni_da_iscrizione": d.get("giorni_da_iscrizione"),
123
- "giorni_da_cessione": d.get("giorni_da_cessione"),
124
- "Zona": d.get("Zona"),
125
- }
126
-
127
- df = pd.DataFrame([row])
128
- logger.info(f"βœ… DataFrame creato: {df.shape}")
129
- return df
130
-
131
- # ENDPOINTS
132
- @app.get("/")
133
- def root():
134
- return {
135
- "ok": True,
136
- "service": "incassi-api-stable",
137
- "model_loaded": model_loaded,
138
- "version": "v1.0-stable"
139
- }
140
-
141
- @app.get("/status")
142
- def status():
143
- """Status del sistema"""
144
- if not mdl:
145
- return {
146
- "error": "Modello non caricato",
147
- "model_loaded": False
148
- }
149
-
150
- try:
151
- return {
152
- "model_loaded": True,
153
- "model_type": str(type(mdl)),
154
- "model_version": getattr(mdl, "model_version", "unknown"),
155
- "has_predict": hasattr(mdl, "predict"),
156
- "has_stage1": hasattr(mdl, "stage1") and mdl.stage1 is not None,
157
- "has_stage2": hasattr(mdl, "stage2") and mdl.stage2 is not None,
158
- "p100_threshold": getattr(mdl, "p100_thr", "unknown")
159
- }
160
- except Exception as e:
161
- return {
162
- "error": f"Errore status: {e}",
163
- "model_loaded": model_loaded
164
- }
165
-
166
- @app.get("/health")
167
- def health():
168
- """Health check"""
169
- if not model_loaded:
170
- raise HTTPException(status_code=503, detail="Modello non caricato")
171
-
172
- return {"status": "healthy", "timestamp": pd.Timestamp.now().isoformat()}
173
-
174
- @app.post("/predict")
175
- def predict(inp: PredictIn):
176
- """Predizione principale"""
177
- try:
178
- logger.info("πŸš€ /predict chiamato")
179
-
180
- if not mdl:
181
- raise HTTPException(status_code=503, detail="Modello non caricato")
182
-
183
- # Converti input
184
- df = to_model_format(inp.dict())
185
- logger.info("βœ… Input convertito")
186
-
187
- # Esegui predizione con gestione errori
188
- logger.info("πŸ”§ Esecuzione predizione...")
189
- try:
190
- result = mdl.predict(df)
191
- logger.info("βœ… Predizione completata")
192
- except Exception as predict_error:
193
- logger.error(f"❌ Errore in mdl.predict(): {predict_error}")
194
- logger.error(f"❌ Traceback predict:\n{traceback.format_exc()}")
195
-
196
- # Restituisci errore dettagliato
197
- error_msg = f"Errore nella predizione: {str(predict_error)}"
198
- if "set" in str(predict_error).lower():
199
- error_msg += " (Problema con funzione set - modello da rigenerare)"
200
-
201
- raise HTTPException(status_code=500, detail=error_msg)
202
-
203
- # Estrai risultati
204
- p100, prob_ord, yhat, final_class, _ = result
205
-
206
- # Formatta response
207
- response = {
208
- "p100": float(p100),
209
- "prob_ord": [float(x) for x in prob_ord], # Converti ogni elemento
210
- "yhat": float(yhat),
211
- "final_class": str(final_class),
212
- }
213
-
214
- logger.info(f"βœ… Response formattato: yhat={response['yhat']:.2f}")
215
- return response
216
-
217
- except HTTPException:
218
- raise # Re-raise HTTP exceptions as-is
219
- except Exception as e:
220
- logger.error(f"❌ Errore generale in /predict: {e}")
221
- logger.error(f"❌ Traceback:\n{traceback.format_exc()}")
222
-
223
- error_detail = f"Errore interno: {str(e)}"
224
- raise HTTPException(status_code=500, detail=error_detail)
225
-
226
- @app.post("/curve_iscrizione")
227
- def curve_iscrizione(inp: CurveIn):
228
- """Curva di crescita giorni iscrizione"""
229
- try:
230
- logger.info("πŸš€ /curve_iscrizione chiamato")
231
-
232
- if not mdl:
233
- raise HTTPException(status_code=503, detail="Modello non caricato")
234
-
235
- # Validazione parametri
236
- if inp.iscr_end <= inp.iscr_start:
237
- raise HTTPException(status_code=400, detail="iscr_end deve essere > iscr_start")
238
-
239
- if (inp.iscr_end - inp.iscr_start) / inp.step > 500: # Limite ragionevole
240
- raise HTTPException(status_code=400, detail="Troppi punti nella curva (max 500)")
241
-
242
- # Esegui curva
243
- base_dict = inp.dict()
244
- logger.info(f"πŸ”§ Calcolo curva: {inp.iscr_start}-{inp.iscr_end} step {inp.step}")
245
-
246
- try:
247
- result = mdl.curve_iscrizione(base_dict, inp.iscr_start, inp.iscr_end, inp.step)
248
- logger.info("βœ… Curva completata")
249
- except Exception as curve_error:
250
- logger.error(f"❌ Errore in curve_iscrizione: {curve_error}")
251
- raise HTTPException(status_code=500, detail=f"Errore curva: {str(curve_error)}")
252
-
253
- # Formatta response (assicura JSON serializzabile)
254
- response = {
255
- "x": [int(v) for v in result.get("x", [])],
256
- "p100": [float(v) for v in result.get("p100", [])],
257
- "classes": {}
258
- }
259
-
260
- for class_name, values in result.get("classes", {}).items():
261
- response["classes"][str(class_name)] = [float(v) for v in values]
262
-
263
- logger.info(f"βœ… Curva completata: {len(response['x'])} punti")
264
- return response
265
-
266
- except HTTPException:
267
- raise
268
- except Exception as e:
269
- logger.error(f"❌ Errore generale in /curve_iscrizione: {e}")
270
- logger.error(f"❌ Traceback:\n{traceback.format_exc()}")
271
- raise HTTPException(status_code=500, detail=f"Errore interno: {str(e)}")
272
-
273
- # Startup message
274
- logger.info("πŸš€ Server inizializzato")
275
- logger.info(f"πŸ“‹ Modello caricato: {model_loaded}")
276
- if model_loaded and mdl:
277
- logger.info(f"πŸ“‹ Versione modello: {getattr(mdl, 'model_version', 'unknown')}")