Qwen3-Omni#
Qwen3-Omni is a multi-modal model that accepts text, image, audio, and video input and can produce text-only or text + audio output. This page covers every supported server configuration — use the generator to get the exact launch command for your hardware, then check the tables to confirm your combination is supported.
Prerequisites#
docker pull hongccc/sglang-omni:dev
docker run -it --shm-size 32g --gpus all hongccc/sglang-omni:dev /bin/zsh
pip install --upgrade pip
pip install uv
uv venv .venv -p 3.12 && source .venv/bin/activate
uv pip install --prerelease=allow "sglang-omni==0.2.0"
See Installation for Docker digests and source installs.
Server Configuration#
Use the selector below to generate the exact launch command for your configuration.
Compatibility Matrix#
Colocated topology requires --config examples/configs/qwen3_omni_colocated_h20.yaml
(or qwen3_omni_colocated_h200.yaml on H200) to set per-stage GPU memory budgets.
All configurations listed below are supported.
Mode |
Topology |
Thinker TP |
Precision |
|---|---|---|---|
Thinker-only |
— |
— |
BF16 |
Thinker-only |
— |
— |
FP8 |
Thinker-only |
— |
— |
AutoRound INT4 |
Thinker-Talker |
Disaggregated |
TP=1 |
BF16 |
Thinker-Talker |
Disaggregated |
TP=1 |
FP8 |
Thinker-Talker |
Disaggregated |
TP=1 |
AutoRound INT4 thinker + BF16 talker/code2wav |
Thinker-Talker |
Disaggregated |
TP=2 |
BF16 |
Thinker-Talker |
Disaggregated |
TP=2 |
FP8 |
Thinker-Talker |
Disaggregated |
TP=2 |
AutoRound INT4 thinker + BF16 talker/code2wav |
Thinker-Talker |
Colocated |
TP=1 |
BF16 |
Thinker-Talker |
Colocated |
TP=1 |
FP8 |
Thinker-Talker |
Colocated |
TP=1 |
AutoRound INT4 thinker + BF16 talker/code2wav |
Input / Output Modalities#
All input modality combinations work with both text-only and speech servers.
modalities: ["text", "audio"] requires a speech-mode server (omit --text-only).
Input |
Output |
Speech server |
Minimal request body |
Notes |
|---|---|---|---|---|
Text |
Text |
No |
|
— |
Image + text |
Text |
No |
|
— |
Audio |
Text |
No |
|
content must be “” when the query is spoken |
Image + audio |
Text |
No |
|
content must be “” when the query is spoken |
Image |
Text |
No |
|
content must be “” when query comes from image |
Video + text |
Text |
No |
|
— |
Video + audio |
Text |
No |
|
content must be “” when the query is spoken |
Video |
Text |
No |
|
content must be “” when query comes from video |
Text |
Text + Audio |
Yes |
|
— |
Image + text |
Text + Audio |
Yes |
|
— |
Audio |
Text + Audio |
Yes |
|
content must be “” when the query is spoken |
Image + audio |
Text + Audio |
Yes |
|
content must be “” when the query is spoken |
Image |
Text + Audio |
Yes |
|
content must be “” when query comes from image |
Video + text |
Text + Audio |
Yes |
|
— |
Video + audio |
Text + Audio |
Yes |
|
content must be “” when the query is spoken |
Video |
Text + Audio |
Yes |
|
content must be “” when query comes from video |
Sampling Parameters#
Standard sampling parameters apply to the thinker stage. When modalities includes "audio", the additional talker-specific parameters below control the speech generation independently.
Parameter |
Type |
Default |
Applies to |
|---|---|---|---|
|
float |
|
Thinker |
|
float |
|
Thinker |
|
int |
|
Thinker |
|
float |
|
Thinker |
|
float |
|
Thinker |
|
int |
|
Thinker |
|
int |
|
Thinker; OpenAI-compatible alias for |
|
str | list |
|
Thinker |
|
int |
|
Thinker |
|
bool |
|
Both |
|
dict |
|
Speech response format config, e.g. |
|
float |
|
Talker (audio output only) |
|
float |
|
Talker (audio output only) |
|
int |
|
Talker (audio output only) |
|
float |
|
Talker (audio output only) |
|
int |
|
Talker (audio output only) |
|
dict |
|
Per-stage sampling override |
|
dict |
|
Per-stage non-sampling params |
|
float |
|
Frame sampling rate for video input (uses server default if unset) |
|
int |
|
Maximum number of frames sampled from a video |
|
int |
|
Minimum pixels per video frame |
|
int |
|
Maximum pixels per video frame |
|
int |
|
Total pixel budget across all video frames |
|
bool |
|
Set to |
Non-streaming chat requests return HTTP 400 for invalid media, HTTP 503 when the request queue is full, and HTTP 500 for other
server failures. With stream=true, errors detected after the event stream
starts are sent as data: {"error": {"message": "...", "type": "invalid_request_error", "code": 400}},
followed by data: [DONE]. A full request queue uses type: "server_error" and code: 503. Other server failures use type: "server_error" and
code: 500. The HTTP status remains 200 once streaming has started; clients
must check for an error event, including after partial output.
Known Limitations#
Multiple videos must have the same sampled frame rate. The processor accepts one frame rate for video token timestamps. Requests with different sampled frame rates follow the invalid-input error contract above.
modalities: ["text", "audio"]has no effect on a text-only server. No error is raised — the response simply contains no audio. Use a speech-mode server (without--text-only) to get audio output.contentmust be""when the query is entirely inaudios,videos, orimages. Leaving a text query incontentalongside audio causes the model to process both, which is usually not what you want.Colocated topology does not support
--thinker.tp_size 2. The server raises aValueErrorat startup (“Qwen Phase 1 colocation does not support thinker TP”). Use disaggregated topology for TP=2.Requests that exceed the model’s context length are rejected with an error. The preprocessor raises a
ValueErrorwhen the prompt token count alone meets or exceedsmax_seq_len, or whenprompt tokens + max_new_tokens ≥ max_seq_len. Reduce input length or lowermax_tokensto stay within the limit. Without--preprocessing.factory.max_seq_lenand--thinker.factory.max_seq_len, the limit is the thinker’s context in the checkpoint config (65,536 tokens for the Instruct checkpoint). Setting both to a lower value caps it. The talker’s context is likewise the checkpoint’s unless--talker_ar.factory.max_seq_lensets it. When a long spoken prompt leaves less room thantalker_max_new_tokens, the talker generates only the frames that fit, so the audio can end before the text.
Qwen3-Omni persistent session stages#
The session profile serves Qwen3-Omni as a turn-based realtime voice assistant on /v1/realtime: a VAD node ends each user turn and the model answers it with the conversation so far. Launching on H100 or H200, settings, the protocol and benchmarking are in Full-Duplex Guide.
Speculative Decoding#
The thinker can verify tokens proposed by SpeechSpec’s DFlash draft yuekai/qwen3_omni_30b_a3b_instruct_dflash_block8 or EAGLE3 draft yuekai/qwen3_omni_30b_a3b_instruct_eagle3_audio on a text-only server.
# DFlash: one 8-token block per step
sgl-omni serve \
--model-path Qwen/Qwen3-Omni-30B-A3B-Instruct \
--text-only \
--thinker.engine.speculative_algorithm DFLASH \
--thinker.engine.speculative_draft_model_path yuekai/qwen3_omni_30b_a3b_instruct_dflash_block8 \
--thinker.engine.speculative_num_draft_tokens 8 \
--port 8000
# EAGLE3: a 3-step chain
sgl-omni serve \
--model-path Qwen/Qwen3-Omni-30B-A3B-Instruct \
--text-only \
--thinker.engine.speculative_algorithm EAGLE3 \
--thinker.engine.speculative_draft_model_path yuekai/qwen3_omni_30b_a3b_instruct_eagle3_audio \
--thinker.engine.speculative_num_steps 3 \
--thinker.engine.speculative_eagle_topk 1 \
--thinker.engine.speculative_num_draft_tokens 4 \
--port 8000
Acceptance length. Send
return_spec_tokens_details: truewith a chat request to get itssglext.spec_tokens_details:spec_accept_length(output tokens per verify, including the token sampled at prefill, so it can read higher than the scheduler log’saccept len, which counts only verified tokens),spec_accept_rate, the draft counts and the per-verify histogram. A streamed response sends it in a chunk with emptychoicesbefore[DONE].spec_accept_rateandspec_num_proposed_draftsare left out when no drafts were proposed or the draft width is adaptive. Only the Thinker draft is reported for now; a per-stage field can follow once the Talker has a draft too.Context. The drafts shown above have an 8,192-token context. The prompt, output budget and speculative reservations must fit within it. Use
--preprocessing.factory.max_seq_len 8192to reject oversized prompts early.Sampling. Keep
repetition_penalty=1,frequency_penalty=0,presence_penalty=0, andmin_p=0. Disable logprobs andreturn_hidden_states. For/generate, sendreturn_logprob: false.Scheduling. Speculative decoding is synchronous by default. Add
--thinker.factory.enable_async_decode trueto either command to enable overlap, keepingasync_decode_min_batch_size=1. Mixed prefill/decode batches (enable_mixed_chunk=true), sessions and weight updates are unsupported with a draft.Overlap trade-offs. Overlap can improve decode throughput. Prefill-heavy workloads or short outputs can see higher TTFT and lower throughput.
Prefill boundary. Set
SGLANG_DISABLE_CONSECUTIVE_PREFILL_OVERLAP=1before launch to process the previous prefill batch’s result before launching the next consecutive prefill batch. This can lower TTFT at a throughput cost. Decode rounds continue to overlap.Execution failure. An execution failure in speculative overlap stops the pipeline and fails its pending requests.
Speech output. Speech generation is unsupported with a draft; use
--text-only.
Compare modes with matching workloads and prefix-cache conditions. Measure TTFT, throughput and accuracy for your workload.