minhahwang commited on
Commit
c5e89ef
Β·
1 Parent(s): c054869

Add interruptible chunked streaming narration + mobile considerations PRD

Browse files
Files changed (4) hide show
  1. future_mobile_app_considerations.md +142 -0
  2. mission.md +45 -12
  3. sprint.md +31 -17
  4. tech_stack.md +64 -20
future_mobile_app_considerations.md ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Future Mobile App Considerations
2
+
3
+ ## Purpose
4
+
5
+ This note captures future mobile deployment guidance for ReadBookMom. The current hackathon plan should remain a Hugging Face Spaces demo, with mobile treated as a later product direction.
6
+
7
+ ## Recommendation
8
+
9
+ Do not plan the first mobile version as a fully on-device app running all models locally. A hybrid mobile app is more realistic for reasonable latency, battery life, interruption behavior, and device coverage.
10
+
11
+ For the mobile app, use the phone as the recording, playback, interruption, and story interaction surface. Keep cloned-voice TTS and Q&A generation on a GPU backend until the models and runtime stack are proven on target devices.
12
+
13
+ The mobile version should inherit the current PRD direction: interruptible chunked streaming with a tap-to-Ask flow. The first mobile product should not attempt always-listening voice barge-in.
14
+
15
+ ## Model Fit For Mobile
16
+
17
+ | Model | Mobile Fit | Notes |
18
+ |---|---|---|
19
+ | Qwen2.5-3B-Instruct | Possible on high-end phones only | With 4-bit quantization, it may fit on flagship devices, but latency, RAM pressure, battery drain, and thermal throttling will vary by device and runtime. |
20
+ | Whisper-small | Borderline | Better suited to server or desktop-class environments. For mobile latency, prefer native iOS/Android speech APIs, Whisper-tiny, or Whisper-base. |
21
+ | QWEN-TTS-0.6B | Hardest to deploy locally | Voice cloning TTS adds audio pipeline cost beyond parameter count. On-device latency may be poor unless a mobile-optimized runtime path is available. |
22
+
23
+ ## Mobile Interaction Model
24
+
25
+ The mobile app should behave like a smart audiobook player:
26
+
27
+ ```text
28
+ Story chunk is playing
29
+ -> child taps Ask
30
+ -> app pauses local playback immediately
31
+ -> question is captured as text or voice
32
+ -> backend generates a short grounded answer
33
+ -> answer audio plays in the cloned voice
34
+ -> story resumes from the saved position
35
+ ```
36
+
37
+ Button-based interruption is the recommended first version. True voice barge-in, where the child talks over narration and the app detects it automatically, should remain a later research item because it requires echo cancellation, voice activity detection, full-duplex audio handling, and careful privacy UX.
38
+
39
+ ## Mobile Architecture
40
+
41
+ | Layer | Responsibility | Recommendation |
42
+ |---|---|---|
43
+ | Mobile app | Recording, playback, Ask interruption, local state, local cache | Native iOS/Android app or React Native/Flutter with native audio modules. |
44
+ | Backend API | Voice profile session, story chunk generation, Q&A answer generation, answer TTS | GPU backend using the same model stack as the Space demo. |
45
+ | Streaming/control channel | Request chunks, pause/resume, cancel queued work, receive generation status | WebSocket for bidirectional control; REST plus polling is acceptable for a prototype. |
46
+ | Audio delivery | Stream or download generated chunks | Prefer short chunk files with signed URLs and local prefetch cache. |
47
+ | Session state | Track story and interruption position | Store `story_id`, `voice_session_id`, `current_chunk_index`, playback state, and cache keys. |
48
+
49
+ The phone should own playback responsiveness. The server can cancel or deprioritize queued generation, but the app should pause current audio locally without waiting for backend confirmation.
50
+
51
+ ## Deployment Options
52
+
53
+ ### Option 1: Cloud-Backed Mobile App
54
+
55
+ The mobile app handles recording, story selection, interruption, playback, and local chunk caching. ASR, Q&A, and cloned-voice TTS run on a GPU backend.
56
+
57
+ **Best for:** first production prototype, hackathon follow-up, broad device support.
58
+
59
+ **Pros:** fastest path to reliable model latency, easier model updates, works across more phones.
60
+
61
+ **Cons:** requires backend hosting, network connectivity, and clear privacy messaging.
62
+
63
+ ### Option 2: Hybrid Mobile App
64
+
65
+ The app uses native or lightweight on-device ASR for the child's question, while Q&A and voice cloning TTS run on a backend. The phone manages interruptible chunk playback, local pause/resume, and cached story chunks.
66
+
67
+ **Best for:** better perceived latency while keeping heavy voice generation off-device.
68
+
69
+ **Pros:** practical performance, less backend work for transcription, smoother UX, and faster interruption response.
70
+
71
+ **Cons:** still depends on server-side TTS and model hosting.
72
+
73
+ ### Option 3: Fully On-Device App
74
+
75
+ The phone runs ASR, Q&A, voice cloning TTS, chunk generation, and playback locally.
76
+
77
+ **Best for:** long-term privacy-first product direction on selected flagship devices.
78
+
79
+ **Pros:** strongest offline and privacy story.
80
+
81
+ **Cons:** highest engineering risk; likely issues with memory, heat, battery drain, app size, cold start, audio session complexity, and inconsistent latency across devices.
82
+
83
+ ## Suggested Mobile Stack
84
+
85
+ | Capability | Near-Term Mobile Choice | Long-Term On-Device Candidate |
86
+ |---|---|---|
87
+ | Q&A | Backend `Qwen/Qwen2.5-3B-Instruct` | Quantized `Qwen2.5-1.5B-Instruct` or quantized `Qwen2.5-3B-Instruct` on flagship devices |
88
+ | ASR | Native iOS/Android speech APIs or backend Whisper | Whisper-tiny/base through a mobile-optimized runtime |
89
+ | Voice cloning TTS | Backend QWEN-TTS-0.6B | Mobile-optimized TTS/voice clone model if quality and latency are proven |
90
+ | Story narration | Backend chunk generation with mobile playback and local chunk cache | Pre-generate and store locally after first generation |
91
+ | Story Q&A audio | Generate short answers on demand | On-device Q&A plus server or local lightweight TTS |
92
+ | Interruption | Tap-to-Ask pauses local playback immediately | Voice barge-in after echo cancellation and VAD are proven |
93
+
94
+ ## Latency Expectations
95
+
96
+ | Flow | Target | Mobile Strategy |
97
+ |---|---|---|
98
+ | Story start | First chunk starts in 3-6 seconds on a good network | Generate the first chunk server-side, then prefetch the next chunks. |
99
+ | Narration interruption | Local playback pauses within 500ms after Ask tap | Pause on-device immediately; backend cancellation is best effort. |
100
+ | Child question transcription | 1-2 seconds | Prefer native mobile speech APIs or a tiny ASR model. |
101
+ | Q&A text answer | 1-3 seconds | Use short prompts, 1-2 sentence answers, and backend Qwen2.5-3B-Instruct. |
102
+ | Spoken Q&A answer | Starts in 4-8 seconds after question submit | Keep answer text short and generate TTS server-side. |
103
+ | Story resume | Under 1 second when next chunk is cached | Resume from saved chunk position; fetch missing chunks in the background. |
104
+ | Cache miss resume | 2-5 seconds | Show a lightweight loading state while the next chunk is generated or downloaded. |
105
+
106
+ Mobile latency depends heavily on network quality. The app should show resilient playback states instead of assuming the backend will always meet desktop demo timing.
107
+
108
+ ## Mobile Constraints
109
+
110
+ | Constraint | Product Impact | Recommendation |
111
+ |---|---|---|
112
+ | Network jitter | Chunks may arrive late or out of order. | Prefetch the next 1-2 chunks and keep a small playback buffer. |
113
+ | Battery and thermals | Continuous local ASR or on-device LLM/TTS can drain battery quickly. | Keep heavy models server-side for v1; avoid always-on microphone. |
114
+ | Audio session complexity | Recording while audio is playing is fragile on mobile. | Pause playback before recording the question; resume after answer playback. |
115
+ | Echo cancellation | Open-mic interruption can capture the story audio instead of the child. | Use tap-to-Ask first; research VAD and echo cancellation later. |
116
+ | App lifecycle | Incoming calls, lock screen, and backgrounding can interrupt playback. | Treat v1 as foreground-first; persist playback state and chunk cache. |
117
+ | Storage | Cached voice/story audio can grow quickly. | Cache by voice session, story ID, chunk index, and model version with TTL cleanup. |
118
+ | Privacy | Family voice data and child questions are sensitive. | Make upload, retention, deletion, and cache behavior explicit. |
119
+
120
+ ## Product Implications
121
+
122
+ - The first mobile app should be a hybrid app, not a full local AI runtime.
123
+ - The phone should own playback state and interruption responsiveness.
124
+ - Privacy messaging must be explicit: explain what audio is sent to the backend, how long it is retained, and whether generated voice samples are cached.
125
+ - If offline mode becomes a requirement, treat it as a separate research milestone, not a launch feature.
126
+ - Device qualification matters. Fully on-device AI should start with a short list of supported flagship phones.
127
+ - Chunk prefetching and caching are key to making bedtime story playback and resume feel instant.
128
+ - Always-listening barge-in should not be promised until echo cancellation, VAD, and mobile privacy UX are proven.
129
+
130
+ ## Future Research Tasks
131
+
132
+ 1. Benchmark quantized Qwen2.5-1.5B-Instruct and Qwen2.5-3B-Instruct on representative iOS and Android devices.
133
+ 2. Compare native speech APIs with Whisper-tiny/base for child speech accuracy and latency.
134
+ 3. Test whether QWEN-TTS-0.6B has a viable mobile runtime path or whether server-side TTS remains required.
135
+ 4. Prototype backend chunk generation and mobile prefetch cache keyed by story ID, voice profile, chunk index, and model version.
136
+ 5. Prototype tap-to-Ask interruption with local pause, backend cancellation/deprioritization, answer playback, and story resume.
137
+ 6. Measure behavior under poor mobile networks, app backgrounding, and audio session interruptions.
138
+ 7. Define privacy and retention policy before any real family audio is stored.
139
+
140
+ ## Decision
141
+
142
+ For the next phase, keep the model stack server-side and design the mobile app as a polished hybrid client with native playback, local chunk cache, tap-to-Ask interruption, and resume state. Revisit fully on-device deployment only after benchmarking smaller Q&A models, mobile ASR options, mobile-ready voice cloning TTS, and reliable barge-in audio handling.
mission.md CHANGED
@@ -2,26 +2,32 @@
2
 
