focus-buddy / docs /PLAN.md
pocanman's picture
move markdown files
507fa4d
|
Raw
History Blame Contribute Delete
7.81 kB
# Plan: Gamified Productivity Buddy
## Context
Building a hackathon entry for HF "Build Small" (Thousand Token Wood track, deadline June 15 2026 β€” 2 days).
The app is a whimsical RPG-flavored productivity companion: a 3D character lives on the left, a local LLM buddy lives on the right, and your focus sessions earn XP, coins, and cosmetic gear.
---
## Tech Stack
| Layer | Choice | Reason |
|---|---|---|
| App framework | Gradio `gr.Blocks` | Required by hackathon |
| Hosting | HF Spaces (GPU T4) | Required; enables Off-the-Grid badge |
| LLM | `Qwen/Qwen2.5-3B-Instruct` via πŸ€— `transformers` | 3B = fast on T4, excellent tool-call support |
| 3D avatar | Three.js + GLB/GLTF model | User confirmed; served from Gradio static |
| Frontend glue | Embedded `<script>` in `gr.HTML` + hidden textbox bridge | JS→Python event passing |
| Python env | `venv` | User requirement |
**Bonus badges targeted**: Off the Grid (no cloud APIs), Off-Brand (custom frontend), Tiny Titan (≀4B model).
---
## Project Structure
```
08/
β”œβ”€β”€ app.py # Gradio entry point
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ llm.py # Model load, chat, tool-call parsing
β”‚ β”œβ”€β”€ game_state.py # XP / coins / levels / inventory dataclass
β”‚ β”œβ”€β”€ tools.py # Tool definitions + executor
β”‚ └── reminder.py # Idle detection thread
β”œβ”€β”€ static/
β”‚ β”œβ”€β”€ js/
β”‚ β”‚ β”œβ”€β”€ avatar.js # Three.js scene, GLB loader, animations
β”‚ β”‚ β”œβ”€β”€ timer.js # Pomodoro / free-flow countdown + JS events
β”‚ β”‚ └── bridge.js # Dispatches JS events β†’ hidden Gradio textbox
β”‚ β”œβ”€β”€ css/
β”‚ β”‚ └── style.css # 2-column RPG dark theme
β”‚ └── models/
β”‚ └── character.glb # Free CC0 character (see note below)
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ .env.example
└── README.md
```
**GLB model source**: Use the free CC0 "Adventurer" from Kenney (kenney.nl/assets/adventurer) or any Mixamo Y-Bot export. Place the file at `static/models/character.glb`. Animations needed: `idle`, `walk`, `celebrate`.
---
## Layout (Gradio custom HTML)
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3D Avatar (Three.js)β”‚ Chat window β”‚
β”‚ [idle / celebrate] β”‚ (gr.Chatbot) β”‚
β”‚ β”‚ β”‚
β”‚ XP: 120 | βš™ Lv.2 β”‚ ── Inventory ── β”‚
β”‚ πŸ’° Coins: 35 β”‚ (slides over chat β”‚
β”‚ β”‚ when [Bag] clicked)β”‚
β”‚ ── Timer ── β”‚ β”‚
β”‚ [πŸ… Pomodoro] β”‚ β”‚
β”‚ [∞ Free Flow] β”‚ β”‚
β”‚ [Start] [Stop] β”‚ β”‚
β”‚ β”‚ β”‚
β”‚ ── To-Do ── β”‚ β”‚
β”‚ [ ] Task 1 β”‚ β”‚
β”‚ [βœ“] Task 2 β”‚ β”‚
β”‚ [+ Add task] β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
The two columns are rendered inside a single `gr.HTML` component that bootstraps Three.js and the timer. Gradio components (`gr.Chatbot`, `gr.Textbox` input, hidden state bridges) sit in `gr.Row`/`gr.Column` alongside.
---
## Implementation Steps
> Tracer-bullet order: each slice is a working vertical cut of the full stack.
### βœ… 1. Bootstrap
- `python -m venv .venv`, install deps, `requirements.txt` β€” **done**
### 2. Chat with local LLM
Goal: bare-bones two-column Gradio app where you can talk to Qwen2.5-3B-Instruct.
- `src/llm.py`: load model with `AutoModelForCausalLM` + `bfloat16` + `device_map="auto"`; `chat(messages) -> str`
- `app.py`: minimal `gr.Blocks` with left placeholder column + right `gr.Chatbot` + `gr.Textbox` input
- System prompt: whimsical RPG companion persona
- Deliverable: type a message, get a reply
### 3. Timer
Goal: functional Pomodoro/free-flow timer in the left column with configurable durations.
- `static/js/timer.js`: countdown logic, work/break modes, start/stop/reset
- `static/css/style.css`: dark RPG theme skeleton, two-column layout
- Left column rendered via `gr.HTML`: timer display + mode selector (Pomodoro / Free Flow) + duration inputs + Start/Stop buttons
- `static/js/bridge.js`: JS β†’ Python bridge via hidden `gr.Textbox`
- Python handler: receives `timer_complete` event, lays groundwork for XP (stub for now)
- Deliverable: timer counts down, rings on completion
### 4. LLM β†’ Timer tool calls
Goal: LLM can start/stop the timer via natural language.
- `src/game_state.py`: add `timer_state` dict to a minimal `GameState` dataclass
- `src/tools.py`: define `start_timer` and `stop_timer` JSON schemas + executor
- `src/llm.py`: extend `chat()` to pass tools, parse Qwen `<tool_call>` tags, execute, re-call model
- Inject current timer state into system prompt each turn
- Python β†’ JS: after tool execution, return a JS command string to update timer UI
- Deliverable: "start a 25 minute focus session" β†’ timer starts in UI
### 5. Todo list
Goal: functional todo list in the left column (below timer).
- Extend `GameState`: add `todos: list[dict]` with `id`, `task`, `done`
- `gr.HTML` todo section: renders current todos from state, checkbox to complete, delete button
- Python handlers: `add_todo`, `complete_todo`, `remove_todo` update state + re-render HTML
- Inject todo list into system prompt each turn
- Deliverable: todos appear, can be checked off manually
### 6. LLM β†’ Todo tool calls
Goal: LLM can manage todos via natural language.
- `src/tools.py`: add `add_todo`, `complete_todo`, `remove_todo` schemas + executors
- Wire into `chat()` tool loop (same pattern as timer)
- On `complete_todo`: award +10 XP (introduce XP to `GameState` here)
- Deliverable: "add a todo: review PR" β†’ todo appears; "mark it done" β†’ checked off, XP ticks up
### βœ… 7. 3D Avatar
Goal: Three.js GLB character in the left column that reacts to app events.
- `static/js/avatar.js`: Three.js scene, `GLTFLoader`, animation mixer
- Animations mapped to events: `idle` (default), `working` (timer running), `celebrate` (timer complete / level up), `cheer` (todo complete)
- `bridge.js`: extend Python β†’ JS channel to accept `{cmd: "avatar", animation: "celebrate"}`
- Hook avatar triggers into existing events: timer complete, todo complete, LLM tool responses
- Deliverable: character idles, animates when timer runs, celebrates on completion
---
## Gamification Values
| Event | XP | Coins |
|---|---|---|
| Complete a to-do | +10 | β€” |
| Finish a Pomodoro | +25 | +5 |
| Finish a free-flow session | +15 | +3 |
| Level up | β€” | +20 bonus |
Level thresholds: 0 / 100 / 250 / 500 / 900 / 1400 XP
### Sample Inventory Items
| Item | Cost | Level Req |
|---|---|---|
| Red Hat | 10 coins | Lv.1 |
| Blue Cape | 25 coins | Lv.2 |
| Gold Crown | 50 coins | Lv.3 |
| Dark Aura | 80 coins | Lv.4 |
---
## Verification
1. **Start app**: `python app.py` β†’ opens at `localhost:7860`
2. **Timer**: Click Start Pomodoro β†’ countdown runs in UI β†’ on complete, XP/coins update, avatar plays celebrate animation
3. **LLM tool use**: Type "add a todo: finish the slides" β†’ LLM calls `add_todo`, todo appears in left column
4. **Idle reminder**: Set idle threshold to 2 min for testing, wait β†’ nudge appears in chat
5. **Inventory**: Click πŸŽ’ β†’ panel slides over chat β†’ buy Red Hat β†’ avatar updates
6. **Deploy**: Push to HF Spaces, confirm GPU Space, verify model loads and chat works