Spaces:
Running on Zero
Running on Zero
John Ho Claude Fable 5.1 commited on
Commit Β·
8557aff
1
Parent(s): 0a42a43
Set per-event Gradio concurrency limits and ZeroGPU queue size
Browse files- detect (ZeroGPU @spaces.GPU): concurrency_limit=2 β each call forks its
own worker/GPU, so VRAM isn't shared; higher mostly waits on the pool and
burns quota faster
- annotate (.change() calling the pilbox Space): concurrency_limit=4 β
network-bound, requests overlap; at the default of 1 it choked after
every detection
- demo.queue(max_size=12) β ZeroGPU otherwise forces max_size=1, so a
second waiting request got HTTP 503 "Queue is full"
- Document the limits in CLAUDE.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CLAUDE.md
CHANGED
|
@@ -20,3 +20,4 @@ Gradio launches with `mcp_server=True` (exposes an MCP endpoint) and `app_kwargs
|
|
| 20 |
- Loads `vikhyatk/moondream2` at revision `2025-04-14` with `trust_remote_code=True`. Pinning the revision is intentional β the model repo changes its API surface across revisions, so bumping it can break `model.point(...)` / `model.detect(...)` return shapes.
|
| 21 |
- `@spaces.GPU(duration=30)` decorators are HF Spaces ZeroGPU directives β they only activate on the Space; locally they are no-ops requiring a CUDA device (the `device_map={"": "cuda"}` hard-codes GPU). Local CPU runs need that removed.
|
| 22 |
- `detect()` returns the inner list (`["points"]` or `["objects"]`) rather than the full dict β callers (including the MCP tool surface) depend on that shape.
|
|
|
|
|
|
| 20 |
- Loads `vikhyatk/moondream2` at revision `2025-04-14` with `trust_remote_code=True`. Pinning the revision is intentional β the model repo changes its API surface across revisions, so bumping it can break `model.point(...)` / `model.detect(...)` return shapes.
|
| 21 |
- `@spaces.GPU(duration=30)` decorators are HF Spaces ZeroGPU directives β they only activate on the Space; locally they are no-ops requiring a CUDA device (the `device_map={"": "cuda"}` hard-codes GPU). Local CPU runs need that removed.
|
| 22 |
- `detect()` returns the inner list (`["points"]` or `["objects"]`) rather than the full dict β callers (including the MCP tool surface) depend on that shape.
|
| 23 |
+
- Concurrency (Gradio queue): `detect` runs at most 2 calls at once (`concurrency_limit=2` on the Interface; ZeroGPU forks a worker per call), the pilbox `annotate` `.change()` event at most 4, and `demo.queue(max_size=12)` caps waiters (ZeroGPU otherwise forces `max_size=1`, so a second waiter gets a 503 "Queue is full"). Limits are per event; work inside a single request is still sequential.
|
app.py
CHANGED
|
@@ -118,6 +118,8 @@ demo = gr.Interface(
|
|
| 118 |
),
|
| 119 |
],
|
| 120 |
outputs=gr.JSON(label="Output JSON"),
|
|
|
|
|
|
|
| 121 |
)
|
| 122 |
with demo, demo.output_components[0].parent: # render inside the output column
|
| 123 |
demo.output_components[0].change(
|
|
@@ -125,7 +127,10 @@ with demo, demo.output_components[0].parent: # render inside the output column
|
|
| 125 |
[demo.input_components[0], demo.output_components[0], demo.input_components[2]],
|
| 126 |
gr.Image(label="Annotated Image"),
|
| 127 |
api_name=False,
|
|
|
|
|
|
|
| 128 |
)
|
|
|
|
| 129 |
demo.launch(
|
| 130 |
mcp_server=True, app_kwargs={"docs_url": "/docs"} # add FastAPI Swagger API Docs
|
| 131 |
)
|
|
|
|
| 118 |
),
|
| 119 |
],
|
| 120 |
outputs=gr.JSON(label="Output JSON"),
|
| 121 |
+
# ZeroGPU: each call forks its own worker/GPU (no shared VRAM); higher just waits on the pool and burns quota faster
|
| 122 |
+
concurrency_limit=2,
|
| 123 |
)
|
| 124 |
with demo, demo.output_components[0].parent: # render inside the output column
|
| 125 |
demo.output_components[0].change(
|
|
|
|
| 127 |
[demo.input_components[0], demo.output_components[0], demo.input_components[2]],
|
| 128 |
gr.Image(label="Annotated Image"),
|
| 129 |
api_name=False,
|
| 130 |
+
# network-bound call to the pilbox Space: requests overlap; at 1 this would choke after every detection
|
| 131 |
+
concurrency_limit=4,
|
| 132 |
)
|
| 133 |
+
demo.queue(max_size=12) # ZeroGPU forces max_size=1 otherwise -> 2nd waiter gets HTTP 503 "Queue is full"; ~2x sum of limits
|
| 134 |
demo.launch(
|
| 135 |
mcp_server=True, app_kwargs={"docs_url": "/docs"} # add FastAPI Swagger API Docs
|
| 136 |
)
|