Spaces:
Running on Zero
Running on Zero
Bobby commited on
Commit Β·
3aac0a4
1
Parent(s): 2fa74f6
Restart Crowd Counter hourly
Browse files
AGENTS.md
CHANGED
|
@@ -7,6 +7,7 @@ Type: code
|
|
| 7 |
- Structure: `app.py` (UI + ZeroGPU handler), `count.py` (model build/inference/tiling/overlay), `PET/` (patched model code), `weights/` (git-lfs).
|
| 8 |
- Rules: this Space is Gradio 6 β `theme`/`css`/`js`/`head` go on `demo.launch()`, NOT `gr.Blocks()` (Gradio 6 moved them). UI must mirror the sibling Spaces' design language (interior-ai-designer is the reference): Markdown hero "# π₯ ... by [SkyeBrowse]", sponsor banner, inter-app nav cluster, forceLight JS, link-rewrite JS, JSON-LD + canonical head, SEO footer.
|
| 9 |
- `@spaces.GPU(duration=7)` β Bobby raised the cap from 5s (2026-07-03) so the two-grid ensemble completes on large drone stills; ZeroGPU quota charges actual seconds used, not the reservation, so typical 2-3s runs cost the same.
|
|
|
|
| 10 |
- Always LIGHT mode on every host (Bobby 2026-07-02): enforced by the `_force_light_theme` FastAPI middleware (307 `/` β `/?__theme=light` for Accept: text/html; relative Location; probes get 200). Gradio 6's CSR frontend does NOT execute `launch(js=...)`/`head=` scripts, so the sibling-style client-side redirect never runs β do not rely on custom_js for anything load-bearing in this repo.
|
| 11 |
- Embedding is restricted through the `Content-Security-Policy: frame-ancestors` response header in `_force_light_theme`: `https://skyebrowse.com`, `https://*.skyebrowse.com`, plus `http://localhost:8080` for local webapp development.
|
| 12 |
- Successful user uploads save the original and first counted overlay to the configured Google Drive folder through `drive_storage.py`; threshold recounts and bundled examples do not create duplicate Drive files. Drive saving is asynchronous and best-effort so storage failures never break inference.
|
|
|
|
| 7 |
- Structure: `app.py` (UI + ZeroGPU handler), `count.py` (model build/inference/tiling/overlay), `PET/` (patched model code), `weights/` (git-lfs).
|
| 8 |
- Rules: this Space is Gradio 6 β `theme`/`css`/`js`/`head` go on `demo.launch()`, NOT `gr.Blocks()` (Gradio 6 moved them). UI must mirror the sibling Spaces' design language (interior-ai-designer is the reference): Markdown hero "# π₯ ... by [SkyeBrowse]", sponsor banner, inter-app nav cluster, forceLight JS, link-rewrite JS, JSON-LD + canonical head, SEO footer.
|
| 9 |
- `@spaces.GPU(duration=7)` β Bobby raised the cap from 5s (2026-07-03) so the two-grid ensemble completes on large drone stills; ZeroGPU quota charges actual seconds used, not the reservation, so typical 2-3s runs cost the same.
|
| 10 |
+
- The Space self-restarts after one hour of container uptime, matching 3D AI and Anime AI; the external five-minute watchdog still handles `RUNTIME_ERROR` when the container cannot run its own restart thread.
|
| 11 |
- Always LIGHT mode on every host (Bobby 2026-07-02): enforced by the `_force_light_theme` FastAPI middleware (307 `/` β `/?__theme=light` for Accept: text/html; relative Location; probes get 200). Gradio 6's CSR frontend does NOT execute `launch(js=...)`/`head=` scripts, so the sibling-style client-side redirect never runs β do not rely on custom_js for anything load-bearing in this repo.
|
| 12 |
- Embedding is restricted through the `Content-Security-Policy: frame-ancestors` response header in `_force_light_theme`: `https://skyebrowse.com`, `https://*.skyebrowse.com`, plus `http://localhost:8080` for local webapp development.
|
| 13 |
- Successful user uploads save the original and first counted overlay to the configured Google Drive folder through `drive_storage.py`; threshold recounts and bundled examples do not create duplicate Drive files. Drive saving is asynchronous and best-effort so storage failures never break inference.
|
app.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
import json
|
| 2 |
import os
|
|
|
|
|
|
|
| 3 |
|
| 4 |
os.environ.setdefault("PYTORCH_ENABLE_MPS_FALLBACK", "1")
|
| 5 |
|
|
@@ -10,6 +12,7 @@ import gradio as gr
|
|
| 10 |
import gradio.route_utils
|
| 11 |
import spaces
|
| 12 |
import torch
|
|
|
|
| 13 |
from PIL import Image
|
| 14 |
from pillow_heif import register_heif_opener
|
| 15 |
from starlette.middleware import Middleware
|
|
@@ -69,6 +72,25 @@ async def _force_light_theme(request, call_next):
|
|
| 69 |
|
| 70 |
force_light_middleware = Middleware(BaseHTTPMiddleware, dispatch=_force_light_theme)
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
TILE = 768
|
| 73 |
OVERLAP = 192
|
| 74 |
UPSCALE = 1.0
|
|
|
|
| 1 |
import json
|
| 2 |
import os
|
| 3 |
+
import threading
|
| 4 |
+
import time
|
| 5 |
|
| 6 |
os.environ.setdefault("PYTORCH_ENABLE_MPS_FALLBACK", "1")
|
| 7 |
|
|
|
|
| 12 |
import gradio.route_utils
|
| 13 |
import spaces
|
| 14 |
import torch
|
| 15 |
+
from huggingface_hub import HfApi
|
| 16 |
from PIL import Image
|
| 17 |
from pillow_heif import register_heif_opener
|
| 18 |
from starlette.middleware import Middleware
|
|
|
|
| 72 |
|
| 73 |
force_light_middleware = Middleware(BaseHTTPMiddleware, dispatch=_force_light_theme)
|
| 74 |
|
| 75 |
+
RESTART_INTERVAL_SECONDS = 3600
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _restart_space_after_interval(space_id):
|
| 79 |
+
time.sleep(RESTART_INTERVAL_SECONDS)
|
| 80 |
+
try:
|
| 81 |
+
HfApi().restart_space(space_id)
|
| 82 |
+
except Exception as exc:
|
| 83 |
+
print(f"Auto-restart failed: {exc}", flush=True)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
space_id = os.getenv("SPACE_ID")
|
| 87 |
+
if space_id:
|
| 88 |
+
threading.Thread(
|
| 89 |
+
target=_restart_space_after_interval,
|
| 90 |
+
args=(space_id,),
|
| 91 |
+
daemon=True,
|
| 92 |
+
).start()
|
| 93 |
+
|
| 94 |
TILE = 768
|
| 95 |
OVERLAP = 192
|
| 96 |
UPSCALE = 1.0
|