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 function
causal_conv1d_varlen_fwd
causal_conv1d_varlen_fwd()
max.nn.legacy.state_space.causal_conv1d_varlen_fwd(x, weight, bias, conv_states, query_start_loc, cache_indices, has_initial_state, activation='silu', channels_last=False, use_residual=False, update_state=None)
Applies a slot-indexed varlen causal depthwise conv1d.
Serves prefill and decode.
Mutates the conv-state pool conv_states in place at slot
cache_indices[batch_item] — the Qwen3.5 GatedDeltaNet conv
pattern. The builtin registers conv_states as a
MutableInputTensor at operand position 4 (after output, x, weight, bias). update_state is the last operand.
-
Parameters:
-
- x (TensorValue) – The
[dim, total_seqlen]input (channels-first, model dtype), or[total_seqlen, dim]whenchannels_lastis true. - weight (TensorValue) – The
[dim, width]depthwise conv weights. - bias (TensorValue) – The
[dim]per-channel bias (empty to disable). - conv_states (BufferValue) – The
[max_slots, dim, width - 1]mutable conv-state pool. - query_start_loc (TensorValue) – The
[batch + 1]int32 cumulative sequence lengths. - cache_indices (TensorValue) – The
[batch]uint32 slot indices intoconv_states, or one[1, batch]row of a per-layer table. - has_initial_state (TensorValue) – The
[batch]bool, whether to use the stored state. - activation (str) –
"silu"or"none". - channels_last (bool) – If true,
xand the output are tokens-major[total_seqlen, dim]. The kernel indexes through runtime strides, so this only relabels the axes — it avoids the materialized transposes the[dim, total_seqlen]contract forces on a tokens-major caller. - use_residual (bool) – If true, adds
xto the convolution sum at each output position, beforeactivation. - update_state (TensorValue | None) – The
[batch]bool, whether each sequence writes its new window back to itsconv_statesslot.Nonewrites every sequence’s, as before the flag existed. A sequence with the flag false leaves its slot untouched, so the op reads the pool without advancing it. The output does not depend on the flag.
- x (TensorValue) – The
-
Returns:
-
The conv output with the same shape/layout as
x.conv_statesis mutated in place. -
Return type:
The following example convolves a ragged batch of two sequences, of lengths 3 and 2, with a width-4 kernel. The first sequence continues from the history stored in slot 2. The second starts fresh in slot 0:
import numpy as np
from max.driver import CPU, Accelerator, Buffer, accelerator_count
from max.dtype import DType
from max.engine import InferenceSession
from max.graph import BufferType, DeviceRef, Graph, TensorType
from max.nn.legacy.state_space import causal_conv1d_varlen_fwd
device = Accelerator() if accelerator_count() > 0 else CPU()
device_ref = DeviceRef.from_device(device)
dim, total_seqlen, width, max_slots = 8, 5, 4, 3
with Graph(
"causal_conv1d_varlen_fwd_example",
input_types=(
TensorType(
DType.float32, [dim, total_seqlen], device=device_ref
),
TensorType(DType.float32, [dim, width], device=device_ref),
TensorType(DType.float32, [dim], device=device_ref),
BufferType(
DType.float32,
[max_slots, dim, width - 1],
device=device_ref,
),
TensorType(DType.int32, [3], device=device_ref),
TensorType(DType.uint32, [2], device=device_ref),
TensorType(DType.bool, [2], device=device_ref),
),
) as graph:
(
x,
weight,
bias,
conv_states,
query_start_loc,
cache_indices,
has_initial_state,
) = graph.inputs
output = causal_conv1d_varlen_fwd(
x.tensor,
weight.tensor,
bias.tensor,
conv_states.buffer,
query_start_loc.tensor,
cache_indices.tensor,
has_initial_state.tensor,
)
graph.output(output)
rng = np.random.default_rng(0)
x_np = rng.standard_normal((dim, total_seqlen), dtype=np.float32)
weight_np = rng.standard_normal((dim, width), dtype=np.float32)
bias_np = rng.standard_normal(dim, dtype=np.float32)
states_np = rng.standard_normal(
(max_slots, dim, width - 1), dtype=np.float32
)
starts = np.array([0, 3, 5], dtype=np.int32)
slots = np.array([2, 0], dtype=np.uint32)
use_history = np.array([True, False])
inputs = [
Buffer.from_numpy(array).to(device)
for array in (
x_np,
weight_np,
bias_np,
states_np.copy(),
starts,
slots,
use_history,
)
]
model = InferenceSession(devices=[device]).load(graph)
result = model.execute(*inputs)[0].to_numpy()
states = inputs[3]
# result.shape is (8, 5), the same layout as x.