Build a tiny offline assistant on Raspberry Pi: combine AI HAT+ 2 with a local voice stack
edge-aivoicetutorial

Build a tiny offline assistant on Raspberry Pi: combine AI HAT+ 2 with a local voice stack

UUnknown
2026-02-27
10 min read
Advertisement

Build a privacy-first offline voice assistant on Raspberry Pi 5 + AI HAT+ 2 with local STT, LLM inference, and TTS—runnable code and wiring tips.

Hook: stop reinventing voice stacks — build a tiny offline assistant on Raspberry Pi 5

If you've ever wasted days stitching together cloud APIs for speech recognition, model inference, and TTS — only to worry about cost, privacy, or flaky connectivity — this guide is for you. In 2026 the edge AI story has matured: the AI HAT+ 2 paired with a Raspberry Pi 5 makes a practical, fully offline voice assistant achievable for prototyping and private deployments. This end‑to‑end walkthrough wires audio hardware, a local speech‑to‑text (STT) pipeline, on‑device LLM inference on the AI HAT+ 2, and a local TTS engine — with runnable examples you can adapt to your use case.

Two trends converged by late 2025 that make an offline Pi‑based assistant compelling:

  • Edge AI hardware has sharpened: accelerator HATs like AI HAT+ 2 provide low‑latency inference and vendor SDKs for gguf/ggml runtimes and ONNX workloads.
  • Model quantization and tiny LLMs matured: robust 4‑bit/3‑bit quantization, faster whisper.cpp STT variants, and compact TTS models let useful assistants run on-device.

Outcome: you get privacy (no audio leaves your network), predictable latency, and the ability to customize prompts and actions without cloud lock‑in.

Project overview — architecture and components

We'll implement a simple, production‑oriented pipeline:

  1. Microphone input + VAD or push‑to‑talk
  2. Offline STT (whisper.cpp or VOSK)
  3. Prompt engineering + local LLM inference on AI HAT+ 2 via a local HTTP/gRPC server
  4. Local TTS (Coqui/OpenTTS or a small Silero model) and audio playback
  5. GPIO button and LED for UX

Assumptions: Raspberry Pi 5 (64‑bit OS), AI HAT+ 2 attached per vendor docs, a USB microphone or I2S mic HAT, and a speaker or USB DAC.

Hardware checklist and wiring

Minimal parts list (links omitted — choose vendor/variant you trust):

  • Raspberry Pi 5 (64‑bit Raspberry Pi OS or Debian 12+)
  • AI HAT+ 2 (installed per vendor instructions)
  • USB microphone (recommended for simplicity) or ReSpeaker 2‑Mic HAT (I2S)
  • USB speaker / USB DAC / HiFiBerry DAC for audio out
  • Momentary push button, LED, 220Ω resistor, jumper wires, breadboard

Button and LED wiring (GPIO)

  • Button: one leg to a GPIO (e.g., GPIO17), other leg to GND. Enable internal pull‑up in software.
  • LED: connect LED anode to GPIO27 via 220Ω resistor, cathode to GND.
Use the AI HAT+ 2 vendor guide for power and connector details. This guide focuses on software wiring and the audio/compute pipeline.

Software stack — what we'll install

On the Pi install:

  • System dependencies (Build tools, Python3)
  • whisper.cpp (for offline STT) or VOSK as alternative
  • Local LLM runtime: a small gguf model served by llama.cpp/text‑generation‑server or vendor runtime that exposes HTTP/gRPC to utilize AI HAT+ 2
  • Coqui TTS or OpenTTS for speech synthesis
  • Python glue script (microphone capture, VAD, orchestration)

Quick install (commands)

Run these on your Pi 5 (64‑bit). Adjust sudo and package manager if using a different distro.

sudo apt update && sudo apt upgrade -y
sudo apt install -y git build-essential python3 python3-venv python3-pip libsndfile1-dev libportaudio2 libasound2-dev curl

Build whisper.cpp (fast local STT):

git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make -j4
# You can download a small whisper model (quantized) - use the project's instructions

Set up a Python venv and install helpers:

python3 -m venv venv
source venv/bin/activate
pip install sounddevice numpy requests python-dotenv RPi.GPIO==0.7.post4

Install Coqui TTS (lightweight):

pip install TTS==0.13.0  # pick a 2026 stable release compatible with Pi

