Enjoying this issue?
Get tomorrow's AI & engineering digest in your inbox — hand-picked, summarized, and always spam-free.
TLDR
A 12GB GPU can run a real-time voice agent if processing stages are overlapped and memory is carefully budgeted. The Pythagoras setup shows that on an RTX 3060, speech generation can keep up, but the total latency depends on scheduling dependencies and the combined memory footprint of language and speech models. The key insight is that not all waiting is necessary—overlapping transcription, model inference, and synthesis can cut perceived delay significantly.
Key points
Pythagoras runs Whisper on CPU to preserve GPU memory for the language model and speech synthesis.
Overlapping transcription, model inference, and speech synthesis can reduce perceived latency from 6.8 to 3 seconds in a simplified example.
The memory budget must include both language and speech models; 12GB may require offloading some weights to CPU.
TrueForge is an MIT-licensed agent harness that can integrate with a speech interface but lacks a documented voice pipeline.
The term 'local' does not guarantee all processing runs on the local machine; configured endpoints must be verified.
Tools mentioned
Techniques
- overlapping processing stages
- turn detection with silence threshold
- Whisper snapshot transcription
- prefill and token generation
- tool execution loop
- sentence boundary handoff for speech synthesis
- queue management for playback
- CPU offloading of model weights
- mixture of experts selective placement
Stop scrolling. Start reading smarter.
Receive the day's most important AI & engineering updates in one concise email. No spam.
Transcript (captions)
Can a local voice agent keep up on a 12-gigabyte graphics card? The published Pythagoras setup shows that useful speech generation is possible with a language model sharing an RTX 3060, but
a quick spoken reply depends on the whole computer and on when each part starts working. That's what I would check before buying more hardware. Suppose you're fixing a build and ask,
"How many builds failed yesterday?" You want the agent to check the records and tell you the answer while you keep working. Waiting through a long silence breaks that flow. Getting an immediate
confident guess is worse. Let's follow that one request from your microphone to the actual result, then see which delays can overlap. There's a useful distinction right at the start. The
first sound from the assistant, the first useful answer, and the completed task are different events. "I'm checking" can tell you a request arrived. It can't tell you how many
builds failed. A latency chart needs to say which of those events stopped its clock. Pythagoras is a web interface for a coding agent. Its voice comparison guide describes a sequential baseline
and several stages of overlap. The hardware samples come from that project. Our database and timing example are teaching examples with their assumptions kept visible. First, the microphone
produces audio. Something has to decide whether that audio contains speech and whether you finished your turn. Speech detection answers the first question. Turn detection answers the second. A
pause in "How many builds failed yesterday?" might be a breath. So, treating every brief silence as permission to answer can cut the question short. The Pythagoras guide
describes a default wait of about 1 second of silence before submitting the turn. That's already time the user can feel before considering a language model. A shorter wait can help a crisp
command, but it also gives someone less room to finish a thought. Push-to-talk is another option when a clear boundary matters more than hands-free conversation. While that boundary is
being decided, speech recognition can already do useful work. Pythagoras sends Whisper rolling snapshots during speech and shortly after silence begins. These are repeated clips, rather than a
recognizer emitting a continuous stream of final words. The distinction matters because a partial transcript can still change when the end of your sentence arrives. At turn end, the application
checks whether a completed transcript covers the last detected speech. If it does, the result can be reused. If it doesn't, the final recording still needs transcription.
That coverage check is the reason the optimization is useful. It can remove work from the wait after your question without throwing away the last word. For the worked example, the final transcript
is how many builds failed yesterday. The agent needs a date and a source of records. Here, yesterday explicitly means September 14th in the example's chosen time zone.
In a real application, resolve that boundary deliberately. A server on a different time zone can answer the wrong question with a perfectly valid database query. The language model receives the
transcript, the relevant conversation, and the available tools. Before it can generate an answer, it has to process that input. That first pass is usually called prefill. Afterward, it generates
output in small pieces called tokens. A high token rate tells you about that generation phase. It doesn't measure the earlier listening or prompt processing. For this request, the model should
choose a tool that reads build records. The application validates the tool name and arguments, runs the query, and returns the result to the model. That execution loop is what makes this an
agent. The model proposes an action. Code outside the model decides whether and how to perform it. The fixture on screen contains eight build records. Three failed on September 14th, while
the other failures belong to different days. The query returns build identifiers 101, 103, and 106. That query was executed against the authored fixture, so the answer, three, has a
small piece of reproducible evidence behind it. Only after that result arrives should the assistant say, "Three builds failed yesterday? It can add which builds failed if that's useful. If
the query errors, the correct response is that the check failed. Making a confident guess arrive faster wouldn't help. This execution layer is also where TrueForge fits. True Foundry describes
it as an agent harness, the runtime around model calls, tools, approvals, and session state. Its repository is MIT licensed. It offers a chat interface and an API, so an application can use the
backend without making the chat window its entire product. You could put a speech interface around that backend, send in a transcript, and return the tool-backed answer to speech
synthesis. That's an integration design. TrueForge doesn't document this exact voice pipeline. Its support for external model endpoints also means local deployment alone
doesn't establish where every request goes. Once the tool result becomes a sentence, speech synthesis turns that sentence into audio. The player then has to receive enough
audio to start reliably and send it to the output device. Those are separate steps. Having text on screen doesn't mean sound has reached the speaker, and receiving the first audio bytes doesn't
necessarily mean playback has started. A sequential implementation can make all these weights add up. It records the question, waits for transcription, waits for the entire model response,
synthesizes the whole reply, then plays it. Each stage may look reasonable on its own. The user experiences their combined delay, including the time spent waiting for material that wasn't needed
to start speaking. Here's a deliberately simplified timing example. Start the clock when speech ends. Give turn detection 1 second, then transcription 6/10 of a second. The model spends 7/10
choosing the tool, and the query takes 3/10. These are selected numbers to make the schedule visible, not measurements from the graphics card. After the query, allow 1.8 seconds for the complete
answer text and 2.4 seconds to synthesize all its audio. In that fully sequential schedule, playback begins 6.8 seconds after the question ends. The arithmetic is in the example files. What
matters is that every block waits for the previous block to finish. Now, preserve the same task and move only the work that can safely start earlier. Suppose a transcript covering the final
speech is ready 8/10 of a second after the user stops. It finishes inside the 1-second turn detection window. When that window closes, the transcript is already there, so transcription adds no
further weight in this particular example. The tool still has its dependencies. The model must choose the query, the query must run, and the result must come back before the
assistant knows the count. Those steps bring the schedule to 2 seconds. Overlap doesn't give permission to invent the database result while the database is still working. After the result, suppose
the first complete answer sentence takes 4/10 of a second to appear. The rest of the explanation can continue forming while speech synthesis starts on that sentence.
If the first playable audio takes another 6/10, sound begins at 3 seconds. The complete paragraph and its complete audio no longer sit in front of the first useful sentence. The change from
6.8 to 3 seconds demonstrates scheduling. Real durations depend on the model, question, and machine, and contention can change the blocks themselves. Find the dependencies, then
stop waiting for work that the next stage doesn't need yet. Sentence boundaries are a practical handoff because speech needs enough context to sound coherent. Passing every new word
straight to a synthesizer can damage phrasing or force more buffering somewhere else. Waiting for a bounded phrase or a complete sentence makes the compromise visible. The goal is to
preserve the answer and its delivery while starting useful output earlier. The next overlap happens after playback has begun. While sentence one plays, the synthesizer can prepare sentence two,
and the model can keep producing text. Think of serving a meal as the courses are ready. You don't have to keep the soup in the kitchen until dessert is finished. The order still matters.
Pythagoras implements separate text synthesis and playback cues. Its code allows one synthesis request at a time with at most two completed phrases waiting ahead of playback. So, overlap
doesn't require two copies of the speech model fighting for the graphics card. Audio playback and preparation are allowed to make progress independently. The repository includes tests for those
rules. All seven queue tests passed in the accompanying research, including sentence order, the prefetch limit, and rejection of stale output. Controlled software events check the scheduling
behavior. They don't measure a live speech model or its hardware. There's still a physical limit to smooth playback. If generating the next sentence consistently takes longer than
playing the current one, the queue eventually runs dry. A startup buffer can absorb a short delay. It can't permanently fix a producer that falls behind. Starting
instantly and then stopping halfway through a word is a poor trade. The project's historical accelerated runtime notes contain a useful, narrowly scoped sample.
With Qwen resident on an RTX 3060, they report generating 4.88 seconds of speech in 3.05 seconds. First audio was reported at 0.94 seconds. That's a warm speech generation
sample, not the full delay from a user's question to an answer. For the same text, the previous Python runtime reportedly took 8.4 seconds and produced 4.32 seconds of audio. Keep those
different output durations visible. The observations don't establish identical delivery or voice quality. They do show why the speech stage deserves its own inspection. The native sample also
reports about 4.3 binary gigabytes of graphics memory used by the speech process. The allocation exists alongside the language model and other runtime needs. Putting 12 gigabytes in a title
doesn't make the speech model free. A setup that fits the language model alone can run out of room when speech joins it. This is why the complete computer matters. Pythagoras documents Whisper
running on the CPU, leaving GPU capacity available for other work. The language model runtime, llama.cpp, also supports placing model work across CPU and GPU. Moving some weights into system memory
can make a larger model fit, but the CPU then has real work to do. For a mixture of experts model, llama.cpp has controls for keeping expert weights on the CPU.
Experts are model components selected for a token, rather than every parameter participating equally in every step. Selective placement can preserve GPU space for the parts you want there.
It doesn't mean the remaining weights vanish, or that system memory becomes as fast as graphics memory. The public voice documentation establishes where speech recognition
runs, but it doesn't provide a complete memory inventory for the comparison recording. So, there's no verified total system RAM requirement to give you for that run.
Treat that as a missing measurement when planning a similar setup. For your own machine, draw two separate budgets. Graphics memory holds the resident model portions, speech model, working buffers,
and caches assigned there. System memory holds the offloaded portions and the rest of the application. Leave room for the operating system and your tools. A build process running beside the agent
can compete for the same CPU and memory you just relied on. Before changing model quality, look for avoidable reloads and repeated preparation. A speech model loaded only when needed
saves idle memory, but its first reply pays the loading cost. Keeping it warm changes that trade-off. A demo recorded after warm-up and a fresh session after a restart answered different questions.
Both can matter to someone using the agent daily. A second source of confusion is the word local. When audio agent is an open-source voice runtime whose default front end uses dash scope,
its documentation also describes a self-hosted speech-to-speech front end. You need to inspect the configured route. Running the interface on your laptop doesn't by itself mean the voice
model or the coding back end runs there, too. The local option is real, but it isn't a promise that every default configuration fits this card. Hugging Face's current speech-to-speech guide
budgets 24 GB of graphics memory for its unquantized Nvidia example plus system RAM. The guide calls that a planning estimate. Different models, quantization, and placement change the
budget, so a 12 GB setup needs a deliberate configuration. Follow the request to check what stays local. Where does microphone audio go? Where does the transcript go? Which machine runs the
language model, and can its tools call outside services? Decide which boundary you need, then verify the configured endpoints and behavior against it. Once the assistant can speak smoothly, it
also needs to stop. Suppose it begins reading the failed builds and you say, "Only the release branch." The old spoken answer is now stale. A good interruption path stops scheduled audio,
cancels pending synthesis, and prevents late results from the old response entering the new playback queue. Pythagoras's Q code creates a fresh run when cancellation happens, clears the
old queues, and aborts their signal. When an older request finishes late, it checks whether it still belongs to the current run before accepting the result. That identity check is small, but it
stops the assistant returning to a sentence you already interrupted. Canceling speech and undoing a tool action are different operations. If a tool already started a build, clearing
the audio queue doesn't roll that build back. For this example, the tool only reads records. For actions that change something, define what cancellation means and when the action becomes
committed. The user needs a truthful account of what actually happened. To judge whether the whole system keeps up, record one timeline with clear event boundaries. Mark the last detected
speech, the final transcript, the tool request and result, the first answer text, and playback. Keep status announcements separate. Pythagoras's profiler does that kind of breakdown,
and its documentation explains which intervals include waiting rather than isolated model computation. Use a common clock for intervals you compare. The browser can estimate playback using its
scheduled output and reported device latency, but that doesn't fully capture leading silence or every output device delay. An acoustic test records the end of the question and the first non-silent
reply on the same time base. Label software estimates as estimates so another person can reproduce the comparison. Then make the comparison fair. Keep the prompt, starting context,
model, voice, and reasoning settings fixed while enabling one overlap at a time. The Pythagoras comparison notes also describe variants that change reasoning
behavior and response instructions. Those can be useful product choices, but combining them with scheduling changes means the result no longer isolates scheduling alone.
A small test set should include a short question, a real tool request, a longer reply, and an interruption. Record cold starts separately from warmed turns. Alongside the delay, check whether the
transcript retained the important words, the tool used the right arguments, and the spoken answer matched its result. Count failures rather than excluding them from the timing summary. So, can it
keep up? The published evidence supports building a carefully configured local voice agent around a 12 GB card. It doesn't establish a universal conversation latency or prove that 12 GB
is the whole memory bill. I'd start with one useful read-only task. Keep the models warm when memory allows and measure the first correct answer before choosing an upgrade. Our built question
ends with three matching records and an answer grounded in those records. The practical win is knowing which waiting can disappear, which work must remain, and what your computer actually has to
hold. For the language model side of that budget, the channel's speculative decoding explainer follows how a model can produce useful output sooner while
checking what it accepts.