Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,14 +1,13 @@
|
|
| 1 |
|
| 2 |
-
from fastapi import FastAPI
|
| 3 |
from pydantic import BaseModel, Field
|
| 4 |
import joblib
|
| 5 |
import json
|
| 6 |
import numpy as np
|
| 7 |
from datetime import datetime
|
| 8 |
from typing import Optional
|
| 9 |
-
import os
|
| 10 |
|
| 11 |
-
# Initialisation
|
| 12 |
app = FastAPI(
|
| 13 |
title="API Détection de Fraude",
|
| 14 |
description="API de détection de fraude dans les transactions bancaires",
|
|
@@ -49,28 +48,15 @@ class PredictionResponse(BaseModel):
|
|
| 49 |
risk_level: str
|
| 50 |
details: dict
|
| 51 |
|
| 52 |
-
#
|
| 53 |
-
@app.get("/")
|
| 54 |
-
def read_root():
|
| 55 |
-
return {
|
| 56 |
-
"message": "API de Détection de Fraude",
|
| 57 |
-
"version": "1.0.0",
|
| 58 |
-
"endpoints": {
|
| 59 |
-
"/predict": "POST - Prédire une transaction",
|
| 60 |
-
"/health": "GET - Statut de l'API",
|
| 61 |
-
"/categories": "GET - Liste des catégories",
|
| 62 |
-
"/docs": "GET - Documentation interactive"
|
| 63 |
-
}
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
@app.get("/health")
|
| 67 |
def health_check():
|
| 68 |
return {
|
| 69 |
-
"status": "healthy"
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
# }
|
| 73 |
|
|
|
|
| 74 |
@app.get("/categories")
|
| 75 |
def get_categories():
|
| 76 |
return {
|
|
@@ -79,6 +65,7 @@ def get_categories():
|
|
| 79 |
"genders": list(mappings['genders'].keys())
|
| 80 |
}
|
| 81 |
|
|
|
|
| 82 |
@app.post("/predict", response_model=PredictionResponse)
|
| 83 |
def predict_fraud(transaction: Transaction):
|
| 84 |
try:
|
|
@@ -93,13 +80,13 @@ def predict_fraud(transaction: Transaction):
|
|
| 93 |
month = trans_dt.month
|
| 94 |
age = (trans_dt - dob_dt).days // 365
|
| 95 |
|
| 96 |
-
# Distance
|
| 97 |
distance = np.sqrt(
|
| 98 |
(transaction.lat - transaction.merch_lat)**2 +
|
| 99 |
(transaction.long - transaction.merch_long)**2
|
| 100 |
) * 111
|
| 101 |
|
| 102 |
-
#
|
| 103 |
if transaction.category not in mappings['categories']:
|
| 104 |
raise HTTPException(400, f"Catégorie inconnue: {transaction.category}")
|
| 105 |
if transaction.gender not in mappings['genders']:
|
|
@@ -112,7 +99,7 @@ def predict_fraud(transaction: Transaction):
|
|
| 112 |
state_encoded = mappings['states'][transaction.state]
|
| 113 |
|
| 114 |
# Construction du vecteur de features
|
| 115 |
-
features = np.array([[
|
| 116 |
transaction.amt,
|
| 117 |
hour,
|
| 118 |
day_of_week,
|
|
@@ -159,61 +146,4 @@ def predict_fraud(transaction: Transaction):
|
|
| 159 |
except ValueError as e:
|
| 160 |
raise HTTPException(status_code=400, detail=f"Erreur de format: {str(e)}")
|
| 161 |
except Exception as e:
|
| 162 |
-
raise HTTPException(status_code=500, detail=f"Erreur interne: {str(e)}")
|
| 163 |
-
|
| 164 |
-
#if __name__ == "__main__":
|
| 165 |
-
# import uvicorn
|
| 166 |
-
# uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 167 |
-
# if __name__ == "__main__":
|
| 168 |
-
# import gradio as gr
|
| 169 |
-
# from app import predict_fraud, Transaction # si tu es déjà dans app.py, inutile de réimporter
|
| 170 |
-
|
| 171 |
-
# # Wrapper pour adapter les inputs de Gradio au modèle FastAPI
|
| 172 |
-
# def api_predict_wrapper(
|
| 173 |
-
# amt, category, merchant, trans_date_trans_time, gender, state,
|
| 174 |
-
# lat, long, city_pop, dob, merch_lat, merch_long,
|
| 175 |
-
# cc_num=None, avg_amt=50, std_amt=30, nb_trans=10
|
| 176 |
-
# ):
|
| 177 |
-
# tx = Transaction(
|
| 178 |
-
# amt=amt,
|
| 179 |
-
# category=category,
|
| 180 |
-
# merchant=merchant,
|
| 181 |
-
# trans_date_trans_time=trans_date_trans_time,
|
| 182 |
-
# gender=gender,
|
| 183 |
-
# state=state,
|
| 184 |
-
# lat=lat,
|
| 185 |
-
# long=long,
|
| 186 |
-
# city_pop=city_pop,
|
| 187 |
-
# dob=dob,
|
| 188 |
-
# merch_lat=merch_lat,
|
| 189 |
-
# merch_long=merch_long,
|
| 190 |
-
# cc_num=cc_num,
|
| 191 |
-
# avg_amt=avg_amt,
|
| 192 |
-
# std_amt=std_amt,
|
| 193 |
-
# nb_trans=nb_trans
|
| 194 |
-
# )
|
| 195 |
-
# result = predict_fraud(tx)
|
| 196 |
-
# return result.dict()
|
| 197 |
-
|
| 198 |
-
# # Définition de l'interface Gradio
|
| 199 |
-
# iface = gr.Interface(
|
| 200 |
-
# fn=api_predict_wrapper,
|
| 201 |
-
# inputs=[
|
| 202 |
-
# gr.Number(label="Montant"),
|
| 203 |
-
# gr.Textbox(label="Catégorie"),
|
| 204 |
-
# gr.Textbox(label="Marchand"),
|
| 205 |
-
# gr.Textbox(label="Date/Heure"),
|
| 206 |
-
# gr.Textbox(label="Genre"),
|
| 207 |
-
# gr.Textbox(label="État"),
|
| 208 |
-
# gr.Number(label="Latitude"),
|
| 209 |
-
# gr.Number(label="Longitude"),
|
| 210 |
-
# gr.Number(label="Population ville"),
|
| 211 |
-
# gr.Textbox(label="Date de naissance"),
|
| 212 |
-
# gr.Number(label="Lat march."),
|
| 213 |
-
# gr.Number(label="Long march."),
|
| 214 |
-
# ],
|
| 215 |
-
# outputs=gr.JSON(label="Résultat")
|
| 216 |
-
# )
|
| 217 |
-
|
| 218 |
-
# # Lancement du front Gradio
|
| 219 |
-
# iface.launch()
|
|
|
|
| 1 |
|
| 2 |
+
from fastapi import FastAPI, HTTPException
|
| 3 |
from pydantic import BaseModel, Field
|
| 4 |
import joblib
|
| 5 |
import json
|
| 6 |
import numpy as np
|
| 7 |
from datetime import datetime
|
| 8 |
from typing import Optional
|
|
|
|
| 9 |
|
| 10 |
+
# Initialisation FastAPI
|
| 11 |
app = FastAPI(
|
| 12 |
title="API Détection de Fraude",
|
| 13 |
description="API de détection de fraude dans les transactions bancaires",
|
|
|
|
| 48 |
risk_level: str
|
| 49 |
details: dict
|
| 50 |
|
| 51 |
+
# Endpoint Health
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
@app.get("/health")
|
| 53 |
def health_check():
|
| 54 |
return {
|
| 55 |
+
"status": "healthy",
|
| 56 |
+
"model_loaded": model is not None
|
| 57 |
+
}
|
|
|
|
| 58 |
|
| 59 |
+
# Endpoint catégories, états et genres
|
| 60 |
@app.get("/categories")
|
| 61 |
def get_categories():
|
| 62 |
return {
|
|
|
|
| 65 |
"genders": list(mappings['genders'].keys())
|
| 66 |
}
|
| 67 |
|
| 68 |
+
# Endpoint de prédiction
|
| 69 |
@app.post("/predict", response_model=PredictionResponse)
|
| 70 |
def predict_fraud(transaction: Transaction):
|
| 71 |
try:
|
|
|
|
| 80 |
month = trans_dt.month
|
| 81 |
age = (trans_dt - dob_dt).days // 365
|
| 82 |
|
| 83 |
+
# Distance client → marchand
|
| 84 |
distance = np.sqrt(
|
| 85 |
(transaction.lat - transaction.merch_lat)**2 +
|
| 86 |
(transaction.long - transaction.merch_long)**2
|
| 87 |
) * 111
|
| 88 |
|
| 89 |
+
# Vérification des catégories
|
| 90 |
if transaction.category not in mappings['categories']:
|
| 91 |
raise HTTPException(400, f"Catégorie inconnue: {transaction.category}")
|
| 92 |
if transaction.gender not in mappings['genders']:
|
|
|
|
| 99 |
state_encoded = mappings['states'][transaction.state]
|
| 100 |
|
| 101 |
# Construction du vecteur de features
|
| 102 |
+
features = np.array([[
|
| 103 |
transaction.amt,
|
| 104 |
hour,
|
| 105 |
day_of_week,
|
|
|
|
| 146 |
except ValueError as e:
|
| 147 |
raise HTTPException(status_code=400, detail=f"Erreur de format: {str(e)}")
|
| 148 |
except Exception as e:
|
| 149 |
+
raise HTTPException(status_code=500, detail=f"Erreur interne: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|