Skip to main content

Standalone causal streaming runtime for Qwen3-ASR

Project description

Qwen3-ASR causal

Standalone runtime for the causal streaming audio tower published at qfuxa/qwen3-asr-0.6b-streaming.

The weights are not stored in this repository. The runtime downloads the causal tower from Hugging Face and loads the unchanged decoder, adapter and feature extractor from Qwen/Qwen3-ASR-0.6B.

Offline Qwen3-ASR vs causal streaming execution

Install

pip install -e ".[streaming]"

For CUDA/vLLM serving, including the causal audio tower path:

pip install -e ".[vllm]"

For Apple Silicon vLLM Metal serving, install vLLM with the official vllm-metal instructions first, then install the Metal extra:

pip install -e ".[metal]"

Usage

HF Transformers causal runtime:

qwen3-asr-causal transcribe audio.wav --backend hf --language en

vLLM CUDA runtime with the live prompt-embedding append path:

WLK_QWEN3_VLLM_LIVE_MULTIPROCESSING=1 \
qwen3-asr-causal transcribe audio.wav \
  --backend vllm \
  --decoder-backend vllm-live \
  --language en

The conservative vLLM fallback uses text-decoder prefix caching:

qwen3-asr-causal transcribe audio.wav \
  --backend vllm \
  --decoder-backend vllm-text \
  --language en

The Apple Silicon backend exposes the same runtime through qwen3_asr_causal.metal for WhisperLiveKit and local benchmark integration.

How it works

The original Qwen3-ASR audio tower is offline and fully bidirectional. This runtime uses a fine-tuned causal tower that runs append-only:

  • fixed 1.92 s audio blocks, with full attention inside each block;
  • causal per-layer KV across blocks;
  • bounded 15 s left attention window;
  • monotonically increasing sinusoidal positions;
  • no re-encoding of already finalized audio blocks.

Decoder-side serving loop

The live text contract is append-only. At each non-final update the runtime cuts the hypothesis portion aligned to the last 250 ms of audio and only publishes text that extends the previously published prefix. End of stream flushes the held-back tail, but still cannot revise words already published.

Results

Long-form evaluation: 21 MCIF/ACL conference talks, about 2 h total, accented scientific English, human references, Whisper text normalization. All three rows run the same base model; the contracts differ.

system scoring contract WER compute per second of audio
Offline, VAD-segmented full file available, no latency 7.6 offline
Streaming Qwen3-ASR (windowed) settled transcript 8.4 126 GFLOPs avg, growing to 172 within each segment
Streaming Qwen3-ASR (windowed) live, no rewrite, 250 ms tail cut + EOS flush 12.6 126 GFLOPs avg, growing to 172
Streaming Qwen3-ASR causal live = settled (0 committed-word retractions on all 21 files) 18.1 42 GFLOPs, constant
Streaming Qwen3-ASR causal committed-only, no EOS flush 19.4 42 GFLOPs, constant

Offline-done-right is the quality ceiling; the windowed backend is that strategy made streaming; the causal tower trades ~1.4x the live windowed WER for 3.0x (avg) to 4.1x (peak) less compute, constant in stream age (benchmarks/suite/run_flops.py, FlopCounterMode on real weights).

Language support: the causal tower is English-only — its LibriSpeech distillation degraded other languages severely (FLEURS: fr 7.8→37.9, de 12.6→49.8 WER, zh 11.4→85.7 CER vs windowed; see benchmarks/suite/results/mps_20260707_fleurs/). Use the windowed backend for non-English sessions.

Short-form through the same streaming stack: LibriSpeech test-clean 3.64 / test-other 7.16 (for reference, Voxtral Mini Realtime 3B @480 ms publishes 2.1 / 5.5 with ~5x the parameters). At the shipped low-latency default (stable_iterations=1) the full test sets measure 3.67 / 7.22 — the latency gain is free on short-form.

Commit latency

Per-committed-word latency (word spoken → word committed, feeding at 1.0x), measured by replaying the 21-talk events under the live contract (benchmarks/suite/results/mps_20260707_latency/):

policy p50 p95 live WER (whisper-norm)
hold 6 / stable 2 (old default) 5.9 s 13.6 s 18.3
hold 6 / stable 1 (default) 4.0 s 7.9 s 18.8
hold 2 / stable 1 (--qwen3-streaming-hold-back-words 2) 2.1 s 7.8 s 18.9

