IMPORTANT: To view this page as Markdown, append `.md` to the URL (e.g. /get-started.md). For the complete documentation index, see llms.txt.
Skip to main content
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)

source

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] when channels_last is 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 into conv_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, x and 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 x to the convolution sum at each output position, before activation.
  • update_state (TensorValue | None) – The [batch] bool, whether each sequence writes its new window back to its conv_states slot. None writes 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.

Returns:

The conv output with the same shape/layout as x. conv_states is mutated in place.

Return type:

TensorValue

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.