--- title: DAYDREAM emoji: ๐ŸŒ™ colorFrom: indigo colorTo: purple sdk: gradio sdk_version: 6.16.0 app_file: app/app.py pinned: true license: mit short_description: "Small models, big dreams: a dream game with your tiger" tags: - track:thousand-token-wood - sponsor:openbmb-minicpm - sponsor:modal - badge:best-agent - badge:off-brand - badge:best-demo --- # ๐ŸŒ™ DAYDREAM โ€” *Press Your Luck, Keep Your Tiger* A bedtime dream you **play** โ€” a real, goal-driven story, dreamed in real time by a **fleet of small models**, none bigger than fits on one GPU. Each world gives you a **quest**; you pursue it by taking **gambits** (safe / bold / reckless) through surreal scenes with your stuffed tiger **Hobbes**, who grows brave because of the bets you take *together*. Code rolls the dice; the little models supply the soul. Reach the goal to wake with the prize โ€” or run out of lucidity and dissolve. > **The thesis โ€” small models, big dreams.** You don't own one giant brain; you command > a *fleet of scrappy small minds*. In a dream, a small model's fuzziness isn't a bug โ€” > it's the aesthetic. **The constraint is the art.** Every model โ‰ค32B, by design. --- ## ๐Ÿ† Submission tags - **Track:** *An Adventure in Thousand Token Wood* (whimsical) โ€” there's even a `Thousand Token Wood` world inside. - **Sponsor prizes:** **OpenBMB / Best MiniCPM** (MiniCPM5-1B is our Keeper) ยท **Modal / Best Use** (4 services + a cost-guardian). - **Bonus badges:** **Best Agent** (a coordinated multi-agent fleet) ยท **Off Brand** (custom dream-deck UI + live generated visuals) ยท **Best Demo**. ## โœจ What makes it different 1. **A real story, not a chat.** Every world is a quest with a visible goal; the Dreamweaver weaves *one coherent tale* that moves toward it each turn (forward on success, setback on failure) and resolves in a genuine climax โ€” reach the prize, or the dream collapses. 2. **A fleet, not a chatbot.** Five small models โ€” ๐ŸŒŒ Dreamweaver, ๐Ÿ‘ Nightmare, ๐Ÿฏ Hobbes, ๐Ÿ—บ Keeper, ๐ŸŽจ Painter โ€” each with one job, coordinated per turn. Every model โ‰ค32B. 3. **Code owns the dice, models own the words.** Pass/fail and every reward is computed by a seeded, model-free resolver. The models *never* decide outcomes โ€” so it's a **fair game**, not a story that flatters you. This is the heart of the design. 4. **Hobbes grows brave because of you.** A COURAGE meter rises when you survive bets made *with* him; his voice shifts cowering โ†’ steady โ†’ "I've got you." The "aww" is earned. 5. **The dream paints itself โ€” fast.** A FLUX image renders each beat on-GPU in **~0.5s**; a pre-generated hero greets you the instant you arrive, then live per-beat images shift the scene. Choices and state run async, so a warm turn is **~5s** with narration streaming in under a second. 6. **Engineered for real Modal deployment.** Multi-backend (vLLM MoE + llama.cpp + FLUX) plus a **cloud cost-guardian** we built after a runaway-GPU lesson โ€” scale-to-zero, hard container caps, a lease-based dead-man's-switch, and robustness so a cold/failed backend degrades gracefully instead of hanging a turn. 7. **Deterministic & shareable.** Same dream seed replays the same dice *and* the same images โ†’ *"beat my run, seed `abc123`."* Download your full run as a keepsake. --- ## ๐Ÿง  Architecture DAYDREAM is a **fleet of small models refereed by code**: a deterministic Python core owns the truth and the dice, while a handful of sub-32B models โ€” each on its own Modal GPU โ€” supply only words and pixels. Three views: ### 1 ยท System โ€” three layers, one rule > **The rule:** outcomes flow *down* from code; only language flows *up* from models. ```mermaid flowchart TB P([๐Ÿ‘ค Player]) subgraph CODE["โš™๏ธ Orchestration โ€” Python ยท owns the truth"] direction LR ENGINE["DreamEngine
turn loop"] RESOLVER{{"๐ŸŽฒ Resolver
seeded dice + rewards"}} STATE[("๐Ÿ—บ๏ธ WorldState
externalized memory")] end subgraph FLEET["๐Ÿค– The Fleet โ€” Modal serverless GPUs ยท every model โ‰ค 32B"] direction LR SPEC["๐ŸŒŒ Dreamweaver ยท ๐Ÿ‘ Nightmare ยท ๐Ÿฏ Hobbes
Qwen3-30B-A3B MoE on vLLM
30B total ยท only 3B active/token"] ROUTER["๐Ÿ—บ Keeper
MiniCPM-1B ยท llama.cpp"] VISION["๐ŸŽจ Painter
FLUX.1-schnell"] end P -- "gambit (safe/bold/reckless)" --> ENGINE ENGINE --> RESOLVER -- "verdict" --> ENGINE ENGINE <-. "context slice โ†” patch" .-> STATE ENGINE == "narrate ยท react" ==> SPEC ENGINE -. "async" .-> ROUTER ENGINE -. "async" .-> VISION SPEC == "prose + 3 choices" ==> P VISION -. "image" .-> P ROUTER -. "state patch" .-> STATE classDef code fill:#1b1640,stroke:#7c5cff,color:#fff; classDef fleet fill:#241a4d,stroke:#9d7bff,color:#fff; classDef dice fill:#2a1022,stroke:#ff5c7c,color:#fff; classDef player fill:#0b0a1c,stroke:#cdbcff,color:#fff; class ENGINE,STATE code; class SPEC,ROUTER,VISION fleet; class RESOLVER dice; class P player; ``` ### 2 ยท One turn โ€” critical path vs. async (why it feels instant) ```mermaid sequenceDiagram autonumber actor P as ๐Ÿ‘ค Player participant C as โš™๏ธ Resolver participant D as ๐ŸŒŒ Dreamweaver participant H as ๐Ÿฏ Hobbes participant K as ๐Ÿ—บ Keeper participant F as ๐ŸŽจ FLUX P->>C: pick gambit C->>C: roll seeded dice โ†’ verdict Note over C: the outcome is FIXED before any model speaks โ€” the game is fair C->>D: narrate this verdict D-->>P: streams prose ยท first words in ~0.4s par off the critical path (async) C-)K: patch world-state (background) C-)F: paint the beat (~0.5s on GPU) end D->>H: finished scene H-->>P: reaction + 3 fresh gambits ยท ~5s F--)P: dream image fades in Note over P,F: you wait only for narration + choices (~5s) โ€”
state and image never block the turn ``` ### 3 ยท The fairness spine โ€” code owns the dice ```mermaid flowchart LR G["gambit + seed + turn"] --> R{{"๐ŸŽฒ resolve()
pure ยท deterministic"}} R --> V["verdict
success / partial / fail
+ reward magnitudes"] V --> A["apply()
move LUCIDITY ยท PROGRESS
ยท COURAGE ยท MENACE"] V --> N["๐ŸŒŒ model narrates
the words, not the outcome"] A --> S[("WorldState")] classDef c fill:#2a1022,stroke:#ff5c7c,color:#fff; classDef m fill:#241a4d,stroke:#9d7bff,color:#fff; class R,V,A c; class N m; ``` *Same `(seed, turn)` โ†’ same dice โ†’ **"beat my run, seed `abc123`"** is honest. A model can never decide whether you succeed.* --- ## ๐ŸŽฎ How it plays 1. Pick a world (Candy Desert, Sunken City, Rain Street, Red Planet, Thousand Token Wood) and a seed. A hero image and your **quest** greet you instantly. 2. Pursue the quest: take a **gambit** โ€” ๐ŸŸข safe / ๐ŸŸก bold / ๐Ÿ”ด reckless (each shows its odds + reward) โ€” or type your own action. Hobbes' three options are concrete, scene-specific steps toward the goal. 3. The **Dreamweaver** narrates the outcome the dice already decided, moving the story toward the goal; the **Nightmare** presses when menace climbs; **Hobbes** reacts in his current mood and offers the next steps; the **Keeper** updates world-state; the **Painter** repaints the scene. 4. Climb **PROGRESS** to 100 to wake with the prize, or run out of **LUCIDITY** and dissolve โ€” both end in a climactic beat. Watch **COURAGE** turn Hobbes brave along the way. Win or lose, the run freezes into a shareable Dream Journal you can download. ## ๐Ÿค– The fleet *Full design + diagrams: **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**.* | Agent | Role | Backend (โ‰ค32B each) | Job | |---|---|---|---| | ๐ŸŒŒ Dreamweaver | specialist | Modal vLLM ยท Qwen3-30B-A3B (MoE, 3B active) | narrate the pre-decided outcome | | ๐Ÿ‘ Nightmare | specialist | Modal vLLM ยท Qwen3-30B-A3B (MoE, 3B active) | press the dread when menace is high | | ๐Ÿฏ Hobbes | specialist | Modal vLLM ยท Qwen3-30B-A3B (MoE, 3B active) | companion; voice keyed to COURAGE; offer gambits | | ๐Ÿ—บ Keeper | router | Modal llama.cpp ยท **MiniCPM5-1B** | structured world-state (location, items, memory) | | ๐ŸŽจ dream image | vision | Modal ยท FLUX.1-schnell | paint each beat, in parallel under the narration | Backends are OpenAI-compatible โ†’ swap models or run "off the grid" via one env var, no code change. ## ๐Ÿง  Why it stays coherent on small models The **world-state lives in code**, outside the models (`agents/world.py`). Each turn the engine feeds each agent a compact slice of truth, so a 1B router can keep a consistent world that a single small context never could. The **resolver** (`agents/resolver.py`) owns all game math, seeded by `(seed, turn)` โ€” fair, replayable, and impossible for a model to fudge. ## โ˜๏ธ Best Use of Modal โ€” and a cost story DAYDREAM runs **four Modal services** (vLLM, llama.cpp, FLUX, and a guardian). After a keep-warm GPU once cold-looped and burned real money, we made cost control *structural*: - **Scale-to-zero + `max_containers=1`** on every GPU app โ€” $0 idle, no fan-out. - A **cloud guardian**: a cheap cron that warm-pings endpoints **only while a time-boxed lease is active** โ€” so warmth is a *pull*, not a pin. Forget to tear down? The lease expires and everything scales to zero on its own, independent of your laptop. - A `make` control surface: `make status` (apps + lease + live spend tracker), `make stop` (panic), `make demo-up/down`. All endpoint URLs derive from one `MODAL_WORKSPACE` slug, so moving workspaces is a one-line change. ## ๐Ÿš€ Run it **Offline (no backend, fully playable):** ```bash python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt DAYDREAM_MOCK=1 python app/app.py ``` **Against Modal inference:** set `MODAL_WORKSPACE` + keys in `.env` (see `.env.example`), then `make deploy && python app/app.py`. ## ๐Ÿ—‚ Layout | Path | What | |---|---| | `agents/dream.py` | the fleet engine (Dreamweaver ยท Nightmare ยท Hobbes ยท Keeper) | | `agents/resolver.py` | seeded, model-free dice + reward math (code owns the game) | | `agents/world.py` | environments + externalized `WorldState` | | `agents/vision.py` | per-beat dream-image prompts + FLUX client | | `agents/base.py` | tiny streaming/JSON Agent + `DAYDREAM_MOCK` offline mode | | `app/app.py` | Gradio dream-deck UI | | `modal_app/*.py` | Modal vLLM ยท llama.cpp ยท FLUX ยท guardian | *Small models, big dreams.* ๐ŸŒ™