focus-buddy / docs /PLAN.md
pocanman's picture
move markdown files
507fa4d
|
Raw
History Blame Contribute Delete
7.81 kB

A newer version of the Gradio SDK is available: 6.19.0

Upgrade

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