--- title: Slyfox emoji: 🦊 colorFrom: yellow colorTo: red sdk: docker app_port: 7860 pinned: false --- # 🦊 Slyfox A minimal, framework-free chat UI for [`transformers serve`](https://huggingface.co/docs/transformers/main/serving) — the OpenAI-compatible chat completions server shipped with 🤗 Transformers. The frontend is plain HTML/JS (no Gradio). A tiny FastAPI backend persists each conversation to a private [HF Bucket](https://huggingface.co/docs/huggingface_hub/en/guides/buckets) — one JSON file per chat. ## Configuration | Variable | Default | Description | | --- | --- | --- | | `SLYFOX_BUCKET` | `HF-slyfox/slyfox-chats` | Private bucket id (`/`) used for persistence. | | `HF_TOKEN` | injected by Spaces | Token used by `huggingface_hub` to read/write the bucket. Needs write access. | Frontend query params (browser-side): | Param | Default | Description | | --- | --- | --- | | `api` | `http://localhost:8000/v1` | OpenAI-compatible base URL for the inference server. | | `model` | `Qwen/Qwen3-0.6B` | Model id sent in the chat completion request. | | `repo` | _(empty)_ | Default Hugging Face repo id for new chats (e.g. `huggingface/transformers`). | Example: ``` https://huggingface.co/spaces/HF-slyfox/slyfox?api=https://your-tunnel/v1&model=Qwen/Qwen3-0.6B ``` ## Bucket layout ``` users// index.json # [{id, title, topic, updated_at}, …] newest first chats/ .json # full conversation: {id, title, topic, history, updated_at} ``` `` is a UUID minted in the browser and stored in `localStorage` (`slyfox.user_id`). Each browser is effectively its own user. Swap for HF OAuth identity to bind to a Hugging Face account. ## API | Method | Path | Description | | --- | --- | --- | | `GET` | `/api/chats` | List the per-user index. | | `GET` | `/api/chats/{id}` | Fetch a single chat. | | `PUT` | `/api/chats/{id}` | Upsert a chat (also updates the index). | | `DELETE` | `/api/chats/{id}` | Delete a chat. | | `GET` | `/healthz` | Health check. | All calls require an `X-User-Id` header. ## Local development ```bash pip install -r requirements.txt HF_TOKEN=hf_… uvicorn app:app --reload --port 7860 ``` Then visit `http://localhost:7860/?api=http://localhost:8000/v1`. ## Jobs page A second route, `/jobs`, exposes two operations that submit Hugging Face Jobs on behalf of the user. Both run via `HfApi.run_uv_job` and report CI-style status back into the UI. | Operation | Submits | Output | | --- | --- | --- | | **Request a new model** | `jobs_scripts/extract_vectors.py` | `hf://buckets/HF-slyfox/emotion-vectors//` | | **Analyze traces** | `jobs_scripts/analyze_traces.py` | `hf://buckets//trace-analysis//` | API surface (additive — none of the existing `/api/chats/*` routes change): ``` POST /api/models/extract { model_id, flavor? } POST /api/analyses { source, prefix?, n_traces, model_id, flavor? } GET /api/jobs list slyfox-submitted jobs with live status GET /api/jobs/{job_id} one job's record + live status GET /api/jobs/{job_id}/logs tail of the job's stdout/stderr POST /api/jobs/{job_id}/cancel cancel a running/queued job ``` Bucket layout extension: ``` SLYFOX_BUCKET/ ...existing chat layout... jobs/.json # sidecar record for each submitted job ``` Extra env vars: | Variable | Default | Description | | --- | --- | --- | | `SLYFOX_JOBS_REF` | `main` | Git ref of `huggingface/slyfox` to pull UV scripts from. | | `SLYFOX_VECTORS_BUCKET` | `HF-slyfox/emotion-vectors` | Where extracted vectors land. | | `SLYFOX_COMMUNITY_BUCKET` | `HF-slyfox/community-index` | Public index of opt-in shared runs. | ## Community (v0) A third route, `/community`, is a placeholder for the upcoming public catalog of opt-in shared analysis runs. The `/api/community/runs` endpoint already reads from `SLYFOX_COMMUNITY_BUCKET`; the publish-side flow (`hf upload-traces --share community`) is on the roadmap. See [`COMMUNITY.md`](./COMMUNITY.md) for the full design.