3
  ## Product Vision
4
 
5
- **ReadBookMom** β€” a parent reads a bedtime story in their own cloned voice, powered by a small local model. Built as a Gradio app on Hugging Face Spaces.
6
 
7
  ## Problem
8
 
9
- Parents can't always be there at bedtime. Children want to hear *their parent's voice* reading to them. Existing TTS is generic and impersonal. Voice cloning APIs are expensive and require sending private audio to third parties.
10
 
11
  ## Demo Loop
12
 
13
  ```
14
- Parent records 15s of voice β†’ Pick a story β†’ Child hears it in parent's voice
15
  ↓
16
- Child asks a question β†’ Hears answer in parent's voice
 
 
 
 
17
  ```
18
 
 
 
19
  ## Hackathon Goal (2 days)
20
 
21
  Ship a working Hugging Face Space that demonstrates:
22
  1. **Voice cloning** β€” parent uploads/records a short audio clip
23
- 2. **Story narration** β€” QWEN-TTS-0.6B reads a children's story in the cloned voice
24
- 3. **Voice Q&A** β€” child asks a question about the story, gets an answer spoken in the cloned voice
25
 
26
  ## Target Demo User
27
 
@@ -32,32 +38,59 @@ A parent at a laptop who records their voice, picks a short story, and shows the
32
  | Criteria | Target |
