vault-sync: 2026-10-14 11:24 (leonard)
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# Apollo — Persistent Voice Agent
|
||||
|
||||
**Phase 3** · Built 2026-10-14
|
||||
|
||||
## Architecture
|
||||
|
||||
Local voice loop: STT → LLM → TTS with barge-in.
|
||||
|
||||
```
|
||||
Microphone → faster-whisper (STT) → LLM endpoint → edge-tts (TTS) → ffplay
|
||||
↑ |
|
||||
└────────── barge-in detection ────────────────┘
|
||||
```
|
||||
|
||||
## Stack
|
||||
|
||||
| Component | Tool | Why |
|
||||
|-----------|------|-----|
|
||||
| STT | `faster-whisper` (tiny) | Local, fast, no API key, English-optimized |
|
||||
| LLM | Configurable endpoint | Defaults to `http://127.0.0.1:1920/v1/chat/completions` (LFM2.5) |
|
||||
| TTS | `edge-tts` 7.2.7 | Free, 6 high-quality neural voices, local |
|
||||
| Audio capture | `sounddevice` | Cross-platform, low latency |
|
||||
| Playback | `ffplay` (ffmpeg) | Killable subprocess for barge-in |
|
||||
| State | `apollo_state.json` | Live status read by dashboard |
|
||||
|
||||
## Voices
|
||||
|
||||
| Name | Edge TTS ID |
|
||||
|------|------------|
|
||||
| Aria (default) | `en-US-AriaNeural` |
|
||||
| Jenny | `en-US-JennyNeural` |
|
||||
| Guy | `en-US-GuyNeural` |
|
||||
| Ana | `en-US-AnaNeural` |
|
||||
| Christopher | `en-US-ChristopherNeural` |
|
||||
| Eric | `en-US-EricNeural` |
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `~/Projects/hermes-dashboard/apollo/apollo_voice.py` | Voice loop script |
|
||||
| `~/Projects/hermes-dashboard/apollo/apollo_state.json` | Live state (auto-generated) |
|
||||
| `~/Projects/hermes-dashboard/apollo/apollo_output.mp3` | Last TTS output (auto-generated) |
|
||||
|
||||
## Launch
|
||||
|
||||
### From dashboard
|
||||
Toggle "▶ Start Apollo" in the Apollo card. Select voice first.
|
||||
|
||||
### From terminal
|
||||
```bash
|
||||
cd ~/Projects/hermes-dashboard/apollo
|
||||
/path/to/hermes/venv/Scripts/python apollo_voice.py --voice Aria
|
||||
```
|
||||
|
||||
Stop with Ctrl+C or dashboard "Stop Apollo" button.
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Continuous listening mode**: Captures mic until 1.5s of silence detected.
|
||||
2. **Transcription**: `faster-whisper` tiny model, CPU int8 (fast enough for real-time).
|
||||
3. **LLM**: POST to configured endpoint with system prompt for concise voice responses.
|
||||
4. **TTS**: `edge-tts` generates MP3, played via `ffplay`.
|
||||
5. **Barge-in**: During playback, checks mic energy every 300ms. If above threshold, kills ffplay and listens again.
|
||||
|
||||
## Current limits
|
||||
|
||||
- **LLM requires a running endpoint**. Without LFM2.5 or similar running on port 1920, Apollo echoes "(No LLM endpoint)" and skips TTS. Start the model first or update `llm_endpoint` in `apollo_state.json`.
|
||||
- **Wake word**: Uses continuous VAD (silence detection), not wake-word. Sherpa "hey Jimmy" runs separately in Hermes and is not integrated here.
|
||||
- **Streaming**: TTS generates full MP3 before playback starts (not streaming synthesis). Latency is ~2-4s for short responses.
|
||||
- **GPU**: faster-whisper runs on CPU (int8). Tiny model is fast enough for real-time use (~200ms for short utterances).
|
||||
|
||||
## State file schema
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "idle|listening|transcribing|thinking|speaking|stopped",
|
||||
"voice": "Aria",
|
||||
"mode": "continuous",
|
||||
"last_utterance": "...",
|
||||
"last_response": "...",
|
||||
"last_active": "2026-10-14T...",
|
||||
"llm_endpoint": "http://127.0.0.1:1920/v1/chat/completions"
|
||||
}
|
||||
```
|
||||
|
||||
## Wiring to dashboard
|
||||
|
||||
The Streamlit dashboard Apollo card reads `apollo_state.json` every render and shows live status. Start/stop buttons spawn/kill the Python process directly.
|
||||
Reference in New Issue
Block a user