A voice-powered language tutor for kids, built for Raspberry Pi.
ChocoPi listens for a wake word, then holds a live conversation to help children practice English, Korean, Spanish, or Chinese. Each language has its own wake word, sleep word, and teaching style — all configurable.
chocopi-demo.mp4
- Wake word detection runs on-device using OpenWakeWord
- Once triggered, a voice conversation starts via the OpenAI Realtime API
- The assistant adapts to the child's age, native language, and comprehension level
- Sessions end with a language-specific sleep word or timeout
- Conversation history is summarized and persisted for continuity across sessions
- 4 languages — English, Korean, Spanish, and Chinese
- On-device wake words — "Hey Choco", "Anyeong Choco", "Hola Choco", "Nihao Choco"
- User profiles — per-child age, native language, and learning levels
- Session memory — remembers jokes, vocab, topics, and progress across conversations
- Display support — animated character and live transcript panel (pygame-ce); also works headless!
- Microphone and speaker (Bluetooth or wired)
- OpenAI API key with Realtime API access (sessions use the OpenAI Realtime API, which is billed per minute — see pricing)
- Python 3.11 (required —
tflite-runtimehas no wheels for 3.12+)
Tested on Raspberry Pi 4+ with 64-bit Raspberry Pi OS Lite (Trixie and Bookworm).
-
Flash Raspberry Pi OS Lite (64-bit) with rpi-imager (configure user, SSH, WiFi)
-
SSH into your Pi and run:
bash <(curl -fsSL https://raw.githubusercontent.com/codesmax/chocopi/main/install.sh)Or clone first:
git clone https://github.com/codesmax/chocopi.git cd chocopi ./install.shThe installer handles system dependencies, audio stack setup, Python environment, and systemd service creation.
git clone https://github.com/codesmax/chocopi.git
cd chocopi
# Install uv if needed
pipx install uv
# Create venv with Python 3.11 and install
uv venv .venv --python 3.11
source .venv/bin/activate # or .venv\Scripts\activate on Windows
uv pip install -e .
# Configure
cp .env.example .env # add your OPENAI_API_KEY
vi config.yml # set active_profile, languages, etc.
# Run
./chocopiNote: On Windows, skip the
./chocopilauncher (it's a bash script) and run directly withpython -m chocopiinstead. WSL is also an option.
All settings live in two files:
| File | Contents |
|---|---|
.env |
OPENAI_API_KEY |
config.yml |
Profiles, languages, wake/sleep words, prompts, audio settings, display settings, OpenAI model config |
Profiles let multiple users share one device. Each profile specifies age, native language, and learning languages with comprehension levels. Set active_profile in config.yml to switch.
For Bluetooth microphone and speaker support:
# Pair your device
sudo -u chocopi bluetoothctl
scan on
pair <MAC_ADDRESS>
trust <MAC_ADDRESS>
connect <MAC_ADDRESS>
exit
# Restart WirePlumber and ChocoPi
sudo -u chocopi XDG_RUNTIME_DIR=/var/run/user/$(id -u chocopi) systemctl --user restart wireplumber
sudo systemctl restart chocopisudo systemctl start chocopi # Start
sudo systemctl stop chocopi # Stop
sudo systemctl status chocopi # Check status
sudo journalctl -u chocopi -f # View logsCHOCO_LOG=DEBUG ./chocopi # verbose logging (default: INFO)
CHOCO_DISPLAY=0 ./chocopi # disable pygame-ce UI (default: enabled)
CHOCO_LOG=DEBUG CHOCO_DISPLAY=0 ./chocopipython -m sounddevice # list audio devices
pactl list sinks short # list output devices (Linux)
pactl list sources short # list input devices (Linux)
wpctl status # PipeWire/WirePlumber status
bluetoothctl # manage Bluetooth connections
sudo journalctl -u chocopi -f # service logs on Pichocopi # Bash entry point
src/chocopi/ # Python package
chocopi.py # Main orchestrator
wakeword.py # Wake word detection
conversation.py # OpenAI Realtime API session
audio.py # Audio I/O
display.py # Optional pygame-ce UI
memory.py # Session memory persistence
language.py # Language detection
config.py # Config and env loading
config.yml # Runtime configuration
models/ # Wake word models (.tflite + .onnx)
assets/ # Sounds, images, fonts
install/ # Systemd service + WirePlumber configs
data/ # Per-profile memory files (gitignored)
- Wake word false activations - nearby environmental noise can trigger false activations of wake words. Limit supported languages to those being used and keep microphone away from TVs and other sources of loud, continuous audio.
- Speech comprehension - issue is variable depending on environment and microphone used. Experiment with
input_gain, VAD and noise reduction settings. - Python 3.11 only —
tflite-runtime(required by OpenWakeWord) has no wheels for Python 3.12+. This is an upstream limitation with no current workaround. - Windows — works, but the
./chocopibash launcher isn't usable; runpython -m chocopidirectly instead (or use WSL). - Bluetooth mic dropouts — if the microphone stops working after a reboot or OS update, the device may have reverted to the A2DP profile. Re-connect and confirm it's using HSP/HFP (
bluetoothctl).
- LiveKit + Ultravox integration with open weight model support
- Support tool calling for image display in instruction
- Expanded language + wake word support
Contributions are welcome. A few good starting points:
- Add a language — add an entry under
languagesinconfig.ymlwith a wake word, sleep word, and model name. Wake word models (.onnx/.tflite) come from OpenWakeWord. - Improve tutor prompts — the
promptssection inconfig.ymldrives all tutor behavior and is easy to iterate on without touching Python. - Bug reports / feature requests — open an issue on GitHub.
See AGENTS.md for architecture notes, key files, and change guidelines.
MIT