33
  |---|---|
34
  | Voice clone from ≀ 30s audio | Recognizable similarity |
35
- | Story narration latency | First audio chunk in ≀ 5s |
36
- | Q&A answer (spoken) | Response in ≀ 8s |
 
 
 
37
  | Works on HF Spaces | Public link, no local setup needed |
38
  | Demo length | 3-minute live walkthrough |
 
39
 
40
  ## Scope
41
 
42
  **In scope:**
43
  - Upload/record parent voice sample (15–30s)
44
  - Select from 3–5 pre-loaded short stories (public domain)
45
- - Play story narrated in cloned voice
46
- - Ask a question about the story, hear answer in cloned voice
 
 
47
  - Clean, child-friendly UI (Google Stitch-inspired via gr.Server)
48
 
49
  **Out of scope:**
50
  - User accounts, auth, database
51
  - Offline mode, progress tracking
52
  - Multiple languages
53
- - Real-time streaming (batch generation is fine)
54
  - COPPA compliance (demo only)
55
 
56
  ## Guardrails (Lite)
57
 
58
  | Constraint | Implementation |
59
  |---|---|
60
- | Content grounding | Q&A answers sourced from story text only (system prompt) |
61
  | Voice privacy | All inference local on HF Space GPU β€” no audio leaves the server |
62
  | Child safety | Pre-curated stories only; no user-uploaded content |
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  ## Product Vision
4
 
5
+ **ReadBookMom** β€” a parent records a short voice sample, then a bedtime story and story Q&A are spoken back in that parent's cloned voice. The demo runs on local models inside a Gradio app on Hugging Face Spaces.
6
 
7
  ## Problem
8
 
9
+ Parents can't always be there at bedtime. Children want to hear *their parent's voice* reading to them. Existing TTS is generic and impersonal, while voice cloning APIs are expensive and require sending private family audio to third parties.
10
 
11
  ## Demo Loop
12
 
13
  ```
14
+ Parent records 15s of voice β†’ Pick a story β†’ Story starts in parent's voice
15
  ↓
16
+ Child taps Ask mid-story β†’ Narration pauses
17
+ ↓
18
+ Child asks a question β†’ Hears answer in parent's voice
19
+ ↓
20
+ Resume story from the same position
21
  ```
22
 
23
+ Latency and natural interruption are part of the demo promise: the story should start quickly, pause cleanly when the child wants to ask something, answer in the cloned voice, then resume without losing the story position.
24
+
25
  ## Hackathon Goal (2 days)
26
 
27
  Ship a working Hugging Face Space that demonstrates:
28
  1. **Voice cloning** β€” parent uploads/records a short audio clip
29
+ 2. **Interruptible story narration** β€” QWEN-TTS-0.6B streams paragraph-sized chunks in the cloned voice
30
+ 3. **Voice Q&A during narration** β€” child taps Ask, narration pauses, Qwen2.5-3B-Instruct answers from the story context, then QWEN-TTS-0.6B speaks the answer in the cloned voice
31
 
32
  ## Target Demo User
33
 
 
38
  | Criteria | Target |
39
  |---|---|
40
  | Voice clone from ≀ 30s audio | Recognizable similarity |
41
+ | Story start latency | First streamed audio chunk in ≀ 5s |
42
+ | Narration interruption | Ask tap pauses playback in ≀ 500ms and preserves story position |
43
+ | Cached story replay | Starts immediately after first generation |
44
+ | Q&A answer (spoken) | Spoken answer starts in ≀ 8s from question submit |
45
+ | Story resume latency | Resume from paused position in ≀ 1s when next chunk is cached |
46
  | Works on HF Spaces | Public link, no local setup needed |
47
  | Demo length | 3-minute live walkthrough |
48
+ | Privacy posture | Voice and Q&A stay on the Space runtime |
49
 
50
  ## Scope
51
 
52
  **In scope:**
53
  - Upload/record parent voice sample (15–30s)
