Form_Api_Model / app.py
khaerulilman's picture
Upload 4 files
edb6aaf verified
Raw
History Blame Contribute Delete
5.93 kB
from flask import Flask, request, jsonify
from flask_cors import CORS
import joblib
import pandas as pd
import os
import psycopg2
from datetime import datetime
import uuid
import jwt
# ================= CONFIG =================
DATABASE_URL = os.environ.get("DATABASE_URL")
JWT_SECRET = os.environ.get("JWT_SECRET")
if not DATABASE_URL:
raise RuntimeError("DATABASE_URL is not set in environment variables")
if not JWT_SECRET:
raise RuntimeError("JWT_SECRET is not set in environment variables")
# ================= LOAD MODEL =================
if not os.path.exists("diabetes_model_tuned2.pkl"):
import gdown
url = "https://drive.google.com/uc?id=1Zo-xI1y3Y64HU6aiwXVUIHXfu84bBphx"
gdown.download(url, "diabetes_model_tuned2.pkl", quiet=False)
model = joblib.load("diabetes_model_tuned2.pkl")
# ================= APP =================
app = Flask(__name__)
# 🔹 Konfigurasi CORS yang lebih lengkap
CORS(app,
resources={r"/*": {
"origins": [
"http://localhost:5173",
"http://localhost:3000",
"https://capstone-dbs-react.vercel.app",
r"https://.*\.ngrok-free\.app"
],
"methods": ["GET", "POST", "OPTIONS"],
"allow_headers": ["Content-Type", "Authorization"],
"supports_credentials": True
}})
def get_db_connection():
try:
return psycopg2.connect(DATABASE_URL)
except Exception as e:
print(f"Database connection error: {e}")
return None
# ================= JWT HELPER =================
def get_user_id_from_token(request):
auth_header = request.headers.get("Authorization")
if not auth_header:
return None
try:
scheme, token = auth_header.split()
if scheme.lower() != "bearer":
return None
decoded = jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
return decoded.get("userId") or decoded.get("id")
except Exception as e:
print("JWT decode error:", e)
return None
# ================= ROUTES =================
@app.route('/')
def home():
return "API is running"
@app.route('/predict-history', methods=['POST'])
def predict_history():
try:
data = request.get_json()
if not data:
return jsonify({'error': 'No data provided'}), 400
required_fields = [
'hypertension', 'heart_disease', 'bmi', 'blood_glucose_level',
'HbA1c_level', 'smoking_history', 'gender', 'age'
]
for field in required_fields:
if field not in data:
return jsonify({'error': f'Missing field: {field}'}), 400
# 🔹 Ambil userId dari JWT (boleh None)
current_user_id = get_user_id_from_token(request)
input_data = pd.DataFrame([{
'hypertension': int(data['hypertension']),
'heart_disease': int(data['heart_disease']),
'bmi': float(data['bmi']),
'blood_glucose_level': float(data['blood_glucose_level']),
'HbA1c_level': float(data['HbA1c_level']),
'smoking_history': data['smoking_history'],
'gender': data['gender'],
'age': float(data['age'])
}])
prediction = model.predict(input_data)[0]
proba = model.predict_proba(input_data)[0]
confidence = float(proba[1]) if prediction == 1 else float(proba[0])
prediction_result = "positive" if prediction == 1 else "negative"
conn = get_db_connection()
if not conn:
return jsonify({'error': 'Database connection failed'}), 500
try:
cursor = conn.cursor()
insert_query = """
INSERT INTO form_check_history
(id, "userId", hypertension, "heartDisease", bmi, "bloodGlucoseLevel",
"hba1cLevel", "smokingHistory", gender, age, "predictionResult", "createdAt", "updatedAt")
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
RETURNING id
"""
record_id = str(uuid.uuid4())
current_time = datetime.now()
cursor.execute(insert_query, (
record_id,
current_user_id,
bool(int(data['hypertension'])),
bool(int(data['heart_disease'])),
float(data['bmi']),
float(data['blood_glucose_level']),
float(data['HbA1c_level']),
data['smoking_history'],
data['gender'],
float(data['age']),
prediction_result,
current_time,
current_time
))
conn.commit()
cursor.close()
conn.close()
return jsonify({
'success': True,
'message': 'Prediction completed and saved successfully',
'recordId': record_id,
'prediction': {
'result': int(prediction),
'resultText': prediction_result,
'confidence': round(confidence, 4)
},
'inputData': data,
'timestamp': current_time.isoformat(),
'userId': current_user_id
}), 200
except Exception as db_error:
conn.rollback()
cursor.close()
conn.close()
return jsonify({'error': f'Database error: {str(db_error)}'}), 500
except Exception as e:
return jsonify({'error': f'Prediction error: {str(e)}'}), 500
# ================= RUN =================
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), debug=False)