mlclaw 0.1.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.agents/skills/mlclaw/SKILL.md +70 -18
  2. package/Dockerfile +21 -4
  3. package/README.md +77 -24
  4. package/assets/hf-logo.svg +8 -0
  5. package/assets/hf-tooling/manifest.json +50 -0
  6. package/assets/hf-tooling/skills/hf-cli/SKILL.md +218 -0
  7. package/assets/hf-tooling/skills/hf-mem/SKILL.md +79 -0
  8. package/assets/hf-tooling/skills/huggingface-best/SKILL.md +134 -0
  9. package/assets/hf-tooling/skills/huggingface-datasets/SKILL.md +107 -0
  10. package/assets/hf-tooling/skills/huggingface-gradio/SKILL.md +298 -0
  11. package/assets/hf-tooling/skills/huggingface-gradio/examples.md +613 -0
  12. package/assets/hf-tooling/skills/huggingface-local-models/SKILL.md +113 -0
  13. package/assets/hf-tooling/skills/huggingface-local-models/references/hardware.md +38 -0
  14. package/assets/hf-tooling/skills/huggingface-local-models/references/hub-discovery.md +178 -0
  15. package/assets/hf-tooling/skills/huggingface-local-models/references/quantization.md +256 -0
  16. package/assets/hf-tooling/skills/huggingface-papers/SKILL.md +239 -0
  17. package/assets/hf-tooling/skills/huggingface-spaces/SKILL.md +239 -0
  18. package/assets/hf-tooling/skills/huggingface-spaces/references/buckets.md +89 -0
  19. package/assets/hf-tooling/skills/huggingface-spaces/references/debugging.md +236 -0
  20. package/assets/hf-tooling/skills/huggingface-spaces/references/gradio.md +200 -0
  21. package/assets/hf-tooling/skills/huggingface-spaces/references/grants.md +56 -0
  22. package/assets/hf-tooling/skills/huggingface-spaces/references/inference-providers.md +85 -0
  23. package/assets/hf-tooling/skills/huggingface-spaces/references/known-errors.md +232 -0
  24. package/assets/hf-tooling/skills/huggingface-spaces/references/requirements.md +169 -0
  25. package/assets/hf-tooling/skills/huggingface-spaces/references/zerogpu.md +349 -0
  26. package/assets/hf-tooling/skills/huggingface-tool-builder/SKILL.md +120 -0
  27. package/assets/hf-tooling/skills/huggingface-tool-builder/references/baseline_hf_api.py +57 -0
  28. package/assets/hf-tooling/skills/huggingface-tool-builder/references/baseline_hf_api.sh +40 -0
  29. package/assets/hf-tooling/skills/huggingface-tool-builder/references/baseline_hf_api.tsx +57 -0
  30. package/assets/hf-tooling/skills/huggingface-tool-builder/references/find_models_by_paper.sh +230 -0
  31. package/assets/hf-tooling/skills/huggingface-tool-builder/references/hf_enrich_models.sh +96 -0
  32. package/assets/hf-tooling/skills/huggingface-tool-builder/references/hf_model_card_frontmatter.sh +188 -0
  33. package/assets/hf-tooling/skills/huggingface-tool-builder/references/hf_model_papers_auth.sh +171 -0
  34. package/assets/hf-tooling/skills/huggingface-zerogpu/SKILL.md +289 -0
  35. package/assets/hf-tooling/skills/huggingface-zerogpu/references/concurrency.md +79 -0
  36. package/assets/hf-tooling/skills/huggingface-zerogpu/references/cuda-and-deps.md +66 -0
  37. package/assets/hf-tooling/skills/huggingface-zerogpu/references/how-quota-works.md +74 -0
  38. package/assets/hf-tooling/skills/huggingface-zerogpu/references/how-zerogpu-works.md +50 -0
  39. package/assets/hf-tooling/templates/.agents/mcp/huggingface.json +11 -0
  40. package/assets/hf-tooling/templates/.env.example +5 -0
  41. package/assets/hf-tooling/templates/examples/huggingface/README.md +16 -0
  42. package/assets/hf-tooling/templates/examples/huggingface/bucket-sync.md +19 -0
  43. package/assets/hf-tooling/templates/examples/huggingface/dataset-upload.py +22 -0
  44. package/assets/hf-tooling/templates/examples/huggingface/hf-discover.md +13 -0
  45. package/assets/hf-tooling/templates/examples/huggingface/runtime-inspection.py +9 -0
  46. package/assets/mlclaw-control-ui/assets/index-D2TFes32.js +9 -0
  47. package/assets/mlclaw-control-ui/assets/index-DP72PFuv.css +1 -0
  48. package/assets/mlclaw-control-ui/index.html +13 -0
  49. package/assets/mlclaw.svg +298 -124
  50. package/dist/hf-tooling-seed.js +261 -0
  51. package/dist/mlclaw-space-runtime.js +6746 -3321
  52. package/dist/mlclaw.mjs +428 -178
  53. package/entrypoint.sh +4 -0
  54. package/mlclaw.ps1 +4 -2
  55. package/mlclaw.sh +5 -3
  56. package/openclaw.default.json +1 -0
  57. package/package.json +16 -2
  58. package/space/README.md +32 -2
  59. package/tsconfig.json +3 -2