54
  - Select from 3–5 pre-loaded short stories (public domain)
55
+ - Play story narrated in cloned voice with interruptible chunked streaming
56
+ - Pause narration through an Ask button, preserve the current story chunk, answer, then resume
57
+ - Cache generated narration per voice session and story
58
+ - Ask a question about the story, receive a grounded 1–2 sentence Qwen2.5-3B-Instruct answer, and hear it in the cloned voice
59
  - Clean, child-friendly UI (Google Stitch-inspired via gr.Server)
60
 
61
  **Out of scope:**
62
  - User accounts, auth, database
63
  - Offline mode, progress tracking
64
  - Multiple languages
65
+ - Always-listening voice barge-in, echo cancellation, and open-mic interruption
66
  - COPPA compliance (demo only)
67
 
68
  ## Guardrails (Lite)
69
 
70
  | Constraint | Implementation |
71
  |---|---|
72
+ | Content grounding | Qwen2.5-3B-Instruct receives the selected story text plus a strict answer-from-story instruction |
73
  | Voice privacy | All inference local on HF Space GPU β€” no audio leaves the server |
74
  | Child safety | Pre-curated stories only; no user-uploaded content |
75
 
76
+ ## Latency Strategy
77
+
78
+ | Bottleneck | Strategy |
79
+ |---|---|
80
+ | Voice setup | Compute and cache the voice representation immediately after recording. |
81
+ | Story narration | Use interruptible chunked streaming: generate the first paragraph chunk, play it immediately, then continue generating queued chunks. |
82
+ | Interruption | Add an Ask state that pauses playback, cancels or deprioritizes queued narration generation, and stores the current chunk index. |
83
+ | Story replay | Cache full generated narration by voice session and story ID. |
84
+ | Q&A context | Send the current story position plus the most relevant story passages to Qwen2.5-3B-Instruct instead of the full story when possible. |
85
+ | Q&A length | Cap answers to 1–2 short child-friendly sentences before sending to TTS. |
86
+ | Story resume | Resume from the paused chunk after the spoken answer; use cached next chunks when available. |
87
+ | Voice question input | Load ASR only when audio questions are used; text questions bypass ASR. |
88
+
89
+ ## Design Review Notes
90
+
91
+ | Topic | Critique | Upgrade |
92
+ |---|---|---|
93
+ | Privacy | An external LLM API would weaken the privacy story even if audio stayed local. | Use Qwen2.5-3B-Instruct for local story Q&A so the demo has one clear privacy narrative. |
94
+ | Latency | A 3B-class Q&A model is a better fit for the demo loop than an 8B-class model, but TTS and interruption responsiveness remain the user-visible bottlenecks. | Cache voice setup, stream chunked narration, make playback cancellable, cap Q&A output, and use 4-bit or 8-bit loading on T4. |
95
+ | Demo clarity | Voice cloning, narration, ASR, and Q&A can feel like too many moving parts. | Present the loop as three simple actions: record, listen, ask. |
96
+
sprint.md CHANGED
@@ -1,7 +1,7 @@
1
  # Sprint Plan β€” 2-Day Hackathon
2
 
3
  ## Goal
4
- Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&A in that voice.
5
 
6
  ---
7
 
@@ -13,9 +13,9 @@ Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&
13
  |---|---|---|---|
14
  | 1 | Set up repo: `app.py`, `requirements.txt`, `stories/` | 30m | ☐ |
15
  | 2 | Load QWEN-TTS-0.6B locally, test basic TTS (text β†’ audio) | 1h | ☐ |
16
- | 3 | Implement voice cloning: reference audio + text β†’ cloned speech | 1.5h | ☐ |
17
  | 4 | Add 3 short stories as `.txt` files (public domain) | 30m | ☐ |
18
- | 5 | Wire up: pick story β†’ generate narration in cloned voice | 30m | ☐ |
19
 
20
  **Checkpoint:** Can generate a story audio file in a cloned voice from CLI.
21
 
@@ -25,11 +25,11 @@ Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&
25
  |---|---|---|---|
26
  | 6 | Build Gradio app with 3 tabs (Clone, Listen, Ask) | 1h | ☐ |
27
  | 7 | Tab 1 (Clone): `gr.Audio` record/upload + preview button | 45m | ☐ |
28
- | 8 | Tab 2 (Listen): story dropdown + play narration button | 45m | ☐ |
29
- | 9 | Add Whisper-small for child voice input (ASR) | 30m | ☐ |
30
- | 10 | Tab 3 (Ask): voice/text input β†’ GPT-4o-mini answer β†’ TTS in cloned voice | 1h | ☐ |
31
 
32
- **Checkpoint:** Full loop works locally β€” clone β†’ listen β†’ ask. Ugly but functional.
33
 
34
  ---
35
 
@@ -43,7 +43,7 @@ Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&
43
  | 12 | Stitch-style CSS: color palette, card layout, rounded corners, fonts | 1h | ☐ |
44
  | 13 | Recording UX: waveform animation, countdown timer, status indicators | 1h | ☐ |
45
  | 14 | Story gallery: cover images (AI-generated or placeholder), card grid | 45m | ☐ |
46
- | 15 | Loading states: spinner/progress during TTS generation | 30m | ☐ |
47
  | 16 | Mobile-responsive check (parents use laptops, demo on projector) | 15m | ☐ |
48
 
