manoj112025 commited on
Commit
5a4fe8b
·
1 Parent(s): e1dcb5d

Backend API's, requirements and Dockerfile added

Browse files
api_flask/Dockerfile ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ ENV PYTHONUNBUFFERED=1 \
4
+ PIP_NO_CACHE_DIR=1 \
5
+ PORT=7860
6
+
7
+ WORKDIR /app
8
+
9
+ # Install system deps
10
+ RUN apt-get update && apt-get install -y --no-install-recommends \
11
+ build-essential \
12
+ && rm -rf /var/lib/apt/lists/*
13
+
14
+ # Install Python dependencies
15
+ COPY api_flask/requirements.txt /app/requirements.txt
16
+ RUN pip install --no-cache-dir -r /app/requirements.txt
17
+
18
+ # Copy entire repository to container
19
+ COPY . /app
20
+
21
+ EXPOSE 7860
22
+
23
+ # Use gunicorn as production server
24
+ CMD ["bash", "-lc", "gunicorn -w 2 -b 0.0.0.0:${PORT} api_flask.app:app"]
api_flask/app.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import joblib
4
+ import pandas as pd
5
+ from pathlib import Path
6
+ from flask import Flask, request, jsonify
7
+ from flask_cors import CORS
8
+
9
+ app = Flask(__name__)
10
+ CORS(app)
11
+
12
+ # Model directory in HF Space (root/models/)
13
+ MODEL_PATH = Path("models") / "best_model.joblib"
14
+
15
+ if MODEL_PATH.exists():
16
+ PIPELINE = joblib.load(MODEL_PATH)
17
+ else:
18
+ PIPELINE = None
19
+
20
+
21
+ @app.get("/")
22
+ def root():
23
+ return jsonify({
24
+ "status": "ok",
25
+ "message": "ExtraaLearn Lead Conversion API",
26
+ "model_loaded": PIPELINE is not None
27
+ })
28
+
29
+
30
+ @app.post("/predict")
31
+ def predict_single():
32
+ """Predict for a single JSON input"""
33
+ if PIPELINE is None:
34
+ return jsonify({"error": "Model not loaded"}), 503
35
+
36
+ payload = request.get_json(force=True)
37
+ X = pd.DataFrame([payload])
38
+
39
+ proba = float(PIPELINE.predict_proba(X)[:, 1][0])
40
+ pred = int(proba >= 0.5)
41
+
42
+ return jsonify({
43
+ "probability": proba,
44
+ "prediction": pred
45
+ })
46
+
47
+
48
+ @app.post("/predict-batch")
49
+ def predict_batch():
50
+ """Predict for multiple JSON rows"""
51
+ if PIPELINE is None:
52
+ return jsonify({"error": "Model not loaded"}), 503
53
+
54
+ payload = request.get_json(force=True)
55
+
56
+ if isinstance(payload, dict) and "records" in payload:
57
+ records = payload["records"]
58
+ elif isinstance(payload, list):
59
+ records = payload
60
+ else:
61
+ return jsonify({"error": "Invalid payload format"}), 400
62
+
63
+ df = pd.DataFrame(records)
64
+ probas = PIPELINE.predict_proba(df)[:, 1]
65
+ preds = (probas >= 0.5).astype(int)
66
+
67
+ df["conversion_proba"] = probas
68
+ df["prediction"] = preds
69
+
70
+ return df.to_json(orient="records")
71
+
72
+
73
+ if __name__ == "__main__":
74
+ port = int(os.environ.get("PORT", 7860))
75
+ app.run(host="0.0.0.0", port=port)
api_flask/requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ flask
2
+ flask-cors
3
+ pandas
4
+ numpy
5
+ scikit-learn
6
+ joblib
7
+ gunicorn
8
+ xgboost
api_flask/wsgi.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from app import app as application
2
+
3
+ # Gunicorn looks for "application"
4
+ app = application
backend_flask_docker DELETED
File without changes
models/best_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e37ad7c789ff9745063c8a980fc28c528585eda61f68327af08ec05614c35b1f
3
+ size 213581