Jin Zhu commited on
Commit
6beed25
·
1 Parent(s): a71717d
Files changed (3) hide show
  1. README.md +0 -1
  2. requirements.txt +0 -1
  3. src/app.py +10 -60
README.md CHANGED
@@ -7,7 +7,6 @@ sdk_version: 5.31.0
7
  app_file: src/app.py
8
  tags:
9
  - gradio
10
- - zero-gpu
11
  pinned: true
12
  license: apache-2.0
13
  emoji: 🚀
 
7
  app_file: src/app.py
8
  tags:
9
  - gradio
 
10
  pinned: true
11
  license: apache-2.0
12
  emoji: 🚀
requirements.txt CHANGED
@@ -1,6 +1,5 @@
1
  # requirements.txt
2
  gradio==5.31.0
3
- spaces>=0.30.0
4
  pandas==2.3.1
5
  torch==2.8.0
6
  numpy==2.1.3
 
1
  # requirements.txt
2
  gradio==5.31.0
 
3
  pandas==2.3.1
4
  torch==2.8.0
5
  numpy==2.1.3
src/app.py CHANGED
@@ -1,10 +1,9 @@
1
  """
2
  DetectGPTPro — Gradio front end for AdaDetectGPT.
3
 
4
- Migrated from Streamlit so the Space can run on Hugging Face's ZeroGPU
5
- (dynamic, pay-per-call GPU allocation, which is only available to Gradio SDK
6
- Spaces). All detection logic still lives in FineTune/model.py, feedback.py,
7
- and stats.py, unchanged — this file only rebuilds the UI layer.
8
 
9
  See streamlit_backup/ (repo root) for the original Streamlit app.
10
  """
@@ -34,45 +33,18 @@ from FineTune.model import ComputeStat
34
  from feedback import FeedbackManager
35
  from stats import StatsManager
36
 
37
- # -----------------------------------------------------------------------
38
- # ZeroGPU support
39
- # -----------------------------------------------------------------------
40
- # `spaces` is preinstalled on every Gradio-SDK HF Space and is what lets a
41
- # Space request/release a GPU per call. It's a no-op outside ZeroGPU
42
- # hardware, but it isn't installed at all when running locally without the
43
- # `spaces` package — so fall back to a plain no-op decorator in that case.
44
- try:
45
- import spaces
46
-
47
- ZERO_GPU_AVAILABLE = True
48
- except ImportError:
49
- ZERO_GPU_AVAILABLE = False
50
-
51
- class _SpacesShim:
52
- """Stand-in for the `spaces` module when developing outside HF Spaces."""
53
-
54
- @staticmethod
55
- def GPU(func=None, **_kwargs):
56
- if func is not None:
57
- return func
58
- return lambda f: f
59
-
60
- spaces = _SpacesShim()
61
-
62
 
63
  def resolve_device() -> str:
64
  """Pick an inference device, in priority order:
65
 
66
  1. `MODEL_DEVICE` env var, if the user wants to force one.
67
- 2. 'cuda' on a ZeroGPU Space (the `spaces` package manages the virtual device).
68
- 3. 'cpu' on any other HF Space (e.g. a plain CPU-tier deployment).
69
- 4. 'mps' / 'cpu' for local development on Apple Silicon / everything else.
70
  """
71
  explicit = os.environ.get("MODEL_DEVICE")
72
  if explicit:
73
  return explicit
74
- if ZERO_GPU_AVAILABLE and os.environ.get("SPACE_ID"):
75
- return "cuda"
76
  if os.environ.get("SPACE_ID"):
77
  return "cpu"
78
  try:
@@ -115,8 +87,7 @@ FEEDBACK_DATASET_ID = os.environ.get("FEEDBACK_DATASET_ID", f"{ACCOUNT_NAME}/use
115
  # process startup, same lifetime as st.cache_resource gave us before).
116
  # -----------------------------------------------------------------------
117
  def load_model():
118
- print(f"🔄 Loading model on device='{MODEL_CONFIG['device']}' "
119
- f"(ZeroGPU {'enabled' if ZERO_GPU_AVAILABLE else 'unavailable'})...")
120
  model = ComputeStat.from_pretrained(
121
  MODEL_CONFIG["from_pretrained"],
122
  MODEL_CONFIG["base_model"],
@@ -148,21 +119,10 @@ stats_manager = StatsManager(
148
 
149
 
150
  # -----------------------------------------------------------------------
151
- # Inference — isolated in its own function and GPU-decorated so ZeroGPU
152
- # can allocate a GPU just for the duration of this call and release it
153
- # right after.
154
- #
155
- # `duration` reserves that many seconds of ZeroGPU quota *up front* for
156
- # every call, regardless of how long the call actually takes — so it
157
- # should track real measured inference time, not just be left generous.
158
- # Override with the ZERO_GPU_DURATION env var once you've profiled a
159
- # typical request (Settings on the Space, or locally via `time.time()`
160
- # around `_run_inference`).
161
  # -----------------------------------------------------------------------
162
- ZERO_GPU_DURATION = int(os.environ.get("ZERO_GPU_DURATION", "60"))
163
-
164
-
165
- @spaces.GPU(duration=ZERO_GPU_DURATION)
166
  def _run_inference(text: str, domain: str):
167
  crit, p_value = model.compute_p_value(text, domain)
168
  if hasattr(crit, "item"):
@@ -172,11 +132,6 @@ def _run_inference(text: str, domain: str):
172
  return crit, p_value
173
 
174
 
175
- def _is_zero_gpu_quota_error(exc: Exception) -> bool:
176
- message = str(exc).lower()
177
- return "quota" in message and "gpu" in message
178
-
179
-
180
  def format_conclusion(p_value: float, alpha: float) -> str:
181
  """Build the conclusion as a framed HTML card (rendered inside gr.Markdown,
182
  which passes raw HTML through) so the verdict stands out instead of
@@ -243,11 +198,6 @@ def run_detection(text: str, domain: str, alpha: float):
243
  except gr.Error:
244
  raise
245
  except Exception as e: # noqa: BLE001 — surfaced to the user via gr.Error
246
- if _is_zero_gpu_quota_error(e):
247
- raise gr.Error(
248
- "⏳ This Space's free GPU quota is used up for now — it resets "
249
- "on a rolling basis, so please try again shortly."
250
- )
251
  raise gr.Error(f"Detection failed: {e}")
252
  elapsed_time = time.time() - start_time
253
 
 
1
  """
2
  DetectGPTPro — Gradio front end for AdaDetectGPT.
3
 
4
+ Runs on plain CPU (HF Spaces "CPU basic" tier ZeroGPU requires a PRO
5
+ account). All detection logic still lives in FineTune/model.py,
6
+ feedback.py, and stats.py, unchanged this file only builds the UI layer.
 
7
 
8
  See streamlit_backup/ (repo root) for the original Streamlit app.
9
  """
 
33
  from feedback import FeedbackManager
34
  from stats import StatsManager
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  def resolve_device() -> str:
38
  """Pick an inference device, in priority order:
39
 
40
  1. `MODEL_DEVICE` env var, if the user wants to force one.
41
+ 2. 'cpu' on the Space (this deployment targets HF's free "CPU basic"
42
+ tier ZeroGPU needs a PRO account, so we don't attempt it).
43
+ 3. 'mps' / 'cpu' for local development on Apple Silicon / everything else.
44
  """
45
  explicit = os.environ.get("MODEL_DEVICE")
46
  if explicit:
47
  return explicit
 
 
48
  if os.environ.get("SPACE_ID"):
49
  return "cpu"
50
  try:
 
87
  # process startup, same lifetime as st.cache_resource gave us before).
88
  # -----------------------------------------------------------------------
89
  def load_model():
90
+ print(f"🔄 Loading model on device='{MODEL_CONFIG['device']}'...")
 
91
  model = ComputeStat.from_pretrained(
92
  MODEL_CONFIG["from_pretrained"],
93
  MODEL_CONFIG["base_model"],
 
119
 
120
 
121
  # -----------------------------------------------------------------------
122
+ # Inference — isolated in its own function so it's easy to time and to
123
+ # swap back to a GPU-decorated version later if this ever moves off CPU
124
+ # basic hardware.
 
 
 
 
 
 
 
125
  # -----------------------------------------------------------------------
 
 
 
 
126
  def _run_inference(text: str, domain: str):
127
  crit, p_value = model.compute_p_value(text, domain)
128
  if hasattr(crit, "item"):
 
132
  return crit, p_value
133
 
134
 
 
 
 
 
 
135
  def format_conclusion(p_value: float, alpha: float) -> str:
136
  """Build the conclusion as a framed HTML card (rendered inside gr.Markdown,
137
  which passes raw HTML through) so the verdict stands out instead of
 
198
  except gr.Error:
199
  raise
200
  except Exception as e: # noqa: BLE001 — surfaced to the user via gr.Error
 
 
 
 
 
201
  raise gr.Error(f"Detection failed: {e}")
202
  elapsed_time = time.time() - start_time
203