49
  **Checkpoint:** App looks polished and professional. Ready for live demo.
@@ -52,10 +52,10 @@ Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&
52
 
53
  | # | Task | Time | Done |
54
  |---|---|---|---|
55
- | 17 | Create HF Space (GPU T4), push code, verify model downloads | 1h | ☐ |
56
- | 18 | Set `OPENAI_API_KEY` in Space secrets | 5m | ☐ |
57
- | 19 | End-to-end test on live Space (clone β†’ listen β†’ ask) | 30m | ☐ |
58
- | 20 | Fix latency issues: cache model, preload weights at startup | 45m | ☐ |
59
  | 21 | Add error handling: graceful failures, loading messages | 30m | ☐ |
60
  | 22 | Record backup demo video (in case live demo fails) | 30m | ☐ |
61
  | 23 | Write README.md for the Space (screenshot, description) | 15m | ☐ |
@@ -70,9 +70,12 @@ Ship a public Hugging Face Space: parent clones voice β†’ child hears story + Q&
70
  | Risk | Mitigation |
71
  |---|---|
72
  | QWEN-TTS-0.6B doesn't clone well | Fall back to longer reference audio (30s+); or use CosyVoice as backup model |
73
- | T4 OOM with TTS + Whisper + Gradio | Load Whisper only on demand; use `whisper-tiny` if needed |
74
  | HF Space cold start too slow | Use persistent Space (not sleep); preload model in `app.py` global scope |
75
- | GPT-4o-mini rate limit | Cache answers per story; answers are short, limit won't hit for demo |
 
 
 
76
  | Live demo fails | Pre-recorded backup video ready |
77
 
78
  ---
@@ -105,7 +108,18 @@ VoiceClone/
105
 
106
  - **No database** β€” stateless demo, voice samples held in memory/session
107
  - **No auth** β€” open access for hackathon judges
108
- - **No streaming** β€” batch TTS is fine for short stories (< 2 min audio)
109
- - **GPT-4o-mini over GPT-4** β€” 10x cheaper, fast enough for short Q&A
110
- - **Stories < 4K tokens** β€” no RAG needed, full text in prompt
 
111
  - **Single `app.py`** β€” keep it simple, refactor later
 
 
 
 
 
 
 
 
 
 
 
1
  # Sprint Plan β€” 2-Day Hackathon
2
 
3
  ## Goal
4
+ Ship a public Hugging Face Space: parent clones voice β†’ story streams in that voice β†’ child can interrupt, ask, hear the answer, and resume.
5
 
6
  ---
7
 
 
13
  |---|---|---|---|
14
  | 1 | Set up repo: `app.py`, `requirements.txt`, `stories/` | 30m | ☐ |
15
  | 2 | Load QWEN-TTS-0.6B locally, test basic TTS (text β†’ audio) | 1h | ☐ |
16
+ | 3 | Implement voice cloning and cache voice representation after recording | 1.5h | ☐ |
17
  | 4 | Add 3 short stories as `.txt` files (public domain) | 30m | ☐ |
18
+ | 5 | Wire up: pick story β†’ stream first narration chunk, track chunk index, cache story audio | 30m | ☐ |
19
 
20
  **Checkpoint:** Can generate a story audio file in a cloned voice from CLI.
21
 
 
25
  |---|---|---|---|
26
  | 6 | Build Gradio app with 3 tabs (Clone, Listen, Ask) | 1h | ☐ |
27
  | 7 | Tab 1 (Clone): `gr.Audio` record/upload + preview button | 45m | ☐ |
28
+ | 8 | Tab 2 (Listen): story dropdown + play/pause/resume controls for streamed chunks | 45m | ☐ |
29
+ | 9 | Add on-demand ASR for child voice input; use lighter ASR fallback if needed | 30m | ☐ |
30
+ | 10 | Tab 3 (Ask): interrupt narration β†’ short grounded Qwen answer β†’ TTS β†’ resume story | 1h | ☐ |
31
 
32
+ **Checkpoint:** Full loop works locally β€” clone β†’ listen β†’ interrupt β†’ ask β†’ resume. Ugly but functional.
33
 
34
  ---
35
 
 
43
  | 12 | Stitch-style CSS: color palette, card layout, rounded corners, fonts | 1h | ☐ |
44
  | 13 | Recording UX: waveform animation, countdown timer, status indicators | 1h | ☐ |
45
  | 14 | Story gallery: cover images (AI-generated or placeholder), card grid | 45m | ☐ |
46
+ | 15 | Loading states: playback status, paused state, TTS progress, and background chunk generation | 30m | ☐ |
47
  | 16 | Mobile-responsive check (parents use laptops, demo on projector) | 15m | ☐ |
48
 
49
  **Checkpoint:** App looks polished and professional. Ready for live demo.
 
52
 
53
  | # | Task | Time | Done |
54
  |---|---|---|---|
55
+ | 17 | Create HF Space (T4 with 4-bit/8-bit loading, or A10G for headroom), push code, verify model downloads | 1h | ☐ |
56
+ | 18 | Confirm no external LLM API secrets are required; set `HF_TOKEN` only if gated models require it | 5m | ☐ |
57
+ | 19 | End-to-end test on live Space (clone β†’ listen β†’ interrupt β†’ ask β†’ resume) | 30m | ☐ |
58
+ | 20 | Fix latency issues: preload weights, cache voice/story audio, cap Q&A tokens, validate pause/resume | 45m | ☐ |
59
  | 21 | Add error handling: graceful failures, loading messages | 30m | ☐ |
