Spaces:
Sleeping
Sleeping
Restore real app (Blocks + mount + uvicorn 7860); space now public
Browse files
app.py
CHANGED
|
@@ -1,138 +1,57 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
import os
|
| 4 |
import gradio as gr
|
| 5 |
|
|
|
|
|
|
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
@spaces.GPU(duration=10)
|
| 8 |
def _gpu_probe():
|
| 9 |
return None
|
| 10 |
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
demo.load(fn=_gpu_probe)
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
def _fmt_ino():
|
| 18 |
-
ino = {}
|
| 19 |
-
for pid in os.listdir("/proc"):
|
| 20 |
-
if not pid.isdigit():
|
| 21 |
-
continue
|
| 22 |
-
try:
|
| 23 |
-
for fd in os.listdir(f"/proc/{pid}/fd"):
|
| 24 |
-
try:
|
| 25 |
-
t = os.readlink(f"/proc/{pid}/fd/{fd}")
|
| 26 |
-
except OSError:
|
| 27 |
-
continue
|
| 28 |
-
if t.startswith("socket:["):
|
| 29 |
-
ino[t[8:-1]] = pid
|
| 30 |
-
except OSError:
|
| 31 |
-
continue
|
| 32 |
-
return ino
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
def _procinfo(pid):
|
| 36 |
-
try:
|
| 37 |
-
with open(f"/proc/{pid}/comm") as f:
|
| 38 |
-
comm = f.read().strip()
|
| 39 |
-
except OSError:
|
| 40 |
-
return None
|
| 41 |
-
try:
|
| 42 |
-
with open(f"/proc/{pid}/cmdline") as f:
|
| 43 |
-
cmd = f.read().replace("\x00", " ").strip()[:200]
|
| 44 |
-
except OSError:
|
| 45 |
-
cmd = ""
|
| 46 |
-
try:
|
| 47 |
-
with open(f"/proc/{pid}/stat") as f:
|
| 48 |
-
ppid = f.read().split()[3]
|
| 49 |
-
except OSError:
|
| 50 |
-
ppid = "?"
|
| 51 |
-
return f"{pid}:{comm}(pp={ppid})|{cmd}"
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
def _dump_env(pid):
|
| 55 |
-
try:
|
| 56 |
-
with open(f"/proc/{pid}/environ") as f:
|
| 57 |
-
env = f.read().replace("\x00", "\n")
|
| 58 |
-
except OSError:
|
| 59 |
-
return
|
| 60 |
-
picks = {}
|
| 61 |
-
for line in env.splitlines():
|
| 62 |
-
k, _, v = line.partition("=")
|
| 63 |
-
if k in (
|
| 64 |
-
"GRADIO_SSR_MODE", "PORT", "GRADIO_SERVER_PORT", "GRADIO_SERVER_NAME",
|
| 65 |
-
"SPACES_ZERO_GPU", "SPACES_ZERO_DEVICE_API_URL", "ZEROGPU_V2",
|
| 66 |
-
"GRADIO_NODE_PATH", "GRADIO_OFFICIAL_EXAMPLE", "SSH_CONNECTION",
|
| 67 |
-
):
|
| 68 |
-
picks[k] = v
|
| 69 |
-
print(f"DIAGENV{pid} " + " ".join(f"{k}={v}" for k, v in picks.items()))
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
def _dump_env_diff():
|
| 73 |
try:
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
|
|
|
| 82 |
pass
|
| 83 |
|
| 84 |
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
out = []
|
| 89 |
-
for proto in ("/proc/net/tcp", "/proc/net/tcp6"):
|
| 90 |
-
try:
|
| 91 |
-
with open(proto) as f:
|
| 92 |
-
next(f)
|
| 93 |
-
for line in f:
|
| 94 |
-
p = line.split()
|
| 95 |
-
if len(p) < 10 or p[3] != "0A":
|
| 96 |
-
continue
|
| 97 |
-
ip_hex, port_hex = p[1].split(":")
|
| 98 |
-
af = sk.AF_INET6 if proto.endswith("6") else sk.AF_INET
|
| 99 |
-
ip = sk.inet_ntop(af, bytes.fromhex(ip_hex))
|
| 100 |
-
port = int(port_hex, 16)
|
| 101 |
-
out.append((ip, port, ino.get(p[9], "?")))
|
| 102 |
-
except OSError:
|
| 103 |
-
continue
|
| 104 |
-
return out
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
def _dump():
|
| 108 |
-
print("DIAGENV " + " ".join(
|
| 109 |
-
f"{k}={os.environ.get(k)}" for k in (
|
| 110 |
-
"GRADIO_SSR_MODE", "PORT", "GRADIO_SERVER_PORT",
|
| 111 |
-
"GRADIO_SERVER_NAME", "GRADIO_NODE_PATH", "SPACES_ZERO_GPU",
|
| 112 |
-
"SPACES_ZERO_DEVICE_API_URL", "ZEROGPU_V2",
|
| 113 |
-
"GRADIO_NUM_WORKERS", "NODE_PATH", "HOME",
|
| 114 |
-
)
|
| 115 |
-
))
|
| 116 |
-
print("DIAGPROC " + " | ".join(x for x in (
|
| 117 |
-
_procinfo(p) for p in ("1", "2", "224", "239", "7860")
|
| 118 |
-
) if x))
|
| 119 |
-
_dump_env("1")
|
| 120 |
-
_dump_env("224")
|
| 121 |
-
print("DIAGL " + " | ".join(f"{ip}:{port}={owner}" for ip, port, owner in _listeners()))
|
| 122 |
-
|
| 123 |
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
-
|
| 127 |
-
|
| 128 |
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
f"{ip}:{port}={owner}" for ip, port, owner in _listeners()
|
| 133 |
-
))
|
| 134 |
-
if os.path.exists("/proc/224"):
|
| 135 |
-
print("DIAG224 alive after 20s")
|
| 136 |
-
else:
|
| 137 |
-
print("DIAG224 EXITED")
|
| 138 |
-
time.sleep(3600)
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
HF Playground — code-driven model playground.
|
| 3 |
+
Enter any HuggingFace model ID in a code template and run.
|
| 4 |
+
"""
|
| 5 |
+
import spaces # MUST be first — signals ZeroGPU infrastructure
|
| 6 |
+
|
| 7 |
+
import sys
|
| 8 |
+
import asyncio
|
| 9 |
|
|
|
|
| 10 |
import gradio as gr
|
| 11 |
|
| 12 |
+
from api import build_fastapi_app
|
| 13 |
+
from ui import build_app, theme, CSS
|
| 14 |
|
| 15 |
+
# ZeroGPU startup probe. The runtime scans Gradio's *registered event handlers*
|
| 16 |
+
# for a @spaces.GPU-marked function and refuses to start if none is found, so this
|
| 17 |
+
# probe is wired to demo.load() below. The real work (run_custom_code) stays
|
| 18 |
+
# undecorated so it runs in-process — models are CPU-bound and the sandbox needs
|
| 19 |
+
# threads + queues that would break inside a forked ZeroGPU worker.
|
| 20 |
@spaces.GPU(duration=10)
|
| 21 |
def _gpu_probe():
|
| 22 |
return None
|
| 23 |
|
| 24 |
|
| 25 |
+
# Python 3.10 asyncio cleanup fix: suppress "Invalid file descriptor: -1" on shutdown
|
| 26 |
+
if sys.version_info >= (3, 10) and sys.platform == 'linux':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
try:
|
| 28 |
+
_cls = asyncio.selector_events.BaseSelectorEventLoop
|
| 29 |
+
_orig = _cls._close_self_pipe
|
| 30 |
+
def _safe_close_self_pipe(self):
|
| 31 |
+
try:
|
| 32 |
+
_orig(self)
|
| 33 |
+
except ValueError:
|
| 34 |
+
pass
|
| 35 |
+
_cls._close_self_pipe = _safe_close_self_pipe
|
| 36 |
+
except Exception:
|
| 37 |
pass
|
| 38 |
|
| 39 |
|
| 40 |
+
with gr.Blocks(title="HF Model Playground") as demo:
|
| 41 |
+
build_app()
|
| 42 |
+
demo.load(fn=_gpu_probe, trigger_mode="once")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
# ZeroGPU client registration happens on the first Blocks.launch() call
|
| 45 |
+
# (spaces.zero wraps gr.Blocks.launch to send the startup report to the device
|
| 46 |
+
# API). Launch once on a throwaway port to trigger that registration, then
|
| 47 |
+
# immediately close it. The real server starts below via uvicorn on 7860 and
|
| 48 |
+
# serves both the Gradio UI and the OpenAI-compatible /v1 routes.
|
| 49 |
+
demo.launch(prevent_thread_lock=True, server_name=None, server_port=8000, quiet=True)
|
| 50 |
+
demo.close()
|
| 51 |
|
| 52 |
+
fastapi_app = build_fastapi_app()
|
| 53 |
+
app = gr.mount_gradio_app(fastapi_app, demo, path="/", theme=theme, css=CSS)
|
| 54 |
|
| 55 |
+
if __name__ == "__main__":
|
| 56 |
+
import uvicorn
|
| 57 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|