At the old default, 93% of words were committed by the ~12-16 s punctuation rollover rather than the stability policy — one stability iteration is enough on the causal hypothesis stream. The 2.1 s point sits at the 1.92 s block cadence floor. The unstable tail is additionally visible immediately through get_buffer() (~2 s behind the audio head).

Streaming RTF

Streaming RTF is ASR compute divided by audio duration, excluding model load. The H100 bars are pure HF Transformers/CUDA. The A100 bars are vLLM CUDA. The Metal bars use vLLM Metal on Apple Silicon.

Key numbers:

  • H100 HF Transformers: normal windowed 0.293 RTF, causal 0.160 RTF.
  • Apple M5 vLLM Metal: normal 0.262 RTF, causal 0.156 RTF.
  • Apple M-series HF/MPS fp16: causal 0.116 RTF over the full 21-talk set, and quality parity with the H100 bf16 run (settled 18.3 vs 18.1).
  • A100 vLLM CUDA: normal 0.146 RTF, causal vllm-live 0.099 RTF.
  • The A100 vllm-text fallback measured 0.113 RTF on the same 22 s smoke.
  • CPU fp32 (Apple M-series cores): causal 0.82 RTF on a 277 s talk — real-time capable, single session.

These speed smokes are not WER claims; use the long-form WER table above for quality comparisons.

Hardware support

target backend dtype status
CUDA (Linux) hf or vllm (vllm-live / vllm-text) bf16 primary; vLLM is the multi-session path
Apple Silicon hf (pure torch/MPS) fp16 measured: quality parity with CUDA bf16, RTF 0.116
Apple Silicon qwen3_asr_causal.metal (vLLM Metal / MLX) fp16 Python 3.12, darwin arm64 only
CPU hf fp32 works, RTF ~0.8; no quantized path yet

The HF backend serializes concurrent sessions behind one decode lock: treat it as the single-session/edge path and use the vLLM CUDA backend when serving many sessions.

Python

from qwen3_asr_causal import Qwen3StreamingASR, Qwen3StreamingOnlineProcessor

asr = Qwen3StreamingASR(
    lan="en",
    model_size="Qwen/Qwen3-ASR-0.6B",
    qwen3_streaming_audio_backend="causal",
    qwen3_streaming_tower_checkpoint="qfuxa/qwen3-asr-0.6b-streaming",
)
processor = Qwen3StreamingOnlineProcessor(asr)

Development

Default tests are lightweight and do not download Qwen weights:

python -m py_compile $(find src/qwen3_asr_causal -name "*.py")
pytest -q

Real inference is opt-in:

QWEN3_ASR_CAUSAL_E2E=1 pytest tests/test_e2e.py

The ongoing research notebooks, training scripts, run logs, and WER/RTF benchmarks live in experiments/qwen3-causal/ and benchmarks/. WhisperLiveKit imports this package instead of carrying a second copy of the Qwen runtime.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qwen3_asr_causal-0.1.0.tar.gz (137.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qwen3_asr_causal-0.1.0-py3-none-any.whl (100.6 kB view details)

Uploaded Python 3

File details

Details for the file qwen3_asr_causal-0.1.0.tar.gz.

File metadata

  • Download URL: qwen3_asr_causal-0.1.0.tar.gz
  • Upload date:
  • Size: 137.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for qwen3_asr_causal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0ac5945f850e76a8563043cd7ec20133b03bd81c3560661d5ff99a69d6f21c3b
MD5 425f29283959d6e1970b1a4e44e18b82
BLAKE2b-256 38e901168faa31b010c07a547f02e5216dc649ec64ffd4df0b4ec8884616f170

See more details on using hashes here.

File details

Details for the file qwen3_asr_causal-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for qwen3_asr_causal-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae060ffcd924f14dc4f9667353bbcabcb7f4d1bbd1be8e29bae9cc828b7cd28e
MD5 87da2aca4673bda9441510bcaca0c4c0
BLAKE2b-256 7d7338758b9f44813cf54916271b18dca539e5c0cf8b2c67df69ea3e49b5d6af

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page