Install or configure the LLM server. Two options:

  1. Use a ggml/llama.cpp-based local server (text-generation-server) on the same Pi if AI HAT+ 2 supports offloading via vendor plugin.
  2. Use the AI HAT+ 2 vendor runtime: install their SDK, load a quantized gguf model, and run the provided HTTP/gRPC server.

Example (llama.cpp text server clone):

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# follow build and server instructions; copy a small gguf model and start server
./server --model ./models/your-small.gguf --port 8080

Model guidance (STT, LLM, TTS)

STT: For an always‑offline assistant use a quantized whisper.cpp model (small or tiny) for low-latency recognition. VOSK is an alternate with low CPU usage for constrained tasks.

LLM: Choose a compact model (<=7B) converted to gguf / ggml and quantized to 4‑bit. In 2026, many vendors provide optimized pipelines for NPUs; leverage the AI HAT+ 2 SDK to offload matrix kernels to the accelerator for large wins in latency and power.

TTS: Coqui TTS or OpenTTS with small multi‑speaker models works well. For lower CPU usage, use models optimized for INT8 inference.

Core orchestration: the assistant loop

We'll build a compact Python controller that:

  1. Waits for a push‑to‑talk button (or VAD)
  2. Records audio and runs whisper.cpp for STT
  3. Sends text to the local LLM server and receives a reply
  4. Synthesizes speech via Coqui TTS and plays it

assistant.py (runnable example)

#!/usr/bin/env python3
import subprocess
import sounddevice as sd
import soundfile as sf
import requests
import RPi.GPIO as GPIO
import time

BUTTON_PIN = 17
LED_PIN = 27
AUDIO_FILE = '/tmp/assistant_in.wav'

GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(LED_PIN, GPIO.OUT)

def record_audio(seconds=5, samplerate=16000, filename=AUDIO_FILE):
    print('Recording...')
    GPIO.output(LED_PIN, True)
    data = sd.rec(int(seconds * samplerate), samplerate=samplerate, channels=1, dtype='int16')
    sd.wait()
    sf.write(filename, data, samplerate)
    GPIO.output(LED_PIN, False)

def stt_whispercpp(audio_path):
    # whisper.cpp binary built earlier
    cmd = ['./whisper.cpp/main', '-m', 'models/ggml-small.bin', '-f', audio_path]
    print('Running STT...')
    result = subprocess.run(cmd, capture_output=True, text=True)
    # parse output - depends on binary's stdout format
    text = result.stdout.strip().splitlines()[-1] if result.stdout else ''
    return text

def query_local_llm(prompt):
    url = 'http://127.0.0.1:8080/generate'
    payload = {'prompt': prompt, 'max_tokens': 200}
    r = requests.post(url, json=payload, timeout=20)
    r.raise_for_status()
    data = r.json()
    return data.get('text') or data.get('output') or ''

def tts_coqui(text, outpath='/tmp/out.wav'):
    # Simple Coqui TTS call via CLI or Python API
    print('Synthesizing TTS...')
    cmd = ['tts', '--text', text, '--out_path', outpath]
    subprocess.run(cmd, check=True)
    # play
    sd.play(sf.read(outpath)[0], samplerate=sf.read(outpath)[1])
    sd.wait()

try:
    print('Assistant ready — press button to talk')
    while True:
        if GPIO.input(BUTTON_PIN) == GPIO.LOW:
            # Debounce
            time.sleep(0.05)
            if GPIO.input(BUTTON_PIN) == GPIO.LOW:
                record_audio(seconds=4)
                text = stt_whispercpp(AUDIO_FILE)
                print('You said:', text)
                if not text:
                    tts_coqui('Sorry, I did not catch that.')
                    continue
                reply = query_local_llm(text)
                print('Assistant:', reply)
                tts_coqui(reply)
                time.sleep(0.5)
        time.sleep(0.1)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

Notes:

  • The exact whisper.cpp and LLM server flags depend on your builds. Adjust paths & model names.
  • Replace the synchronous sd.play call with a background player for smoother UX.

Optimizations for AI HAT+ 2

To get best performance on the AI HAT+ 2:

  • Install the vendor SDK and follow their offloading guide — typically you will convert a gguf/ONNX model and start the vendor server.
  • Use model quantization (4‑bit/3‑bit) to reduce memory and increase speed. In 2026, tools standardize on gguf and optimized kernels for NPUs.
  • Batch requests judiciously (single‑turn chat uses small batches); tune generation tokens and temperature for latency.

Example: call a vendor runtime via HTTP

