Spaces:
Running on Zero
Running on Zero
| title: Townlet | |
| emoji: ποΈ | |
| colorFrom: red | |
| colorTo: indigo | |
| sdk: gradio | |
| sdk_version: 6.17.3 | |
| python_version: "3.12" | |
| app_file: app.py | |
| startup_duration_timeout: 1h | |
| preload_from_hub: | |
| - HuggingFaceTB/SmolLM2-360M-Instruct-GGUF | |
| - nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF | |
| - Qwen/Qwen2.5-Coder-3B-Instruct-GGUF | |
| - openbmb/MiniCPM3-4B-GGUF | |
| - bartowski/Llama-3.2-3B-Instruct-GGUF | |
| models: | |
| - HuggingFaceTB/SmolLM2-360M-Instruct-GGUF | |
| - nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF | |
| - Qwen/Qwen2.5-Coder-3B-Instruct-GGUF | |
| - openbmb/MiniCPM3-4B-GGUF | |
| - bartowski/Llama-3.2-3B-Instruct-GGUF | |
| tags: | |
| - thousand-token-wood | |
| - nemotron | |
| - llama-cpp | |
| - smolagents | |
| - agent-simulation | |
| - track:wood | |
| - sponsor:nvidia | |
| - achievement:offgrid | |
| - achievement:offbrand | |
| - achievement:llama | |
| - achievement:fieldnotes | |
| - award:tiny-titan | |
| - award:best-agent | |
| short_description: Agents share a Python interpreter, mine, message, dream. | |
| # Townlet | |
| Build Small Hackathon entry (Thousand Token Wood track). | |
| ## Demo, blog & social | |
| <video controls width="640" src="https://huggingface.co/spaces/build-small-hackathon/townlet/resolve/main/docs/townlet.mp4"></video> | |
| - **Demo video:** [Watch on the Space](https://huggingface.co/spaces/build-small-hackathon/townlet/blob/main/docs/townlet.mp4) Β· [direct mp4](https://huggingface.co/spaces/build-small-hackathon/townlet/resolve/main/docs/townlet.mp4) | |
| - **Blog (Field Notes):** [Small models β its about the harness](https://www.linkedin.com/pulse/small-models-its-harness-matthew-auburn-gixwe/) | |
| - **Social post:** [LinkedIn announcement](https://www.linkedin.com/posts/matthew-a-b62b7b6b_i-entered-a-hackathon-that-hugging-face-put-ugcPost-7472246708526157825-H39G/) | |
| Townlet is a multi-agent simulation. LLM-driven characters live on a | |
| tile-grid map. They walk to a cave to mine electricity, to a well to draw | |
| water, and to a shared shell to spend resources running Python statements | |
| in a single long-lived interpreter. They post on a public message board. | |
| They sleep, they dream, they evolve. The shared interpreter is the world's | |
| only mutable substrate β characters can read or rewrite each other's state, | |
| and crash the operating system if they so choose. Every character knows | |
| this. Mutual awareness of the brick-risk is the source of dramatic tension. | |
| The game element is **customisation**: click a character to edit their | |
| personality (system prompt), swap which small model drives them, or spawn | |
| new ones from a pre-baked archetype pool. The simulation is otherwise | |
| self-driving. | |
| ## Model stack | |
| Every character runs on **NVIDIA Nemotron 3 Nano 4B** | |
| (`nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF`) by default. One model across the | |
| whole town means each `@spaces.GPU` fork pays a single cold-load and every | |
| subsequent character decision reuses the same weights in VRAM β a real | |
| quota saving on Zero-GPU. | |
| Click any character in the side panel to swap them to a different model | |
| mid-simulation; the roster bundled at build time covers: | |
| - **NVIDIA Nemotron 3 Nano 4B** β default | |
| - **Qwen2.5 Coder 3B** β for code-heavy goals | |
| - **OpenBMB MiniCPM3 4B** | |
| - **Meta Llama 3.2 3B** | |
| - **SmolLM2 360M** β terse, cheap, useful for testing the model-swap UI | |
| All run on Zero-GPU via [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python), | |
| which gives us the π¦ Llama Champion badge regardless of which roster | |
| model is selected (the badge requirement is "model runs through llama.cpp | |
| runtime", not a specific model family). | |
| Agent loops use [smolagents](https://huggingface.co/docs/smolagents) `CodeAgent`, | |
| emitting Python tool calls the scheduler queues onto the world. | |
| The map is rendered by the frontend canvas β no image model in the loop. | |
| ## Local development | |
| The project runs in **mock mode** locally β no model weights downloaded, no | |
| CUDA needed. Mocks return canned tool-call sequences whose style varies by | |
| model_id (deliberate / terse / verbose / chaotic), so the model-swap UI is | |
| exercisable without GPUs. | |
| ```bash | |
| python -m venv .venv | |
| source .venv/bin/activate | |
| pip install -r requirements-dev.txt | |
| python app.py | |
| ``` | |
| Or hit βΆ on the **"Run Small Stage (mocks)"** config in VS Code. | |
| The mode is selected automatically: | |
| - `SPACE_ID` env var present (set by HF Spaces) β real models | |
| - Otherwise β mocks | |
| - Set `FORCE_REAL_MODELS=1` to override locally (requires Spaces deps). | |
| ## Deploy to Hugging Face Spaces | |
| ```bash | |
| git remote add hf https://huggingface.co/spaces/<org>/<space-name> | |
| git push hf main | |
| ``` | |
| Then in the Space *Settings* β Hardware, pick **Zero-GPU**. The | |
| `preload_from_hub` block above pre-downloads every roster model at build | |
| time so the first user click hits a warm cache. | |
| ## Project layout | |
| ``` | |
| app.py # gr.Server entrypoint | |
| backend/ # inference layer (mock + real, env-selected) | |
| factory.py # get_llm(model_id) β per-id cached | |
| mock.py, real.py # MockLLMBackend / RealLLMBackend | |
| interfaces.py # LLMBackend Protocol | |
| game/ # the simulation | |
| models.py # model roster (id β repo + gguf + style) | |
| character.py # Character dataclass | |
| world.py # tile grid, BFS pathing, message board | |
| actions.py # smolagents.Tool subclasses + per-tick drivers | |
| interpreter.py # the long-lived shared Python subprocess | |
| scheduler.py # tick loop + per-character CodeAgent invocations | |
| perception.py # builds the prompt the CodeAgent receives | |
| the_dot.py # the shared system-prompt prefix (substrate truth) | |
| archetypes.py # ~15 hand-written personality templates | |
| dreams.py # the sleep β insight + delta + trait nudge cycle | |
| sentiment.py # board-mood classifier for the UI tint | |
| smol_adapter.py # smolagents.Model wrapper around LLMBackend | |
| frontend/index.html # vanilla HTML/JS top-down view served by app.py | |
| requirements.txt # Spaces deps | |
| requirements-dev.txt # local mock-only deps | |
| docs/hackathon.md # hackathon rules summary | |
| CONTEXT.md # canonical glossary | |
| ``` | |