atakan Claude Sonnet 5 commited on
Commit
d9203b7
·
1 Parent(s): f950fd2

fix: Launch the ZeroGPU probe Gradio app on its own port, not mounted

Browse files

gr.mount_gradio_app added the demo's routes to our own FastAPI app, but
Gradio still spun up its own server components on the same public port
when the app started -- colliding with our own uvicorn.run() and
crashing on bind with "address already in use" right after startup
completed. Launching the probe demo separately on an internal port
(server_port+1, prevent_thread_lock=True) avoids the collision; the
real app is still the only thing on the public port.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +10 -11
app.py CHANGED
@@ -274,15 +274,15 @@ async def chat_endpoint(req: ChatRequest) -> ChatResponse:
274
  )
275
 
276
 
277
- # A minimal Gradio Blocks app is mounted (at a sub-path, not "/") purely so
278
- # this Space is recognized as a Gradio SDK app -- required for ZeroGPU
279
- # hardware. The real UI is still served by our own FastAPI routes above.
280
- #
281
- # ZeroGPU's startup check only registers @spaces.GPU functions that are
282
- # wired to an actual Gradio event handler -- a bare decorated function that's
283
- # only ever called from a FastAPI route isn't enough and fails startup with
284
- # "No @spaces.GPU function detected". A hidden button bound to the same
285
- # function used by the real endpoints satisfies that check.
286
  _gpu_demo = gr.Blocks()
287
  with _gpu_demo:
288
  gr.Markdown("ControlAI is running. Visit the Space's root URL for the full app.")
@@ -291,14 +291,13 @@ with _gpu_demo:
291
  _probe_btn = gr.Button(visible=False)
292
  _probe_btn.click(fn=_zerogpu_registration_probe, inputs=_probe_in, outputs=_probe_out)
293
 
294
- app = gr.mount_gradio_app(app, _gpu_demo, path="/gradio")
295
-
296
 
297
  def main() -> None:
298
  import uvicorn
299
 
300
  if os.environ.get("SPACE_ID"):
301
  port = int(os.environ.get("PORT", 7860))
 
302
  print(f"ControlAI Web UI running on Hugging Face Spaces (port {port})...")
303
  uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")
304
  return
 
274
  )
275
 
276
 
277
+ # A minimal Gradio Blocks app exists purely so this Space is recognized as a
278
+ # Gradio SDK app -- required for ZeroGPU hardware -- and so the @spaces.GPU
279
+ # registration probe below is wired to a real Gradio event handler ("No
280
+ # @spaces.GPU function detected" otherwise). It is launched on its own
281
+ # internal port rather than mounted into our FastAPI app: mounting it and
282
+ # then binding our own uvicorn to the same public port collided with
283
+ # Gradio's own server startup ("address already in use"). The real UI and
284
+ # API are still served entirely by our own FastAPI routes above, on the
285
+ # public port.
286
  _gpu_demo = gr.Blocks()
287
  with _gpu_demo:
288
  gr.Markdown("ControlAI is running. Visit the Space's root URL for the full app.")
 
291
  _probe_btn = gr.Button(visible=False)
292
  _probe_btn.click(fn=_zerogpu_registration_probe, inputs=_probe_in, outputs=_probe_out)
293
 
 
 
294
 
295
  def main() -> None:
296
  import uvicorn
297
 
298
  if os.environ.get("SPACE_ID"):
299
  port = int(os.environ.get("PORT", 7860))
300
+ _gpu_demo.launch(server_name="0.0.0.0", server_port=port + 1, prevent_thread_lock=True, show_error=False, quiet=True)
301
  print(f"ControlAI Web UI running on Hugging Face Spaces (port {port})...")
302
  uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")
303
  return