60
  | 22 | Record backup demo video (in case live demo fails) | 30m | ☐ |
61
  | 23 | Write README.md for the Space (screenshot, description) | 15m | ☐ |
 
70
  | Risk | Mitigation |
71
  |---|---|
72
  | QWEN-TTS-0.6B doesn't clone well | Fall back to longer reference audio (30s+); or use CosyVoice as backup model |
73
+ | GPU OOM with TTS + Whisper + Qwen + Gradio | Use 4-bit/8-bit Qwen loading on T4; prefer A10G for the live demo; load Whisper only on demand; use `whisper-tiny` if needed |
74
  | HF Space cold start too slow | Use persistent Space (not sleep); preload model in `app.py` global scope |
75
+ | Qwen answer latency too slow | Keep answers to 1–2 sentences; cap story prompt length; cache answers per story/question pair |
76
+ | Story narration feels slow | Stream paragraph chunks; play the first chunk quickly; continue remaining chunks in the background; cache full narration |
77
+ | Interrupt/resume feels brittle | Track playback state, current chunk index, queued generation jobs, and cached next chunks |
78
+ | ASR adds too much delay | Let text questions bypass ASR; use Whisper-tiny/base or browser transcription for demo mode |
79
  | Live demo fails | Pre-recorded backup video ready |
80
 
81
  ---
 
108
 
109
  - **No database** β€” stateless demo, voice samples held in memory/session
110
  - **No auth** β€” open access for hackathon judges
111
+ - **Interruptible chunked streaming** β€” play paragraph chunks quickly, pause on Ask, answer, then resume from the saved story position
112
+ - **Qwen2.5-3B-Instruct for Q&A** β€” keeps story comprehension local while improving latency and GPU fit
113
+ - **Short grounded Q&A** β€” retrieve relevant story passages, cap answers to 1–2 sentences, then synthesize audio
114
+ - **Button-based interruption first** β€” tap Ask to pause narration; always-listening voice barge-in is out of scope for the hackathon
115
  - **Single `app.py`** β€” keep it simple, refactor later
116
+
117
+ ---
118
+
119
+ ## Review Notes
120
+
121
+ | Area | Critique | Upgrade |
122
+ |---|---|---|
123
+ | Model plan | Replacing an external Q&A API with Qwen2.5-3B-Instruct removes API risk while keeping latency practical. | Treat T4 with quantization as viable; use A10G when demo reliability matters more than cost. |
124
+ | Secrets | The old plan required an external LLM API secret, which contradicts the privacy-first positioning. | Remove LLM API secrets from deployment; use only HF credentials when required for model access. |
125
+ | Demo schedule | The original plan left little time for model loading, user-visible wait states, and interruption edge cases. | Add explicit validation around model downloads, quantization, cold-start behavior, chunked playback, pause/resume, and cache hits. |
tech_stack.md CHANGED
@@ -10,15 +10,15 @@ Single Python file Gradio app. Everything runs in one process on a GPU-enabled H
10
  β”‚ β”‚
11
  β”‚ app.py (Gradio + gr.Server) β”‚
12
  β”‚ β”œβ”€β”€ UI: Stitch-styled tabs/cards β”‚
13
- β”‚ β”œβ”€β”€ QWEN-TTS-0.6B (voice clone + narration) β”‚
14
  β”‚ β”œβ”€β”€ Whisper-small (ASR for child questions) β”‚
15
- β”‚ └── OpenAI GPT-4o-mini (Q&A from story text) β”‚
16
  β”‚ β”‚
17
  β”‚ stories/ (3–5 .txt files, public domain) β”‚
