Spaces:
Sleeping
Sleeping
| title: Piclets Discovery Server | |
| emoji: ๐ฎ | |
| colorFrom: purple | |
| colorTo: indigo | |
| sdk: gradio | |
| sdk_version: 5.49.0 | |
| app_file: app.py | |
| pinned: false | |
| short_description: Backend for the Piclets monster-discovery game | |
| # ๐ฎ Piclets Discovery Server | |
| The backend for **Piclets**, a photo-to-monster discovery game. Photograph a real | |
| object, and this server turns it into a collectible creature and saves it to a | |
| shared, public database โ so the first person to scan a given object *discovers* | |
| its canonical monster, and everyone else who scans it finds the same one. | |
| This Space does **only two things**: | |
| 1. **Orchestrates the AI pipeline** for a scan, forwarding the *player's* Hugging | |
| Face token to three ZeroGPU Spaces so the GPU time is billed to the player, not | |
| to this server: | |
| ``` | |
| photo โโโถ identify object (VLM) โโโถ design monster as JSON (LLM) โโโถ art (T2I) | |
| ``` | |
| 2. **Writes new monsters** to a public HF Dataset in a single commit, and keeps the | |
| small aggregate index files (dex / feed / leaderboard / stats) in sync. | |
| Everything the frontend *reads* โ the dex, the feed, the leaderboard, a player's | |
| collection โ is fetched **directly from the dataset CDN**, never through this | |
| server. That asymmetry is the whole design; see **[ARCHITECTURE.md](ARCHITECTURE.md)**. | |
| > **Note on `hf_oauth`:** this server does **not** set `hf_oauth`. The *frontend* | |
| > Space runs "Sign in with Hugging Face" and forwards the resulting access token | |
| > here as a parameter; this server just verifies it against the HF userinfo | |
| > endpoint. OAuth config belongs on the frontend, not here. | |
| ## Setup | |
| 1. **Create the dataset** (the shared database). Run once, locally, with a token | |
| that has write access: | |
| ```bash | |
| HF_TOKEN=hf_xxx DATASET_REPO=<you>/piclets python init_dataset.py | |
| ``` | |
| 2. **Create this Space** (Gradio SDK, free CPU basic) and push these files. | |
| 3. **Add secrets** in *Space Settings โ Variables and secrets*: | |
| | Name | Type | Purpose | | |
| | -------------- | ------ | -------------------------------------------------- | | |
| | `HF_TOKEN` | secret | **This server's** write token for the dataset. | | |
| | `DATASET_REPO` | var | The dataset id, e.g. `you/piclets`. | | |
| | `ADMIN_TOKEN` | secret | *(optional)* guards the `/admin_*` endpoints. | | |
| Optional tuning vars: `CAPTION_SPACE`, `CONCEPT_SPACE`, `IMAGE_SPACE`, | |
| `MAX_IMAGE_BYTES`, `OUTPUT_IMAGE_MAX`, `SCAN_MAX_IN_WINDOW`, `SCAN_WINDOW_S`, | |
| `CONCURRENCY`. | |
| 4. **Verify** the AI Space signatures before trusting a scan (they change over | |
| time). See [ARCHITECTURE.md โ *Swapping the AI Spaces*](ARCHITECTURE.md). Quick | |
| check: | |
| ```python | |
| from gradio_client import Client | |
| Client("multimodalart/Qwen-Image-Fast").view_api() | |
| ``` | |
| ## API | |
| One write endpoint (the UI on this page is just for manual testing): | |
| - **`/scan`** โ inputs `image` (file) and `hf_token` (the player's OAuth access | |
| token). Returns: | |
| ```json | |
| {"success": true, "status": "new", "descriptor": "...", "monster": { ... }, | |
| "message": "You discovered ...!"} | |
| ``` | |
| `status` is `"new"` (a monster was created and committed) or `"existing"` (the | |
| object was already discovered โ returned read-only, no commit, minimal GPU). | |
| - **`/admin_delete`**, **`/admin_rebuild`** โ moderation tools, gated by `ADMIN_TOKEN`. | |
| Read paths for the frontend (direct from the CDN): | |
| ``` | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/index/monsters.json | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/index/feed.json | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/index/leaderboard.json | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/index/stats.json | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/monsters/<key>.json | |
| https://huggingface.co/datasets/<DATASET_REPO>/resolve/main/images/<key>.webp | |
| ``` | |
| ## Limits worth knowing | |
| - **Per-player GPU quota** (ZeroGPU, daily): ~2 min anonymous, ~5 min free, ~40 min | |
| Pro. A scan is three GPU calls, so a free player gets on the order of a handful of | |
| *new* discoveries per day. Repeat scans of known objects are deduped before the | |
| expensive stages and cost almost nothing. | |
| - **Write ceiling:** every discovery commits under this server's single token, and | |
| HF rate-limits commits (the exact number is undocumented). `huggingface_hub` | |
| โฅ 1.2.0 auto-retries on 429. New-monster writes naturally slow as common objects | |
| get claimed. | |
| - **Free CPU Space** sleeps after 48h idle and wakes on the next visit (cold start | |
| up to ~a minute). It's a single replica โ which is why one in-process lock is | |
| enough to serialize all writes. | |
| Full reasoning, the exact numbers, and how to stress-test them are in | |
| **[ARCHITECTURE.md](ARCHITECTURE.md)**. Development notes are in **[CLAUDE.md](CLAUDE.md)**. | |