@@ -0,0 +1,200 @@
1
+ # Gradio for Spaces
2
+
3
+ Patterns and quirks specific to running Gradio inside a Space. Assumes you're already comfortable with stock Gradio components and `gr.Blocks` / `gr.Interface`.
4
+
5
+ For deeper Gradio API guidance — components, layouts, event listeners, chatbots, the Gradio 5→6 migration — use the dedicated `huggingface-gradio` skill. Install it with `hf skills add huggingface-gradio` (add `--claude --global` to also install for Claude Code, user-level).
6
+
7
+ For ZeroGPU-specific decorator + worker semantics, see [`zerogpu.md`](zerogpu.md).
8
+
9
+ ## Themes and layout
10
+
11
+ - Default theme preference: `gr.themes.Citrus()`. Alternatives: `gr.themes.Soft()` or no theme. Pick once and don't over-style.
12
+ - For apps that don't need full-width, constrain with CSS so they're readable on 4K displays:
13
+ ```python
14
+ CSS = """
15
+ #col-container { max-width: 1100px; margin: 0 auto; }
16
+ .dark .gradio-container { color: var(--body-text-color); }
17
+ """
18
+ with gr.Blocks(theme=gr.themes.Citrus(), css=CSS) as demo: ...
19
+ ```
20
+ Always include the `.dark .gradio-container` override with `gr.themes.Citrus()` — without it Citrus's dark mode renders dark text on a dark background (text inherits unset colors). The same fix is harmless (and worth keeping) under other themes.
21
+ - Width-cap with `!important` if Gradio 6's own breakpoints fight you — target `main`, `.gradio-container`, and the inner fillable wrapper, otherwise the width caps but goes flush-left.
22
+
23
+ ## Minimal layout most demos converge to
24
+
25
+ ```python
26
+ with gr.Row():
27
+ prompt = gr.Textbox(show_label=False, placeholder="…", container=False, scale=4)
28
+ run = gr.Button("Run", variant="primary", scale=1)
29
+ output = gr.Image(...)
30
+ with gr.Accordion("Advanced settings", open=False):
31
+ ...
32
+ ```
33
+
34
+ `container=False` on the inline Textbox removes the default outer border for a tighter look.
35
+
36
+ ## `gr.Markdown` for the intro
37
+
38
+ Be succinct. Title, one-line description, a links section. Don't over-explain how it works — that's what the model card is for.
39
+
40
+ ## `gr.Examples`
41
+
42
+ **Add `gr.Examples` whenever it makes sense** (the app takes user input and representative inputs exist). It's the first thing a visitor clicks and it doubles as an instant smoke test. Prefer examples that mirror the **official examples from the original repo / model card** — the prompts, images, and settings the authors showcase — over inventing your own.
43
+
44
+ Keep each example row to the **few variables a user actually changes** (the prompt, the input image). Give the handler **default values for everything else** (steps, guidance, seed, …) so an example row is `["a cat on a windowsill"]`, not a wall of knobs. Design the signature so the interesting inputs come first and the rest default:
45
+
46
+ ```python
47
+ @spaces.GPU(duration=60)
48
+ def generate(prompt, seed=42, steps=28, guidance=5.0): # only `prompt` varies in examples
49
+ ...
50
+
51
+ gr.Examples(
52
+ examples=[
53
+ ["a cat sitting on a windowsill"],
54
+ ["mountains at sunset, photorealistic"],
55
+ ],
56
+ inputs=[prompt], # just the varied inputs; the rest use the handler defaults
57
+ outputs=output,
58
+ fn=generate,
59
+ cache_examples=True,
60
+ cache_mode="lazy",
61
+ )
62
+ ```
63
+
64
+ Why these flags:
65
+
66
+ - `cache_examples=True` makes example clicks instant (no re-inference per visitor).
67
+ - **`cache_mode="lazy"`** — caches on first user click for each example. **Required on ZeroGPU** (Gradio's default on ZeroGPU is already lazy via `GRADIO_CACHE_MODE=lazy`). Eager would pre-run every example at app startup, but ZeroGPU has no GPU attached at startup — it'd fail and burn the creator's daily quota.
68
+ - `cache_examples=True` silently disables `run_on_click` / `run_examples_on_click`. If your app relies on click-only behavior, set `cache_examples=False`.
69
+
70
+ The cache key is the **example row's file path**, not a content hash. Regenerating an asset in place serves the stale cached output forever. If you replace example files, bump a `cache_version` marker or wipe `.gradio/cached_examples/<id>/`.
71
+
72
+ Hot-reload (rung 1) does **not** rebuild the cache. A `cache_version` bump needs a real commit + restart.
73
+
74
+ ## Streaming and generators
75
+
76
+ `gr.Interface(fn=...)` and `.click(fn=...)` both accept generator functions. Each `yield` pushes a new value:
77
+
78
+ ```python
79
+ @spaces.GPU(duration=120)
80
+ def generate(prompt):
81
+ yield gr.update(value=None, label="Starting…")
82
+ for k in range(num_steps):
83
+ yield gr.update(value=preview(k), label=f"Step {k+1}/{num_steps}")
84
+ yield gr.update(value=final, label="Done")
85
+ ```
86
+
87
+ Use `gr.update(label=...)` for status narration — feels like a status line without a separate component.
88
+
89
+ **Caveat**: `gr.Progress(track_tqdm=True)` and `yield` partial outputs fight each other — pick one streaming mechanism.
90
+
91
+ ## Useful UX bits
92
+
93
+ - `progress=gr.Progress(track_tqdm=True)` in the GPU function gives a free tqdm-driven progress bar.
94
+ - Pair a "Randomize seed" checkbox with the seed input, and write the actually-used seed back so users can re-run deterministically:
95
+ ```python
96
+ randomize = gr.Checkbox(label="Randomize seed", value=True)
97
+ seed = gr.Number(label="Seed", value=0, precision=0)
98
+
99
+ @spaces.GPU
100
+ def gen(..., seed, randomize_seed):
101
+ if randomize_seed:
102
+ seed = random.randint(0, 2**31 - 1)
103
+ seed = int(seed)
104
+ yield ..., gr.update(value=seed) # write back into the Seed input
105
+ ...
106
+
107
+ run.click(gen, inputs=[..., seed, randomize], outputs=[..., seed])
108
+ ```
109
+
110
+ ## Custom HTML components
111
+
112
+ Stock Gradio components cover 95% of cases. When they don't, `gr.HTML(...)` lets you build contextual custom UI without leaving the Gradio Space (no need to switch to Docker).
113
+
114
+ Guide: https://www.gradio.app/guides/custom-HTML-components
115
+ Example with a 3D camera-angle picker that makes sense in context: https://huggingface.co/spaces/multimodalart/qwen-image-multiple-angles-3d-camera
116
+
117
+ Don't reach for this if a stock component covers the need.
118
+
119
+ ## Custom frontends — `gr.Server`
120
+
121
+ For fully custom frontends with their own HTML/JS, while keeping Gradio's queue + GPU scheduling:
122
+
123
+ ```python
124
+ from gradio import Server
125
+ from fastapi.responses import HTMLResponse
126
+
127
+ app = Server(title="my-app")
128
+
129
+ @spaces.GPU(duration=60)
130
+ def _run_gpu(prompt): return inference(prompt)
131
+
132
+ @app.api(name="generate", concurrency_limit=1, time_limit=180)
133
+ def generate(prompt: str) -> str:
134
+ return _run_gpu(prompt) # @app.api wraps, doesn't stack with @spaces.GPU
135
+
136
+ @app.get("/", response_class=HTMLResponse)
137
+ async def homepage():
138
+ return open("index.html").read()
139
+
140
+ demo = app # HF runtime expects `demo`
141
+ if __name__ == "__main__":
142
+ demo.launch(ssr_mode=False)
143
+ ```
144
+
145
+ Required for the custom `/` route to actually serve:
146
+
147
+ ```bash
148
+ hf spaces variables add <ns>/<name> --env GRADIO_SSR_MODE=false
149
+ ```
150
+
151
+ `launch(ssr_mode=False)` is ignored on HF — must be the env var.
152
+
153
+ Valid `@app.api` kwargs: `name`, `description`, `concurrency_limit`, `concurrency_id`, `queue`, `batch`, `max_batch_size`, `api_visibility`, `time_limit`, `stream_every`.
154
+
155
+ **Don't stack `@spaces.GPU` and `@app.api`** on the same function — silently breaks request flow. Keep them on separate functions.
156
+
157
+ **Two-ceiling coordination**: both `@spaces.GPU(duration=N)` and `@app.api(time_limit=M)` apply; the lower wins. Set `time_limit` to your max duration across modes — a too-low `time_limit` kills the request even if GPU duration would have allowed it.
158
+
159
+ Hot-reload (rung 1 in [`debugging.md`](debugging.md)) does **not** work with `gr.Server` — always `hf upload` or commit.
160
+
161
+ Reference Space: https://huggingface.co/spaces/huggingface-projects/rf-detr-realtime-webcam
162
+
163
+ ## Slow-startup Gradio (big-model Spaces)
164
+
165
+ For Spaces that take 10–20 min to load weights:
166
+
167
+ - Set `startup_duration_timeout: 1h` in README frontmatter (default 30 min).
168
+ - Disable SSR: `hf spaces variables add <id> --env GRADIO_SSR_MODE=false`. Otherwise the SSR health check times out before the app finishes loading.
169
+
170
+ ## Expose the Space as an MCP server
171
+
172
+ Launch with `demo.launch(mcp_server=True)` (Gradio 5+) so every API endpoint is also exposed as an MCP tool — free, and makes the Space usable by agents. For it to be useful:
173
+
174
+ - **Every API-triggered function needs a docstring and type hints.** Each Gradio event handler is auto-exposed over the API; Gradio turns the signature into the MCP tool's input schema and the docstring into its description. A function without them still works but surfaces as an opaque, unusable tool.
175
+ - Give the important endpoints stable names (`api_name="generate"` on the `.click(...)`, or `@app.api(name=...)`), so tool names don't churn.
176
+ - MCP mode can pull in extra deps (`gradio[mcp]`); if `launch` complains, see the pin note in [`known-errors.md`](known-errors.md).
177
+
178
+ ```python
179
+ @spaces.GPU(duration=60)
180
+ def generate(prompt: str, seed: int = 42) -> str:
181
+ """Generate an image from a text prompt.
182
+
183
+ Args:
184
+ prompt: what to generate.
185
+ seed: RNG seed for reproducibility.
186
+ """
187
+ ...
188
+
189
+ btn.click(generate, inputs=[prompt, seed], outputs=out, api_name="generate")
190
+ demo.launch(mcp_server=True)
191
+ ```
192
+
193
+ ## Don't
194
+
195
+ - `gr.Button(text="X")` — `text=` was removed; use `gr.Button("X")`.
196
+ - `gr.Button(type="button")` — drop the kwarg.
197
+ - `.click(..., _js=share_js)` — renamed to `js=`.
198
+ - `.style(height=...)` — removed in gradio 4+.
199
+ - `gr.ImageMask(brush_color=...)` — kwarg removed.
200
+ - `demo.launch(mcp_server=True)` on gradio 4.x — only valid on 5+.
@@ -0,0 +1,56 @@
1
+ # Community GPU grants
2
+
3
+ When a non-PRO user has a good use case for ZeroGPU (open research demo, hobbyist project, educational tool, institutional showcase) and doesn't want to subscribe, they can request a free community grant from Hugging Face.
4
+
5
+ ## The flow
6
+
7
+ 1. **Build the Space.** Create it as `--flavor cpu-basic` (the user is not PRO, so creating with `--flavor zero-a10g` will fail at `create_repo`). Code the app for ZeroGPU anyway — `import spaces`, `@spaces.GPU`, module-scope `.to("cuda")`. The Space will technically run on CPU until the grant is approved, but it'll be ready to switch over instantly.
8
+
9
+ In this mode you **can't iterate-with-real-inference** before the grant — the CPU Space won't actually run heavy compute. Get the app to BUILD cleanly and `RUNNING` (even if the runtime would OOM on real input), then submit.
10
+
11
+ 2. **Submit a Community Tab discussion** on the Space. Title:
12
+
13
+ ```
14
+ Apply for a GPU community grant: <Personal|Company|Academic> project
15
+ ```
16
+
17
+ Pick the closest fit. Body:
18
+
19
+ ```
20
+ Description of the app: one paragraph on what it does + who it's for.
21
+ Justification: one paragraph on why this should run on ZeroGPU
22
+ (open-source, research, educational, etc.).
23
+ ```
24
+
25
+ If the user didn't give you a justification, a reasonable default is "Non-PRO wants to build a public ZeroGPU app — happy to provide more context if helpful."
26
+
27
+ 3. **Wait.** Open and publicly-facing applications by researchers, tinkerers, and institutions are typically approved. Approval can take days.
28
+
29
+ 4. **Once approved**, the Space is moved to ZeroGPU automatically — no code change needed. The user comes back and you can iterate / refine with real GPU access.
30
+
31
+ ## When to suggest this
32
+
33
+ - User is not on PRO but their use case is a clear fit for ZeroGPU (a public ML demo, not a private tool).
34
+ - The model fits in `large` (≤ 48 GB VRAM at the chosen precision).
35
+
36
+ ## When NOT to suggest this
37
+
38
+ - Private / commercial / closed-source projects — push the user toward PRO instead.
39
+ - The model genuinely needs dedicated paid hardware (huge LLM, vLLM/JAX/ONNX as main model with heavy init) — `canPay=True` users can use paid flavors directly.
40
+ - The user is already PRO — they have ZeroGPU access; no grant needed.
41
+
42
+ ## Posting the request programmatically
43
+
44
+ ```python
45
+ from huggingface_hub import HfApi
46
+
47
+ api = HfApi(token="hf_...")
48
+ api.create_discussion(
49
+ repo_id="<ns>/<space>",
50
+ repo_type="space",
51
+ title="Apply for a GPU community grant: Personal project",
52
+ description="<description and justification>",
53
+ )
54
+ ```
55
+
56
+ The Community Tab must be enabled on the Space (default — keep it on).
@@ -0,0 +1,85 @@
1
+ # Inference Providers — when not to host the model
2
+
3
+ Some Spaces don't need a GPU at all. If the model is available through HF Inference Providers (Cerebras, Fireworks, Together, Replicate, OpenRouter, etc.), the Space can be a thin Gradio shell that proxies to a hosted endpoint:
4
+
5
+ - Zero VRAM, no `@spaces.GPU`, no model download.
6
+ - Works for models too large to fit on ZeroGPU (120B+).
7
+ - Hardware can be `cpu-basic` — no GPU at all.
8
+
9
+ ## When to use this pattern
10
+
11
+ - **Stateless chat or text completion** with a big model.
12
+ - **The user wants a public demo of a frontier-scale model** that obviously doesn't fit on a single 48 GB MIG.
13
+ - **The user wants to ship something fast** without worrying about quantization / sharding.
14
+
15
+ ## When NOT to use this pattern
16
+
17
+ - The model isn't available on any Inference Provider. Check with:
18
+ ```bash
19
+ curl "https://huggingface.co/api/models/<ns>/<repo>?expand[]=inferenceProviderMapping"
20
+ ```
21
+ - The Space needs **custom decoding** (special sampling, tool use, retrieval, anything stateful or interactive across calls).
22
+ - The Space needs **multimodal** beyond what the provider exposes.
23
+ - The user explicitly wants to own the inference stack (model loading, decoding, performance tuning).
24
+
25
+ For those, host the model yourself on ZeroGPU — see [`zerogpu.md`](zerogpu.md).
26
+
27
+ ## Two billing modes
28
+
29
+ Choose based on who pays for inference.
30
+
31
+ ### Mode A — Space creator pays (simple)
32
+
33
+ Set `HF_TOKEN` as a Space secret. The Space uses `InferenceClient` directly. Every visitor's call is billed to the Space creator's account.
34
+
35
+ ```python
36
+ import os, gradio as gr
37
+ from huggingface_hub import InferenceClient
38
+
39
+ client = InferenceClient(api_key=os.environ["HF_TOKEN"], provider="fireworks-ai")
40
+
41
+ def chat(msg, history):
42
+ return client.chat_completion(
43
+ model="<org>/<model>",
44
+ messages=[*history, {"role": "user", "content": msg}],
45
+ max_tokens=512,
46
+ ).choices[0].message.content
47
+
48
+ gr.ChatInterface(chat).launch()
49
+ ```
50
+
51
+ Use when you want users to "just click and try it" — no sign-in friction. Cost is on you.
52
+
53
+ ### Mode B — Visitor pays (recommended for public demos)
54
+
55
+ `gr.LoginButton` + `gr.load("models/...")` with `accept_token=button`. Each visitor signs in with their HF account; inference is billed to **their** account.
56
+
57
+ ```python
58
+ import gradio as gr
59
+
60
+ with gr.Blocks(fill_height=True) as demo:
61
+ with gr.Sidebar():
62
+ button = gr.LoginButton("Sign in")
63
+ gr.load("models/<org>/<model>", accept_token=button, provider="fireworks-ai")
64
+ demo.launch()
65
+ ```
66
+
67
+ README frontmatter needs:
68
+
69
+ ```yaml
70
+ hf_oauth: true
71
+ hf_oauth_scopes:
72
+ - inference-api
73
+ ```
74
+
75
+ This is the **recommended pattern for public demos** — sustainable cost-wise, and visitors get to use their own provider quotas (which most have paid for or get free).
76
+
77
+ ## Hardware
78
+
79
+ `cpu-basic`. No GPU. Don't put `--flavor zero-a10g` — you'd waste a paid grant.
80
+
81
+ ## Anti-pattern: `@spaces.GPU` wrapping a provider call
82
+
83
+ If you do use Inference Providers, do **not** wrap the call in `@spaces.GPU`. The decorator reserves a GPU slot on your Space for the full `duration=`, but the function does no GPU work — just an HTTP call out. You burn your own ZeroGPU quota for nothing.
84
+
85
+ A provider-proxy Space wants `cpu-basic` hardware and zero `@spaces.GPU`.
@@ -0,0 +1,232 @@
1
+ # Known errors
2
+
3
+ Check if this is a known issue before trying your own fix. Entries are keyed by the substring that actually appears in `runtime.errorMessage`, the build log, or a Python traceback — grep this file for the error you saw.
4
+
5
+ If you hit something not listed here and figure out a fix, please ask your human to PR it back so future runs benefit.
6
+
7
+ ---
8
+
9
+ ## Build / config errors
10
+
11
+ These come from the Space build pipeline before the app starts. Read with `hf spaces logs <id> --build --tail 500` — find the **first** error, not the last.
12
+
13
+ ### `CONFIG_ERROR: torch version in requirements.txt is not compatible with ZeroGPU`
14
+
15
+ **Cause**: `requirements.txt` pins `torch==X.Y.Z` to a version outside the supported set (`2.8.0`, `2.9.1`, `2.10.0`, `2.11.0`).
16
+ **Fix**: Unpin torch (preferred — the runtime preinstalls the latest supported version), or pin to one of the supported values.
17
+
18
+ ### `Cannot install … because these package versions have conflicting dependencies` / `ResolutionImpossible`
19
+
20
+ **Cause**: A dep conflicts with the Gradio SDK pinned by `sdk_version:` in README. Most commonly `pydantic`, `uvicorn`, `huggingface_hub`, or `jinja2` pinned to old values that the SDK no longer accepts.
21
+ **Fix**: Unpin the offender. For `gradio[mcp]` specifically, `uvicorn>=0.31.1` and `pydantic>=2.11.10` are required.
22
+
23
+ ### Build hangs in dependency resolution > 10 min
24
+
25
+ **Cause**: pip backtracking through a deep version space.
26
+ **Fix**: Pin the conflicting transitive dep. The `--build` logs will show which one. Bump `startup_duration_timeout: 1h` in README frontmatter if heavy downloads are expected.
27
+
28
+ ### `ModuleNotFoundError: No module named 'pkg_resources'`
29
+
30
+ **Cause**: setuptools 81 dropped `pkg_resources`; an old package's `setup.py` imports it.
31
+ **Fix**: Bump or unpin the offender. Typical culprits: `deepspeed==0.15.x` (training-only — usually safe to drop from inference Spaces), `openai-whisper==20231117`.
32
+
33
+ ### `400 Bad Request` from `/api/validate-yaml` during `create_repo` / `upload_file`
34
+
35
+ **Cause**: README frontmatter failed server validation. Most common: `short_description` over the (undocumented) character cap — target ≤ 60.
36
+ **Fix**: Shorten `short_description`. Long descriptions go in the README body. Also double-check `colorFrom`/`colorTo` are one of `red|yellow|green|blue|indigo|purple|pink|gray`.
37
+
38
+ ### `403 Forbidden` from `create_repo` with `space_hardware="zero-a10g"`
39
+
40
+ **Cause**: The user isn't on PRO / Team / Enterprise so the API rejects ZeroGPU at creation.
41
+ **Fix**: Retry without `space_hardware=`. Keep `hardware:` out of README frontmatter (silently ignored anyway). The Space is created on CPU; point the user at PRO upgrade or [community grant](grants.md).
42
+
43
+ ### `403 Forbidden` from `create_commit(..., create_pr=True)`
44
+
45
+ **Cause**: Upstream Space has Discussions disabled.
46
+ **Fix**: Ask the maintainer to enable Discussions, or push directly if you have write access.
47
+
48
+ ---
49
+
50
+ ## Startup / RUNTIME_ERROR
51
+
52
+ These come from `hf spaces logs <id> --tail 500`.
53
+
54
+ ### `RuntimeError: CUDA has been initialized before importing the spaces package`
55
+
56
+ **Cause**: Something triggered CUDA init in the main process before `import spaces`. Usually wrong import order; sometimes a third-party lib eagerly initializing CUDA at import time (e.g. `numba.cuda`).
57
+ **Fix**: Reorder so `import spaces` is first. For numba-using stacks (NeMo, RAPIDS bits):
58
+ ```python
59
+ import os
60
+ os.environ.setdefault("NUMBA_DISABLE_CUDA", "1")
61
+ import spaces
62
+ ```
63
+
64
+ ### `RuntimeError: No @spaces.GPU function detected during startup`
65
+
66
+ **Cause**: The function bound to `.click(fn=...)` / `.submit(...)` isn't decorated. Decorating an inner helper doesn't count — the startup scan only walks Gradio's registered handlers.
67
+ **Fix**: Decorate the function Gradio binds. If that conflicts with another decorator, wrap explicitly:
68
+ ```python
69
+ @spaces.GPU(duration=60)
70
+ def gpu_inner(...): ...
71
+ def gradio_handler(...): return gpu_inner(...)
72
+ ```
73
+ (Or just decorate `gradio_handler` directly.)
74
+
75
+ ### `ImportError: cannot import name 'HfFolder' from 'huggingface_hub'`
76
+
77
+ **Cause**: Old gradio (`4.44` and similar) imports `HfFolder` from `huggingface_hub`, which was removed in recent hub releases.
78
+ **Fix**: Two options.
79
+ - Pin `huggingface-hub==0.25.0` in `requirements.txt` (keeps old gradio happy).
80
+ - Bump `sdk_version` in README to `5.x` or `6.x` (also fixes a lot of other API breaks).
81
+ If a Gradio custom component locks the major (`gradio-image-prompter`, `gradio_litmodel3d`, …), install it with `--no-deps` so its `gradio<5.0` requirement doesn't bind.
82
+
83
+ ### `ImportError: cannot import name 'is_traceable_wrapper_subclass' from 'torch.utils._python_dispatch'`
84
+
85
+ **Cause**: A dep with `torchaudio<2.1` / `torch<2` in its `setup.py` (e.g. `demucs`, `audiocraft`) downgraded torch silently. The build succeeded, the app booted, and `import spaces` then died on a missing torch symbol.
86
+ **Fix**: Install the offender from `app.py` with `--no-deps` *before* `import spaces`:
87
+ ```python
88
+ import subprocess, sys
89
+ subprocess.run([sys.executable, "-m", "pip", "install", "--no-deps",
90
+ "git+https://github.com/facebookresearch/demucs"], check=True)
91
+ import spaces
92
+ ```
93
+ List its actual runtime deps (`dora-search einops julius lameenc openunmix pyyaml tqdm` for demucs) yourself in `requirements.txt`.
94
+
95
+ ### `_pickle.UnpicklingError: Weights only load failed`
96
+
97
+ **Cause**: `torch.load` weights-only default flipped to `True` in torch 2.6. Old checkpoints pickling numpy/object globals fail.
98
+ **Fix**: For trusted upstream checkpoints, monkey-patch before the package import:
99
+ ```python
100
+ import torch
101
+ _orig = torch.load
102
+ torch.load = lambda *a, **k: _orig(*a, **{**k, "weights_only": k.get("weights_only", False)})
103
+ ```
104
+
105
+ ### Stuck at `ZeroGPU init – 10.0%` then 60 s timeout
106
+
107
+ **Cause**: A library called `cuInit` in the parent process, poisoning the fork (most often `numba.cuda` via NeMo). The actual `@spaces.GPU` body never starts.
108
+ **Fix**: `os.environ.setdefault("NUMBA_DISABLE_CUDA", "1")` as the first line of `app.py`, before `import spaces`.
109
+
110
+ ### `RUNTIME_ERROR` right after long `APP_STARTING`, logs sparse
111
+
112
+ **Cause**: Boot exceeded `startup_duration_timeout` (default 30 min). Big-model loads commonly trigger this.
113
+ **Fix**: Bump `startup_duration_timeout: 1h` in README frontmatter. For Gradio 6 specifically, also set `GRADIO_SSR_MODE=false` via `hf spaces variables add <id> --env GRADIO_SSR_MODE=false` to dodge SSR health-check timeouts during slow boot.
114
+
115
+ ### `RUNNING` but the public URL returns 404
116
+
117
+ **Cause**: The Space is private. Anonymous Client / browser hits return 404.
118
+ **Fix**: Authenticate. `gradio_client.Client(space, token=os.environ["HF_TOKEN"])`. The kwarg is `token=`, not `hf_token=`.
119
+
120
+ ### `workload was not healthy after 30 min`
121
+
122
+ **Cause**: Infra-side scheduling or a build that genuinely can't finish in time.
123
+ **Fix**: Usually not actionable in code. Bump `startup_duration_timeout` if heavy downloads are expected; otherwise wait or report.
124
+
125
+ ### Exit code 128 / containerd / scheduling failure
126
+
127
+ **Cause**: HF infra glitch.
128
+ **Fix**: `hf spaces restart <id> --factory-reboot`. If it persists, retry later or report. Not fixable in code.
129
+
130
+ ---
131
+
132
+ ## Inference-time errors
133
+
134
+ These appear in `hf spaces logs <id> --follow` while a request is running.
135
+
136
+ ### `ZeroGPU illegal duration`
137
+
138
+ **Cause**: `@spaces.GPU(duration=N)` is larger than the visitor's tier per-call cap.
139
+ **Fix**: Lower `N`. Tier caps live in the [ZeroGPU docs](https://huggingface.co/docs/hub/spaces-zerogpu).
140
+
141
+ ### `ZeroGPU quota exceeded (X requested vs Y left)`
142
+
143
+ **Cause**: The visitor's remaining quota < `requested duration`. The comparison is `requested vs remaining`, not `actual vs remaining` — a 10-second task left at the default 60 s blocks the user as soon as their remaining drops below 60 s.
144
+ **Fix**: Lower `duration` to the realistic worst case. For input-dependent runtime, use a callable estimator.
145
+
146
+ ### `RuntimeError: NVML_SUCCESS == r INTERNAL ASSERT FAILED at .../CUDACachingAllocator.cpp`
147
+
148
+ **Cause**: Allocator fragmentation under transient memory spikes (high-res pixel-space ops, large attention activations, SR models, video DiTs). Not a clean OOM.
149
+ **Fix**: Set expandable segments at the **very top** of `app.py`, before any torch import:
150
+ ```python
151
+ import os
152
+ os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
153
+ import spaces
154
+ import torch
155
+ ```
156
+ Usually a single-line fix that replaces lowering resolution or moving to `xlarge`.
157
+
158
+ ### Call hangs forever on first `@spaces.GPU` entry
159
+
160
+ **Cause**: The decorated function returned a CUDA tensor. Unpickling it in the main process triggers `torch.cuda._lazy_init()`, which ZeroGPU blocks.
161
+ **Fix**: Convert to CPU before returning: `return tensor.cpu()` or `.cpu().numpy()`. For `gr.State`, scrub before yielding.
162
+
163
+ ### `PicklingError` at call entry
164
+
165
+ **Cause**: An argument crossing the fork boundary contains an unpicklable object — file handle, lock, lambda, closure, or `gr.SelectData`.
166
+ **Fix**: Extract the picklable fields in a thin un-decorated wrapper, pass plain values to the `@spaces.GPU` function. For `gr.SelectData` specifically, pull out `evt.index[0]`, `evt.index[1]` etc. outside the decorator.
167
+
168
+ ### `RecursionError` inside `gr.SelectData.__getattr__`
169
+
170
+ **Cause**: Same as above — `gr.SelectData` doesn't survive pickle.
171
+ **Fix**: Same — extract its fields before crossing the boundary.
172
+
173
+ ### `CUDA error … flash_fwd_launch_template.h: no kernel image is available for execution on the device` (or `:188: invalid argument`)
174
+
175
+ **Cause**: A Flash Attention 3 kernel was loaded — directly via `kernels-community/{flash-attn3,vllm-flash-attn3,sgl-flash-attn3}`, or indirectly via an old `xformers` wheel that auto-dispatched to FA3. FA3 has no Blackwell sm_120 build.
176
+ **Fix**: Use `attn_implementation="sdpa"`, or `"flash_attention_2"` with the FA2 wheel from `multimodalart/zerogpu-blackwell-wheels`. For xformers, the prebuilt wheel from the same dataset auto-dispatches to FA2 — no monkey-patch.
177
+
178
+ ### `NotImplementedError: sgl_flash_attn3 is only supported on sm80 and above with CUDA >= 12.3`
179
+
180
+ **Cause**: `kernels-community/sgl-flash-attn3` rejects sm_120 at runtime despite the error wording. Same root cause as the FA3 entry above.
181
+ **Fix**: Same — SDPA or FA2.
182
+
183
+ ### `ImportError: cannot import name 'flash_attn_varlen_func' from 'flash_attn'` / model insists on `attn_implementation="flash_attention_2"`
184
+
185
+ **Cause**: The model imports flash_attn at module top with no escape hatch, and the runtime doesn't ship it.
186
+ **Fix**: Install the prebuilt `flash_attn-2.8.3-cp310-cp310-linux_x86_64.whl` from `multimodalart/zerogpu-blackwell-wheels`. Requires `python_version: "3.10"` in README (wheel is cp310 only). Real `flash_attn_2_cuda` satisfies xformers' `flash_attn_gpu` probe too.
187
+
188
+ For transformers `AutoModel`-style configs that aren't a hard import, swap `attn_implementation="flash_attention_2"` → `"sdpa"`. Torch-native, zero deps.
189
+
190
+ ### `selective_scan_cuda.so undefined symbol` / `_torchaudio.abi3.so undefined symbol`
191
+
192
+ **Cause**: A direct-URL prebuilt CUDA wheel pinned to an old torch ABI (`cu12torch2.4cxx11abiFALSE`, etc.) — won't load on the current runtime.
193
+ **Fix**: Drop the URL-pinned wheel from `requirements.txt`. Use a torch-current wheel from `multimodalart/zerogpu-blackwell-wheels`, kernels-community, or upstream's release page.
194
+
195
+ ### `TypeError: 'dict' object is not hashable` inside `jinja2/utils.py:get`
196
+
197
+ **Cause**: Old gradio (4.44) + modern starlette / jinja2 cache clash.
198
+ **Fix**: Either pin `jinja2<3.2` + `starlette<0.40` (keeps old gradio), or bump `sdk_version` past 5.0.
199
+
200
+ ---
201
+
202
+ ## Smoke-test / client errors
203
+
204
+ ### `Client.__init__() got an unexpected keyword argument 'hf_token'`
205
+
206
+ **Cause**: Older `gradio_client` API used `hf_token=`; current uses `token=`.
207
+ **Fix**: `Client(space, token=os.environ["HF_TOKEN"])`.
208
+
209
+ ### `httpx.ReadTimeout` on `client.predict(...)`
210
+
211
+ **Cause**: Default timeout too small for the GPU duration.
212
+ **Fix**: `Client(..., httpx_kwargs={"timeout": 600})`. Set this to at least your `@spaces.GPU(duration=N)` plus 60 s.
213
+
214
+ ### `404` on what looks like a valid endpoint name
215
+
216
+ **Cause**: Streaming endpoint (function uses `yield`), or a custom `gr.Server` `@app.get/post` route that doesn't appear in `view_api()`.
217
+ **Fix**: For streaming, use `client.submit(...).result()` (or iterate the job). For custom routes, use `httpx.post(base_url + "/route", ...)` directly — bypass `gradio_client`.
218
+
219
+ ### Result file looks empty / dimensions wrong
220
+
221
+ **Cause**: HTTP 200 ≠ correct output. The model snapped to a different size, or the wrong endpoint was hit.
222
+ **Fix**: Sniff the returned file's magic bytes (`glTF`, `\x89PNG`, `RIFF…WEBP`, `RIFF…WAVE`, `[4:8]==b"ftyp"`) and check returned dimensions match what was requested.
223
+
224
+ ---
225
+
226
+ ## Submitting new entries
227
+
228
+ If you hit an error not in this file and figure out the fix, please ask your human to PR it back to this skill. Format:
229
+
230
+ - A 1-line heading with the exact error substring an agent would grep for.
231
+ - **Cause**: one sentence on what triggered it.
232
+ - **Fix**: concrete commands or code. If the fix needs more than 5 lines of narrative, point to another reference file (e.g. [`debugging.md`](debugging.md), [`zerogpu.md`](zerogpu.md)) for depth.