File size: 10,577 Bytes
dd7a5cf
125f9c0
 
 
 
dd7a5cf
125f9c0
 
 
 
 
 
 
 
 
 
 
 
dd7a5cf
 
125f9c0
 
f91a40d
 
 
 
 
 
125f9c0
 
 
 
 
 
 
 
 
 
 
 
 
 
f91a40d
 
 
 
 
 
 
125f9c0
0dadc4e
 
3f6ba8c
0dadc4e
3f6ba8c
 
 
 
 
 
 
0dadc4e
 
3f6ba8c
 
 
 
 
 
 
 
0dadc4e
 
3f6ba8c
 
 
 
 
0dadc4e
 
3f6ba8c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0dadc4e
 
3f6ba8c
 
0dadc4e
 
3f6ba8c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0dadc4e
3f6ba8c
 
 
 
f91a40d
3f6ba8c
 
 
 
 
 
 
 
 
 
 
 
 
 
0dadc4e
3f6ba8c
0dadc4e
 
 
125f9c0
0dadc4e
f91a40d
 
 
 
125f9c0
 
0dadc4e
 
125f9c0
 
0dadc4e
 
 
125f9c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
---
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<br/><i>turn loop</i>"]
        RESOLVER{{"๐ŸŽฒ Resolver<br/><i>seeded dice + rewards</i>"}}
        STATE[("๐Ÿ—บ๏ธ WorldState<br/><i>externalized memory</i>")]
    end

    subgraph FLEET["๐Ÿค– The Fleet โ€” Modal serverless GPUs ยท every model โ‰ค 32B"]
        direction LR
        SPEC["๐ŸŒŒ Dreamweaver ยท ๐Ÿ‘ Nightmare ยท ๐Ÿฏ Hobbes<br/><b>Qwen3-30B-A3B</b> MoE on vLLM<br/><i>30B total ยท only 3B active/token</i>"]
        ROUTER["๐Ÿ—บ Keeper<br/><b>MiniCPM-1B</b> ยท llama.cpp"]
        VISION["๐ŸŽจ Painter<br/><b>FLUX.1-schnell</b>"]
    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) โ€”<br/>state and image never block the turn
```

### 3 ยท The fairness spine โ€” code owns the dice

```mermaid
flowchart LR
    G["gambit + seed + turn"] --> R{{"๐ŸŽฒ resolve()<br/>pure ยท deterministic"}}
    R --> V["verdict<br/>success / partial / fail<br/>+ reward magnitudes"]
    V --> A["apply()<br/>move LUCIDITY ยท PROGRESS<br/>ยท COURAGE ยท MENACE"]
    V --> N["๐ŸŒŒ model narrates<br/><i>the words, not the outcome</i>"]
    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.* ๐ŸŒ™