sourize commited on
Commit
4c76a6d
·
1 Parent(s): f0dc8ba

Updated Backend

Browse files
.gitattributes DELETED
@@ -1,35 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use official Python 3.10 slim image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory to /app
5
+ WORKDIR /app
6
+
7
+ # Copy requirements (relative to backend/ folder)
8
+ COPY requirements.txt requirements.txt
9
+
10
+ # Install dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Copy the current directory contents (backend code) into /app
14
+ COPY . .
15
+
16
+ # Set permissions for Hugging Face (User 1000)
17
+ RUN useradd -m -u 1000 user
18
+ USER user
19
+ ENV HOME=/home/user \
20
+ PATH=/home/user/.local/bin:$PATH
21
+
22
+ # Expose port 7860
23
+ EXPOSE 7860
24
+
25
+ # Run uvicorn (module is main:app since we are inside the folder)
26
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,10 +1,25 @@
1
  ---
2
  title: NavAI Guard Backend
3
- emoji: 📉
4
- colorFrom: indigo
5
- colorTo: pink
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: NavAI Guard Backend
3
+ emoji: 🚢
4
+ colorFrom: blue
5
+ colorTo: cyan
6
  sdk: docker
7
  pinned: false
8
+ app_port: 7860
9
  ---
10
 
11
+ # Nav-AI Guard Backend
12
+
13
+ This repository is configured to deploy the **Nav-AI Guard Backend** to Hugging Face Spaces using Docker.
14
+
15
+ ## Configuration
16
+
17
+ * **SDK**: Docker
18
+ * **App Port**: 7860
19
+ * **Docker Path**: This repo contains the `Dockerfile` in the `backend/` directory.
20
+
21
+ ## How to Deploy
22
+
23
+ 1. **Create a Space**: Select **Docker** SDK.
24
+ 2. **Connect Repo**: Point to this repository.
25
+ 3. **Context**: Ensure the Space build context is set to the `backend/` subdirectory if possible, OR if syncing only the backend folder, this `README.md` at the root will auto-configure it.
__pycache__/main.cpython-310.pyc ADDED
Binary file (2.91 kB). View file
 
main.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import joblib
3
+ import numpy as np
4
+ import pandas as pd
5
+ from fastapi import FastAPI, HTTPException
6
+ from pydantic import BaseModel
7
+ from tensorflow.keras.models import load_model
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+
10
+ app = FastAPI(title="NavAI-Guard API", description="Maritime Anomaly Detection API")
11
+
12
+ # Enable CORS for frontend
13
+ # In production, you might want to restrict this to your Vercel domain
14
+ app.add_middleware(
15
+ CORSMiddleware,
16
+ allow_origins=["*"], # Allows all origins
17
+ allow_credentials=True,
18
+ allow_methods=["*"], # Allows all methods
19
+ allow_headers=["*"], # Allows all headers
20
+ )
21
+
22
+ # Global variables to hold model and scaler
23
+ model = None
24
+ scaler = None
25
+ THRESHOLD = 0.1
26
+
27
+ class AISData(BaseModel):
28
+ timestamp_str: str = "27/02/2024 03:42:19"
29
+ mmsi: float
30
+ latitude: float
31
+ longitude: float
32
+ sog: float
33
+ cog: float
34
+ heading: float
35
+
36
+ @app.on_event("startup")
37
+ def load_assets():
38
+ global model, scaler
39
+ try:
40
+ base_path = os.path.dirname(os.path.abspath(__file__))
41
+ model_path = os.path.join(base_path, "models", "autoencoder_model.keras")
42
+ scaler_path = os.path.join(base_path, "models", "scaler.pkl")
43
+
44
+ print(f"Loading model from {model_path}...")
45
+ model = load_model(model_path)
46
+ print(f"Loading scaler from {scaler_path}...")
47
+ scaler = joblib.load(scaler_path)
48
+ print("Assets loaded successfully.")
49
+ except Exception as e:
50
+ print(f"Error loading assets: {e}")
51
+ raise RuntimeError(f"Could not load model or scaler: {e}")
52
+
53
+ @app.get("/")
54
+ def health_check():
55
+ return {"status": "active", "system": "NavAI-Guard"}
56
+
57
+ @app.post("/predict")
58
+ def predict_anomaly(data: AISData):
59
+ if model is None or scaler is None:
60
+ raise HTTPException(status_code=503, detail="Model/Scaler not loaded")
61
+
62
+ try:
63
+ # 1. Process Timestamp
64
+ # Format: DD/MM/YYYY HH:MM:SS
65
+ timestamp_sec = pd.to_datetime(data.timestamp_str, format="%d/%m/%Y %H:%M:%S").value / 1e9
66
+ except Exception as e:
67
+ raise HTTPException(status_code=400, detail=f"Invalid Timestamp Format: {e}")
68
+
69
+ # 2. Prepare Input Vector
70
+ # Order matches app.py: [timestamp_sec, mmsi, latitude, longitude, sog, cog, heading]
71
+ input_features = np.array([[
72
+ timestamp_sec,
73
+ data.mmsi,
74
+ data.latitude,
75
+ data.longitude,
76
+ data.sog,
77
+ data.cog,
78
+ data.heading
79
+ ]])
80
+
81
+ try:
82
+ # 3. Scale
83
+ input_scaled = scaler.transform(input_features)
84
+
85
+ # 4. Reconstruct
86
+ reconstructed = model.predict(input_scaled)
87
+
88
+ # 5. Calculate Error (MSE)
89
+ reconstruction_error = np.mean(np.square(input_scaled - reconstructed))
90
+
91
+ # 6. Determine Anomaly
92
+ is_anomaly = float(reconstruction_error) > THRESHOLD
93
+
94
+ return {
95
+ "anomaly": is_anomaly,
96
+ "score": float(reconstruction_error),
97
+ "threshold": THRESHOLD,
98
+ "status": "Anomalous" if is_anomaly else "Normal"
99
+ }
100
+
101
+ except Exception as e:
102
+ raise HTTPException(status_code=500, detail=f"Prediction error: {e}")
103
+
104
+ if __name__ == "__main__":
105
+ import uvicorn
106
+ uvicorn.run(app, host="0.0.0.0", port=8000)
models/autoencoder_model.keras ADDED
Binary file (62.4 kB). View file
 
models/scaler.pkl ADDED
Binary file (1.15 kB). View file
 
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pandas
4
+ numpy
5
+ scikit-learn
6
+ tensorflow
7
+ joblib
8
+ python-multipart