piclets-backend / README.md
Fraser's picture
claude
d37642c
|
Raw
History Blame Contribute Delete
4.9 kB
---
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)**.