For the complete documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /get-started.md).
Python module
max.pipelines.architectures.qwen3_5
Qwen3.5 architecture: a hybrid model interleaving Gated DeltaNet linear attention with full attention, plus a vision encoder.
Qwen3_5Config
class max.pipelines.architectures.qwen3_5.Qwen3_5Config(*, hidden_size, num_attention_heads, num_key_value_heads, num_hidden_layers, rope_theta, rope_scaling_params, max_seq_len, intermediate_size, interleaved_rope_weights, vocab_size, dtype, model_quantization_encoding, quantization_config, kv_params, return_logits=ReturnLogits.LAST_TOKEN, norm_method='rms_norm', norm_dtype=None, attention_bias=False, rms_norm_eps=None, tie_word_embeddings=False, stacked_mlp=False, stacked_qkv=False, attention_multiplier, embedding_multiplier, residual_multiplier, devices, clip_qkv, quant_config=None, longrope_scaling_params=None, logits_scaling=1.0, return_hidden_states=ReturnHiddenStates.NONE, target_layer_ids=None, use_subgraphs=True, data_parallel_degree=1, sliding_window=None, quantization_encoding=None, layer_types=<factory>, full_attention_interval=4, linear_key_head_dim=128, linear_value_head_dim=128, linear_num_key_heads=16, linear_num_value_heads=48, linear_conv_kernel_dim=4, partial_rotary_factor=0.25, attn_output_gate=True, mamba_ssm_dtype=float32, state_pool_dtype=None, vision_config=None, mrope_without_encoder=False, image_token_id=None, video_token_id=None, vision_start_token_id=None, mrope_section=None, hf_quantization_config=None, quant_scheme=None, declared_dtype=None)
Bases: Llama3Config, ArchConfigWithVisionCache
Configuration for Qwen3.5 hybrid attention models.
Qwen3.5 uses a hybrid architecture with both full (standard) attention and linear attention (Gated DeltaNet) layers. Every full_attention_interval-th layer uses full attention, and the rest use linear attention.
-
Parameters:
-
- hidden_size (int)
- num_attention_heads (int)
- num_key_value_heads (int)
- num_hidden_layers (int)
- rope_theta (float)
- rope_scaling_params (Llama3RopeScalingParams | None)
- max_seq_len (int)
- intermediate_size (int)
- interleaved_rope_weights (bool)
- vocab_size (int)
- dtype (DType)
- model_quantization_encoding (QuantizationEncoding | None)
- quantization_config (QuantizationConfig | None)
- kv_params (KVCacheParamInterface)
- return_logits (ReturnLogits)
- norm_method (Literal['rms_norm', 'layer_norm'])
- norm_dtype (DType | None)
- attention_bias (bool)
- rms_norm_eps (float | None)
- tie_word_embeddings (bool)
- stacked_mlp (bool)
- stacked_qkv (bool)
- attention_multiplier (float)
- embedding_multiplier (float)
- residual_multiplier (float)
- devices (list[DeviceRef])
- clip_qkv (float | None)
- quant_config (QuantConfig | None)
- longrope_scaling_params (LongRoPEScalingParams | None)
- logits_scaling (float)
- return_hidden_states (ReturnHiddenStates)
- target_layer_ids (list[int] | None)
- use_subgraphs (bool)
- data_parallel_degree (int)
- sliding_window (int | None)
- quantization_encoding (SupportedEncoding | None)
- layer_types (list[str])
- full_attention_interval (int)
- linear_key_head_dim (int)
- linear_value_head_dim (int)
- linear_num_key_heads (int)
- linear_num_value_heads (int)
- linear_conv_kernel_dim (int)
- partial_rotary_factor (float)
- attn_output_gate (bool)
- mamba_ssm_dtype (DType)
- state_pool_dtype (DType | None)
- vision_config (VisionConfig | None)
- mrope_without_encoder (bool)
- image_token_id (int | None)
- video_token_id (int | None)
- vision_start_token_id (int | None)
- mrope_section (list[int] | None)
- hf_quantization_config (dict[str, Any] | None)
- quant_scheme (Qwen3_5QuantScheme | None)
- declared_dtype (DType | None)
DEFAULT_ENCODING
DEFAULT_ENCODING: ClassVar[SupportedEncoding] = 'bfloat16'
SUPPORTED_ENCODINGS
SUPPORTED_ENCODINGS: ClassVar[set[SupportedEncoding]] = {'bfloat16', 'float32', 'float4_e2m1fnx2', 'float8_e4m3fn'}
attn_kv_params
property attn_kv_params: KVCacheParams
The attention child of kv_params.
attn_output_gate
attn_output_gate: bool = True
Whether full attention layers use a sigmoid output gate.
calculate_attention_multiplier()
static calculate_attention_multiplier(huggingface_config)
Compute attention scaling factor using explicit head_dim.
-
Parameters:
-
huggingface_config (AutoConfig)
-
Return type:
calculate_max_seq_len()
classmethod calculate_max_seq_len(huggingface_config, model_config)
Bounds against the text config’s max_position_embeddings.
-
Parameters:
-
- huggingface_config (AutoConfig)
- model_config (MAXModelConfig)
-
Return type:
compute_dtype
property compute_dtype: DType
Dtype of activations and every unquantized weight.
dtype is the storage dtype the resolved encoding implies
(uint8 for packed NVFP4), which is not what the norms, embeddings,
conv1d or linear-attention state pools use.
quant_scheme is authoritative but only exists after
finalize; declared_dtype covers the earlier window so a
pre-finalize caller does not silently read the storage dtype.
construct_kv_params()
classmethod construct_kv_params(huggingface_config, pipeline_config, devices, kv_cache_config, cache_dtype, *, allow_kv_head_replication=False)
Returns the attention leaf beside the recurrent state.
The graph’s input types are built from these params, so a state derived any later cannot appear among them. A model with no linear-attention layers gets the attention leaf alone.
-
Parameters:
-
- huggingface_config (AutoConfig)
- pipeline_config (PipelineConfig)
- devices (list[DeviceRef])
- kv_cache_config (KVCacheConfig)
- cache_dtype (DType)
- allow_kv_head_replication (bool)
-
Return type:
declared_dtype
The dtype the checkpoint declares for its unquantized tensors.
Captured at initialize_from_config so compute_dtype is right
before finalize resolves quant_scheme. Memory planning runs in
that window.
declared_state_dtype()
static declared_state_dtype(text_config, kv_cache_config)
Returns state_dtype as far as it is knowable pre-finalize.
The state leaves are declared before a quantization scheme resolves.
cache_dtype is not a stand-in: --kv-cache-format may put the
KV in fp8 while the state stays bf16.
-
Parameters:
-
- text_config (AutoConfig)
- kv_cache_config (KVCacheConfig)
-
Return type:
estimate_vision_cache_entry_bytes()
classmethod estimate_vision_cache_entry_bytes(huggingface_config)
Estimates per-entry bytes for the Qwen3.5 vision encoder cache.
Qwen3.5’s tower is NaViT-style: an image keeps its aspect ratio and yields one token per merged patch, so — unlike Gemma4’s fixed pooled patch count — no per-image token count exists in the config to read. The bound that does exist is the image processor’s post-resize pixel ceiling, which every served image is smart-resized under, so the largest entry the cache can be asked to hold is that ceiling divided by the patch area and the spatial merge.
-
Returns:
-
Estimated bytes per vision cache entry, or 0 for a checkpoint with no vision tower.
-
Parameters:
-
huggingface_config (AutoConfig)
-
Return type:
full_attention_interval
full_attention_interval: int = 4
Every N-th layer uses full attention.
get_num_layers()
static get_num_layers(huggingface_config)
Layer count for the decoder stack (override when HF uses a different field).
-
Parameters:
-
huggingface_config (AutoConfig)
-
Return type:
get_vision_cache_row_spec()
classmethod get_vision_cache_row_spec(huggingface_config)
One embedding row per merged vision token, at the LM hidden size.
The dtype is the checkpoint’s declared one rather than a fixed
bfloat16, because the block pool has to match the buffers the encoder
hands it: those are cast to compute_dtype, which for every
encoding this architecture supports resolves to the declared dtype.
hf_quantization_config
The checkpoint’s resolved Hugging Face quantization config.
Captured at initialize_from_config because it lives on the top-level
multimodal config, while finalize is handed text_config.
image_token_id
Token ID used for image placeholders in the input sequence.
infer_optimal_batch_size()
infer_optimal_batch_size(devices, *, weights_size, device_memory_utilization, extra_per_request_bytes=0)
Return a memory-safe default max_batch_size for this architecture.
The states get up to half the post-weights utilization budget and the
KV absorbs the rest, under the same device_memory_utilization
headroom factor as the rest of the pipeline. The halving bounds
concurrency; it allocates nothing.
Falls back to 32—safe for the 27B model on H100/A100 (80 GB)—when the device query fails.
-
Parameters:
-
- devices (list[Device]) – Loaded devices the model will run on.
- weights_size (int) – Estimated model weights size in bytes.
- device_memory_utilization (float) – Headroom factor.
- extra_per_request_bytes (int) – Per-request state the architecture holds beyond the pool set this config declares – a speculative arch’s verify ring, for one. Added to the divisor so the inferred batch fits what will really be allocated.
-
Return type:
initialize()
classmethod initialize(pipeline_config, model_config=None, *, max_seq_len)
Initialize the config from a PipelineConfig.
-
Parameters:
-
- pipeline_config (PipelineConfig) – The pipeline configuration.
- model_config (MAXModelConfig | None) – The model configuration to read from. When
None(the default),pipeline_config.modelis used. Pass an explicit config (such aspipeline_config.draft_model) to initialize the arch config for a different model. - max_seq_len (int) – The effective maximum sequence length to store on
the config. The value is received, never derived here: the
pipeline model passes the memory plan’s VRAM-clamped length,
while memory planning (which runs before a plan exists)
passes the construction-resolved
model_config.max_length. Configs whose sequence length is pure model metadata (such as diffusion components) ignore it.
-
Return type:
initialize_from_config()
classmethod initialize_from_config(pipeline_config, huggingface_config, model_config=None, *, max_seq_len)
Initialize config from pipeline and HuggingFace configurations.
Handles both multimodal (Qwen3_5ForConditionalGeneration) and text-only (Qwen3_5ForCausalLM) configs by extracting the text config.
-
Parameters:
-
- pipeline_config (PipelineConfig)
- huggingface_config (AutoConfig)
- model_config (MAXModelConfig | None)
- max_seq_len (int)
-
Return type:
kv_params
kv_params: KVCacheParamInterface
The cache tree: an attention child beside a recurrent-state one.
attn_kv_params is the leaf the attention layers take.
layer_types
Per-layer attention type: ‘full_attention’ or ‘linear_attention’.
linear_conv_kernel_dim
linear_conv_kernel_dim: int = 4
Causal conv1d kernel size for linear attention layers.
linear_key_head_dim
linear_key_head_dim: int = 128
Key head dimension for linear attention layers.
linear_num_key_heads
linear_num_key_heads: int = 16
Number of key heads for linear attention layers.
linear_num_value_heads
linear_num_value_heads: int = 48
Number of value heads for linear attention layers.
linear_value_head_dim
linear_value_head_dim: int = 128
Value head dimension for linear attention layers.
mamba_ssm_dtype
mamba_ssm_dtype: DType = 81
Dtype for SSM (state space model) computations in linear attention layers.
mrope_enabled
property mrope_enabled: bool
Whether the model takes 3-axis M-RoPE positions.
vision_config stands in for “an image can appear in context”,
and mrope_without_encoder keeps them without the tower.
mrope_section
MRoPE section lengths for multimodal rotary position encoding.
mrope_without_encoder
mrope_without_encoder: bool = False
Keep M-RoPE on a graph that compiles no vision encoder.
vision_config normally carries two facts at once: that an encoder must
be built, and that images can appear in a request’s context. The fused
speculative graph separates them — it compiles no encoder and takes the
encoder’s output as inputs instead, but a request whose context holds an
image still needs 3-axis positions for every token after it. Setting this
keeps mrope_enabled true with vision_config cleared.
partial_rotary_factor
partial_rotary_factor: float = 0.25
Fraction of head_dim that gets rotary position embedding.
quant_scheme
quant_scheme: Qwen3_5QuantScheme | None = None
Which modules are quantized and how; set by _parse_quant_config().
state_dtype
property state_dtype: DType
Storage dtype of the linear-attention state pools.
Every declarer of a pool buffer reads this one property, since the base and fused speculative graphs share one allocation at serve time. Never the KV cache’s dtype.
state_pool_dtype
Storage dtype override for the linear-attention state pools.
None (the default) stores both pools at compute_dtype
(bfloat16), the configuration every exported artifact and the Mach
registry declare. float32 makes a speculated generation follow the
exact state trajectory of an unspeculated one — the recurrence rounds to
the pool dtype only at a call boundary, so a lossy pool makes the
trajectory depend on speculation’s chunking — at roughly double the
per-request state memory (74.8 to 149.6 MiB for Qwen3.8-27B). Set via the
state_pool_dtype KV-cache config knob; read through
state_dtype.
video_token_id
Token ID used for video placeholders in the input sequence.
vision_config
vision_config: VisionConfig | None = None
Vision encoder configuration; None for text-only models.
vision_start_token_id
Token ID that marks the start of vision content.
Qwen3_5Inputs
class max.pipelines.architectures.qwen3_5.Qwen3_5Inputs(tokens, input_row_offsets, signal_buffers, return_n_logits, data_parallel_splits=None, request_ids=None, decoder_position_ids=None, vision_inputs_in_graph=True, *, kv_cache_inputs=None, lora_buffers=(), vision_embeddings=<factory>, vision_scatter_indices=<factory>, hidden_states=None)
Bases: Llama3Inputs
Inputs for Qwen3.5, including the linear-attention state pools.
Image embeddings come from the pipeline-driven encoder cache on the base
vision_embeddings / vision_scatter_indices fields.
-
Parameters:
-
- tokens (Buffer)
- input_row_offsets (Buffer)
- signal_buffers (list[Buffer])
- return_n_logits (Buffer)
- data_parallel_splits (Buffer | Sequence[Sequence[int]] | None)
- request_ids (list[RequestID] | None)
- decoder_position_ids (Buffer | None)
- vision_inputs_in_graph (bool)
- kv_cache_inputs (KVCacheInputs[Buffer, Buffer] | None)
- lora_buffers (tuple[Buffer, ...])
- vision_embeddings (list[Buffer])
- vision_scatter_indices (list[Buffer])
- hidden_states (Buffer | list[Buffer] | None)
buffers
Returns positional Buffer inputs for model ABI calls.
decoder_position_ids
[3, total_seq_len] M-RoPE positions, one column per active token.
Present only when the graph was built with M-RoPE wired in; see
Qwen3_5.mrope_enabled.
request_ids
Request IDs for this batch, used to manage per-request state cache slots.
vision_inputs_in_graph
vision_inputs_in_graph: bool = True
Whether the graph declares the vision-merge inputs. False for text-only checkpoints, which compile no vision encoder and so take none.
Qwen3_5Model
class max.pipelines.architectures.qwen3_5.Qwen3_5Model(pipeline_config, session, devices, kv_cache_config, weights, *, memory_plan, adapter=None, return_logits=ReturnLogits.LAST_TOKEN, return_hidden_states=ReturnHiddenStates.NONE, max_batch_size=1)
Bases: AlwaysSignalBuffersMixin, LlamaModelBase
Qwen3.5 pipeline model implementation.
Supports the hybrid linear/full attention architecture with KV cache for full attention layers and conv/recurrent states for linear layers.
-
Parameters:
-
- pipeline_config (PipelineConfig) – The configuration for this pipeline.
- session (InferenceSession) – The container for the runtime for this model.
- devices (list[Device])
- kv_cache_config (KVCacheConfig)
- weights (Weights)
- memory_plan (MemoryPlan)
- adapter (WeightsAdapter | None)
- return_logits (ReturnLogits)
- return_hidden_states (ReturnHiddenStates)
- max_batch_size (int)
attention_bias
attention_bias: bool = False
Whether to use attention bias.
batch_processor_cls
batch_processor_cls
alias of Qwen3_5BatchProcessor
build_module()
classmethod build_module(context)
Builds the hybrid model from the checkpoint context names.
A caller that sized the cache passes its KV params. A module that encodes no images builds no vision tower, but keeps the 3-axis positions of a checkpoint that has one.
-
Parameters:
-
context (ModelLoadContext)
-
Return type:
-
tuple[Qwen3_5, Qwen3_5Config]
check_state_budget()
check_state_budget()
Checks the state the cache declares against what planning budgeted.
The two resolve state_dtype either side of finalize, and a
disagreement surfaces only as an OOM at load.
-
Return type:
-
None
empty_vision_embeddings()
empty_vision_embeddings(devices)
Per-device zero-row image embeddings for cached / text-only batches.
Cached: hit on every text-only / decode step, so it must not allocate per call, and graph-capture replay only skips an input refresh for an identical buffer object.
execute()
execute(model_inputs)
Executes the graph with the given inputs.
-
Parameters:
-
model_inputs (ModelInputs) – The model inputs to execute, containing tensors and any other required data for model execution.
-
Returns:
-
ModelOutputs containing the pipeline’s output tensors.
-
Return type:
This is an abstract method that must be implemented by concrete PipelineModels to define their specific execution logic.
graph_specs()
graph_specs(model_config)
Returns the decoder, and the vision encoder unless the checkpoint is text-only, in one compile group.
-
Parameters:
-
model_config (Qwen3_5Config)
-
Return type:
load_model()
load_model(session)
Loads the decoder graph graph_specs() returns.
A subclass that still overrides _build_graph_for_compile loads
through that hook instead.
-
Parameters:
-
session (InferenceSession) – The session that compiles and initializes the graph.
-
Returns:
-
The initialized decoder.
-
Return type:
model
model: Model
Compiled and initialized model ready for inference.
model_config_cls
model_config_cls
alias of Qwen3_5Config
norm_method
norm_method: Literal['rms_norm', 'layer_norm'] = 'rms_norm'
Normalization layer.
pack_vision_inputs()
pack_vision_inputs(selection, devices)
Pack the pipeline-selected cache-miss images to device.
Runs in the pipeline’s prep-ahead window so the host-to-device copy overlaps the prior batch.
state_dict
Weights to load into the model.
vision_execute()
vision_execute(selection, devices, packed)
Run the vision encoder on the media pack_vision_inputs packed.
Returns explicit per-item token counts rather than letting the driver
derive them from placeholder spans. A clip’s span covers grid_t
placeholder runs AND the timestamp text between them, so its width
exceeds the rows the encoder emits; an image’s span happens to match,
which is why the derived counts were correct until now.
vision_model
Qwen3_5ReasoningParser
class max.pipelines.architectures.qwen3_5.Qwen3_5ReasoningParser(think_start_token_id, think_end_token_id, tool_call_start_token_id=None)
Bases: ReasoningParser
Qwen 3.5 / 3.6 reasoning parser for <think>...</think> sections.
Qwen 3.5/3.6’s chat template prepends <think>\n to every assistant
turn when enable_thinking is true (the default), so reasoning
begins implicitly without an explicit <think> token in the model
output stream. Reasoning ends explicitly at </think>, or
implicitly when a tool call begins (<tool_call>) — the tool-call
marker is left in the content region for the tool parser to consume.
-
Parameters:
REASONING_END
Text delimiter that closes a reasoning span, such as "</think>".
See REASONING_START for the declaration contract.
REASONING_START
Text delimiter that opens a reasoning span, such as "<think>".
Subclasses declare their delimiters here and resolve token ids from them, so each model’s delimiters are written down exactly once. Consumers that work in the text domain rather than the token domain read them from here instead of restating them.
Declare both delimiters or neither. None means this parser has no text
form at all, so a text-domain consumer cannot bound a reasoning span and
will leave reasoning in the assistant’s content; declaring only one is a
bug, since a span needs both ends. A parser whose chat template prefills
the opening delimiter still declares it – whether a given turn emits it is
a property of the request, not of the parser.
from_tokenizer()
async classmethod from_tokenizer(tokenizer)
Construct a reasoning parser from a tokenizer.
-
Parameters:
-
tokenizer (PipelineTokenizer[Any, Any, Any])
-
Return type:
reasoning_end_token_id()
async classmethod reasoning_end_token_id(tokenizer)
Returns the </think> token id that closes a reasoning span.
-
Parameters:
-
tokenizer (PipelineTokenizer[Any, Any, Any])
-
Return type:
-
int | None
stream()
stream(delta_token_ids, is_currently_reasoning=True)
Identify a reasoning span within a streaming delta chunk.
When is_currently_reasoning=False and the chunk contains no
<think> opener, returns an empty span so post-reasoning content
chunks aren’t misclassified as reasoning.
-
Parameters:
-
Return type:
will_reason_after_prompt()
will_reason_after_prompt(prompt_token_ids)
Decide whether the next generated token continues a reasoning span.
Overrides the ABC default (which delegates to stream scanning
left-to-right). That default is wrong for Qwen: the chat template
embeds a literal <tool_call> example in the tool instructions,
and <tool_call> is a reasoning-end delimiter — so a left-to-right
scan hits the example and falsely concludes reasoning already ended,
leaking the model’s <think> block into content.
Multi-turn prompts can also contain <think>/</think> tokens
from prior assistant turns; only the most-recently-emitted delimiter
describes the current state. Scan right-to-left: the last delimiter
before generation is the chat template’s prefilled <think>.
Qwen3_5ToolParser
class max.pipelines.architectures.qwen3_5.Qwen3_5ToolParser
Bases: object
Parser for Qwen 3.5 / 3.6 tool calls.
CALL_BEGIN
XGRAMMAR_FORMAT
XGRAMMAR_FORMAT = 'qwen_3_5'
generate_tool_call_grammar()
static generate_tool_call_grammar(response_format_schema=None, tools=None, tokenizer=None, backend='xgrammar', tool_choice=None, reject_unsupported=False, **kwargs)
Build a constrained-decoding grammar for Qwen 3.5 tool calls.
Returns a serialized xgrammar StructuralTag that frames the
<tool_call> envelope and constrains each call’s arguments to that
tool’s JSON schema. When response_format_schema is provided, the
grammar also accepts a JSON response matching the schema (the model’s
first tokens select the branch).
-
Parameters:
-
- response_format_schema (dict[str, Any] | None) – Optional JSON schema dict. When provided, the grammar also accepts a JSON response matching the schema.
- tools (list[dict[str, Any]] | None) – Optional list of OpenAI-style tool dicts.
- tokenizer (Any | None) – Unused (the xgrammar tag references literal markers).
- backend (str) – Structured-output backend; must be
"xgrammar". - tool_choice (str | dict[str, Any] | None) –
"auto","required", or a named choice. - reject_unsupported (bool) – Whether to raise an error during grammar compilation when a tool’s schema cannot be enforced. Otherwise, the schema is enforced best-effort.
- **kwargs (Any) – Ignored; accepts future kwargs.
-
Returns:
-
The StructuralTag serialized as a JSON string.
-
Return type:
parse_complete()
parse_complete(response)
Parse a complete model response into tool calls.
-
Parameters:
-
response (str)
-
Return type:
parse_delta()
parse_delta(delta)
Incrementally process one decoded-token delta.
Returns content text to forward to the client and any tool-call
increments to emit, in the order they were produced. Content
deltas have content set; tool-call deltas have one or more of
id / name / arguments set.
-
Parameters:
-
delta (str)
-
Return type:
-
list[ParsedToolCallDelta] | None
reset()
reset()
Reset internal state for a new streaming session.
-
Return type:
-
None
set_streaming_tool_schemas()
set_streaming_tool_schemas(schemas)
Records the schemas for typed argument decoding while streaming.
See ToolParser.set_streaming_tool_schemas and
set_tool_schemas().
set_tool_schemas()
set_tool_schemas(schemas)
Supplies each tool’s parameters schema, keyed by function name.
Optional hook, called by the router before parsing a request’s output (streaming or not) so values are decoded by their declared type.