Spaces:
Sleeping
Sleeping
Dan Vancea commited on
Commit ·
30771f0
1
Parent(s): 3269a5c
siuuuuuuuuuu
Browse files- Dockerfile +11 -17
- call_models.py +3 -3
- model.npz +3 -0
- predict_from_supabase.py +11 -4
- requirements.txt +1 -0
- scheduler_ppo.zip +3 -0
Dockerfile
CHANGED
|
@@ -1,36 +1,30 @@
|
|
| 1 |
-
# Use an official Python runtime as a parent image.
|
| 2 |
-
# 3.10-slim is lightweight but maintains high compatibility with ML libraries like PyTorch.
|
| 3 |
FROM python:3.10-slim
|
| 4 |
|
| 5 |
-
# Set environment variables to prevent Python from writing .pyc files
|
| 6 |
-
# and to ensure output is logged directly to the terminal.
|
| 7 |
ENV PYTHONDONTWRITEBYTECODE=1
|
| 8 |
ENV PYTHONUNBUFFERED=1
|
| 9 |
ENV FLASK_APP=call_models.py
|
| 10 |
|
| 11 |
-
#
|
|
|
|
|
|
|
| 12 |
WORKDIR /app
|
| 13 |
|
| 14 |
-
# Install system dependencies
|
| 15 |
-
# gcc and python3-dev are often required to compile certain Python C-extensions
|
| 16 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 17 |
gcc \
|
| 18 |
python3-dev \
|
| 19 |
&& rm -rf /var/lib/apt/lists/*
|
| 20 |
|
| 21 |
-
# Copy only the requirements file first to leverage Docker cache for dependency installation
|
| 22 |
COPY requirements.txt .
|
| 23 |
|
| 24 |
-
# Install
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
|
| 28 |
-
COPY . .
|
| 29 |
|
| 30 |
-
# Expose the port that the Flask app uses
|
| 31 |
EXPOSE 7860
|
| 32 |
|
| 33 |
-
|
| 34 |
-
# is standard practice for handling concurrent requests and better resource management.
|
| 35 |
-
# You can revert to `CMD ["python", "call_models.py"]` if you strictly want the built-in server.
|
| 36 |
-
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "2", "--timeout", "120", "call_models:app"]
|
|
|
|
|
|
|
|
|
|
| 1 |
FROM python:3.10-slim
|
| 2 |
|
|
|
|
|
|
|
| 3 |
ENV PYTHONDONTWRITEBYTECODE=1
|
| 4 |
ENV PYTHONUNBUFFERED=1
|
| 5 |
ENV FLASK_APP=call_models.py
|
| 6 |
|
| 7 |
+
# HuggingFace Spaces runs containers as uid=1000
|
| 8 |
+
RUN useradd -m -u 1000 user
|
| 9 |
+
|
| 10 |
WORKDIR /app
|
| 11 |
|
|
|
|
|
|
|
| 12 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 13 |
gcc \
|
| 14 |
python3-dev \
|
| 15 |
&& rm -rf /var/lib/apt/lists/*
|
| 16 |
|
|
|
|
| 17 |
COPY requirements.txt .
|
| 18 |
|
| 19 |
+
# Install CPU-only torch first to avoid pulling the ~2GB CUDA build,
|
| 20 |
+
# then install the rest of the requirements.
|
| 21 |
+
RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu && \
|
| 22 |
+
pip install --no-cache-dir -r requirements.txt
|
| 23 |
+
|
| 24 |
+
COPY --chown=user:user . .
|
| 25 |
|
| 26 |
+
USER user
|
|
|
|
| 27 |
|
|
|
|
| 28 |
EXPOSE 7860
|
| 29 |
|
| 30 |
+
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "2", "--timeout", "120", "call_models:app"]
|
|
|
|
|
|
|
|
|
call_models.py
CHANGED
|
@@ -94,8 +94,8 @@ def schedule():
|
|
| 94 |
except ValueError:
|
| 95 |
return jsonify({"error": f"invalid timestamp: {timestamp_str}"}), 400
|
| 96 |
|
| 97 |
-
ppo_path = f"
|
| 98 |
-
model_path = f"
|
| 99 |
|
| 100 |
if not os.path.exists(f"{ppo_path}.zip"):
|
| 101 |
return jsonify({"error": f"no PPO model found for printer {printer_id}"}), 404
|
|
@@ -118,4 +118,4 @@ def schedule():
|
|
| 118 |
|
| 119 |
|
| 120 |
if __name__ == "__main__":
|
| 121 |
-
app.run(host="0.0.0.0", port=
|
|
|
|
| 94 |
except ValueError:
|
| 95 |
return jsonify({"error": f"invalid timestamp: {timestamp_str}"}), 400
|
| 96 |
|
| 97 |
+
ppo_path = f"scheduler_ppo"
|
| 98 |
+
model_path = f"model.npz"
|
| 99 |
|
| 100 |
if not os.path.exists(f"{ppo_path}.zip"):
|
| 101 |
return jsonify({"error": f"no PPO model found for printer {printer_id}"}), 404
|
|
|
|
| 118 |
|
| 119 |
|
| 120 |
if __name__ == "__main__":
|
| 121 |
+
app.run(host="0.0.0.0", port=7861, debug=False)
|
model.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6d226c2b94e8ccd47fec4156e87a618a3421563b99d3c16c297b81851b81228d
|
| 3 |
+
size 3506
|
predict_from_supabase.py
CHANGED
|
@@ -15,7 +15,13 @@ from scheduling_rl import _ACTION_TABLE, COMPONENT_NAMES
|
|
| 15 |
# Supabase client
|
| 16 |
# ---------------------------------------------------------------------------
|
| 17 |
|
| 18 |
-
_sb =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
# Column order must match the obs vector expected by the PPO (C=7 conditions)
|
| 21 |
_CONDITION_COLS = [
|
|
@@ -46,8 +52,9 @@ _HEALTH_COLS = [
|
|
| 46 |
|
| 47 |
def _fetch_health(printer_id: str, t: datetime) -> np.ndarray:
|
| 48 |
"""Snapshot whose time_step_id matches hours elapsed since last_repair."""
|
|
|
|
| 49 |
printer = (
|
| 50 |
-
|
| 51 |
.select("last_repair")
|
| 52 |
.eq("id", printer_id)
|
| 53 |
.single()
|
|
@@ -61,7 +68,7 @@ def _fetch_health(printer_id: str, t: datetime) -> np.ndarray:
|
|
| 61 |
time_step_id = int((t - last_repair).total_seconds() // 3600)
|
| 62 |
|
| 63 |
row = (
|
| 64 |
-
|
| 65 |
.select(", ".join(_HEALTH_COLS))
|
| 66 |
.eq("id", printer_id)
|
| 67 |
.gte("time_step_id", time_step_id)
|
|
@@ -78,7 +85,7 @@ def _fetch_health(printer_id: str, t: datetime) -> np.ndarray:
|
|
| 78 |
def _fetch_conditions(printer_id: str, t: datetime) -> np.ndarray:
|
| 79 |
"""Closest conditions row at or before t."""
|
| 80 |
row = (
|
| 81 |
-
|
| 82 |
.select(", ".join(_CONDITION_COLS))
|
| 83 |
.eq("id", printer_id)
|
| 84 |
.lte("timestamp", t.isoformat())
|
|
|
|
| 15 |
# Supabase client
|
| 16 |
# ---------------------------------------------------------------------------
|
| 17 |
|
| 18 |
+
_sb = None
|
| 19 |
+
|
| 20 |
+
def _get_sb():
|
| 21 |
+
global _sb
|
| 22 |
+
if _sb is None:
|
| 23 |
+
_sb = create_client(os.environ["SUPABASE_URL"], os.environ["SUPABASE_SERVICE_KEY"])
|
| 24 |
+
return _sb
|
| 25 |
|
| 26 |
# Column order must match the obs vector expected by the PPO (C=7 conditions)
|
| 27 |
_CONDITION_COLS = [
|
|
|
|
| 52 |
|
| 53 |
def _fetch_health(printer_id: str, t: datetime) -> np.ndarray:
|
| 54 |
"""Snapshot whose time_step_id matches hours elapsed since last_repair."""
|
| 55 |
+
sb = _get_sb()
|
| 56 |
printer = (
|
| 57 |
+
sb.table("printers")
|
| 58 |
.select("last_repair")
|
| 59 |
.eq("id", printer_id)
|
| 60 |
.single()
|
|
|
|
| 68 |
time_step_id = int((t - last_repair).total_seconds() // 3600)
|
| 69 |
|
| 70 |
row = (
|
| 71 |
+
sb.table("snapshots")
|
| 72 |
.select(", ".join(_HEALTH_COLS))
|
| 73 |
.eq("id", printer_id)
|
| 74 |
.gte("time_step_id", time_step_id)
|
|
|
|
| 85 |
def _fetch_conditions(printer_id: str, t: datetime) -> np.ndarray:
|
| 86 |
"""Closest conditions row at or before t."""
|
| 87 |
row = (
|
| 88 |
+
_get_sb().table("conditions")
|
| 89 |
.select(", ".join(_CONDITION_COLS))
|
| 90 |
.eq("id", printer_id)
|
| 91 |
.lte("timestamp", t.isoformat())
|
requirements.txt
CHANGED
|
@@ -12,6 +12,7 @@ supabase>=2.3.0
|
|
| 12 |
|
| 13 |
# Required for loading PPO .zip models (Standard for Stable Baselines3)
|
| 14 |
stable-baselines3>=2.2.1
|
|
|
|
| 15 |
torch>=2.2.0 # Required backend for Stable Baselines3
|
| 16 |
|
| 17 |
# Production WSGI Server (Recommended over standard Flask app.run)
|
|
|
|
| 12 |
|
| 13 |
# Required for loading PPO .zip models (Standard for Stable Baselines3)
|
| 14 |
stable-baselines3>=2.2.1
|
| 15 |
+
gymnasium>=0.29.0
|
| 16 |
torch>=2.2.0 # Required backend for Stable Baselines3
|
| 17 |
|
| 18 |
# Production WSGI Server (Recommended over standard Flask app.run)
|
scheduler_ppo.zip
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8503dac424ae9073edfd74be9661097dc39b5319fd44b7fb16a40f9db2d603eb
|
| 3 |
+
size 564738
|