Spaces:
Sleeping
Sleeping
Deploy backend Flask app
Browse files- Dockerfile +1 -1
- bot_detector_api.py +5 -16
Dockerfile
CHANGED
|
@@ -16,4 +16,4 @@ EXPOSE 7860
|
|
| 16 |
# - `-w 4`: Uses 4 worker processes for handling requests
|
| 17 |
# - `-b 0.0.0.0:7860`: Binds the server to port 7860 on all network interfaces
|
| 18 |
# - `app:app`: Runs the Flask app (assuming `app.py` contains the Flask instance named `app`)
|
| 19 |
-
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:7860", "app
|
|
|
|
| 16 |
# - `-w 4`: Uses 4 worker processes for handling requests
|
| 17 |
# - `-b 0.0.0.0:7860`: Binds the server to port 7860 on all network interfaces
|
| 18 |
# - `app:app`: Runs the Flask app (assuming `app.py` contains the Flask instance named `app`)
|
| 19 |
+
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:7860", "bot_detector_api:app"]
|
bot_detector_api.py
CHANGED
|
@@ -4,17 +4,12 @@ import pandas as pd
|
|
| 4 |
from flask import Flask, request, jsonify
|
| 5 |
from urllib.parse import urlparse, parse_qs
|
| 6 |
|
| 7 |
-
# Initialize the Flask application
|
| 8 |
-
|
| 9 |
|
| 10 |
-
|
| 11 |
-
# Define a route for the home page (GET request)
|
| 12 |
-
@bot_detector_api.get('/')
|
| 13 |
def home():
|
| 14 |
-
"""
|
| 15 |
-
This function handles GET requests to the root URL ('/') of the API.
|
| 16 |
-
It returns a simple welcome message.
|
| 17 |
-
"""
|
| 18 |
return "Welcome to the bot Prediction API!"
|
| 19 |
|
| 20 |
# Load all model artifacts
|
|
@@ -33,7 +28,6 @@ def parse_url_params(url):
|
|
| 33 |
return {}
|
| 34 |
|
| 35 |
def prepare_features(row_dict):
|
| 36 |
-
# Start with base info
|
| 37 |
base = {
|
| 38 |
'region': row_dict.get('region', 'unknown'),
|
| 39 |
'browser': row_dict.get('browser', 'unknown'),
|
|
@@ -41,19 +35,16 @@ def prepare_features(row_dict):
|
|
| 41 |
'd': row_dict.get('d', '')
|
| 42 |
}
|
| 43 |
|
| 44 |
-
# Extract features from URL
|
| 45 |
query_params = parse_url_params(base['d'])
|
| 46 |
combined = {**base, **query_params}
|
| 47 |
combined.pop('d', None)
|
| 48 |
|
| 49 |
-
# Ensure all required columns exist
|
| 50 |
for col in feature_names:
|
| 51 |
if col not in combined and col not in ["iso_anomaly_prob", "svm_anomaly_prob"]:
|
| 52 |
combined[col] = "unknown"
|
| 53 |
|
| 54 |
df = pd.DataFrame([combined])
|
| 55 |
|
| 56 |
-
# Encode categorical variables or convert to numeric
|
| 57 |
for col in df.columns:
|
| 58 |
if col in encoders:
|
| 59 |
try:
|
|
@@ -63,7 +54,6 @@ def prepare_features(row_dict):
|
|
| 63 |
else:
|
| 64 |
df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
|
| 65 |
|
| 66 |
-
# Apply scaler and compute anomaly scores
|
| 67 |
df_scaled = scaler.transform(df)
|
| 68 |
iso_score = if_model.decision_function(df_scaled)
|
| 69 |
svm_score = svm_model.decision_function(df_scaled)
|
|
@@ -76,8 +66,7 @@ def prepare_features(row_dict):
|
|
| 76 |
|
| 77 |
return df[feature_names]
|
| 78 |
|
| 79 |
-
|
| 80 |
-
@bot_detector_api.post('/v1/predict')
|
| 81 |
def predict():
|
| 82 |
row = request.get_json()
|
| 83 |
X = prepare_features(row)
|
|
|
|
| 4 |
from flask import Flask, request, jsonify
|
| 5 |
from urllib.parse import urlparse, parse_qs
|
| 6 |
|
| 7 |
+
# Initialize the Flask application with standard naming for deployment
|
| 8 |
+
app = Flask("Bot detector")
|
| 9 |
|
| 10 |
+
@app.get('/')
|
|
|
|
|
|
|
| 11 |
def home():
|
| 12 |
+
"""Health check or welcome route."""
|
|
|
|
|
|
|
|
|
|
| 13 |
return "Welcome to the bot Prediction API!"
|
| 14 |
|
| 15 |
# Load all model artifacts
|
|
|
|
| 28 |
return {}
|
| 29 |
|
| 30 |
def prepare_features(row_dict):
|
|
|
|
| 31 |
base = {
|
| 32 |
'region': row_dict.get('region', 'unknown'),
|
| 33 |
'browser': row_dict.get('browser', 'unknown'),
|
|
|
|
| 35 |
'd': row_dict.get('d', '')
|
| 36 |
}
|
| 37 |
|
|
|
|
| 38 |
query_params = parse_url_params(base['d'])
|
| 39 |
combined = {**base, **query_params}
|
| 40 |
combined.pop('d', None)
|
| 41 |
|
|
|
|
| 42 |
for col in feature_names:
|
| 43 |
if col not in combined and col not in ["iso_anomaly_prob", "svm_anomaly_prob"]:
|
| 44 |
combined[col] = "unknown"
|
| 45 |
|
| 46 |
df = pd.DataFrame([combined])
|
| 47 |
|
|
|
|
| 48 |
for col in df.columns:
|
| 49 |
if col in encoders:
|
| 50 |
try:
|
|
|
|
| 54 |
else:
|
| 55 |
df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
|
| 56 |
|
|
|
|
| 57 |
df_scaled = scaler.transform(df)
|
| 58 |
iso_score = if_model.decision_function(df_scaled)
|
| 59 |
svm_score = svm_model.decision_function(df_scaled)
|
|
|
|
| 66 |
|
| 67 |
return df[feature_names]
|
| 68 |
|
| 69 |
+
@app.post('/v1/predict')
|
|
|
|
| 70 |
def predict():
|
| 71 |
row = request.get_json()
|
| 72 |
X = prepare_features(row)
|