Omni Models: Qwen2.5-Omni and the Thinker-Talker Split
GPT-4o's May 2024 demo was disruptive because of the product shape, not the underlying model: you talk, the model sees what the camera sees, and it talks back in under 250ms. The open ecosystem spent the rest of 2024 and 2025 racing to reach that surface. Qwen2.5-Omni (March 2025) is the reference open design: a Thinker (a large text-generating transformer) plus a Talker (a parallel speech-generating transformer), linked by streaming speech tokens. Mini-Omni simplified it, Moshi matched its latency, and GLM-4-Voice extended it to Chinese. This lesson reads the Thinker-Talker architecture and the latency budget that makes real-time streaming dialogue work.
Learning Objectives
- Split the inference pipeline into Thinker (text reasoning) and Talker (speech synthesis) and explain why parallel streaming works.
- Compute the time-to-first-audio-byte (TTFAB) budget for a conversational interaction, component by component.
- Describe TMRoPE's time-aligned position encoding across vision, audio, and text within the Thinker.
- Name the three real-time conversational patterns: half-duplex, turn-taking, full-duplex.
The Problem
A real-time voice assistant has to do four things, fast:
- Hear the user. That means real-time speech tokenization, plus voice activity detection (VAD) to know when they're done speaking.
- Optionally see. Camera input at 2-4 FPS gets streamed into the Thinker alongside the audio.
- Think. Compose a response conditioned on the conversation history.
- Speak. Synthesize audio tokens, decode them to a waveform, and stream that to the user's speakers.
Each step adds latency. A conversational feel needs a total round trip under 500ms. Below that, the user stops noticing the lag. GPT-4o claims ~250ms, Moshi ~160ms, Qwen2.5-Omni ~350-500ms.
The components have to stream. A pipeline that batches a full response and then decodes it blows the budget before the user hears anything.
The Concept
Thinker and Talker
Qwen2.5-Omni splits the work into three parts:
- Thinker: a 7B-80B text-generating transformer. It consumes interleaved text, image, and audio tokens and outputs text tokens representing what to say.
- Talker: a smaller speech-generating transformer (200M-1B). It consumes the Thinker's text output tokens plus recent speech-context tokens, and outputs discrete speech tokens (residual-VQ indices).
- Speech decoder: a streaming waveform decoder (SNAC, MoVQGAN family) that turns speech tokens into audio samples in real time.
The separation matters. The Thinker has to be big for good reasoning. The Talker can be small because its job is local: convert text to speech tokens. A bigger Talker is not more expressive, only slower.
Both run in parallel:
- Thinker emits text token t_i.
- Talker consumes t_i (via streaming) and emits speech tokens s_i, s_{i+1}, ..., s_{i+k}.
- Speech decoder consumes speech tokens as they arrive and emits audio samples.
- By the time the Thinker is at text token t_{i+3}, the Talker has already streamed audio for t_0..t_{i+2}.
TMRoPE: time-aligned multimodal positions
The Thinker has to integrate image frames (arriving at, say, 4 FPS), audio frames (arriving at 50 frames/second), and text from conversation history. A naive sequence order, with all images first, then audio, then text, loses the temporal alignment.
TMRoPE assigns an absolute timestamp to each token. A vision token lands at t=2.3s, an audio token at t=2.32s, and the user's text token "stop" at t=2.35s. RoPE rotates attention by timestamp, so the model sees them as temporally concurrent.
That is the infrastructure behind "he waved while saying hello": the model sees the video frame and the audio at the same conceptual moment.
Streaming speech synthesis
Speech tokens have to stream. Mini-Omni (Xie & Wu, 2024) introduced "language models can hear, talk while thinking in streaming": Thinker output tokens and Talker output tokens interleave in the same sequence. The Talker fires as soon as the Thinker commits the next text token, with no batch boundaries.
Moshi (Défossez et al., October 2024) is the fastest open implementation, at 160ms TTFAB on a single A100. It is a single 7B transformer that emits text and speech tokens on alternating positions, with an "inner monologue" that separates the thinking stream from the speaking stream. In effect that is Thinker + Talker fused into one model through careful training.
VAD and turn-taking
Voice activity detection runs on the input side. Two patterns:
- Half-duplex: the user speaks while the model listens, then the model speaks while the user listens. VAD silence detection (~200ms) makes the handoff.
- Full-duplex: both can speak at once. The model can backchannel ("uh-huh") or interrupt. This is much harder, and Moshi supports it.
Qwen2.5-Omni supports half-duplex by default, with turn-taking via a silence threshold. Full-duplex needs application-layer handling.
Qwen3-Omni (November 2025)
The successor has a Qwen3-80B Thinker, a larger Talker, and an improved TMRoPE-v2. Latency comes close to GPT-4o's 250ms. Weights are open, and benchmarks on OmniBench are competitive with Gemini 2.0 Live.
Production latency budget
For a typical streaming interaction:
- Mic -> audio tokens: 40-80ms.
- Prefill (prompt + history): 100-200ms at 7B, much more at 70B.
- First Thinker text token: 40ms.
- Talker processes first text token: 20ms.
- First speech tokens commit: 40ms.
- Residual-VQ decode: 30ms.
- Speech waveform decode: 50-80ms.
Total TTFAB: 320-510ms at 7B, 600-900ms at 70B. Frontier quality usually means 70B+, which is where the frontier latency gap comes from.
Token-rate math
At 16kHz speech with 50 Hz base speech tokens, you need 50 speech tokens per second of output, so the Talker must emit ≥50 tok/s to keep up. Typical LLM throughput on an H100 is 30-80 tok/s. A small (200-300M) Talker is fast enough, and a 7B Talker would fall behind.
That is why small dedicated Talker models exist instead of reusing the main model.
Use It
code/main.py is a calculator, with no audio in it. It:
- Simulates a Thinker-Talker pipeline with mock token-emission rates.
- Computes TTFAB for configurable model sizes and mic sample rates.
- Demonstrates half-duplex turn-taking with a VAD silence threshold.
Ship It
This lesson produces outputs/skill-omni-streaming-budget.md. Given a real-time voice product's target TTFAB and feature set (vision-in, bilingual, full-duplex), it picks Qwen2.5-Omni, Qwen3-Omni, Moshi, or Mini-Omni and sizes the Thinker and Talker.
I'd run main.py and read the four configs side by side before trusting any latency figure in the body. The 7B Thinker with a 200M Talker comes out at 305ms, which lands in the conversational band. Add vision and a 300M Talker and it moves to 390ms, almost all of it from the extra prefill.
My bet is that the Talker rows are the ones worth staring at. In the code the Talker's first-token cost is max(15, 20 * (talker_m / 300.0)), so going from 300M to 1B adds about 47ms while the Thinker terms scale with thinker_b / 7.0. That matches the argument for a small Talker, though the toy only prices size in latency and does not model the token-rate constraint at all.
I'd also treat the 70B rows with suspicion. Prefill and first-token time scale linearly with parameter count here, so the 70B and 72B configs print about 1.7 seconds, well outside the 600-900ms the budget section quotes. Real serving stacks use batching, tensor parallelism, and quantization, none of which are in this model. Use the script to see where the milliseconds go, and use measured numbers from your own hardware for a real product decision.
The turn-taking demo is a fixed timeline, not a VAD. The silence threshold only shifts when the end-of-turn event fires, and the "~400ms" it prints is a hard-coded string covering the two 200ms steps after the trigger. Add the 200ms threshold and the timeline actually shows 600ms from the user stopping to first audio.
Exercises
-
Your target TTFAB is 300ms. On a 7B Thinker and 300M Talker, write out every component's latency.
-
Qwen2.5-Omni uses TMRoPE. Describe what the model sees for a prompt where the user starts speaking at t=1s and the camera catches a gesture at t=1.2s.
-
Full-duplex support requires the model to emit audio while listening. Propose a training data format that teaches this.
-
Read Moshi's paper Section 4. Describe the "inner monologue" separation and why it avoids the Thinker-Talker split.
-
Compute the throughput budget: how fast must a Talker emit tokens to keep up with 16kHz speech at 50 base-layer tokens/sec?
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Thinker | "Reasoning brain" | Large text-generating transformer producing what to say |
| Talker | "Speech-generating mouth" | Small transformer producing discrete speech tokens from Thinker's text |
| TTFAB | "Latency budget" | Time-to-first-audio-byte: from user speech end to first audio sample out |
| TMRoPE | "Time-aligned RoPE" | Position encoding using absolute timestamps across vision, audio, text |
| Half-duplex | "Turn-taking" | User and model alternate; VAD silence detects user-done |
| Full-duplex | "Simultaneous" | Model can speak and listen at the same time; backchannel capable |
| Inner monologue | "Moshi separation" | Single-model design where thinking-stream and speaking-stream interleave |
Code
- main.py (python, 139 lines)