Dan Vancea commited on
Commit
30771f0
·
1 Parent(s): 3269a5c

siuuuuuuuuuu

Browse files
Files changed (6) hide show
  1. Dockerfile +11 -17
  2. call_models.py +3 -3
  3. model.npz +3 -0
  4. predict_from_supabase.py +11 -4
  5. requirements.txt +1 -0
  6. 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
- # Set the working directory in the container
 
 
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 dependencies
25
- RUN pip install --no-cache-dir -r requirements.txt
 
 
 
 
26
 
27
- # Copy the rest of the application code, including the custom modules and models
28
- COPY . .
29
 
30
- # Expose the port that the Flask app uses
31
  EXPOSE 7860
32
 
33
- # While your script uses `app.run()`, running a production WSGI server like Gunicorn
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"scheduler_{printer_id}_ppo"
98
- model_path = f"model_{printer_id}.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,4 +118,4 @@ def schedule():
118
 
119
 
120
  if __name__ == "__main__":
121
- app.run(host="0.0.0.0", port=7860, debug=False)
 
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 = create_client(os.environ["SUPABASE_URL"], os.environ["SUPABASE_SERVICE_KEY"])
 
 
 
 
 
 
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
- _sb.table("printers")
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
- _sb.table("snapshots")
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
- _sb.table("conditions")
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