Voice Agent

About

This is an implementation of a real-time voice assistant. Your speech is transcribed live, reasoned with a language model and responded to with a natural voice. It can also answer questions about PDF or TXT files you upload, and reach live tools for weather, currency conversion, and more.

Pipeline

Speech is streamed to the server as raw audio over a single WebSocket; transcription, generation, and synthesis are chained so stages overlap: the transcript streams while you speak, and playback starts while the voice is still being synthesised.

Agent

H · Document search

G · Tool picker

Agent loop · up to 5 iterations

PDF ≤ 10 pages · 1000-char chunks · bge-small · top-4

weather · calculator · wikipedia · dictionary · exchange_rate · world_time · search_document

B · LLM

C · Tool calls?

D · Execute tool

A · Turn input

E · Final text

F · Speak reply

yes

no

result appended

picks from

search_document

Delivery

A GitHub Actions workflow is set up to identify affected components and rebuild only what has changed. Both the backend and frontend are containerized (compatible with Docker Compose) and built for linux/amd64, leveraging the GitHub Actions layer cache to keep rebuilds fast and efficient.

The application is hosted on a Hetzner CX33 server, running a K3s cluster orchestrated by the voice-agent Helm chart. This chart provisions the namespace, Deployments, and Services, alongside an ingress-nginx Ingress configured with cert-manager for automated Let’s Encrypt TLS at qharo-voice-agent.duckdns.org. The Ingress is explicitly tuned with WebSocket-friendly timeouts and a 20 MB upload cap. Sensitive credentials like the GROQ_API_KEY are safely committed to the repository as a Bitnami SealedSecret, remaining encrypted until decrypted in-cluster. During deployment, the workflow applies changes efficiently: it runs helm upgrade if the chart itself changed, or falls back to a targeted kubectl rollout restart for the specific Deployment, waiting for the rollout to stabilize.

For observability, the backend exposes Prometheus metrics at /metrics. A ServiceMonitor scrapes these endpoints every 15 seconds, feeding a comprehensive Grafana dashboard that is shipped directly as a Kubernetes ConfigMap. This provides real-time visibility into active sessions, queue depth, per-stage latencies (STT, LLM, TTS), tool call rates, and error counts.

Notes

Design tradeoffs

Known limitations

Credits & links

The models and tools are all free and keyless: Moonshine (STT), Piper (TTS), gpt-oss-20b served by Groq, and open APIs for weather (Open-Meteo), currency (Frankfurter), Wikipedia, dictionary, and world time.