Every wake is kept
Its 3 seconds of audio, the scores and what followed. Close calls, the near-misses, too. All of it stays on the Pi, and in the household's own bucket if the backup is on: none of it is sent anywhere to learn from.
TARS is a voice assistant for one household. It runs on a Raspberry Pi at home and uses a few cloud services for the hard parts. This page follows one real request from the first word to the follow-up.
Alon Hey TARS, how long do I boil an egg?
TARS Nine minutes for hard, six for soft.
Alon And for a runny one?
The second question needs no wake word.Everything before 0 happens while you are still speaking. That is why the answer comes so fast: by the time you finish, the connections are open, the speaker is known and the reply is already being drafted.
A typical run, built from measured medians. Real answers take 1.2 to 1.5 s to the first sound. Detailed shows every lane.
A typical run, built from measured medians; measured 1.2 to 1.5 s to the first sound. After 0 the axis is 3 times wider per second, so the dense part is readable; the follow-up at the far right is not to scale. Drag the playhead along the seconds row to scrub, or tap anything to jump to it. Play moves the playhead at an even, slow pace, and Space plays or pauses.
Every real answer is measured the same way. Each one is kept with how long each stage took and which model wrote it, so the 1.2 to 1.5 s range can be checked against real use, not only a benchmark.
You say “hey TARS”.
YouStage 1 fires: the small wake model scores 0.2 or more.
PiStage 2 says answer. Only now can anything leave the house, and TARS opens its connections while you are still talking.
Pi to cloudYou ask “how long do I boil an egg?” and the audio streams to Flux as you talk.
You, Pi, FluxFlux says “maybe done”. TARS starts the answer early, in the background, while still recording.
Flux, PiFlux says “done”. Now the draft may be played, logged and allowed to send anything.
FluxQwen on Groq has the first sentence, about 0.4 s after “maybe done”, streamed.
GroqJames, the Cartesia voice, has the first sentence's audio.
CartesiaFirst sound: “Nine minutes for hard, six for soft.”
PiIt listens a few seconds for a follow-up. “And for a runny one?” goes straight in, no wake word.
EveryoneTime runs down. Of the two strips beside each step, the left is at home and the right is the cloud. The cloud stays hatched, closed, until stage 2 says yes, and the blue line marks the moment it opens.
A typical run, built from measured medians; measured 1.2 to 1.5 s to the first sound.
Every real answer is kept with how long each stage took and which model wrote it, so that range can be checked against real use, not only a benchmark.
Stage 1 is cheap enough to run on every 80 ms of sound, so it is allowed to be a little eager. Stage 2 only runs when stage 1 fires, and it is the one that opens the door.
microWakeWord, local, 69 KB. A score of 0.2 or more goes on.
Logged, never answered. It may be a missed “hey TARS”.
Still on the Pi. Nothing has left the house yet.
Trained on synthetic and converted voices, never on a household member. These are the models every new install starts with. The clips are on Hugging Face.
The generic models start out good on voices they have never heard. The loop makes them good on yours. People only take part in three places, all in the web app.
Its 3 seconds of audio, the scores and what followed. Close calls, the near-misses, too. All of it stays on the Pi, and in the household's own bucket if the backup is on: none of it is sent anywhere to learn from.
What happened next says whether a wake was real.
A few taps a day. Each unsure wake has its audio, what TARS heard, what happened, and TARS's guess shaded.
TARS wasn't sure these were meant for it. Its guess is shaded. Answers move to Reviewed at the next Refresh.
Naming one lets TARS greet that person by name.
TARS groups requests by voice. Name a voice and TARS greets them by name.
A new stage 1 and stage 2, trained on those wakes in about 20 to 25 minutes. Every fifth wake is kept aside for testing, and the new pair is tested end to end against the one in use.
Better means it answers more of the household's real wakes, or lets fewer through that weren't for TARS. If not, it asks. Once installed, the Pi switches within seconds, and the Models page can switch back.
| Test | In use | New | |
|---|---|---|---|
| Other voices, quiet | 94.4% | 97.8% | better |
| Other voices, noise | 83.5% | 88.3% | better |
| Lookalikes let through | 3.0% | 4.8% | worse |
| False answers per hour, audiobooks | 0 | 1 | worse |
Not installed. Better on other voices, but worse on two things that matter. That is the rule doing its job.
The first real run said no: better on other voices, worse on two things that matter. Detailed shows the numbers.
The wake word TARS listens for, and how each version tested.
The same voice that answers can also speak first. You set it by voice or from the web app, and TARS says it when it's due.
TARS says it when it's due, then again every 5 minutes, at most 4 times, until someone says “got it”. After that it's marked Missed.
Until someone turns them off, for at most 15 minutes. TARS can't hear while it makes a sound, so it rings in bursts and listens in between: “stop” works without the wake word.
Waits until TARS next recognises that voice, then says it.
Timers, reminders and messages TARS says aloud, and says again until someone says “got it”.
“Your eggs timer is done.”
“Stacey, a message from Alon: the plumber is coming at four.”
“Your pasta timer is done.”
“Alon, a reminder: call the bank about the mortgage.”
“Stacey, a message from Alon: the parcel is at the Cohens'.”
The Reminders page shows each one and who acknowledged it and how, and sets new ones from a phone.
TARS locks the door, runs the boiler, sets the AC and plays things on the TV, through Home Assistant on the home network. It says something's done only once the device reports it.
After locking, TARS reads the lock back until it says locked. An AC worked by infrared can't report back, so TARS says it sent the command, never that it's on. A lock that jams is said to have jammed, and an open door is never locked.
TARS starts answering before you finish, but a change waits until you have. “Turn off the boiler… no, leave it” leaves it.
The door unlocks only for a voice TARS knows and trusts with it, recognised from the request itself, and only when it heard “unlock”. Anyone can lock.
For anything that takes several steps, a model works an Android TV box like a person with its remote, reading the screen after every step. It runs in the background, and TARS says how it went after a chime. Devices Home Assistant doesn't work are plugins: a little code of the household's own.
Alon Hey TARS, lock the front door.
TARS One moment. Locked.
Alon And play Toy Story on Stremio.
TARS On it.
A minute later, after a chime: “Toy Story is playing.”Each person can chat with TARS on Telegram, in writing or with a voice message: ask it something, set a reminder, have it send something, or have a message said aloud at home. TARS asks Telegram for new messages, so nothing at home is opened to the internet.
It answers the chats named in its settings, each as that person. Anyone else gets no answer at all, so a stranger can't even tell it's there.
One set in a chat is posted to that chat when it's due. “Tell the house dinner's ready” is said aloud at home instead, and the chat hears when it was said and who said “got it”. Whatever TARS sends at home for someone with a chat comes to their phone as well.
A voice message is written down by the same speech to text as at home, and the reply comes in writing. Chats go straight to OpenAI's model: a chat is read whole, so Qwen's faster first word buys nothing there. Each person has their own conversation, kept until the chat has been quiet for an hour, or until they send /new.
Alon Remind me to call the bank at nine.
TARS Set for 9 AM. It'll come here.
Alon And tell the house dinner's at eight.
TARS Saying it at home now.
A minute later the chat reads: “Stacey said they got it at 7:42 PM.”TARS fails soft, and when it can't recover it tells you in its own voice.
| Stage | Normally | If that fails |
|---|---|---|
| End of turn | Deepgram Flux | Local rules |
| Speech to text | Flux | OpenAI transcribes the same recording |
| Brain | Qwen on Groq | Qwen on Cerebras, then OpenAIIf Groq hasn't started answering within half a second, Cerebras is asked too and the first to answer is kept. A service that fails is skipped for the next two minutes, so an outage doesn't cost every turn its timeout; with both out, OpenAI answers. A reply too long for Groq's cap, like a long note, is written on Cerebras. |
| Voice | Cartesia Sonic | A spoken error line, made at startup |
| Wake models | The newest trained pair | The pair it was installed with |
| Mic or speaker | The USB speakerphone | TARS exits and the system restarts it |
A failed answer is kept in its conversation, with where it failed, and the web app shows it.
They share the database on the same machine, and a crash in one never takes another down. The backup copies everything to an S3 bucket, and makes room on the card after a month.
TriggerTranscriberBrainVoiceSwapping a cloud service for a local model is one new class and a config change.
Each answer is kept with how long each stage took, which model wrote it and, if it failed, where and why. 29 whole conversations, hand-offs followed through, check the brain: 143 of 145 runs right.
voice-assistant --check checks the keys, devices, models, services, the voice and the mic,
and says what's wrong and what to do. Once it runs, the web app's Status page shows much of the same,
live: each process by its heartbeat, each service with its key and its own status page, and the Pi's CPU,
memory, temperature and disk.
A Raspberry Pi 5 and a USB speakerphone, an Anker PowerConf.