Spaces:
Sleeping
Sleeping
Commit Β·
a7a32a6
1
Parent(s): dd6f45c
removed weight endpts
Browse files- Dockerfile +3 -1
- dashboard.html +20 -0
- src/adaptive_alert_triage/server.py +29 -3
Dockerfile
CHANGED
|
@@ -66,8 +66,10 @@ HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=3 \
|
|
| 66 |
CMD curl -f http://localhost:${PORT}/health || exit 1
|
| 67 |
|
| 68 |
# ββ Add non-root user βββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
| 69 |
RUN useradd -m -u 1000 appuser \
|
| 70 |
-
&& mkdir -p /app/weights /app/results \
|
| 71 |
&& chown -R appuser:appuser /app
|
| 72 |
USER appuser
|
| 73 |
# ββ Default command: start the FastAPI server βββββββββββββββββββββββββββββββββ
|
|
|
|
| 66 |
CMD curl -f http://localhost:${PORT}/health || exit 1
|
| 67 |
|
| 68 |
# ββ Add non-root user βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 69 |
+
# Save a pristine copy of repo weights so cached HF weights can be overridden
|
| 70 |
+
RUN cp -r /app/weights /app/weights_pristine 2>/dev/null || true
|
| 71 |
RUN useradd -m -u 1000 appuser \
|
| 72 |
+
&& mkdir -p /app/weights /app/results /app/weights_pristine \
|
| 73 |
&& chown -R appuser:appuser /app
|
| 74 |
USER appuser
|
| 75 |
# ββ Default command: start the FastAPI server βββββββββββββββββββββββββββββββββ
|
dashboard.html
CHANGED
|
@@ -296,6 +296,12 @@
|
|
| 296 |
<button class="btn btn-primary" onclick="startTraining()" id="trainBtn">βΆ Start Training</button>
|
| 297 |
</div>
|
| 298 |
<div class="terminal" id="trainTerminal">Ready to train. Run PPO to update weights.</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
</div>
|
| 300 |
|
| 301 |
<div class="testing-container active" id="testingView">
|
|
@@ -858,6 +864,20 @@ async function pollTraining() {
|
|
| 858 |
} catch(e) {}
|
| 859 |
}
|
| 860 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 861 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 862 |
// Init
|
| 863 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 296 |
<button class="btn btn-primary" onclick="startTraining()" id="trainBtn">βΆ Start Training</button>
|
| 297 |
</div>
|
| 298 |
<div class="terminal" id="trainTerminal">Ready to train. Run PPO to update weights.</div>
|
| 299 |
+
<div style="margin-top:12px; display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
|
| 300 |
+
<span style="font-size:12px; color:var(--text-muted);">π₯ Download Weights:</span>
|
| 301 |
+
<button class="btn" onclick="downloadWeights('easy')" style="font-size:11px; padding:4px 10px;">π’ Easy</button>
|
| 302 |
+
<button class="btn" onclick="downloadWeights('medium')" style="font-size:11px; padding:4px 10px;">π‘ Medium</button>
|
| 303 |
+
<button class="btn" onclick="downloadWeights('hard')" style="font-size:11px; padding:4px 10px;">π΄ Hard</button>
|
| 304 |
+
</div>
|
| 305 |
</div>
|
| 306 |
|
| 307 |
<div class="testing-container active" id="testingView">
|
|
|
|
| 864 |
} catch(e) {}
|
| 865 |
}
|
| 866 |
|
| 867 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 868 |
+
// Weight Downloads
|
| 869 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 870 |
+
function downloadWeights(taskId) {
|
| 871 |
+
const url = `${SERVER}/agent/weights/${taskId}`;
|
| 872 |
+
const a = document.createElement('a');
|
| 873 |
+
a.href = url;
|
| 874 |
+
a.download = `ppo_${taskId}.json`;
|
| 875 |
+
document.body.appendChild(a);
|
| 876 |
+
a.click();
|
| 877 |
+
document.body.removeChild(a);
|
| 878 |
+
showToast(`Downloading ${taskId} weightsβ¦`, 'info');
|
| 879 |
+
}
|
| 880 |
+
|
| 881 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 882 |
// Init
|
| 883 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
src/adaptive_alert_triage/server.py
CHANGED
|
@@ -263,10 +263,37 @@ async def _episode_loop() -> None:
|
|
| 263 |
|
| 264 |
# ββ Startup / shutdown ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
@app.on_event("startup")
|
| 267 |
async def startup():
|
| 268 |
global env, _loop_task
|
| 269 |
|
|
|
|
|
|
|
|
|
|
| 270 |
env = AdaptiveAlertTriageEnv(task_id="hard")
|
| 271 |
env.real_alerts_queue = deque(maxlen=50)
|
| 272 |
env.reset() # β FIX 1: immediately populate env.alerts
|
|
@@ -536,12 +563,11 @@ async def recommend():
|
|
| 536 |
|
| 537 |
@app.get("/agent/weights/{task_id}")
|
| 538 |
async def download_weights(task_id: str):
|
| 539 |
-
"""
|
|
|
|
| 540 |
path = os.path.join(_project_root if _project_root else os.getcwd(), "weights", f"ppo_{task_id}.json")
|
| 541 |
if not os.path.exists(path):
|
| 542 |
-
from fastapi import HTTPException
|
| 543 |
raise HTTPException(status_code=404, detail=f"No trained weights found for {task_id}")
|
| 544 |
-
from fastapi.responses import FileResponse
|
| 545 |
return FileResponse(path, media_type='application/json', filename=f"ppo_{task_id}.json")
|
| 546 |
# ββ WebSocket βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 547 |
|
|
|
|
| 263 |
|
| 264 |
# ββ Startup / shutdown ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 265 |
|
| 266 |
+
def _restore_pristine_weights():
|
| 267 |
+
"""
|
| 268 |
+
On HF Spaces, the filesystem cache persists across rebuilds.
|
| 269 |
+
Old trained weights survive and override repo weights.
|
| 270 |
+
Fix: copy the pristine repo weights (saved during Docker build)
|
| 271 |
+
back into the working weights/ directory on every startup.
|
| 272 |
+
"""
|
| 273 |
+
import shutil
|
| 274 |
+
pristine_dir = os.path.join(_project_root if _project_root else os.getcwd(), "weights_pristine")
|
| 275 |
+
weights_dir = os.path.join(_project_root if _project_root else os.getcwd(), "weights")
|
| 276 |
+
|
| 277 |
+
if not os.path.exists(pristine_dir):
|
| 278 |
+
print(" [STARTUP] No pristine weights found, skipping restore.")
|
| 279 |
+
return
|
| 280 |
+
|
| 281 |
+
os.makedirs(weights_dir, exist_ok=True)
|
| 282 |
+
for f in os.listdir(pristine_dir):
|
| 283 |
+
if f.startswith("ppo_") and f.endswith(".json"):
|
| 284 |
+
src = os.path.join(pristine_dir, f)
|
| 285 |
+
dst = os.path.join(weights_dir, f)
|
| 286 |
+
shutil.copy2(src, dst)
|
| 287 |
+
print(f" [STARTUP] Restored pristine weights: {f}")
|
| 288 |
+
|
| 289 |
+
|
| 290 |
@app.on_event("startup")
|
| 291 |
async def startup():
|
| 292 |
global env, _loop_task
|
| 293 |
|
| 294 |
+
# Restore repo-committed weights, overriding any stale HF cache
|
| 295 |
+
_restore_pristine_weights()
|
| 296 |
+
|
| 297 |
env = AdaptiveAlertTriageEnv(task_id="hard")
|
| 298 |
env.real_alerts_queue = deque(maxlen=50)
|
| 299 |
env.reset() # β FIX 1: immediately populate env.alerts
|
|
|
|
| 563 |
|
| 564 |
@app.get("/agent/weights/{task_id}")
|
| 565 |
async def download_weights(task_id: str):
|
| 566 |
+
"""Download trained weights for a task."""
|
| 567 |
+
from fastapi import HTTPException
|
| 568 |
path = os.path.join(_project_root if _project_root else os.getcwd(), "weights", f"ppo_{task_id}.json")
|
| 569 |
if not os.path.exists(path):
|
|
|
|
| 570 |
raise HTTPException(status_code=404, detail=f"No trained weights found for {task_id}")
|
|
|
|
| 571 |
return FileResponse(path, media_type='application/json', filename=f"ppo_{task_id}.json")
|
| 572 |
# ββ WebSocket βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 573 |
|