18
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19
  ```
20
 
21
- No database. No external storage. Stories are flat files. Audio is generated on demand.
22
 
23
  ---
24
 
@@ -30,13 +30,14 @@ No database. No external storage. Stories are flat files. Audio is generated on
30
  | `gr.Server` | Custom CSS/JS for Stitch-style polish (animations, palette, layout) |
31
  | `gr.Audio` | Record/upload parent voice sample |
32
  | `gr.Dropdown` / `gr.Gallery` | Story selection with cover art |
33
- | `gr.Audio` (output) | Playback of narrated story / Q&A answer |
34
  | `gr.Textbox` + `gr.Audio` (input) | Child question via text or voice |
 
35
 
36
  **UI Tabs:**
37
  1. **🎀 Clone Voice** β€” record/upload 15–30s, preview clone
38
- 2. **πŸ“– Listen** β€” pick story, hear it in cloned voice
39
- 3. **❓ Ask** β€” ask about the story, hear answer in cloned voice
40
 
41
  ---
42
 
@@ -46,10 +47,11 @@ No database. No external storage. Stories are flat files. Audio is generated on
46
  |---|---|
47
  | Model | `Qwen/Qwen-TTS-0.6B` from Hugging Face Hub |
48
  | Size | 0.6B params β€” fits comfortably on T4 (16GB VRAM) |
49
- | Capability | Zero-shot voice cloning + TTS from text |
50
  | Input | Reference audio (β‰₯5s) + target text |
51
  | Output | WAV audio in cloned voice |
52
  | Latency | ~3–5s for a paragraph on T4 |
 
53
 
54
  ---
55
 
@@ -57,9 +59,10 @@ No database. No external storage. Stories are flat files. Audio is generated on
57
 
58
  | Choice | Detail |
59
  |---|---|
60
- | Model | `openai/whisper-small` (local, 244M params) |
61
  | Why | Fast, accurate for short child utterances; fits in GPU alongside TTS |
62
- | Fallback | `gr.Audio` with browser transcription if GPU memory is tight |
 
63
 
64
  ---
65
 
@@ -67,10 +70,12 @@ No database. No external storage. Stories are flat files. Audio is generated on
67
 
68
  | Choice | Detail |
69
  |---|---|
70
- | Model | OpenAI `gpt-4o-mini` (API) |
71
- | Why | Cheap, fast, good at grounded Q&A from short context |
72
- | Method | Full story text in system prompt + child question β†’ short answer |
73
- | No RAG needed | Stories are short (< 4K tokens); entire text fits in context |
 
 
74
 
75
  ---
76
 
@@ -93,17 +98,44 @@ Each file: title on line 1, text below. No metadata DB needed.
93
  |---|---|
94
  | Platform | Hugging Face Spaces |
95
  | SDK | Gradio |
96
- | Hardware | GPU T4 (free tier) or A10G (paid, faster) |
97
  | Deploy | `git push` to HF Space repo |
98
- | Secrets | `OPENAI_API_KEY` in HF Space settings |
99
  | Domain | `huggingface.co/spaces/{user}/readbookmom` |
100
 
101
  ---
102
 
103
- ## 7. Local Dev
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  ```bash
106
- pip install gradio transformers torch openai whisper
107
  python app.py
108
  # β†’ http://localhost:7860
109
  ```
@@ -112,21 +144,21 @@ No Docker, no DB, no infra setup.
112
 
113
  ---
114
 
115
- ## 8. Dependencies
116
 
117
  ```
118
  gradio>=5.0
119
  transformers
120
  torch
121
  accelerate
122
- openai
123
  soundfile
124
  numpy
125
  ```
126
 
127
  ---
128
 
129
- ## 9. Google Stitch UI Customization (via gr.Server)
130
 
131
  `gr.Server` injects custom HTML/CSS/JS to achieve Stitch-quality polish:
132
 
@@ -136,3 +168,15 @@ numpy
136
  - **Custom favicon + title**: Branded for demo presentation
137
 
138
  All in a `static/` folder loaded by gr.Server mount.
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  β”‚ β”‚
11
  β”‚ app.py (Gradio + gr.Server) β”‚
12
  β”‚ β”œβ”€β”€ UI: Stitch-styled tabs/cards β”‚
13
+ β”‚ β”œβ”€β”€ QWEN-TTS-0.6B (voice clone + chunks) β”‚
14
  β”‚ β”œβ”€β”€ Whisper-small (ASR for child questions) β”‚
15
+ β”‚ └── Qwen2.5-3B-Instruct (story Q&A) β”‚
16
  β”‚ β”‚
17
  β”‚ stories/ (3–5 .txt files, public domain) β”‚
18
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19
  ```
20
 
21
+ No database. No external storage. No external LLM API. Stories are flat files. Audio is generated as interruptible chunks, then cached in the session for replay and resume.
22
 
23
  ---
24
 
 
30
  | `gr.Server` | Custom CSS/JS for Stitch-style polish (animations, palette, layout) |
31
  | `gr.Audio` | Record/upload parent voice sample |
32
  | `gr.Dropdown` / `gr.Gallery` | Story selection with cover art |
33
+ | `gr.Audio` (output) | Playback of streamed story chunks / Q&A answer |
34
  | `gr.Textbox` + `gr.Audio` (input) | Child question via text or voice |
35
+ | Play/Pause/Ask buttons | Manual interruption and resume without open-mic barge-in |
36
 
37
  **UI Tabs:**
38
  1. **🎀 Clone Voice** β€” record/upload 15–30s, preview clone
39
+ 2. **πŸ“– Listen** β€” pick story, hear streamed chunks in cloned voice
40
+ 3. **❓ Ask** β€” pause narration, ask about the story, hear answer, resume
41
 
42
  ---
43
 
 
47
  |---|---|
48
  | Model | `Qwen/Qwen-TTS-0.6B` from Hugging Face Hub |
49
  | Size | 0.6B params β€” fits comfortably on T4 (16GB VRAM) |
50
+ | Capability | Zero-shot voice cloning + TTS from text chunks |
51
  | Input | Reference audio (β‰₯5s) + target text |
52
  | Output | WAV audio in cloned voice |
53
  | Latency | ~3–5s for a paragraph on T4 |
54
+ | Optimization | Cache the voice representation after recording; generate story audio in interruptible paragraph chunks |
55
 
56
  ---
57
 
 
59
 
60
  | Choice | Detail |
61
  |---|---|
62
+ | Model | Whisper-small checkpoint via Transformers (local, 244M params) |
63
  | Why | Fast, accurate for short child utterances; fits in GPU alongside TTS |
64
+ | Load strategy | Load only when the Ask tab receives audio; text questions bypass ASR |
65
+ | Fallback | Whisper-tiny/base or browser transcription if GPU memory or latency is tight |
66
 
67
  ---
68
 
 
70
 
71
  | Choice | Detail |
72
  |---|---|
