Spaces:
Sleeping
Sleeping
File size: 4,850 Bytes
0f8fe33 |
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 |
# backend/routes/predict_route.py
from flask import Blueprint, request, jsonify
import time
import numpy as np
import pandas as pd
from utils.model_selector import load_model, get_active_model
from utils.logger import classify_risk
predict_bp = Blueprint("predict", __name__)
@predict_bp.route("/", methods=["GET"])
def info():
active = get_active_model()
return jsonify({
"message": "POST JSON to /api/predict/ to get model prediction.",
"active_model": active,
"note": "For 'bcc' model send ordered features or dict; for 'cicids' send named features matching artifacts['features']."
})
@predict_bp.route("/", methods=["POST"])
def predict():
active = get_active_model()
mdl = load_model(active)
if active == "bcc":
model = mdl.get("model")
scaler = mdl.get("scaler")
encoder = mdl.get("encoder")
if model is None or scaler is None or encoder is None:
return jsonify({"error": "BCC model/scaler/encoder not loaded on server."}), 500
data = request.get_json(force=True, silent=True)
if data is None:
return jsonify({"error": "No JSON body provided"}), 400
# Accept either list/array or dict of features
# You must keep the same feature order as used in training (15 values)
if isinstance(data, dict):
# if the client provides named keys, try to coerce to ordered list
# fallback: take values in insertion order
vals = list(data.values())
else:
vals = list(data)
try:
X = np.array([float(v) for v in vals], dtype=float).reshape(1, -1)
except Exception as e:
return jsonify({"error": f"Failed to coerce input to numeric vector: {e}"}), 400
try:
Xs = scaler.transform(X)
except Exception:
# fallback: try prediction without scaler
Xs = X
try:
pred_idx = model.predict(Xs)[0]
conf = None
if hasattr(model, "predict_proba"):
conf = float(np.max(model.predict_proba(Xs))) * 100.0
label = encoder.inverse_transform([int(pred_idx)])[0]
risk = classify_risk(label)
return jsonify({
"prediction": str(label),
"confidence": round(conf, 2) if conf is not None else None,
"risk_level": risk
})
except Exception as e:
return jsonify({"error": f"Model predict failed: {str(e)}"}), 500
elif active == "cicids":
obj = mdl.get("artifacts", None)
model = mdl.get("model", None)
if model is None or obj is None:
return jsonify({"error": "CICIDS model or artifacts not available on server."}), 500
# artifacts expected to have 'features' and 'scaler'
features = obj.get("features") or obj.get("features_used") or obj.get("feature_list")
scaler = obj.get("scaler") or obj.get("scaler_object")
if not features or scaler is None:
return jsonify({"error": "CICIDS artifacts missing features or scaler."}), 500
data = request.get_json(force=True, silent=True)
if data is None:
return jsonify({"error": "No JSON body provided"}), 400
# Accept dict of named features or list
if isinstance(data, dict):
# build row using artifacts feature order (missing -> 0)
row = [float(data.get(f, 0)) for f in features]
else:
# list or array
try:
row = [float(x) for x in data]
except Exception as e:
return jsonify({"error": "Provided input must be array or dict of numbers."}), 400
if len(row) != len(features):
return jsonify({"error": f"Expecting {len(features)} features for cicids: {features}"}), 400
X_df = pd.DataFrame([row], columns=features)
try:
Xs = scaler.transform(X_df)
except Exception:
Xs = X_df.values
try:
pred = model.predict(Xs)[0]
conf = None
if hasattr(model, "predict_proba"):
conf = float(np.max(model.predict_proba(Xs))) * 100.0
# label may already be string; try safe conversion
try:
label = str(pred)
except Exception:
label = repr(pred)
risk = classify_risk(label)
return jsonify({
"prediction": label,
"confidence": round(conf, 2) if conf else None,
"risk_level": risk
})
except Exception as e:
return jsonify({"error": f"CICIDS predict failed: {str(e)}"}), 500
else:
return jsonify({"error": "Unknown active model"}), 500
|