from flask import Flask, request, jsonify import os import pickle import uuid import json from datetime import datetime import threading # 🛑 NO HEAVY IMPORTS AT TOP LEVEL # We import them inside functions to prevent "Memory Limit" crashes on startup. app = Flask(__name__) # Global Cache model_cache = { "lucid": None, "mouse": None, "fusion": None, "loaded": False, "error": None, "logs": [] } # --- CONFIGURATION --- # We write to /tmp because the root folder is Read-Only on HF Spaces LOG_FILE_PATH = "/tmp/predictions.log" # ------------------ LOGGING HELPERS ------------------ def log_prediction(req_id, payload, output): """Safely logs predictions to a temp file.""" try: record = { "request_id": req_id, "time": datetime.utcnow().isoformat(), "input": payload, "output": output } with open(LOG_FILE_PATH, "a") as f: f.write(json.dumps(record) + "\n") except Exception as e: print(f"⚠️ LOGGING FAILED (Non-Fatal): {e}") def log_feedback(feedback): """Safely logs user feedback.""" try: feedback["time"] = datetime.utcnow().isoformat() with open(LOG_FILE_PATH, 'a') as f: f.write(json.dumps(feedback) + "\n") except Exception as e: print(f"⚠️ FEEDBACK LOGGING FAILED: {e}") # ------------------ MODEL LOADING ------------------ def load_heavy_brains(): if model_cache["loaded"]: return model_cache["logs"] log = [] try: log.append("⏳ Importing TensorFlow...") import tensorflow as tf log.append("✅ TensorFlow Imported") log.append("⏳ Importing XGBoost...") import xgboost as xgb log.append("✅ XGBoost Imported") # Define Architecture locally Sequential = tf.keras.models.Sequential Input = tf.keras.layers.Input LSTM = tf.keras.layers.LSTM Dense = tf.keras.layers.Dense Dropout = tf.keras.layers.Dropout BatchNormalization = tf.keras.layers.BatchNormalization LeakyReLU = tf.keras.layers.LeakyReLU # Load LUCID if os.path.exists("lucid_cnn.h5"): model_cache["lucid"] = tf.keras.models.load_model("lucid_cnn.h5") log.append("✅ LUCID Model Loaded") else: log.append("⚠️ lucid_cnn.h5 missing") # Load MOUSE if os.path.exists("delbot_rnn.h5"): mouse_model = Sequential([ Input(shape=(None, 10)), LSTM(128, return_sequences=True), BatchNormalization(), LeakyReLU(alpha=0.1), Dropout(0.3), LSTM(64), LeakyReLU(alpha=0.1), Dropout(0.1), Dense(2, activation='softmax') ]) mouse_model.load_weights("delbot_rnn.h5") model_cache["mouse"] = mouse_model log.append("✅ Mouse Model Loaded") else: log.append("⚠️ delbot_rnn.h5 missing") # Load FUSION if os.path.exists("fusion_xgboost.pkl"): with open("fusion_xgboost.pkl", "rb") as f: model_cache["fusion"] = pickle.load(f) log.append("✅ Fusion Model Loaded") else: log.append("⚠️ fusion_xgboost.pkl missing") model_cache["loaded"] = True model_cache["logs"] = log return log except Exception as e: err = f"❌ CRITICAL LOAD ERROR: {str(e)}" print(err) model_cache["error"] = err return log + [err] # ------------------ DATA PROCESSING ------------------ def process_mouse_data(trace): try: import numpy as np MAX_STEPS = 60 if not trace or len(trace) < 2: return None vectors = [] for i in range(1, len(trace)): dt = (trace[i]['t'] - trace[i-1]['t']) or 1 dx = trace[i]['x'] - trace[i-1]['x'] dy = trace[i]['y'] - trace[i-1]['y'] angle = np.arctan2(dy, dx) vectors.append([dx, dy, dt, dx/dt, dy/dt, angle, 0.0, 0.0, 0.0, 0.0]) data = np.array(vectors) if len(data) > MAX_STEPS: data = data[:MAX_STEPS] else: data = np.vstack([data, np.zeros((MAX_STEPS - len(data), 10))]) return np.expand_dims(data, axis=0) except: return None # ------------------ ROUTES ------------------ @app.route("/") def home(): return "
so it looks like code in the browser
return f"Prediction Logs
{content}"
else:
return "Log file is empty (No requests yet).
"
except Exception as e:
return f"Error reading logs: {e}"
if __name__ == "__main__":
start_auto_retrain()
app.run(host="0.0.0.0", port=7860)