Teaching a 4B Model to Run a City-Wide Scavenger Hunt — Without Naming a Single Street

Community Article
Published June 15, 2026

HF Space: CityQuest-AI Field notes from building CityQuest AI

We wanted to make the city feel like a game board again.

CityQuest AI generates complete, playable real-world games — scavenger hunts, hide-and-seek, tag — for any city. Pick a game type, a city, your player count, a duration, and a vibe; seconds later you get a full game design: rules, scored tasks, progressive hints, safety constraints, and a recap to read aloud when someone wins. One person spins up a room, everyone joins with a 6-character code, and the app tracks progress while you run around outside. We built it on Gradio and shipped it on Hugging Face Spaces.

One design decision shaped everything else.

The rule that made it hard (and good)

The naive build — "make a scavenger hunt for Paris" — breaks fast. The model only knows famous landmarks, hallucinates geography confidently, and can't reason about a neighborhood it's never seen. So we inverted it and made one invariant the spine of the whole system:

Every spatial instruction must be derivable from landscape_tags alone. No proper nouns — ever.

A location isn't "Paris." It's a handful of generic features from a ~27-tag vocabulary: plaza_or_square, narrow_alley_network, river_waterfront, market_covered. So a task reads "find where a narrow alley opens onto an outdoor market — photograph the busiest stall," never "meet at Borough Market."

The payoff is enormous: games become portable. A player who's never been to the city can follow one using only what's in front of them, the same game works across a dozen neighborhoods, and the model never needs to know a city — just reason about generic affordances, which a small model does well.

How a game gets generated

Three stages, and the LLM is deliberately the weakest link:

  1. Retrieval grounding (RAG) — pull the most similar games from ~300 validated examples per game type as exemplars, anchoring structure and difficulty.
  2. GenerationNVIDIA Nemotron 3 Nano 4B, 4-bit GGUF (~2.8 GB), via llama.cpp. Local, no per-call cost, and enough — because we don't ask it to do the hard parts.
  3. Validate & repair — proper-noun blocklist, tag-consistency, difficulty mix, hint progression, scoring math, safety rules. Fail → repair → re-validate. Nothing ships unchecked.

The best decision we made:

Python computes every number; the LLM only writes prose.

Counts, points, durations, scoring method, safety exclusions — all pre-computed deterministically and handed to the model as fixed facts. An auto_fix() step re-applies them right before validation, so we never fight the model over arithmetic. That's why a 4B model punches so far above its weight: we never gave it a chance to get the math wrong.

Two things that didn't make the demo reel

The data pipeline is a real system. Our first generation run died at 11 examples — Gemini's free-tier daily quota, then 80 straight 429s. That forced rotating multi-key management and resumable batching. We ended at 316 / 314 / 304 validated examples across the three games. "Works once by hand" ≠ "runs to 300."

The unglamorous UI is 60% of the feel. Voice journals via Cohere Transcribe (14 languages, lazy-loaded), streaming recaps, toast confirmations, loading states, and adaptive polling (fast while things change, easing when idle). Zero game-logic changes — all feel.

What we'd tell ourselves at the start

  • Constrain the model, then trust it. "No proper nouns" looked like a limitation; it was the unlock that let a 4B model do a frontier-model-sized job.
  • Deterministic code owns anything with a right answer. The LLM writes prose; Python owns the truth.
  • Validate everything, ship nothing unchecked. A repair loop turns an unpredictable generator into a product.
  • Small models are enough more often than you think — if you build the scaffolding instead of throwing tokens at it.

We set out to turn a city into a game board. The twist: the best way to do it was to make the AI forget the city entirely, and reason only about what any player, anywhere, can see with their own eyes.

Community

Sign up or log in to comment