SynLayers commited on
Commit
fbdaf23
·
verified ·
1 Parent(s): 4980a79

Upload demo/app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. demo/app.py +101 -31
demo/app.py CHANGED
@@ -4,6 +4,22 @@ import os
4
  import sys
5
  from pathlib import Path
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import gradio as gr
8
  import torch
9
 
@@ -32,6 +48,20 @@ DEFAULT_EXAMPLE_DIR = Path(
32
  )
33
 
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def list_example_images(limit: int = 6) -> list[list[str]]:
36
  if not DEFAULT_EXAMPLE_DIR.exists():
37
  return []
@@ -63,36 +93,83 @@ def get_gpu_name() -> str:
63
  return f"Unavailable ({exc})"
64
 
65
 
 
 
 
 
 
 
 
 
 
 
66
  def get_runtime_status_markdown() -> str:
67
  accelerator = os.environ.get("ACCELERATOR", "unknown")
68
  space_id = os.environ.get("SPACE_ID", "local")
69
  model_repo = os.environ.get("SYNLAYERS_MODEL_REPO", "(unset)")
70
- cuda_available = torch.cuda.is_available()
71
-
72
- lines = [
73
- "## Runtime Status",
74
- f"- `SPACE_ID`: `{space_id}`",
75
- f"- `ACCELERATOR`: `{accelerator}`",
76
- f"- `CUDA available`: `{cuda_available}`",
77
- f"- `GPU device`: `{get_gpu_name()}`",
78
- f"- `SYNLAYERS_MODEL_REPO`: `{model_repo}`",
79
- "",
80
- ]
81
-
82
- if accelerator == "none" or not cuda_available:
83
  lines.extend(
84
  [
85
- "This Space is not currently running with a usable CUDA GPU.",
86
- "The GPU type must be chosen by the Space owner in Hugging Face `Settings -> Hardware`.",
87
- "Visitors cannot switch GPUs from inside the Gradio app.",
 
 
 
 
 
 
88
  ]
89
  )
90
  else:
91
- lines.append("The CUDA runtime is available and the full SynLayers pipeline can run here.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  return "\n".join(lines)
94
 
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def run_demo(
97
  image_path: str,
98
  sample_name: str,
@@ -102,18 +179,12 @@ def run_demo(
102
  if not image_path:
103
  raise gr.Error("Please upload an input image first.")
104
 
105
- seed = int(seed_value) if seed_value >= 0 else None
106
-
107
  try:
108
- result = run_real_world_pipeline(
109
  image_path=image_path,
110
- sample_name=sample_name or None,
111
- work_dir=DEFAULT_WORK_DIR,
112
- bbox_model=DEFAULT_BBOX_MODEL,
113
- config_path=DEFAULT_REAL_CONFIG_PATH,
114
- max_new_tokens=int(max_new_tokens),
115
- seed=seed,
116
- run_name=DEFAULT_RUN_NAME,
117
  )
118
  except Exception as exc:
119
  raise gr.Error(str(exc)) from exc
@@ -139,11 +210,10 @@ with gr.Blocks(title="SynLayers Real-World Demo") as demo:
139
  1. VLM for whole-caption + bounding-box detection
140
  2. SynLayers real-image layer decomposition
141
 
142
- This Space is intended to run on GPU hardware. The first request may take time
143
- while model assets are loaded from Hugging Face.
144
 
145
- GPU hardware is selected in the Hugging Face Space settings by the owner,
146
- not from inside this app.
147
  """
148
  )
149
  runtime_status = gr.Markdown(get_runtime_status_markdown())
 
4
  import sys
5
  from pathlib import Path
6
 
7
+ try:
8
+ import spaces
9
+ except ImportError:
10
+ class _SpacesCompat:
11
+ @staticmethod
12
+ def GPU(*decorator_args, **decorator_kwargs):
13
+ if decorator_args and callable(decorator_args[0]) and len(decorator_args) == 1 and not decorator_kwargs:
14
+ return decorator_args[0]
15
+
16
+ def decorator(fn):
17
+ return fn
18
+
19
+ return decorator
20
+
21
+ spaces = _SpacesCompat()
22
+
23
  import gradio as gr
24
  import torch
25
 
 
48
  )
49
 
50
 
51
+ def read_int_env(name: str, default: int) -> int:
52
+ raw = os.environ.get(name)
53
+ if raw is None:
54
+ return default
55
+ try:
56
+ return int(raw)
57
+ except ValueError:
58
+ return default
59
+
60
+
61
+ ZERO_GPU_SIZE = (os.environ.get("SYNLAYERS_ZERO_GPU_SIZE", "large").strip() or "large").lower()
62
+ ZERO_GPU_DURATION = max(60, read_int_env("SYNLAYERS_ZERO_GPU_DURATION", 900))
63
+
64
+
65
  def list_example_images(limit: int = 6) -> list[list[str]]:
66
  if not DEFAULT_EXAMPLE_DIR.exists():
67
  return []
 
93
  return f"Unavailable ({exc})"
94
 
95
 
96
+ def is_zero_gpu_space() -> bool:
97
+ accelerator = os.environ.get("ACCELERATOR", "").lower()
98
+ return (
99
+ os.environ.get("ZEROGPU_V2", "").lower() == "true"
100
+ or os.environ.get("ZERO_GPU_PATCH_TORCH_DEVICE") == "1"
101
+ or accelerator == "zerogpu"
102
+ or accelerator.startswith("zero")
103
+ )
104
+
105
+
106
  def get_runtime_status_markdown() -> str:
107
  accelerator = os.environ.get("ACCELERATOR", "unknown")
108
  space_id = os.environ.get("SPACE_ID", "local")
109
  model_repo = os.environ.get("SYNLAYERS_MODEL_REPO", "(unset)")
110
+ zero_gpu_enabled = is_zero_gpu_space()
111
+
112
+ lines = ["## Runtime Status", f"- `SPACE_ID`: `{space_id}`", f"- `ACCELERATOR`: `{accelerator}`"]
113
+
114
+ if zero_gpu_enabled:
 
 
 
 
 
 
 
 
115
  lines.extend(
116
  [
117
+ f"- `ZeroGPU mode`: `True`",
118
+ f"- `Requested GPU size`: `{ZERO_GPU_SIZE}`",
119
+ f"- `Requested max duration`: `{ZERO_GPU_DURATION}` seconds",
120
+ f"- `SYNLAYERS_MODEL_REPO`: `{model_repo}`",
121
+ f"- `CUDA probe outside @spaces.GPU`: `{torch.cuda.is_available()}`",
122
+ "",
123
+ "This Space is configured for Hugging Face ZeroGPU.",
124
+ "A shared H200 GPU is requested on demand when you click `Run Full Pipeline`.",
125
+ "Queueing and quota are managed by Hugging Face ZeroGPU, not by an in-app GPU selector.",
126
  ]
127
  )
128
  else:
129
+ cuda_available = torch.cuda.is_available()
130
+ lines.extend(
131
+ [
132
+ f"- `CUDA available`: `{cuda_available}`",
133
+ f"- `GPU device`: `{get_gpu_name()}`",
134
+ f"- `SYNLAYERS_MODEL_REPO`: `{model_repo}`",
135
+ "",
136
+ ]
137
+ )
138
+
139
+ if accelerator == "none" or not cuda_available:
140
+ lines.extend(
141
+ [
142
+ "This Space is not currently running with a usable CUDA GPU.",
143
+ "The GPU type must be chosen by the Space owner in Hugging Face `Settings -> Hardware`.",
144
+ "Visitors cannot switch GPUs from inside the Gradio app.",
145
+ ]
146
+ )
147
+ else:
148
+ lines.append("The CUDA runtime is available and the full SynLayers pipeline can run here.")
149
 
150
  return "\n".join(lines)
151
 
152
 
153
+ @spaces.GPU(duration=ZERO_GPU_DURATION, size=ZERO_GPU_SIZE)
154
+ def run_demo_inference(
155
+ image_path: str,
156
+ sample_name: str,
157
+ max_new_tokens: int,
158
+ seed_value: float,
159
+ ) -> dict:
160
+ seed = int(seed_value) if seed_value >= 0 else None
161
+ return run_real_world_pipeline(
162
+ image_path=image_path,
163
+ sample_name=sample_name or None,
164
+ work_dir=DEFAULT_WORK_DIR,
165
+ bbox_model=DEFAULT_BBOX_MODEL,
166
+ config_path=DEFAULT_REAL_CONFIG_PATH,
167
+ max_new_tokens=int(max_new_tokens),
168
+ seed=seed,
169
+ run_name=DEFAULT_RUN_NAME,
170
+ )
171
+
172
+
173
  def run_demo(
174
  image_path: str,
175
  sample_name: str,
 
179
  if not image_path:
180
  raise gr.Error("Please upload an input image first.")
181
 
 
 
182
  try:
183
+ result = run_demo_inference(
184
  image_path=image_path,
185
+ sample_name=sample_name,
186
+ max_new_tokens=max_new_tokens,
187
+ seed_value=seed_value,
 
 
 
 
188
  )
189
  except Exception as exc:
190
  raise gr.Error(str(exc)) from exc
 
210
  1. VLM for whole-caption + bounding-box detection
211
  2. SynLayers real-image layer decomposition
212
 
213
+ This Space can run either on a dedicated GPU Space or on Hugging Face ZeroGPU.
214
+ The first request may take time while model assets are loaded from Hugging Face.
215
 
216
+ In ZeroGPU mode, a shared GPU is requested only while inference is running.
 
217
  """
218
  )
219
  runtime_status = gr.Markdown(get_runtime_status_markdown())