73
+ | Model | `Qwen/Qwen2.5-3B-Instruct` |
74
+ | Why | Strong small-model instruction following with lower latency and VRAM pressure than an 8B-class model |
75
+ | Method | Current story position + relevant story passages + strict answer-from-story instruction + child question β†’ short answer |
76
+ | Retrieval | Simple paragraph keyword overlap is enough for the demo; full-story prompt remains a fallback |
77
+ | Output cap | 1–2 child-friendly sentences, typically 40–80 new tokens |
78
+ | Runtime note | Use 4-bit/8-bit loading on T4; use bf16 or 8-bit on A10G for more headroom |
79
 
80
  ---
81
 
 
98
  |---|---|
99
  | Platform | Hugging Face Spaces |
100
  | SDK | Gradio |
101
+ | Hardware | T4 with quantized Qwen for the budget path; A10G for lower risk live demos |
102
  | Deploy | `git push` to HF Space repo |
103
+ | Secrets | None for LLM inference; `HF_TOKEN` only if any selected model requires gated access |
104
  | Domain | `huggingface.co/spaces/{user}/readbookmom` |
105
 
106
  ---
107
 
108
+ ## 7. Latency Plan
109
+
110
+ | Flow | Target | Implementation |
111
+ |---|---|---|
112
+ | Voice setup | One-time after recording | Compute and cache the voice representation before story generation. |
113
+ | Story narration start | First streamed chunk in ≀ 5s | Split the story into paragraph chunks; synthesize and play the first chunk first. |
114
+ | Narration interruption | Pause in ≀ 500ms after Ask tap | Stop playback, preserve current chunk index, and cancel or deprioritize queued narration jobs. |
115
+ | Q&A interruption loop | Spoken answer starts in ≀ 8s | Use current story position, retrieve relevant passages, cap answer length, then synthesize the final answer. |
116
+ | Story resume | ≀ 1s when next chunk is cached | Resume from the paused chunk or the next queued chunk after the answer finishes. |
117
+ | Story replay | Immediate after first generation | Cache generated audio by voice session and story ID. |
118
+ | Child audio transcription | 1–2s target | Load ASR only for audio questions; prefer lighter ASR fallback for demo mode. |
119
+ | Q&A text answer | 1–3s target | Send only relevant story passages to Qwen and cap output tokens. |
120
+ | Spoken Q&A answer | ≀ 8s total target | Synthesize only the final short answer, not intermediate reasoning or context. |
121
+
122
+ ## 8. Interaction State
123
+
124
+ | State | Meaning | Key Data |
125
+ |---|---|---|
126
+ | `playing` | Story chunk is currently playing. | `story_id`, `voice_session_id`, `current_chunk_index` |
127
+ | `paused` | Playback is paused by user action. | Current chunk, elapsed position if available |
128
+ | `asking` | Narration is interrupted while the child asks a question. | Current chunk, relevant passages, pending ASR input |
129
+ | `answering` | Qwen answer or answer TTS is being generated. | Question text, short answer, answer audio path |
130
+ | `resuming` | Answer finished and story playback is restarting. | Resume chunk index, cached next chunk |
131
+ | `finished` | Story narration completed. | Cached full-story audio |
132
+
133
+ ---
134
+
135
+ ## 9. Local Dev
136
 
137
  ```bash
138
+ pip install gradio transformers torch accelerate bitsandbytes soundfile numpy
139
  python app.py
140
  # β†’ http://localhost:7860
141
  ```
 
144
 
145
  ---
146
 
147
+ ## 10. Dependencies
148
 
149
  ```
150
  gradio>=5.0
151
  transformers
152
  torch
153
  accelerate
154
+ bitsandbytes
155
  soundfile
156
  numpy
157
  ```
158
 
159
  ---
160
 
161
+ ## 11. Google Stitch UI Customization (via gr.Server)
162
 
163
  `gr.Server` injects custom HTML/CSS/JS to achieve Stitch-quality polish:
164
 
 
168
  - **Custom favicon + title**: Branded for demo presentation
169
 
170
  All in a `static/` folder loaded by gr.Server mount.
171
+
172
+ ---
173
+
174
+ ## 12. Review Notes
175
+
176
+ | Area | Critique | Upgrade |
177
+ |---|---|---|
178
+ | Privacy | Using an external Q&A API would undermine the local-inference claim. | Qwen2.5-3B-Instruct keeps questions, story text, and generated answers inside the Space runtime. |
179
+ | GPU fit | QWEN-TTS-0.6B, Whisper-small, and a 3B-class LLM are a more realistic fit for a single Space than an 8B-class LLM, but running all three hot can still pressure T4. | Quantize Qwen on T4, use A10G for demo headroom, cache voice/story artifacts, and load ASR only when the Ask tab receives audio. |
180
+ | Latency | Full-story generation and spoken Q&A can feel slow if every step waits for complete outputs. | Use interruptible paragraph chunks, cache full narration, retrieve only relevant passages, and synthesize only short final answers. |
181
+ | Interaction | Streaming without cancellation can still feel rigid if the child must wait for a chunk to finish. | Add explicit playback state, Ask interruption, queued job cancellation/deprioritization, and resume from the saved chunk. |
182
+ | Dependencies | External LLM SDKs and API secrets are no longer aligned with the model choice. | Use local inference dependencies and optional HF authentication only. |