# curl example
curl -s -X POST "http://127.0.0.1:9000/v1/generate" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What is the weather in Seattle?", "max_new_tokens": 100}'

Security, licensing, and production tips

  • Model licensing: carefully check model licenses — some “open” weights require non‑commercial or research‑only use.
  • Sandbox inference: run LLM servers under a dedicated user, restrict network access if you truly require offline operation.
  • Privacy: disable update or telemetry features in vendor SDKs. Keep the filesystem encrypted if handling sensitive transcripts.
  • Power and heat: Pi 5 + AI HAT+ 2 can produce heat under load — add a fan and monitor CPU/NPU temperature.
  • Fallback: implement simple intent recognition rules locally (regex/NLU) to handle urgent actions if the LLM is busy.

Performance expectations and debugging

On a properly configured Pi 5 with AI HAT+ 2 you can expect

  • STT (small whisper.cpp) latency around 500ms–2s for 4s audio, depending on model size
  • LLM generation 0.5–3s for compact models (<4B) with NPU offload; larger models take longer
  • TTS synthesis from lightweight Coqui voices: 0.5–2s

For troubleshooting:

  • Check vendor logs for NPU allocations
  • Use top/htop and iostat to spot CPU/IO bottlenecks
  • Test audio capture/playback separately (arecord/aplay or ffmpeg)

Advanced topics and future directions (2026+)

As of 2026 the cutting edge in edge voice assistants includes:

  • Multimodal prompts: local vision models feeding context to the assistant for tasks like “what’s in my fridge”.
  • Personalization on-device: few-shot adapters and small personalizers running in secure enclaves on HAT NPUs.
  • Federated updates: secure model updates that let devices learn without sending raw audio to the cloud.
  • Standardized runtimes: gguf + ONNX + ONNX-RT with NPU backends reduce vendor lock‑in — check for updated runtime compatibility on AI HAT+ 2.

Case study: a privacy-first home assistant prototype

We tested a prototype in late 2025: Raspberry Pi 5 + AI HAT+ 2, tiny‑whisper STT, a 3B quantized gguf model offloaded to the HAT, and Coqui TTS. It handled information queries and simple home automation reliably and with local response latency <2s. The main win: no external audio left the home network and customization of persona and prompts was straightforward via a config file.

Actionable checklist — get this running this weekend

  1. Buy parts: Pi 5, AI HAT+ 2, USB mic, USB speaker, button, LED.
  2. Flash 64‑bit Raspberry Pi OS and enable SSH.
  3. Install dependencies and build whisper.cpp + LLM server as shown above.
  4. Load a small quantized gguf model and start the LLM server (use vendor SDK if you want NPU offload).
  5. Install Coqui TTS and test speech synthesis.
  6. Wire the button + LED and run assistant.py to tie it together.

Troubleshooting cheatsheet

  • No audio recorded? Run arecord -l and check device indices; specify device in sounddevice.
  • STT returns garbage? Try a smaller model or reduce sample rate mismatch problems.
  • LLM server times out? Increase timeout, verify model loaded (server logs), and verify NPU drivers.
  • TTS fails on Pi? Ensure Coqui TTS dependencies are installed, or use the CLI binary fallback.

Conclusion — when to use this pattern

If your priorities are privacy, reliability, and controllability, an offline assistant on Raspberry Pi 5 + AI HAT+ 2 is a practical architecture in 2026. It’s not a drop‑in replacement for large cloud assistants in raw capability, but for many home and edge automation tasks, the latency, privacy, and customization benefits outweigh the limitations.

Next steps and call to action

Ready to build? Start with the minimal pipeline: get audio I/O working, run whisper.cpp for STT, and spin up an LLM server with a tiny gguf model. Then add TTS and a button UX. Share your model choices and performance numbers in the comments or on GitHub — and if you forked this project, open a PR with notes about AI HAT+ 2 vendor SDK integration so the community can reuse your vendor‑specific wiring and runtime flags.

Want a tested starter repo? I maintain a compact template (Pi 5 + AI HAT+ 2 compatible) with installation scripts, a ready‑to‑run assistant.py, and a config file for swapping STT/LLM/TTS engines. Clone, adapt, and contribute — your improvements help everyone move the edge‑AI ecosystem forward.

Advertisement

Related Topics

#edge-ai#voice#tutorial
U

Unknown

Contributor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

Advertisement
2026-02-27T02:57:36.299Z