<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Modular Blog</title>
        <link>https://docs.modular.com/releases/</link>
        <description>Modular Blog</description>
        <lastBuildDate>Sat, 25 Jul 2026 05:57:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[MAX nightly]]></title>
            <link>https://docs.modular.com/releases/nightly/</link>
            <guid>https://docs.modular.com/releases/nightly/</guid>
            <pubDate>Sat, 25 Jul 2026 05:57:00 GMT</pubDate>
            <description><![CDATA[This version is still a work in progress.]]></description>
            <content:encoded><![CDATA[<p>This version is still a work in progress.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-models">MAX models<a href="https://docs.modular.com/releases/nightly/#max-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">Added GLM-5.2 (<code>GlmMoeDsaForCausalLM</code>) support, extending the existing
GLM-5.1 sparse-attention architecture with cross-layer index sharing.</li>
<li class="">Added multi-token prediction (MTP) speculative decoding for GLM-5.2
(<code>UnifiedMTPGlm5_2ForCausalLM</code>). The baked-in NextN layer is served as a
single-layer sparse-MLA draft (its own lightning indexer plus a paired
<code>{mla, indexer}</code> KV cache); per <code>index_share_for_mtp_iteration</code>, the draft
computes its top-k selection on the first MTP step and reuses it on the
rest. Enabled automatically for GLM checkpoints that ship a NextN layer when
speculative decoding is requested with no separate draft model. Validated on
<code>zai-org/GLM-5.2-FP8</code> and <code>nvidia/GLM-5.2-NVFP4</code> across 8 B200s
(<code>--speculative-method mtp</code>).</li>
<li class="">Added Laguna (<code>LagunaForCausalLM</code>), poolside's decoder-only sparse-MoE
language model. It uses sigmoid expert routing with a per-expert
score-correction bias, a per-element softplus attention-output gate, and
per-head QK-RMSNorm. Verified on <code>poolside/Laguna-M.1-NVFP4</code> (131B,
compressed-tensors NVFP4 experts) on a single B200, including chat-template
serving and tool calling. On GSM8K (0-shot) it scores ~0.81 with light
sampling (<code>temperature=0.3</code> plus a frequency penalty); greedy decoding
(<code>temperature=0</code>) is <strong>not</strong> recommended for this NVFP4 checkpoint, since it
falls into repetition loops on a sizable fraction of prompts (dropping GSM8K
to ~0.59). An experimental, not-yet-accuracy-validated FP8 KV cache (unscaled
cast) is available behind <code>--kv-cache-format float8_e4m3fn</code>; the default bf16
KV cache is the validated configuration.</li>
<li class="">Added DiffusionGemma (<code>DiffusionGemmaForBlockDiffusion</code>), an
encoder/decoder block-diffusion text model that generates 256-token
blocks per step via an inner denoising loop. Supports NVFP4 and bfloat16
weights; text-only for now.</li>
<li class="">Added Nemotron-H (<code>NemotronHForCausalLM</code>), NVIDIA's hybrid Mamba-2 +
attention + relu-squared-MLP decoder, with modelopt per-tensor FP8. Adds a
new Mamba-2 SSD chunked-scan varlen prefill kernel (also used for decode as
length-1 sequences). Verified on <code>nvidia/NVIDIA-Nemotron-3-Nano-4B-FP8</code> on a
single B200: random-weight logit-verify cosine 0.9999 vs HuggingFace, GSM8K
strict-match ~0.70. Decode is optimized with an in-place SSM state-pool
read-modify-write that writes only the active slots (+52% output tok/s at
concurrency 32).</li>
<li class="">Extended Nemotron-H with the Nemotron-3-Nano-30B-A3B hybrid MoE variant (a
sigmoid-plus-bias top-6 router over 128 routed experts plus a shared expert)
and enabled the Nemotron-H architecture on Apple silicon GPUs in bfloat16.
The MoE path on Metal uses an integer-domain expert-gather index
(<code>ops.floor_div</code>, avoiding a 64-bit-float divide) and a 32-bit
<code>moe_create_indices</code> atomic (Apple GPUs lack 64-bit atomics), and adds an
Apple FP4 (W4A16) decode GEMV with an f16-domain E2M1 decode plus a
redesigned varlen causal-conv1d kernel. Verified on M5: the 30B-A3B MoE
serves in bfloat16 at GSM8K 8-shot ~0.85.</li>
<li class="">Added an <code>enable_dp_cross_replica_prefix_copy</code> KV cache config flag
(default on). When serving with data parallelism, a prefix-cache hit
resident on another DP replica's GPU is normally served by a
device-to-device copy onto the request's replica. Disabling the flag turns
those copies off so cross-replica reuse is served only from the shared
host/disk tier via the KV connector (or recomputed), which can be
preferable when a connector is configured and GPU block-pool pressure
matters more than copy bandwidth.</li>
<li class="">Added tool-calling and reasoning support to Qwen 3.5 / 3.6.</li>
<li class="">Added tool-calling, reasoning, and structured-output (<code>response_format</code>)
support to GLM-5.1 / GLM-5.2, enabled with
<code>--tool-parser glm45 --reasoning-parser glm45 --enable-structured-output</code>.
Reasoning uses <code>&lt;think&gt;</code>/<code>&lt;/think&gt;</code>; tool calls use the model's native
<code>&lt;tool_call&gt;…&lt;arg_key&gt;…&lt;arg_value&gt;…&lt;/tool_call&gt;</code> format. With constrained
decoding, tool-call arguments are constrained to each tool's JSON schema
(declared keys, <code>required</code> properties, and per-property types — including
nested objects/arrays, enums, numeric bounds, and string patterns), and the
call sequence terminates on the model's turn-ender so it can't loop. Validated
on <code>zai-org/GLM-5.2-FP8</code>.</li>
<li class="">Added support for the Ideogram 4 (<code>Ideogram4Pipeline</code>) text-to-image
flow-matching diffusion transformer. The pipeline pairs a Qwen3-VL text
encoder (run text-only, emitting concatenated intermediate hidden states)
with a single-stream DiT that uses QK-RMSNorm, 3D MRoPE, SwiGLU, and AdaLN,
and an asymmetric dual-branch classifier-free guidance scheme. FP8
(<code>float8_e4m3fn</code>) checkpoint weights are dequantized to <code>bfloat16</code> at load.
Serve via <code>/v1/responses</code>; benchmark with
<code>--benchmark-task text-to-image</code>.</li>
<li class="">Added the <code>reasoning_split</code> chat-completion request field for MiniMax M3.
It defaults to <code>true</code>, which keeps the existing behavior of returning the
model's thinking in a separate <code>reasoning</code> field. Setting it to <code>false</code> folds
the thinking back into the <code>content</code> field wrapped in <code>&lt;think&gt;...&lt;/think&gt;</code>
tags, matching the official MiniMax M3 endpoint. The field is a no-op for
every other model.</li>
<li class="">FLUX.2-klein bf16 checkpoints on Apple M5 GPUs now default to int8 W8A8
quantization (weights round-to-nearest-quantized at load, per-token dynamic
activation scales in a fused Metal matmul — MAX's own Mojo kernel).
Measured ~1.45x faster end-to-end than bf16 on FLUX.2-klein-4B (1024x1024,
4 steps) at near-lossless quality (PSNR 34.2 dB, SSIM 0.9966). Set
<code>APPLE_FLUX2_INT8_W8A8=0</code> to opt back into bf16; FLUX.2-dev and non-M5
devices are unaffected.</li>
<li class="">NVFP4 FLUX.2 checkpoints (for example FLUX.2-dev) can now opt into an int8
W8A8 requant at load on Apple M5 with <code>APPLE_FLUX2_INT8_W8A8=1</code>: each
quantized layer's weight is reconstructed from its FP4 data and scales,
then requantized to int8 one weight at a time, so no full-model
high-precision copy is ever resident. Measured ~2.56x faster end-to-end
than the default weight-only W4A16 path on FLUX.2-dev (1024x1024, 24
steps) at faithful quality (SSIM 0.996-0.999). Unset, NVFP4 keeps its
W4A16 default.</li>
<li class="">Renamed the FLUX.2 int8 W8A8 override env var <code>FLUX2_KLEIN_INT8_W8A8</code> to
<code>APPLE_FLUX2_INT8_W8A8</code> (the path is Apple-Metal-only and no longer
klein-only). The old name is still honored with a one-time deprecation
warning; the new name wins when both are set.</li>
<li class="">FLUX.2 diffusion pipelines now support both denoising-cache backends to skip
redundant transformer passes during generation: <code>--taylorseer</code> (Taylor-series
step skipping — the recommended default, with <code>balanced</code> and <code>fast</code> presets)
and <code>--first-block-caching</code> (first-block-residual reuse — zero-tuning and
data-adaptive). The two are mutually exclusive and both off by default. See
the <a class="" href="https://docs.modular.com/max/inference/image-generation/">image generation guide</a>.</li>
<li class="">Gemma 4 with multi-token prediction (MTP) speculative decoding
(<code>UnifiedMTPGemma4ForCausalLM</code>) now supports image and video input.
Previously this path was served text-only: image tokens were ingested by
the tokenizer but the vision encoder output never reached the language
model, so image prompts were answered as if the model were blind. The
vision encoder now runs during prefill and its projected soft-token
embeddings are merged into the target model, matching the non-MTP Gemma 4
path.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-framework">MAX framework<a href="https://docs.modular.com/releases/nightly/#max-framework" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">Added opt-in token-balanced CE scheduling across data-parallel replicas.
With <code>--dp-ce-balance-timeout-ms</code> &gt;= 0 (default -1 = off), new context
encoding requests wait in an unbound pool and are placed by a per-step
planner that prices them at their post-prefix-cache length (a read-only
probe of each replica's device cache and the shared host/disk tiers) and
binds them to the least-loaded replica when first scheduled. Unbalanced CE
work may be deferred up to the timeout while its replica runs decode
instead, until per-step occupancy reaches <code>--dp-ce-balance-threshold</code>
(default 0.8). A below-threshold step with CE work on two or more replicas
still runs immediately with each replica's chunk size reduced to the
balance level, so only the excess defers
(<code>--dp-ce-balance-enable-dynamic-chunk-size</code>, default on; skipped when the
balance level is under half the CE chunk target, where the extra chunks
would cost more than the imbalance).</li>
<li class="">Added <code>--chunked-prefill-min-chunk-size</code> (config key
<code>runtime.chunked_prefill_min_chunk_size</code>, default 0 = off) to set a floor,
in tokens, on any chunk created by chunked prefill. When splitting a
request against the CE token budget, the cut is moved earlier so that
neither the chunk nor its remainder is smaller than the floor; if no legal
cut point exists within the remaining budget, the request is left unsplit
for a later step. This avoids degenerate slivers (for example an 8-token
tail chunk after an 8192-token budget cut) that pay a full step's overhead
and re-read the request's entire context in attention for almost no
progress.</li>
<li class="">Fixed non-streaming chat completions leaking a literal structural tool-call
marker (for example <code>&lt;tool_call&gt;</code>) into <code>message.content</code> when a
<code>max_tokens</code> truncation landed mid tool-call block. The response now
surfaces only the content before the marker, with
<code>finish_reason == "length"</code>.</li>
<li class="">Added an experimental <code>--fold-sampler-into-graph</code> option (default off) that
folds greedy token selection (argmax) into the captured forward graph, so a
single device-graph replay materializes the sampled token instead of a
separate sampler submission with a blocking readback. Applies to all-greedy
decode batches on architectures that emit the folded token output (currently
Nemotron-H); non-greedy requests fall back to the separate sampler.</li>
<li class="">Added a <code>max-pending-futures</code> config (default 1, the classic
overlap-scheduler depth of one forward in flight per request). Request
bookkeeping now tracks unrealized future-token placeholders with a counted
model instead of a single-sentinel check, and setting the value to 2 enables
experimental schedule-ahead decoding: two forwards in flight per request,
with the next step's input token realized on-device from the folded sampler
output. Behavior at the default depth is unchanged.</li>
<li class="">Fixed the serve CLI dropping the <code>fold-sampler-into-graph</code>,
<code>max-pending-futures</code>, and greedy-sampling gate settings on their way to the
model worker, which silently disabled the folded greedy sampler. With the
flags threaded through, <code>--fold-sampler-into-graph</code> removes the per-token
blocking sampler submission and substantially improves decode latency on
architectures that support it.</li>
<li class="">Added <code>max.engine.read</code> for loading a compiled-model artifact (a <code>.mef</code>
file) without an <code>InferenceSession</code>. The resulting <code>CompiledModel</code> can
be initialized on any session via <code>InferenceSession.init</code>. It replaces
<code>InferenceSession.read</code>, which has been removed.</li>
<li class="">Image generation responses on the Open Responses endpoint now report
<code>usage</code>: <code>output_tokens</code> and <code>total_tokens</code> carry the total pixel count of
the generated images, counted from the actual output arrays, and
<code>input_tokens</code> is 0 (prompt text is not counted). Previously <code>usage</code> was
always <code>null</code>.</li>
<li class="">Added <code>InferenceSession.read</code> for loading a compiled-model artifact (a
<code>.mef</code> file) previously saved with <code>CompiledModel.export_mef</code>. It accepts a
path or a binary file-like object (such as <code>io.BytesIO</code>), deserializes
without invoking the graph compiler, and returns a <code>CompiledModel</code> ready to
pass to <code>InferenceSession.init</code>.</li>
<li class="">Added <code>--no-enable-tool-call-constrained-decode</code> (config key
<code>sampling.enable_tool_call_constrained_decode</code>, default enabled) to decouple
tool-call parsing from constrained decoding. When disabled, a configured
<code>--tool-parser</code> still parses tool calls out of the generated text, but no
server-generated grammar is produced and the bitmask constrained-decode path
is skipped for tool calls. Note that with it disabled, <code>tool_choice=required</code>
or a named function can no longer force a tool call. This is independent of
<code>--enable-structured-output</code>, which continues to gate user-supplied
<code>response_format</code> JSON schemas.</li>
<li class="">Fixed the <code>code</code> label on the <code>maxserve_request_count</code> metric so it reports
the HTTP status code actually returned to the client. The count is now
recorded from the HTTP layer, so failures rejected before generation (for
example a request with an unreachable image URL) are counted with their real
status code instead of being labeled <code>200</code> or dropped entirely. Liveness and
observability endpoints (<code>/health</code>, <code>/version</code>, <code>/ping</code>, <code>/metrics</code>) are not
counted.</li>
<li class="">Failed request submissions in the OpenAI-compatible serving endpoints now
surface as HTTP error responses instead of a <code>200 OK</code> streaming response that
carries an error payload. Request tokenization and the handoff to the model
worker now complete before the streaming response headers are sent, so a
failure at submission time (for example, a dead model worker) maps to an HTTP
5xx (or 4xx for input errors). Errors that occur mid-stream, after the first
chunk has been sent, are still serialized as an error event within the stream.</li>
<li class="">Added request-queue backpressure to MAX serve via two cooperating caps. The
<code>--max-queue-size</code> flag (env var <code>MAX_SERVE_MAX_QUEUE_SIZE</code>, cap <em>N</em>) bounds
the request queue to the model worker; once it is full, new requests are
rejected immediately with HTTP 429 instead of being enqueued. The
<code>--max-pending-requests</code> flag (env var <code>MAX_SERVE_MAX_PENDING_REQUESTS</code>, cap
<em>M</em>) stops the worker from draining the request queue once its pending
(prefill) queue is <em>M</em> deep, so the request queue actually backs up under
load. Together they form a self-calibrating mechanism that sheds load to keep
latency within SLAs and naturally accounts for long requests holding batch
space. Both default to unbounded. Rejections are observable via the existing
<code>maxserve.request_count</code> metric with <code>code="429"</code>.</li>
<li class="">Added <code>MAX_SERVE_GRACEFUL_SHUTDOWN_TIMEOUT_S</code> to control how long the server
waits for in-flight requests to finish after receiving <code>SIGTERM</code> before
exiting (default 5 seconds). Raise it so long-running requests are drained
rather than dropped during a rolling restart.</li>
<li class="">Data-parallel (DP) serving now shares the prefix cache across replicas, so a
multi-turn conversation gets cache hits even when a later turn is scheduled on
a different replica than the previous one. GPU prefix-cache hits are served by
a cheap device-to-device copy of the cached pages onto the assigned replica,
and the CPU/disk offload tiers are now a single pool shared by every replica
(a block offloaded by one replica can be loaded by another). As a result,
<code>host_kvcache_swap_space_gb</code> now sizes one shared host pool of that size for
the whole deployment, rather than allocating a separate pool of that size per
replica.</li>
<li class="">The dKV external KV-cache connector (<code>--kv-connector dkv</code>) now supports
data-parallel (DP) serving and shares its prefix cache across DP replicas on
the default single-tenant path, matching the <code>local</code> and <code>tiered</code> connectors.
Every replica resolves to the same replica-agnostic store, and the stored
block key carries no replica component, so a block offloaded through one
replica is served to any other.</li>
<li class="">The dKV external KV-cache connector now supports tensor parallelism
(TP greater than 1) on the multi-tenant path for head-sharded (MHA/GQA), MLA
(replicated-KV), and GQA head-replicated (<code>allow_kv_head_replication</code>) models.
Each GPU handshakes its own per-shard store, and every KV load/offload fans
out across the processing replica's shard clients with identical block ids and
hashes; a block counts as loaded only once every shard has it. The store key
reflects the KV-head slice each GPU holds: the TP rank when head-sharded, a
single shared shard for MLA, and the head-group index under head replication.</li>
<li class="">On the dKV multi-tenant tensor-parallel path, a KV load that returns
differing block counts across a replica's per-GPU shard clients now drains
the over-loading shards' in-flight device reads before returning the minimum
count. This keeps a stray in-flight host-to-device copy (into a block the
block manager frees because it did not land on every shard) from later
clobbering a reallocated block. The drain host-completes the reads on the
remote (NIXL) transport and enqueues a cross-stream ordering on the
co-located same-host (CUDA) transport, so it closes the window on both. The
common equal-count path is unchanged and pays no extra synchronization.</li>
<li class="">The dKV external KV-cache connector (<code>--kv-connector dkv</code>) now requires a
non-empty tenant identity (<code>MODULAR_DKV_TENANT_ID</code>, set by the deployment
operator); the empty-tenant "default" path is removed. Both the connector and
the dKV server now reject an unset/empty tenant rather than keying an unfenced
shared store, so every deployment (single-tenant included) routes through the
per-tenant region-sharded store — DP replicas of one tenant still share one
store. Multi-cache models (speculative draft+target, quantized values+scales)
now resolve on this path, folded into the handshake's <code>kv_config_hash</code>. A
single-tenant node spanning more than one GPU must set the dKV server's
<code>--fair-share-partitions</code> to its GPU count.</li>
<li class="">The graph compiler now fuses query/key RMSNorm followed by rotate-half RoPE
into a single <code>rms_norm_rope</code> GPU kernel even when the RMSNorm is written "in
float32" — that is, when a <code>bfloat16</code>/<code>float16</code> activation is upcast to
<code>float32</code>, normalized, and cast back before RoPE. Previously the intervening
<code>float32</code>-to-<code>bfloat16</code> downcast blocked the fusion and the idiom compiled to
several separate elementwise kernels. The fused kernel now decouples its
output dtype from its input dtype, so the reduction and weight/epsilon scaling
stay in <code>float32</code> and only the result is produced in the activation dtype; the
input upcast is absorbed by ordinary prologue fusion. Numerics match the
unfused graph (the normalized value is rounded to the output dtype before
RoPE).</li>
<li class="">Added a <code>poison-all</code> mode to the <code>MODULAR_DEBUG_DEVICE_ALLOCATOR</code> environment
variable for debugging uninitialized device-memory reads. Unlike the existing
<code>uninitialized-poison</code> (which fills graph tensors with a type-aware, non-NaN
sentinel and is detected by an instrumented load check), <code>poison-all</code> fills
<em>every</em> memory-manager allocation — including internal scratch and other
non-tensor buffers — with a raw byte (default <code>0xFF</code>, a NaN pattern for
<code>float32</code>/<code>bfloat16</code>), so an uninitialized read propagates NaN into the output
and trips existing differential tests without any kernel instrumentation. The
fill byte is configurable via
<code>MODULAR_DEVICE_CONTEXT_MEMORY_MANAGER_POISON_PATTERN</code>, and the mode composes
with <code>out-of-bounds</code> redzone checks. Because the NaN can also surface on
legitimately-uninitialized allocation padding, it is a manual debugging aid
rather than a default.</li>
<li class="">Added a <code>max-benchmark</code> conda package for parity with the <code>max[benchmark]</code>
wheel extra.</li>
<li class="">Added a <code>max-serve</code> conda package for parity with the <code>max[serve]</code> wheel
extra.</li>
<li class="">Added a <code>max[all]</code> extra to the wheel, and <code>max-all</code> package for Conda.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="inference-server">Inference server<a href="https://docs.modular.com/releases/nightly/#inference-server" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">Raised the maximum tool function name length from 64 to 1024 characters.
Client-supplied tool names that legitimately exceed 64 characters are now
accepted instead of rejected with a 400 error.</li>
<li class="">Added vision encoder statistics to the scheduler's per-iteration batch log
for multimodal models. Each batch line now includes a <code>Vision Encoder</code>
clause reporting the number of images encoded this iteration versus served
from the vision encoder cache (with the cache hit rate), and the image
patches and vision tokens encoded. This makes it clear when a slow
context-encoding iteration is driven by the vision encoder rather than the
language model. The same values are exported as OpenTelemetry metrics under
the <code>maxserve.vision.*</code> namespace. Applies to models backed by the shared
vision encoder cache (Gemma 4, Kimi K2.5, and Gemma 4 MTP).</li>
<li class="">Added an opt-in <code>emit_reasoning_content</code> server config. When enabled, chat
completion responses emit a reasoning model's chain-of-thought under
<code>reasoning_content</code> instead of <code>reasoning</code> (the two are never emitted
together). This restores the <code>reasoning_content</code> field for clients that
require it; it remains off by default, so responses emit <code>reasoning</code> only.</li>
<li class="">Improved time-to-first-token for multimodal requests by making the image and
video preprocessor reject and decode media more efficiently. Oversized media
is now rejected before its bytes are fully materialized: an <code>http(s)</code> download
is aborted as soon as the advertised <code>Content-Length</code> (or the streamed total)
crosses the per-item cap, and a <code>data:</code> URI is rejected from its base64 length
before it is decoded. Large <code>data:</code> base64 decoding now runs on a worker
thread instead of blocking the server event loop, so one big payload no longer
stalls other in-flight requests. Per-request video count and per-video byte
limits are also enforced up front (mirroring the existing image limits).</li>
<li class="">Reduced per-iteration latency for structured-output (constrained decoding)
requests on speculative-decode models. The overlap pipeline now enqueues the
asynchronous FSM-advance and bitmask compute once the next iteration's batch
order is known, so the bitmask is written directly in the consuming batch's
row order. This removes both the host-synchronization point that previously
stalled the GPU-feeding thread when the batch composition changed between
iterations and the device-side gather that earlier reconciled the order. The
improvement applies across all six supported speculative-decode architectures
(Kimi K2.5 MLA and MHA, DeepseekV3 MTP and Eagle3, Gemma 4 MTP,
and EAGLE Llama 3).</li>
<li class="">Constrained decoding (structured output) now unpacks the grammar bitmask on
the GPU. The packed <code>int32</code> bitmask is transferred to device as-is and
unpacked and applied to the logits in a single fused kernel
(<code>apply_packed_bitmask</code>), instead of unpacking to a <code>bool</code> tensor on the CPU.</li>
<li class="">Made numpy array transport across the API-server-to-model-worker request
queue zero-copy. Large arrays (notably multi-image or high-resolution vision
<code>pixel_values</code>) now ride out-of-band as their own ZMQ frame instead of being
copied into the message body and then again through the socket, and the
receiver decodes them as views with no copy. This is faster than both the
previous copy and shared-memory transports at every payload size (for example
~5x faster than the copy path and ~2x faster than shared memory at 24-32 MiB
in the transport microbenchmark), and removes the per-request shared-memory
segment (and its sizing, leak, and page-fault costs) from this path entirely.</li>
<li class="">Fixed image requests failing with a 400 or 500 across all vision models. Two
bugs in the shared image-resolution layer: <code>data:</code> URIs with unpadded or
URL-safe base64 (sent routinely by clients and relays) were rejected by the
strict decoder, and truncated, animated, or content-negotiated images (for
example a <code>.jpg</code> URL that a host serves as WebP) passed the lazy header-only
validation and then crashed later in the tokenizer's pixel decode with an
unhandled error. Image payloads are now decoded tolerantly and validated with
a full pixel decode that the tokenizer reuses (so each image is decoded only
once), and undecodable content fails fast as a clean 400.</li>
<li class="">Fixed intermittently-dropped Kimi K2.5 tool calls under reasoning-enabled
<code>tool_choice="auto"</code>. The model often opens a tool-call section directly from
inside its <code>&lt;think&gt;</code> block without emitting a closing <code>&lt;/think&gt;</code> (an implicit
end-of-reasoning, part of Kimi's interleaved-thinking design). The reasoning
parser previously ended a reasoning span only on <code>&lt;/think&gt;</code>, so the entire
tool-call section was misclassified as reasoning and never reached the tool
parser, so the response came back with empty <code>content</code> and the tool-call
payload stranded in <code>reasoning</code>. Because whether the model emits <code>&lt;/think&gt;</code>
is sampling-dependent, the failure was flaky. The reasoning parser now also
ends the span at <code>&lt;|tool_calls_section_begin|&gt;</code>, leaving the marker as
content so the tool call is parsed correctly.</li>
<li class="">Fixed a structured-output runaway: a <code>response_format</code> JSON schema that omits
the root <code>"type"</code> (for example <code>{"properties": {"x": {}}}</code>, valid JSON Schema)
previously compiled to a grammar that permitted a bare, unbounded top-level
value, so a model that looped inside that value could never emit a terminator
and generated until <code>max_length</code> (<code>finish_reason="length"</code>). Such schemas with
an object-implying keyword (<code>properties</code>, <code>required</code>, <code>additionalProperties</code>,
<code>patternProperties</code>) are now normalized to <code>"type": "object"</code> before grammar
compilation, matching the behavior of xgrammar-based engines. A genuinely
empty <code>{}</code> schema is still treated as "any value".</li>
<li class="">Retuned the Prometheus/OpenTelemetry histogram buckets for MAX metrics.
Previously every histogram shared one millisecond-latency bucket range, which
was inaccurate for non-latency metrics. Each histogram now uses bucket
boundaries matched to its actual range (percentages bucket 0–100, token and
occupancy counts use power-of-two buckets, batch size is fine-grained up to
512, throughput and time metrics use appropriately wide ranges, and time
metrics now extend out to 30 minutes). Quantile queries become more accurate;
dashboards that hardcoded specific bucket boundaries may need updating.</li>
<li class="">Changed <code>maxserve.cache.num_used_blocks</code> and <code>maxserve.cache.num_total_blocks</code>
from counters to gauges. These report an instantaneous level, so a gauge is
correct; as counters their exported values were meaningless. The Prometheus
type changes to <code>gauge</code> and the exported series drops the counter <code>_total</code>
suffix.</li>
<li class="">Added <code>maxserve.cache.disk_blocks_read</code> and
<code>maxserve.cache.disk_blocks_written</code> counters, reporting KV blocks read from
and written to the disk cache tier when tiered (disk) KV caching is enabled.</li>
<li class="">Added opt-in SHA-256 KV-cache block hashing. A new <code>kv_cache_hash_algo</code>
field on <code>KVCacheConfig</code> (default <code>ahash64</code>; opt-in <code>sha256</code> and
<code>sha256_64</code>) threads through the pipeline and serve config, selecting a
Mojo <code>block_hasher_sha256</code> and the matching <code>hash_request_tokens</code> SHA-256
path. Chat-completion requests also accept an optional <code>cache_salt</code> field
that scopes prefix-cache reuse to a single per-request KV chain. Default
behavior is the same as the existing <code>ahash64</code> path.</li>
<li class="">Added opt-in SHA-256 KV-cache block hashes through host-tier KV
connectors. <code>NullConnector</code>, <code>LocalConnector</code>, and <code>TieredConnector</code> now
accept 32-byte SHA-256 digests alongside 64-bit <code>ahash64</code> hashes. The
<code>KVConnector</code> Protocol's <code>load</code> and <code>offload</code> take <code>Sequence[bytes]</code>
block hashes and a <code>bytes | None</code> parent-sequence hash; the block
manager coerces legacy <code>ahash64</code> int hashes to bytes (8-byte
big-endian, signed) at the boundary, so a connector implementation only
ever sees one hash shape. Connectors advertise what they accept via a
new <code>supported_hash_algos: frozenset[KVHashAlgo]</code> property (default
<code>frozenset({"ahash64"})</code>), which the block manager validates against
the configured <code>kv_hash_algo</code> at startup so a mismatch fails fast with
a clear remediation message. The disk tier names files <code>&lt;hex&gt;.bin</code> (16
hex chars for 64-bit hashes, 64 hex chars for SHA-256 digests) and pins
the algo in a <code>kv-disk-cache.meta.json</code> sidecar to refuse cross-algo
reuse of a cache directory. <code>KVHashAlgo</code> is re-exported from
<code>max.nn.kv_cache</code> for downstream consumers. Default behavior is
unchanged.</li>
<li class="">Extended SHA-256 KV-cache block hashes to the dKV (<code>DKVConnector</code>)
external tier. <code>DKVConnector.supported_hash_algos</code> now advertises
<code>frozenset({"ahash64", "sha256", "sha256_64"})</code>, and <code>load</code>/<code>offload</code>
accept both 8-byte (<code>ahash64</code> / <code>sha256_64</code>) and 32-byte (full
<code>sha256</code>) block hashes; 32-byte digests are truncated to their first
8 bytes at the boundary into the unchanged <code>dkv_connector</code> Rust
client, which continues to carry a <code>uint64 seq_hash</code> on the wire.
Truncation is byte-identical to the existing <code>sha256_64</code> algorithm,
so configuring MAX with <code>sha256</code> or <code>sha256_64</code> produces the same
dKV key for the same logical block — no change to the dkv wire
format, stored block identity, or <code>DKVExternalBlockMetadata</code>
orchestrator hint shape. Default behavior is unchanged.</li>
<li class="">MAX now refreshes an external KV cache tier's recency when a request's prefix
is served from the on-GPU cache. Such a hit sends no traffic to the external
tier, so a hot shared prefix could otherwise go cold there and be evicted
while still resident on device; a best-effort recency <code>touch</code> now keeps hot
shared prefixes warm in an external tier such as dKV. Set
<code>MODULAR_DKV_DISABLE_G0_TOUCH=1</code> to disable the refresh.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/nightly/#max-cli" class="hash-link" aria-label="Direct link to max-cli" title="Direct link to max-cli" translate="no">​</a></h3>
<ul>
<li class="">The entrypoint for the CLI, formerly <code>max.entrypoints</code>, has been marked as
private and moved to <code>max._entrypoints</code>. The CLI is still a public facing API,
but the code within it is not.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="python-api">Python API<a href="https://docs.modular.com/releases/nightly/#python-api" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added <code>max.graph.ops.reduce_scatter_rms_norm</code>, a distributed op that
reduce-scatters a bfloat16 tensor across devices and RMSNorm-normalizes each
device's row shard in a single collective launch, keeping the reduced sum in
float32 registers so there is no global-memory round-trip between the
reduce-scatter and the norm. It returns both the normed shard and the
reduce-scatter sum (residual) shard, and is numerically identical to a
standalone reduce-scatter followed by <code>rms_norm</code>.</p>
</li>
<li class="">
<p>Added an optional <code>init_value</code> argument to <code>max.graph.ops.buffer_create</code>.
When set, the buffer becomes persistent state: it is allocated and filled
with the scalar <code>init_value</code> exactly once when the model is loaded, and the
same buffer (with its mutations preserved) is reused across every execution,
rather than being re-created per call. Use it for a buffer that a kernel
mutates in place and only needs initialized once, such as a counter a kernel
resets at the end of each call.</p>
</li>
<li class="">
<p>Added <code>max.graph.ops.floor_div</code> (and <code>F.floor_div</code>), element-wise floor
division matching Python <code>//</code>. Unlike <code>ops.div</code>, integer operands stay in
the integer domain instead of being promoted to <code>float64</code>, so integer floor
division compiles on backends without 64-bit float support (for example,
Metal GPUs).</p>
</li>
<li class="">
<p>Added <code>max.driver.set_virtual_cpu_target()</code> and <code>get_virtual_cpu_target()</code>.
Set a fixed CPU codegen target (for example <code>"x86-64-v3"</code>, <code>"neoverse-n1"</code>,
or <code>"generic"</code> for the most-portable baseline of the host arch family) before
importing <code>max._interpreter_ops</code> so the eager interpreter's CPU kernel cache
is compiled host-independently and can be shipped and reused across hosts of
the same architecture family. Mirrors <code>set_virtual_device_target_arch()</code> for
GPUs. Leaving it unset compiles for the build host's CPU, as before.</p>
</li>
<li class="">
<p><code>InferenceSession.profiling</code> now records libkineto traces in
<code>--config=kineto</code> builds (Linux x86_64). libkineto is auto-enabled when the
pipeline entrypoints configure a session with profiling enabled;
<code>session.profiling.start()</code> also enables it explicitly and (on hosts with a
live CUDA primary context) subscribes to CUPTI's Activity Callback API, and
<code>session.profiling.stop()</code> flushes and serializes a Chrome-trace JSON file
compatible with Meta's
<a href="https://github.com/facebookresearch/HolisticTraceAnalysis" target="_blank" rel="noopener noreferrer" class="">HTA</a>.
<code>session.profiling.wait_for_trace()</code> blocks until serialization is done and
raises <code>max.engine.ProfilingError</code> if libkineto could not write the trace.
Default builds — including the shipped wheels — do not link the libkineto
backend yet, so the control surface remains a safe no-op there.</p>
</li>
<li class="">
<p><code>ProfilingConfig</code> gains six new fields for the libkineto profiler, each
configurable from Python through the matching <code>session.debug.profiling_*</code>
setter or its <code>MODULAR_MAX_DEBUG_PROFILING_*</code> environment variable:
<code>profiling_enabled</code>, <code>profiling_output_path</code>, <code>profiling_dynolog_enabled</code>,
<code>profiling_warmup_steps</code>, <code>profiling_active_steps</code>, and
<code>profiling_periodic_flush_seconds</code>.</p>
</li>
<li class="">
<p><code>profiling_output_path</code> accepts template variables (<code>{pid}</code>, <code>{rank}</code>) and a
directory form (<code>/tmp/traces/</code>) that auto-generates a distinct per-process
file (keyed on rank, PID, timestamp, and a sequence counter), so
multi-process and multi-rank captures no longer collide on a single fixed
filename. <code>{rank}</code> resolves to <code>MODULAR_RANK</code> / <code>OMPI_COMM_WORLD_RANK</code> /
<code>"0"</code>.</p>
</li>
<li class="">
<p>Forking while the profiler is enabled is safe for host applications that
embed <code>InferenceSession</code> and fork (Python <code>multiprocessing</code> with the <code>fork</code>
start method, pre-fork servers, or a bare <code>os.fork()</code>) — child processes
start with the profiler disabled and can call <code>start()</code> again; the parent
retains its enabled state across the fork. (MAX itself launches
workers with the <code>spawn</code> start method and is unaffected.)</p>
</li>
<li class="">
<p><code>session.profiling.range(name)</code> is a new context manager that annotates a
named CPU span in the trace. The span appears as a <code>user_annotation</code> bar in
Perfetto/HTA with the GPU kernels launched inside it correlated to it, and
also records during Dynolog-initiated on-demand traces. When no trace is
live the calls reduce to a single predicted branch, so annotations are safe
to leave in production code. The companion <code>session.profiling.is_recording</code>
property reports whether a trace of either origin is live — the right gate
for eliding annotation work on hot paths (<code>is_enabled</code> reflects only the
session API and stays <code>False</code> during daemon-driven traces).</p>
</li>
<li class="">
<p>MAX processes launched with <code>KINETO_USE_DAEMON=1</code> now register with a
<a href="https://github.com/facebookincubator/dynolog" target="_blank" rel="noopener noreferrer" class="">Dynolog</a> daemon at device
initialization, so <code>dyno gputrace --pids &lt;pid&gt;</code> captures any such process
on demand with no profiling flags and no code changes. Set
<code>profiling_dynolog_enabled = False</code> (or
<code>MODULAR_MAX_DEBUG_PROFILING_DYNOLOG_ENABLED=0</code>) to opt a process out.</p>
</li>
<li class="">
<p>Profiling can now be armed and disarmed at runtime for CUDA-graph
(capture/replay) workloads: a mid-run <code>session.profiling.start()</code> or a
Dynolog <code>dyno gputrace</code> request captures kernels replayed from graphs that
were instantiated before profiling was enabled, and replay overhead reverts
when the trace stops. Enabling at session construction is no longer
required for these workloads.</p>
</li>
<li class="">
<p>This API is orthogonal to the existing <code>session.gpu_profiling()</code>
(NVTX/Nsight) path. See <code>max/docs/profiling.md</code> in the repository for the
full user guide.</p>
</li>
<li class="">
<p>Eager execution in <code>max.experimental</code> now routes every realization through
the <code>max.experimental.executor.Executor</code> abstraction. The out-of-the-box
path is unchanged — graphs within the <code>MAX_INTERPRETER_MAX_OPS</code> threshold run
on the interpreter and fall back to a cached compile otherwise — but it is
now expressed as a new <code>CompositeExecutor</code> selected by
<code>MAX_EAGER_EXECUTOR=composite</code> (the new default). The
<code>MAX_USE_EAGER_INTERPRETER</code> environment variable has been removed; force
compilation with <code>MAX_EAGER_EXECUTOR=compile</code> instead. The
<code>EagerRealizationContext(use_interpreter=...)</code> argument is deprecated in
favor of <code>EagerRealizationContext(executor=...)</code>.</p>
</li>
<li class="">
<p>The eager interpreter now compiles its matmul and unary-elementwise
graph-compiler models lazily, per target on first dispatch, by default —
bounding compile cost to the targets a program uses instead of JIT-compiling
the full kernel library at import. Set <code>MAX_EAGER_OP_PRECOMPILE=1</code> to
precompile the full matrix at import instead.</p>
</li>
<li class="">
<p>The eager interpreter's binary-elementwise and comparison ops (<code>add</code>, <code>sub</code>,
<code>mul</code>, <code>div</code>, <code>mod</code>, <code>max</code>, <code>min</code>, <code>pow</code>, <code>and</code>, <code>or</code>, <code>xor</code>, and the
comparison predicates) now run through pre-compiled graph-compiler models
instead of hand-written Mojo bindings, matching the matmul and
unary-elementwise migrations. On CPU they run float32/float64; the
float16/bfloat16 CPU inputs the Mojo path accepted are no longer supported
and raise.</p>
</li>
<li class="">
<p>The eager interpreter's reduce-along-axis ops (<code>max</code>/<code>min</code>/<code>add</code>/<code>mul</code>/<code>mean</code>
reductions, <code>softmax</code>/<code>logsoftmax</code>, <code>argmax</code>/<code>argmin</code>, and <code>cumsum</code>) now run
through pre-compiled graph-compiler models instead of hand-written Mojo
bindings. On CPU the reduction/argmax family runs float32/float64: the
float16/bfloat16 CPU inputs the Mojo path accepted are no longer supported
and raise. On accelerators it narrows to 32/64-bit integers (CUDA's reduce
kernels don't compile 8/16-bit int reduction). An unsupported dtype raises
immediately instead of silently falling back.</p>
</li>
<li class="">
<p>The eager interpreter's shape-rearrange ops (<code>pad</code> constant/reflect/edge,
<code>tile</code>, <code>split</code>, <code>concat</code>, and <code>slice</code>) now run through pre-compiled
graph-compiler models instead of hand-written Mojo bindings, matching the
matmul, elementwise, and reduce migrations. Structural parameters (pad
widths, repeat counts, split/slice bounds) stay runtime operands, so one
compiled graph per <code>(op, device, dtype[, rank])</code> serves every shape.</p>
</li>
<li class="">
<p>The eager interpreter's pooling ops (<code>max_pool</code>/<code>avg_pool</code>, floor and
ceil-mode variants) now run through pre-compiled graph-compiler models
instead of hand-written Mojo bindings. Window shape, strides, dilations,
and paddings are runtime operands, so one compiled graph per <code>(op, device, dtype[, count_boundary])</code> serves every configuration. CPU float16 isn't
supported (a graph-compiler limitation); GPU float16 still works.</p>
</li>
<li class="">
<p>The eager interpreter's <code>conv2d</code> op now runs through a pre-compiled
graph-compiler model instead of a hand-written Mojo binding. Filter
shape, input shape, stride, dilation, and padding are runtime operands,
so one compiled graph per <code>(device, dtype)</code> serves every conv shape.
Dilation != 1 and grouped convolution now raise a clear error instead of
computing silently. <code>conv2d_transpose</code> is no longer supported: its old
Mojo binding depended on cuDNN, which crashed on Apple GPUs and failed on
CUDA, and has been removed rather than kept as a broken fallback.</p>
</li>
<li class="">
<p>The eager interpreter's <code>resize</code> ops (<code>resize_linear</code> and
<code>resize_nearest</code>) now run through pre-compiled graph-compiler models
instead of hand-written Mojo bindings, with output size as a runtime
operand, so one compiled graph per <code>(op, device, dtype, rank, variant)</code>
serves every output size. <code>resize_bicubic</code> is no longer supported: its
old Mojo binding has been removed rather than kept as a fallback, due to
a graph-compiler gap. CPU float16 isn't supported (a graph-compiler
limitation); GPU float16 still works.</p>
</li>
<li class="">
<p>The eager interpreter's <code>top_k</code>/<code>bottom_k</code> ops now run through pre-compiled
graph-compiler models instead of hand-written Mojo bindings. <code>k</code> stays a
runtime operand, so one compiled graph per <code>(op, device, dtype)</code> serves
every <code>k</code>. CPU float16 isn't supported (a graph-compiler limitation); GPU
narrows integers to 32/64-bit (the same shuffle-kernel limitation as the
reduce migration).</p>
</li>
<li class="">
<p>The eager interpreter's <code>Select</code>/<code>where</code> op now runs through a pre-compiled
graph-compiler model instead of a hand-written Mojo binding. Dtype coverage
is unchanged: it still runs the full float, signed-int, unsigned-int, and
bool value set on both CPU and accelerators.</p>
</li>
<li class="">
<p>Added a <code>max warm-interpreter-cache</code> command that batch-compiles the full
eager interpreter model matrix into the on-disk cache for the current
machine's devices and drops a stamp. A later lazy eager process on the same
device set adopts the warm — one batched cache load instead of compiling each
target on first use — so later programs start warm. Run it as a provisioning
step (for example a Dockerfile <code>RUN</code>) on the target hardware. Pure
optimization: if skipped, or on a different device set, dispatch compiles each
target lazily.</p>
</li>
<li class="">
<p>Added <code>max.experimental.nn.subgraphable</code> for <code>Module</code> subgraph compilation: a
repeated block (via the <code>@subgraphable</code> class decorator, or the
<code>subgraphable(layer)(x)</code> call form) lowers to one shared subgraph reused per
call. Opt out per compile with <code>Module.compile(..., allow_subgraphs=False)</code>.</p>
</li>
<li class="">
<p><code>max.nn.hooks.PrintHook</code> now supports <code>max.experimental.nn.Module</code>.</p>
</li>
<li class="">
<p>Added <code>F.print</code>, which supports both single-device and multi-device tensors.</p>
</li>
<li class="">
<p>Added <code>max.graph.default_custom_extensions()</code> and the
<code>default_custom_extensions_scope()</code> context manager. Paths registered as
defaults are merged into the <code>custom_extensions</code> of every new <code>Graph</code>, so a
backend can make its custom-op kernel library reachable from graphs built
without an explicit <code>custom_extensions=</code> — including the eager-realization
graph that backs <code>max.experimental</code> tensors. Empty by default.</p>
</li>
<li class="">
<p>Moved the <code>max.entrypoints</code> package to be private. In doing so, we
deprecated the <code>max.entrypoints.LLM</code> API and we'll introduce a new API
for offline inference in a future release.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="c-api">C API<a href="https://docs.modular.com/releases/nightly/#c-api" class="hash-link" aria-label="Direct link to C API" title="Direct link to C API" translate="no">​</a></h3>
<ul>
<li class="">Fixed <code>M_borrowTensorInto()</code> copying instead of borrowing a GPU input. When
the borrowed pointer already lived on the target accelerator, the call
allocated a fresh device buffer and copied into it, so in-place mutation of a
<code>BufferType</code> model input was applied to the engine's private copy and never
reflected back into the caller's buffer. Such pointers are now borrowed in
place (zero-copy) on CUDA devices, matching the documented borrow semantics
and the existing behavior for host inputs. Host pointers passed with a device
spec are still staged via a host-to-device copy, as are device pointers on
backends that do not yet implement in-place borrowing (AMD and Apple).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-kernels">MAX kernels<a href="https://docs.modular.com/releases/nightly/#max-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">The <code>LayoutTensor.get_immutable()</code> method has been renamed to
<code>as_imm()</code>, matching the shorter <code>imm</code> spelling used across the
immutability API. The old name remains as a <code>@deprecated</code> alias and
will be removed in a future release.</li>
<li class="">GPU token sampling with <code>top_k &gt;= 10</code> is now 2-4x faster. The softmax,
temperature scaling, and min-p masking steps are fused into the top-k/top-p
rejection-sampling kernel, eliminating an intermediate probability buffer
and two kernel launches per sampling call. The dispatch threshold between
the two-stage top-k kernel and the rejection-sampling kernel was lowered
from <code>top_k = 32</code> to <code>top_k = 10</code> to match the new performance crossover.</li>
<li class="">The <code>TileTensor</code> layout type no longer takes an <code>element_size</code> parameter. A
tensor's logical element width is now carried by its <code>Storage</code> parameter via
<code>PointerStorage[element_width]</code> (default <code>PointerStorage[1]</code>), and
<code>element_size</code> remains available as a derived comptime member. Code that
passed <code>element_size=N</code> should now pass
<code>Storage=PointerStorage[element_width=N]</code>, or use <code>TileTensor.vectorize()</code> to
build the vectorized view.</li>
<li class="">Apple silicon GPU support for running MAX models has been extended to M1 and
M2 systems. Previously, the optimized matrix multiplication kernels for Apple
silicon GPUs only returned correct results on M3 and newer systems. That has
now been fixed for M1 and M2 systems, allowing many common MAX models to run
correctly on them.</li>
<li class="">The split-K decode attention kernel for Apple GPUs is now the default for
token-generation attention, covering paged-KV-cache MHA and GQA decode for
head dims that are a multiple of 32. It was previously opt-in;
<code>MODULAR_ENABLE_APPLE_NAIVE_FA_DECODE=0</code> now opts out, falling back to
<code>mha_gpu_naive</code>.</li>
<li class="">Sped up GPU RMS norm on AMD CDNA4 (MI355X) for prefill-sized shapes. The
warp-tiling path runs one row per block, so the per-thread SIMD width sets
how many warps a row needs; on CDNA4, when there are enough rows to keep the
GPU busy, using a 2x-wider per-thread SIMD halves the warps per row, which
cheapens the block reduction and raises blocks-per-CU. This improves
throughput by roughly 15-31% on shapes such as 8192x{2880,4096,5120,8192}
and 4096x4096 (bfloat16), with no change to small-row shapes or other
architectures.</li>
<li class="">Fixed a rare illegal-instruction crash in the SM100 (Blackwell)
flash-attention prefill kernels under chunked prefill with tensor
parallelism. When the attention grid shared SMs with the tensor-parallel
all-reduce collective under device graph capture, a consumer warp could read
a stale tensor-memory base address and issue a tensor-core MMA against an
invalid operand. The kernels now read the tensor-memory base once after it
is published and carry it in a register, so there is no in-loop re-read to
race.</li>
<li class="">Enabled the low-latency (Lamport) all-reduce on B200 for small messages
(up to 1 MiB at 2, 4, and 8 GPUs), where it beats the one-stage path by
roughly 1.1-1.68x. The barrier-free protocol marks unwritten slots with a
negative-zero sentinel, so its communication region is now initialized when
pipeline signal buffers are allocated; without that the region read as
already-written and produced non-deterministic results.</li>
<li class="">The <code>layout</code> package is now bundled with MAX instead of Mojo.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="breaking-changes">Breaking changes<a href="https://docs.modular.com/releases/nightly/#breaking-changes" class="hash-link" aria-label="Direct link to Breaking changes" title="Direct link to Breaking changes" translate="no">​</a></h2>
<ul>
<li class=""><code>PipelineTokenizer.eos</code> (a single scalar token id) is replaced by
<code>PipelineTokenizer.eos_token_ids</code> (a set): the tokenizer's declared EOS
plus any additional terminators from the model config's <code>eos_token_id</code>
entries. The runtime previously assembled that full set privately while
the protocol exposed only the scalar, so consumers that needed every
terminator (for example, grammar backends for constrained decoding) had
no public way to get it.</li>
<li class="">MAX Serve now fails at startup when the device KV cache cannot hold a
single request at the configured max sequence length. Previously this
condition only logged a warning, and a request approaching the max
sequence length would exhaust the KV cache pool at runtime and crash the
model worker with <code>InsufficientBlocksError</code>. The startup error reports the
largest <code>--max-length</code> that fits in the allocated KV cache pool.</li>
<li class=""><code>max.nn.Module.build_subgraph()</code> now takes representative input <em>values</em>
(<code>inputs=</code>) instead of input <em>types</em> (<code>input_types=</code>). Each argument may be a
single <code>Value</code>, a nested list/tuple of values, or a structured
<code>FlattenableGraphInput</code> such as <code>PagedCacheValues</code>; the subgraph signature is
derived from the flattened leaves and the structure is rebuilt before the
layer runs. This lets structured inputs cross the subgraph boundary directly,
so <code>DistributedTransformerBlock</code> now accepts <code>list[PagedCacheValues]</code> rather
than the hand-decomposed per-field lists. Update call sites from
<code>build_subgraph(name, input_types=[v.type for v in values])</code> to
<code>build_subgraph(name, inputs=values)</code>.</li>
<li class="">Removed the <code>MAX_SERVE_METRIC_LEVEL</code> and
<code>MAX_SERVE_DETAILED_METRIC_BUFFER_FACTOR</code> environment variables along with
the <code>BASIC</code>/<code>DETAILED</code> metric-level distinction. MAX Serve now always emits
its full set of metrics, so panels that previously required <code>DETAILED</code> (for
example batch execution time) are populated in every deployment rather than
only when detailed metrics were explicitly enabled. High-volume
per-iteration scheduler metrics are still coalesced into a single
cross-process flush, so there is no change in per-metric recording overhead.
To record no metrics at all (previously <code>MAX_SERVE_METRIC_LEVEL=NONE</code>), set
<code>MAX_SERVE_METRIC_RECORDING_METHOD=NOOP</code> or <code>MAX_SERVE_DISABLE_TELEMETRY=1</code>.</li>
<li class="">Removed <code>InferenceSession.use_old_top_k_kernel()</code> and the
<code>USE_OLD_TOP_K_KERNEL</code> environment variable. The legacy top-k sampling
kernel this fallback selected has been deleted; the current two-stage
top-k kernel is now used unconditionally.</li>
<li class="">The <code>Input</code>, <code>Output</code>, <code>MutableInput</code>, <code>FusedInput</code>, and <code>FusedOutput</code>
<code>IOSpec</code> values used in custom-op signatures (for example,
<code>Tensor[Input, spec]</code>) are now static members of <code>IOSpec</code>
(<code>IOSpec.Input</code>, <code>IOSpec.Output</code>, <code>IOSpec.MutableInput</code>,
<code>IOSpec.FusedInput</code>, <code>IOSpec.FusedOutput</code>) instead of module-level aliases.
Update custom-op call sites to qualify these names under <code>IOSpec</code>, for
example <code>Tensor[IOSpec.Input, spec]</code>.</li>
<li class="">The <code>compiler</code> Mojo package has been removed. It only re-exported 4 symbols
from <code>extensibility</code>, please use that directly instead.</li>
<li class="">Renamed the MAX Serve metric <code>maxserve_cache_hit_rate_percent_utilization</code>
(OTEL name <code>maxserve.cache.hit_rate</code>) to
<code>maxserve_cache_request_prefix_coverage_percent</code> (OTEL name
<code>maxserve.cache.request_prefix_coverage</code>). The old name was misread as a
token-weighted cache hit rate; it's actually an unweighted average of each
admitted request's <code>cached_prefix_length / prompt_length</code>, so it can read
much lower than the true hit rate on workloads with many short, low-overlap
requests. Derive the token-weighted cache hit rate from
<code>maxserve_cache_hits_tokens</code> and <code>maxserve_cache_misses_tokens</code> instead.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fixes">Fixes<a href="https://docs.modular.com/releases/nightly/#fixes" class="hash-link" aria-label="Direct link to Fixes" title="Direct link to Fixes" translate="no">​</a></h2>
<ul>
<li class="">
<p>Fixed MAX Serve container pods ignoring <code>SIGTERM</code> during the model
cold-start window. The serving image ran Python directly as PID 1, and the
Linux kernel silently discards a default-disposition signal sent to a
namespaced PID 1 — so a <code>SIGTERM</code> arriving before the server installed its
handler (for example, during the long graph compile) was dropped, leaving
pods stuck <code>Terminating</code> until the termination grace period elapsed (holding
GPUs during rollouts). The container now runs under <code>dumb-init</code> as PID 1,
which handles <code>SIGTERM</code> (a signal the kernel otherwise drops when sent to
PID 1) and reaps the process tree, so the pod shuts down promptly and
releases its GPU.</p>
</li>
<li class="">
<p>Fixed a graph-compilation failure on B200 (<code>constraint failed: split-K (M2) supports only check_mask==False masks</code>) for models whose attention uses a
materialized attention mask, such as the padded text encoders in diffusion
pipelines (for example FLUX.2's Qwen3 text encoder). The SM100 FA4 dispatch
no longer instantiates its split-K kernels for such masks and routes them to
the single-partition path instead.</p>
</li>
<li class="">
<p>Fixed Nemotron-3-Nano (<code>NemotronHForCausalLM</code>) leaking chain-of-thought and
a raw <code>&lt;/think&gt;</code> delimiter into <code>message.content</code> (with the reasoning field
left empty), and <code>tool_choice="required"</code> emitting zero tool calls. The
architecture now defaults both <code>--reasoning-parser</code> and <code>--tool-parser</code> to
<code>qwen3_5</code>, matching its Qwen-format chat template (implicit <code>&lt;think&gt;</code> open,
explicit <code>&lt;/think&gt;</code> close, <code>&lt;tool_call&gt;</code>/<code>&lt;function=…&gt;</code> tool blocks). Pass
<code>--reasoning-parser=none</code> / <code>--tool-parser=none</code> to restore the old
behavior.</p>
</li>
<li class="">
<p>Fixed <code>ops.scatter_add</code> / <code>ops.scatter_mul</code> / <code>ops.scatter_max</code> /
<code>ops.scatter_min</code> silently returning wrong results when <code>indices</code> contains
duplicates and the update count is large. These ops run on CPU, and once
the update count exceeded roughly 32k elements the reduction was split
across worker threads with a plain read-modify-write, so concurrent
updates to the same output element raced and got dropped. The reduce path
now applies updates atomically; the plain overwrite <code>ops.scatter</code> is
unchanged (duplicates keep last-writer-wins semantics).</p>
</li>
<li class="">
<p>Fixed <code>ops.scatter_nd_add</code> / <code>ops.scatter_nd_mul</code> / <code>ops.scatter_nd_max</code> /
<code>ops.scatter_nd_min</code> silently returning wrong results when <code>indices</code>
contains duplicate index vectors. The reduction applied each update with a
plain read-modify-write, so concurrent threads targeting the same output
element raced and dropped updates — on GPU always, and on CPU once the
index count was large enough to split across worker threads. The reduce
path now applies updates atomically (a compare-exchange loop around the
reduction), so duplicate indices accumulate correctly on both devices, in
line with ONNX <code>ScatterND</code> reduction semantics.</p>
</li>
<li class="">
<p>Fixed the compiled-model cache (<code>.max_cache</code>) not invalidating when the
Mojo kernel libraries change. The cache key previously content-hashed only
the two built-in kernel packages, not the packages they import
(<code>linalg</code>, <code>nn</code>, ...), so rebuilding after a kernel-source edit could
silently serve a stale compiled model — for example during back-to-back
kernel A/B benchmarking. The key now covers every Mojo binary package on
the module import path, so kernel changes correctly trigger a recompile
and clearing caches by hand is no longer needed.</p>
</li>
<li class="">
<p>Fixed the structured-output grammar backend silently defaulting to
<code>llguidance</code> instead of the intended global default <code>xgrammar</code> for models
launched via <code>max serve</code>. The <code>--structured-output-backend</code> flag hardcoded
<code>llguidance</code> as its default value, which shadowed the <code>None</code> "unset" sentinel
the resolver relies on to apply the global default (<code>xgrammar</code>) or an
architecture's pinned backend. The flag now defaults to unset, so any model
without an explicit <code>--structured-output-backend</code> (and no architecture pin)
correctly resolves to <code>xgrammar</code>.</p>
</li>
<li class="">
<p>Sparse-attention MLA models (DeepSeek V3.2, GLM 5.1/5.2) with an FP8 latent
KV cache now run prefill on the absorbed sparse MLA prefill kernel instead
of the dense unabsorbed fallback, matching the decode kernel's unit-scale
read of the scale-less FP8 latent cache. The dense fallback re-quantized the
up-projected Q/K/V to FP8, measurably costing accuracy (GLM 5.2 TP8 gsm8k
0.95 -&gt; 1.0), and forfeited sparse attention's linear-cost prefill at long
context. The kernel also gained a cache-native blockwise scale path (int8
granularity-32), dormant until FP8 KV-cache scales land.</p>
</li>
<li class="">
<p>Fixed the SM100 sparse MLA prefill kernel gathering K/V latents from the
wrong layer's KV-cache region for every layer above the first
(<code>num_layers &gt; 1</code>). The gather consumed raw encoded indices without folding
in the paged per-layer block stride, silently corrupting attention for
multi-layer sparse-attention models (DeepSeek V3.2 and GLM 5.1/5.2) served
with a bfloat16 latent cache. Also enabled the sparse prefill kernel for
GLM 5.2's tensor-parallel head shards (8/16/32 heads per device) over a
bfloat16 latent cache; FP8 latent caches keep the decode-kernel routing.</p>
</li>
<li class="">
<p>Fixed MiniMax-M3 tool-call grammar enforcement silently disabling itself
when the model emits more than one tool-call section in a single response.
Enforcement used to switch off once the first section closed, so a second
section's start marker was rejected against the completed matcher
(<code>Matcher rejected N token(s)…</code>) and the rest of the request ran
unconstrained. Enforcement now stays on through the end of the turn: after
the single tool-call section closes, only EOS is allowed, matching the
model's chat template (all invocations in one section, followed
immediately by end of turn).</p>
</li>
<li class="">
<p>Fixed MiniMax-M3 streaming chat completions aborting with a 500 when the
model emits a malformed tool call. The streaming tool parser now fails open
like the non-streaming path: the raw tool-call text degrades to assistant
content, tool parsing is bypassed for the rest of the request, and the
stream terminates normally.</p>
</li>
<li class="">
<p>Fixed a precision loss in the normalization ops where the <code>epsilon</code> value was
carried in the input's dtype (for example <code>bfloat16</code>) before use. A small
epsilon such as <code>1e-6</code> is not representable in <code>bfloat16</code>, so it was silently
rounded. The <code>epsilon</code> for <code>rms_norm</code>, <code>layer_norm</code>, <code>group_norm</code>, and the
fused residual, FP8-quantized, and distributed all-reduce variants is now
carried as <code>float32</code> end to end — from the graph op through the graph
compiler to the kernel. The Python <code>epsilon: float</code> argument is unchanged.</p>
</li>
<li class="">
<p>Fixed MAX crashing the model worker on the first host KV-cache
offload/reload when run with <code>--kv-connector dkv</code>. The dKV connector had
drifted out of sync with its client and no longer passed the required
attention group on the load/offload path; it now supplies it, so the
same-host prefix-cache path completes instead of raising.</p>
</li>
<li class="">
<p>Fixed inflated <code>maxserve.cache.h2d_blocks_copied</code> and
<code>maxserve.cache.d2h_blocks_copied</code> telemetry on tiered and local KV cache
deployments. The scheduler now resets connector transfer counters after each
batch metrics sample so OpenTelemetry counters report per-batch deltas.</p>
</li>
<li class="">
<p>Fixed <code>max.nn.WeightNormConvTranspose1d</code> raising <code>AttributeError</code> when
constructed with its default <code>has_bias=False</code>. The constructor
unconditionally deleted the wrapped conv's <code>bias</code> attribute, which is only
set when <code>has_bias=True</code>; the delete is now guarded.</p>
</li>
<li class="">
<p>Fixed a GPU memory fault when benchmarking GPU layer norm: the benchmark's
output lambda copy-captured the wrong tensor, so the actual output tensor was
captured by reference and dereferenced as a host pointer on the device. This
faulted on AMD GPUs (and was undefined behavior elsewhere). The lambda now
captures the output tensor it writes to.</p>
</li>
<li class="">
<p>Fixed <code>max.experimental.nn.Conv2d.forward</code> moving the weight to the
input's device but leaving the bias behind, which failed with a device
mismatch when the bias started on a different device than the input. The
bias is now moved alongside the weight.</p>
</li>
<li class="">
<p>Fixed a constrained-decoding bug that could intermittently drop grammar
enforcement during speculative decoding with grammar-guided tool calling.
The speculative bitmask walk advanced the matcher through draft tokens and
restored it with <code>rollback</code>, but <code>rollback</code> does not correctly restore the
matcher across certain tool-call structural tags (e.g.
<code>&lt;|tool_call_begin|&gt;</code>). The walk now runs on a deep copy of the matcher,
leaving the real matcher untouched.</p>
</li>
<li class="">
<p>Fixed speculative decoding (Eagle) requests that reached the per-request
<code>max_tokens</code> cap stopping up to <code>num_speculative_tokens</code> tokens short of it,
returning <code>finish_reason="length"</code> with fewer completion tokens than
requested. The response builder reserved a full worst-case speculative
chunk of slack against the per-request cap instead of only against the
hard model/KV limit, ending the request before its final (and possibly
partial) chunk could run. That chunk now runs, and the per-token accept
loop truncates it to land exactly on the cap.</p>
</li>
<li class="">
<p>Fixed slicing and <code>view()</code> on a <code>max.driver.DevicePinnedBuffer</code> silently
returning a plain <code>Buffer</code>. The decayed type lost the pinned buffer's
no-synchronization behavior, so a later <code>to_numpy()</code> on the slice triggered
an unexpected device synchronization. Slices and views now preserve the
<code>DevicePinnedBuffer</code> type.</p>
</li>
<li class="">
<p>Fixed virtual-device mode on macOS. Previously the
<code>max.driver.set_virtual_device_*()</code> settings had no effect on device
creation: <code>Accelerator()</code> still took the real-hardware path, so requesting
more devices than physically present failed and single-device
cross-compilation silently used the real GPU. The virtual-device state now
lives in a single shared library, so the setters and device creation always
observe the same configuration on every platform.</p>
</li>
<li class="">
<p>Fixed DeepSeek-V3.1-NVFP4 multi-token prediction (MTP) failing to load with
<code>dispatch_quant_config must be specified when dispatch_dtype is not bfloat16</code> when expert parallelism was enabled. When a quantized model has no
resolvable quantization config for its draft (BF16 NextN) weights, the draft
config is now built with a bfloat16 dispatch dtype instead of constructing an
invalid <code>EPConfig</code>.</p>
</li>
<li class="">
<p>Fixed over-provisioned KV cache offload configurations bringing the server
down mid-startup instead of failing fast. The <code>local</code> and <code>tiered</code>
connectors reserved their full host (pinned DRAM) and disk budgets eagerly,
so an impossible <code>host_kvcache_swap_space_gb</code> grew the pinned buffer until
the process was OOM-killed, and an impossible <code>disk_offload_max_gb</code> filled
the filesystem. They now run a startup preflight that checks the host budget
against available memory (including the process cgroup limit) and the disk
budget against filesystem free space, raising an actionable error before
allocating.</p>
</li>
<li class="">
<p>Fixed grouped (<code>groups &gt; 1</code>) <code>ops.conv2d</code>/<code>ops.conv3d</code> on CPU raising
<code>grouped conv requires packed filter</code> whenever the filter was a non-constant
graph value, even with a fully static graph. The compiler only pre-packed
the filter into the layout the grouped-conv kernel requires when the filter
traced back to a compile-time constant; it now also packs a non-constant
filter when <code>groups &gt; 1</code>, since the kernel cannot run without one.</p>
</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v26.4]]></title>
            <link>https://docs.modular.com/releases/v26.4/</link>
            <guid>https://docs.modular.com/releases/v26.4/</guid>
            <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-highlights">Highlights<a href="https://docs.modular.com/releases/v26.4/#26-4-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>The new <code>import-model</code> skill converts a Hugging Face model into a
high-performance model for production inference on MAX. The new <code>debug-model</code>
skill also finds and resolves output token divergences compared to the
original model. Get the skills from
<a href="https://github.com/modular/skills/tree/main" target="_blank" rel="noopener noreferrer" class="">our skills repo</a>, and check out
the guide to
<a class="" href="https://docs.modular.com/max/develop/model-bringup-skills/">bringing up a model with AI agent skills</a>.</p>
</li>
<li class="">
<p>MAX now serves many common models on M3 and newer Apple silicon GPUs,
including the Llama and Qwen model families (among others that can fit into
the system memory). Work continues in the following nightly builds to add
support for Apple M1 and M2 GPUs.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-docs">Documentation<a href="https://docs.modular.com/releases/v26.4/#26-4-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">Added a <a class="" href="https://docs.modular.com/max/inference/video-generation/">video generation</a> guide for serving
text-to-video models (such as <code>Wan-AI/Wan2.2-T2V-A14B-Diffusers</code>) with the
<code>v1/responses</code> endpoint.</li>
<li class="">Added new model developer guides covering
<a class="" href="https://docs.modular.com/max/develop/read-model-config/">reading a Hugging Face model config</a>
and <a class="" href="https://docs.modular.com/max/develop/tensor-realization/">tensor realization</a>.</li>
<li class="">Added a guide to using the new <code>import-model</code> skill, called
<a class="" href="https://docs.modular.com/max/develop/model-bringup-skills/">Bringing up a model with AI agent skills</a>.</li>
<li class="">Updated guides for
<a class="" href="https://docs.modular.com/max/serve/speculative-decoding/">speculative decoding</a> (Kimi K2.6 EAGLE3 and
Gemma 4 MTP), <a class="" href="https://docs.modular.com/max/serve/prefix-caching/">prefix caching</a>, and
<a class="" href="https://docs.modular.com/max/develop/max-pipeline-bring-your-own-model/">fine-tuned model serving</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-models">MAX models<a href="https://docs.modular.com/releases/v26.4/#26-4-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">Added support for Tencent Hunyuan Hy3-preview (<code>HYV3ForCausalLM</code>).</li>
<li class="">Added support for LiquidAI LFM2 (<code>LFM2ForCausalLM</code>).</li>
<li class="">Added support for GLM-5 and GLM-5.1 (<code>GlmMoeDsaForCausalLM</code>) with FP8/NVFP4
weights and FP8 sparse MLA decode for GLM-5.1-FP8.</li>
<li class="">Expanded DeepSeek support:
<ul>
<li class="">Added DeepSeek V2 and V3 (ModuleV3) on a single GPU, with FP8 block-scaled
quantization for V3.</li>
<li class="">Added long-context sparse multi-head latent attention (MLA) support for
DeepSeek-V3.2.</li>
<li class="">Added tool-call parsers for DeepSeek V3 and V3.1.</li>
</ul>
</li>
<li class="">Expanded MiniMax-M2 support:
<ul>
<li class="">Added MXFP4 quantization support for MiniMax-M2.</li>
<li class="">Added tensor-parallel attention + expert-parallel MoE (TP+EP) support for
MiniMax-M2. Set <code>data_parallel_degree: 1</code> with <code>runtime.ep_size &gt; 1</code> to
shard attention heads across GPUs while distributing MoE experts via
expert parallelism. Both reduce-scatter (default) and allreduce
(<code>runtime.ep_use_allreduce: true</code>) collective strategies are supported.</li>
<li class="">Added tensor-parallel support.</li>
<li class="">Added tool-call grammar support and tool-call parsing for MiniMax M2.7.</li>
</ul>
</li>
<li class="">Expanded Gemma 4 support:
<ul>
<li class="">Added support for native FP8 attention with an FP8 KV cache on B200 (SM100).
This roughly matches bf16 accuracy while improving decode throughput and
roughly doubling KV cache capacity at the same memory.</li>
<li class="">Added NVFP4 quantization support.</li>
<li class="">Added structured output (<code>response_format</code>) and tool calling with grammar
enforcement, and tool-call parsing.</li>
<li class="">Extended tool parameter schemas with JSON Schema <code>anyOf</code>, <code>$ref</code>/<code>$defs</code>,
and <code>additionalProperties</code>.</li>
<li class="">Added a reasoning parser.</li>
<li class="">Added MTP speculative decoding (including <code>TP=2</code>) with constrained decoding
when MTP is the draft method.</li>
<li class="">Added multi-GPU support for Gemma 4 31B.</li>
</ul>
</li>
<li class="">Kimi K2.5 tool calling now supports interleaved thinking: a single
assistant turn may interleave multiple <code>&lt;think&gt;...&lt;/think&gt;</code> reasoning
blocks with multiple tool-call sections and end with <code>&lt;|im_end|&gt;</code>. The
constrained-decoding grammar (used for <code>tool_choice</code> and JSON
<code>response_format</code>) admits up to eight tool-call sections with an optional
reasoning block before each, and lets the model stop before the cap. This
fixes a <code>tool_choice=auto</code> failure where a second tool-call section
disabled grammar enforcement for the rest of the request.</li>
<li class="">Expanded speculative decoding model support:
<ul>
<li class="">Added DFlash speculative decoding for Kimi K2.5 and Llama 3, with CUDA
device-graph capture for the Kimi path.</li>
<li class="">Added GQA-based EAGLE drafters for DeepSeek and Kimi.</li>
<li class="">Added Kimi K2.6 Eagle3 speculative decoding and Kimi-K2.6-NVFP4 model
support.</li>
</ul>
</li>
<li class="">Expanded pixel-generation model support:
<ul>
<li class="">Added FLUX.2-Klein-NVFP4 architecture support.</li>
<li class="">Enabled multi-GPU FLUX.2 and FLUX.2-Klein pipelines.</li>
<li class="">Added diffusion pipeline configuration for <code>Qwen-Image</code>.</li>
<li class="">Added TaylorSeer cache support to the Wan T2V pipeline.</li>
<li class="">Added FP8 weight support for Wan 2.2 T2V.</li>
</ul>
</li>
<li class="">Removed FLUX.1 model support.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-max">MAX framework<a href="https://docs.modular.com/releases/v26.4/#26-4-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-max-serve">Inference server<a href="https://docs.modular.com/releases/v26.4/#26-4-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Improved OpenAI-compatible endpoint responses:</p>
<ul>
<li class="">Added <code>reasoning_tokens</code> to <code>usage</code> objects when applicable for chat
completion responses.</li>
<li class="">Omitted JSON fields set to <code>null</code> from streaming deltas in chat completion
responses.</li>
<li class=""><code>/v1/models</code> now includes each model's <code>max_model_len</code>.</li>
<li class=""><code>/v1/completions</code> now reports <code>usage</code> statistics in non-streaming responses.</li>
</ul>
</li>
<li class="">
<p>Added <code>temperature</code> and <code>thinking_temperature</code> to CLI/server arguments.</p>
</li>
<li class="">
<p>Chat completion responses now emit reasoning only under <code>reasoning</code>, aligning
with OpenAI's Responses API naming. The <code>reasoning_content</code> alias is no longer
included in responses. (Previously we emitted <code>reasoning_content</code> for
compatibility with vLLM, SGLang, and the DeepSeek API; vLLM has deprecated
<code>reasoning_content</code> in favor of <code>reasoning</code>.) Clients should read
chain-of-thought tokens from the <code>reasoning</code> field.</p>
</li>
<li class="">
<p><code>response_format</code> JSON schemas with a non-object root are now accepted when
the root <code>type</code> is missing or when it's a type union that includes <code>object</code>
(for example <code>{"type": ["object", "array", "string"]}</code>); these are valid
JSON Schema and compile to a constraining grammar. A root pinned to a single
non-object type (for example <code>{"type": "string"}</code>) is still rejected,
matching OpenAI's structured-outputs contract.</p>
</li>
<li class="">
<p>Added a <code>"none"</code> option for <code>runtime.tool_parser</code> and
<code>runtime.reasoning_parser</code> in <code>PipelineConfig</code> (CLI flags <code>--tool-parser</code>
and <code>--reasoning-parser</code>). Pass <code>none</code> (case-insensitive) to explicitly
disable the parser, overriding any architecture-declared default. Leaving
the field unset still applies the architecture default as before.</p>
</li>
<li class="">
<p>Improved the 400 Bad Request response with the underlying message when a
prompt is too long for the model, instead of a generic "Value error" response
(or, for streaming completions, a 500 Internal Server Error). All
architectures now raise a structured <code>PromptTooLongError</code> exposing
<code>num_tokens</code> and <code>max_length</code> attributes so callers can handle the failure
programmatically. The user-facing message identifies the relevant limit
(context window vs sequence length; for example, "Prompt is too long: N tokens
exceeds the configured maximum context length of M tokens. Please shorten your
prompt").</p>
</li>
<li class="">
<p>Added support for <code>role: "developer"</code> on <code>/v1/chat/completions</code>,
normalizing it to <code>system</code> at the OpenAI-compat route layer. The OpenAI
o1/o3 chat-completion spec uses <code>developer</code> in place of <code>system</code>, and
recent OpenAI SDKs emit it by default.</p>
</li>
<li class="">
<p>Added two opt-in server flags for accepting OpenAI-compatible requests
that the default behavior rejects:</p>
<ul>
<li class="">
<p><code>--allow-unsupported-logprobs</code>: when a request asks for <code>logprobs</code>
against a runtime that cannot honor them (today, the overlap
scheduler), MAX logs a warning and serves the request without
logprobs instead of returning a <code>400</code>.</p>
</li>
<li class="">
<p><code>--allow-extra-request-fields</code>: unknown top-level fields on
<code>/v1/chat/completions</code> and <code>/v1/completions</code> request bodies are
dropped (with a warning) before Pydantic validation, instead of
returning a <code>400</code>. Useful when an upstream proxy sends vendor-specific
fields that MAX doesn't need to honor.</p>
</li>
</ul>
<p>Both flags default to <code>False</code>; the existing strict behavior is
unchanged. The corresponding <code>400</code> error messages now reference the new
flags. As a side effect, the legacy <code>/v1/completions</code> route now surfaces
<code>InputError</code> detail strings to the client instead of the generic
<code>"Value error."</code> message.</p>
</li>
<li class="">
<p>Expanded auto-enablement of overlap scheduler and device graph capture:</p>
<ul>
<li class="">Auto-enabled for OLMo, OLMo2, OLMo3, Qwen2, Qwen3, Qwen3 MoE, and Qwen3.5
text-generation models.</li>
<li class="">Restricted auto-enablement to text-generation pipelines; embedding
pipelines (for example <code>Qwen/Qwen3-Embedding-0.6B</code>) are excluded.</li>
<li class="">Enabled HIP device graph capture by default for supported ROCm
architectures.</li>
</ul>
</li>
<li class="">
<p>Expanded overlap scheduling with structured output:</p>
<ul>
<li class="">Overlap scheduling now supports speculative decoding together with
structured output (<code>response_format</code> and tool-call grammars).</li>
<li class="">Tool-call grammars are no longer gated behind <code>--enable-structured-output</code>.</li>
</ul>
</li>
<li class="">
<p>The <code>local</code> and <code>tiered</code> KV connectors now support EAGLE speculative
decoding with an MLA target model and an MHA draft model, and can offload
the draft model's KV cache to host memory or disk alongside the target
model's cache.</p>
</li>
<li class="">
<p>Extended <code>top_k</code> sampling to support values greater than 255.</p>
</li>
<li class="">
<p>Benchmark request payloads now forward an OpenAI-style <code>tools=[...]</code> field
on chat-completions requests. <code>SampledRequest</code> and <code>RequestFuncInput</code> gained
a <code>tools: list[dict] | None = None</code> field;
<code>OpenAIChatCompletionsRequestDriver</code> serializes it into the POST body when
set. Datasets that supply per-row tool schemas (currently
<code>nemotron-opencode</code>) now exercise the server's tool-call grammar /
structured-output path end-to-end. Pass <code>enable_tool_calls=False</code> on
Nemotron-OpenCode to suppress forwarding.</p>
</li>
<li class="">
<p>Removed multi-step decode from the text-generation pipelines. The flag
<code>--max-num-steps</code> no longer works.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-server-metrics">Server metrics<a href="https://docs.modular.com/releases/v26.4/#26-4-server-metrics" class="hash-link" aria-label="Direct link to Server metrics" title="Direct link to Server metrics" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added a per-phase startup breakdown to the <code>maxserve.model_load_time</code>
Prometheus histogram (milliseconds), previously only available in the
server logs. In addition to the existing untagged model-load aggregate,
the model worker now records each startup phase on the same metric split
by a <code>component</code> tag (<code>build</code>, <code>compile</code>, <code>init</code>, <code>graph_capture</code>,
<code>pinned_memory</code>, <code>spawn</code>, and <code>total</code>), so a single metric can be plotted and
broken down by startup phase to track pod startup time in production.</p>
</li>
<li class="">
<p>Added a <code>maxserve.time_per_output_token</code> Prometheus histogram (milliseconds).
Emitted once per request, it reports the mean decode-phase latency per
generated token (<code>decode_time / (num_generated_tokens - 1)</code>), excluding the
first token and prefill time. Because the denominator counts the tokens the
model actually produced, the metric accounts for speculative decoding.</p>
</li>
<li class="">
<p>The <code>maxserve.batch_size</code> Prometheus histogram is now labeled by
<code>batch_type</code> (<code>CE</code> for prefill, <code>TG</code> for decode), so the token-generation
(decode) batch size can be observed separately from prefill. For the
prefill token-count view, use <code>maxserve.batch_input_tokens</code> (also labeled
by <code>batch_type</code>). Existing aggregate queries over <code>maxserve.batch_size</code>
continue to work; selectors that pin a single series now gain the
<code>batch_type</code> dimension.</p>
</li>
<li class="">
<p>Added Prometheus metrics for the API-server ingress backlog: requests accepted
by the API server but not yet handed off to the model worker (still API-side,
for example in tokenization):</p>
<ul>
<li class=""><code>maxserve.num_requests_awaiting_admission</code>: an up/down counter with the
live value (incremented on arrival, decremented at handoff).</li>
<li class=""><code>maxserve.requests_awaiting_admission</code>: a companion histogram that captures
the distribution and tail (p50/p99) over time. A persistently high value
points at a backlog in the API server rather than in the scheduler queue
(the latter is visible via <code>maxserve.num_requests_queued</code>).</li>
</ul>
</li>
<li class="">
<p>Added Prometheus metrics for the egress (response) path, which show whether
the API server is shipping tokens back to clients slower than the model
produces them:</p>
<ul>
<li class=""><code>maxserve.num_responses_buffered</code>: a gauge sampling the total model-worker
responses received but not yet streamed to clients, with a companion
<code>maxserve.responses_buffered</code> distribution histogram.</li>
<li class=""><code>maxserve.response_queue_time</code>: a millisecond histogram of how long a
response waits in the API server's per-request output queue before the
streaming layer consumes it.</li>
</ul>
<p>Together they surface API-side egress bottlenecks (de-tokenization,
serialization, slow clients) and the associated unbounded-output-queue memory
growth.</p>
</li>
<li class="">
<p>Added the <code>maxserve.num_requests_queued</code> OTel/Prometheus metric (changed
from an <code>UpDownCounter</code> to a synchronous <code>Gauge</code>). The gauge is sampled once
per scheduler iteration and reports the depth of the scheduler's CE / prefill
queue (the same value as the <code>Pending: N reqs</code> line in scheduler logs). It's
published by every text-path scheduler that drives <code>BatchMetrics</code>:
<code>TokenGenerationScheduler</code> and <code>PrefillScheduler</code> (via
<code>TextBatchConstructor</code>), and <code>DecodeScheduler</code> (via
<code>len(pending_reqs) + len(prefill_reqs)</code>). This shows queue buildup during
overload conditions.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v26.4/#26-4-max-cli" class="hash-link" aria-label="Direct link to 26-4-max-cli" title="Direct link to 26-4-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added <code>--devices=gpu:all</code> to use every visible GPU.</p>
</li>
<li class="">
<p>Removed the <code>default</code> value for <code>--devices</code>; omit <code>--devices</code> to use the model
or config default.</p>
</li>
<li class="">
<p>The benchmark now defaults <code>--seed</code> to a fixed value instead of drawing a
fresh random seed on each run. The seed drives the workload generator
(input/output lengths, session structure, content), so a fixed default makes
repeated and scheduled runs reproducible and keeps run-to-run deltas
reflecting the change under test rather than workload-draw variance. To opt
into a fresh seed, pass <code>--seed none</code> on the CLI (or <code>seed: null</code> in a
workload/config YAML); the drawn seed is logged and recorded with the results
so the run stays reproducible after the fact.</p>
</li>
<li class="">
<p>Added <code>--profile</code> to <code>max pipelines generate</code> for rudimentary,
one-command profiling. With Nsight Systems (<code>nsys</code>) on <code>PATH</code> and an
NVIDIA GPU, the timed run is captured into an <code>.nsys-rep</code> file and a
ranked top-N GPU kernel summary is printed. Without <code>nsys</code>, a Python/CPU
profile is produced from <code>cProfile</code>. The capture window is bounded by
<code>cudaProfilerStart</code>/<code>Stop</code> so warmup and graph-compile time are excluded.
Use <code>--profile-output</code> to override the report path.</p>
</li>
<li class="">
<p>Added <code>--profile</code> to <code>max benchmark</code> as a synonym for
<code>--trace</code> that also prints a ranked top-N GPU kernel summary at the end
of the run. The server still needs to be launched under <code>nsys launch</code>
(matching the existing <code>--trace</code> requirement); <code>--profile</code> removes the
"now run <code>nsys stats</code> by hand" step.</p>
</li>
<li class="">
<p>Added architecture YAML recipe support to the CLI:</p>
<ul>
<li class="">Added reusable recipe files under each architecture's <code>recipes/</code> directory.</li>
<li class="">Wired recipes to <code>max serve</code> and <code>max benchmark</code> via <code>--config-file</code>.</li>
<li class="">CLI flags override recipe YAML values when both are supplied.</li>
</ul>
</li>
<li class="">
<p>Added the <code>nemotron-opencode</code> dataset for
<a class="" href="https://docs.modular.com/max/cli/benchmark/"><code>max benchmark</code></a>, backed by
<code>nvidia/Nemotron-SFT-OpenCode-v1</code>. Each row is a full Qwen3-Coder OpenCode
trace (system prompt, multi-turn user/assistant/tool messages, and tool
schemas). Each subset is multi-GB, so the loader streams via
<code>datasets.load_dataset(..., streaming=True)</code> and pulls only enough rows to
satisfy <code>--num-prompts</code>.</p>
</li>
<li class="">
<p>The serving benchmark now reports a per-turn KV cache retention percentile
metric for multi-turn workloads. For each turn after the first, it compares
the server-reported cached prefix against the block-aligned prefix carried
over from the previous turn, surfacing when cached tokens are dropped between
turns (distinct from the existing cached-token-rate metrics, whose denominator
includes new and uncacheable tokens). The KV cache block size used to align
the expected prefix is configurable via <code>--kv-block-size</code> (default <code>128</code>);
match it to the server's <code>--kv-cache-page-size</code>.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-max-python">Python API<a href="https://docs.modular.com/releases/v26.4/#26-4-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Module/"><code>max.graph.Module</code></a> for
grouping multiple <code>Graph</code> instances into a single compilation unit, replacing
the previous alias for the underlying MLIR module. Construct one with
<code>Module()</code> and pass it as the <code>module=</code> argument to each <code>Graph</code>; the
resulting <code>Module</code> is what you hand to <code>InferenceSession.load_all()</code> to
compile every graph together.</p>
<ul>
<li class="">Removed <code>Graph.empty_module()</code> in favor of <code>max.graph.Module()</code>,
and <code>Graph</code> now exposes a <code>module</code> property returning the <code>Module</code> it
belongs to.</li>
</ul>
</li>
<li class="">
<p><code>InferenceSession.load_all()</code> now returns a <code>dict[str, Model]</code> keyed by each
model's <code>sym_name</code> (the name of its <code>mo.graph</code> op), instead of a <code>list[Model]</code>
ordered by MEF position. It also now supports <code>max.graph.Module</code> as a model
input, so you can compile a pre-built module containing multiple <code>mo.graph</code>
ops directly.</p>
<p>To migrate positional unpacking call sites, index the returned dict:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code># Before
module = Graph.empty_module()
with Graph("vision", input_types=..., module=module): ...
with Graph("language", input_types=..., module=module): ...
vision_model, language_model = session.load_all(graph, ...)

# After
module = Module()
with Graph("vision", input_types=..., module=module) as vision_graph: ...
with Graph("language", input_types=..., module=module) as language_graph: ...
models = session.load_all(module, ...)
vision_model = models[vision_graph.name]
language_model = models[language_graph.name]</code></pre></div></div>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/generated/max.engine.CompiledModel/"><code>CompiledModel</code></a>,
which represents the compile artifact. It holds the MEF bytes and one or more
sub-models; it is not directly executable. <code>Model</code> continues to represent the
runnable, post-init handle.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.driver.CompletionFlag/"><code>CompletionFlag</code></a>, an
8-byte completion flag in pinned host memory mapped into a device's address
space. It lets host code signal a GPU stream (or peer host observer) by
writing a 64-bit value to a single location visible to both. Currently
CUDA-only; constructing against any other backend raises <code>RuntimeError</code>.</p>
</li>
<li class="">
<p>Added <code>CompiledModel.export_mef(path)</code> to get the compiled artifact as a MEF
file. It serializes the compiled artifact directly, without requiring the
model to be initialized on a device, so it works in cross-compilation /
virtual-device scenarios where the target device isn't attached.
<code>max.experimental.nn.Module.compile()</code> also returns the same artifact.</p>
</li>
<li class="">
<p>Added <code>Graph.copy()</code> to create a deep copy of a graph's MLIR module (backed
by a new <code>Operation.clone()</code> in <code>max._core</code>). The copy shares no MLIR state
with the original graph, so you can hand it to another thread (for example,
for background compilation) while the original continues to be staged or
executed.</p>
</li>
<li class="">
<p>Added <code>DeviceStream.wait_for_host_value(flag, value)</code> for dispatching a
Python callable onto an explicit AsyncRT worker pool from a host-function
node and gating the GPU stream on its completion (via the
<code>CompletionFlag</code>). The kickoff trampoline returns immediately, letting
the GPU stream proceed concurrently with the worker; a downstream
<code>wait_for_host_value</code> blocks the stream until the worker stores <code>value</code>.
The <code>__unsafe_</code> prefix marks that the API has no safety net for
callbacks that capture state outliving the compiled graph.</p>
</li>
<li class="">
<p>Added <code>max.nn.kernels.wait_host_value()</code>, which stalls the device stream until
a 64-bit host-visible flag reaches a given value. It lets a captured forward
graph gate a downstream consumer kernel on CPU-produced data while the rest of
the forward body runs concurrently.</p>
</li>
<li class="">
<p>Increased the default allreduce signal buffer size from 513 MiB to 1025 MiB
per GPU (<code>max.nn.comm.allreduce.Signals.NUM_BYTES</code> and the matching constant
in <code>max.experimental.realization_context</code>). The previous 512 MiB scratch
couldn't hold the per-peer allgather intermediate for models with large
hidden dimensions (for example, Kimi-K2.5 at <code>hidden_dim=20480</code> with
<code>max-batch-input-tokens=16384</code> needs 640 MiB in bf16). This adds ~512 MiB
of per-GPU memory use for any multi-GPU model.</p>
</li>
<li class="">
<p>Added <code>max.experimental.functional.ceil()</code>, an element-wise unary op that
rounds each element of a floating-point tensor up toward positive infinity.
Complements the existing <code>floor()</code>, <code>round()</code>, and <code>trunc()</code> ops.</p>
</li>
<li class="">
<p><code>max.experimental.functional.while_loop()</code> now passes <code>Tensor</code> (not
<code>TensorValue</code>) into its <code>predicate</code> and <code>body</code> callbacks. Callbacks can
use ordinary <code>Tensor</code> operations directly, without wrapping arguments
via <code>Tensor.from_graph_value(...)</code>.</p>
</li>
<li class="">
<p><code>max.experimental.nn.Module.compile()</code> now emits the same log sequence that
pipeline-level <code>CompilationTimer</code> produces, and wraps the compile body
in <code>max.profiler.Tracer</code> spans so an <code>nsys</code> capture
with <code>MODULAR_ENABLE_PROFILING=1</code> shows compilation as named ranges. Every
ModuleV3 caller, including pixel-generation pipelines that previously
compiled silently, now gets this observability for free.</p>
</li>
<li class="">
<p><code>max.experimental.nn.Module.load_state_dict()</code> and
<code>Module.compile(weights=...)</code> now accept an <code>auto_cast</code> keyword
(default <code>False</code>). The framework remains strict by default. When you pass
<code>auto_cast=True</code>, loaded weights are automatically cast
between <code>float32</code> and <code>bfloat16</code> when shapes match, logging a single
summary message per load instead of raising. Other dtype mismatches
(<code>float16</code>, <code>fp8</code>, <code>fp4</code>, integers, etc.) continue to raise as before.
This removes the need for per-adapter <code>astype</code> shims when checkpoint
dtypes differ from the module's declared parameter dtype. MAX
pipelines opt in via the <code>MODULAR_AUTO_CAST_WEIGHTS</code> environment
variable (default <code>true</code>, parsed by
<code>max.pipelines.lib.weight_loading.auto_cast_weights_from_env</code>).</p>
</li>
<li class="">
<p><code>CPUMetricsCollector</code> in <code>max.diagnostics.cpu</code> is now used as a context
manager instead of <code>start</code>/<code>stop</code>, and exposes <code>get_stats()</code> instead of
<code>dump_stats()</code>, matching the interface of <code>GPUDiagContext</code>.</p>
</li>
<li class="">
<p>Added <code>Tensor.from_dim</code> for building symbolic-dimension predicates inside
traced graph regions (for example, comparing a tensor dimension against a
compile-time constant inside <code>ops.cond</code>). <code>from_dim</code> also works in eager
mode.</p>
</li>
<li class="">
<p>Bound <code>AsyncValue</code> with asyncio interop so <code>InferenceSession.compile()</code> and
related compile paths can be awaited from async Python code.</p>
</li>
<li class="">
<p>Added caching for eager-compiled models for built-in op graphs to speed
repeated eager execution.</p>
</li>
<li class="">
<p>Raised the default <code>MAX_INTERPRETER_MAX_OPS</code> threshold from 30 to 1024 so
larger eager graphs stay on the interpreter path without setting the env var.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-max-kernels">MAX kernels<a href="https://docs.modular.com/releases/v26.4/#26-4-max-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">
<p>The GPU <code>scatter_nd</code> kernel now vectorizes its slice copy with 128-bit
accesses when the slice size, row strides, and base pointers are all
vector-aligned (scalar fallback otherwise). On B200 this brings the
measured row-scatter benchmark (4096 fp32 rows of 1024 columns into a
131072-row table) from 0.25 ms to 0.19 ms end to end, on par with PyTorch
<code>index_put_</code> for the same shape.</p>
</li>
<li class="">
<p>The GPU <code>scatter_nd</code> kernel (all <code>mo.scatter_nd*</code> variants) now parallelizes
over total update elements instead of one thread per index row, removing the
serial per-row slice copy. Slice-style scatters (for example row updates into
a large table) run roughly 1.7x-2.8x faster end to end on B200 depending on
shape; the update kernel itself speeds up far more, but the op's mandatory
<code>data</code>-to-<code>output</code> copy now dominates its runtime. Element-style scatters and
the CPU path are unchanged.</p>
</li>
<li class="">
<p>Removed the <code>use_blocking_impl</code> parameter from the <code>foreach</code> custom op helper
(and the underlying <code>elementwise</code> primitive), and removed the analogous
<code>single_thread_blocking_override</code> parameter from the <code>concat</code> and
<code>concat_shape</code> kernels and the reduction-based kernels. Work is always
dispatched the same way, with a single worker used automatically when the
problem size is small. Removed the dedicated small-tensor <code>concat</code> fast path
in favor of the existing serial/parallel dispatch.</p>
</li>
<li class="">
<p>The <code>axis</code> of the <code>nn.split</code>, <code>nn.cumsum</code>, and <code>fused_concat</code> kernels is now a
keyword-only compile-time parameter instead of a runtime argument. Pass it in
the parameter list, for example <code>split[..., axis=axis](input, outputs, ctx)</code>,
<code>cumsum[dtype, exclusive, reverse, axis=axis](output, input)</code>, or
<code>fused_concat[..., axis=axis](...)</code>.</p>
</li>
<li class="">
<p>Added <code>ManagedTensorSlice.shape_coord()</code> and
<code>ManagedTensorSlice.strides_coord()</code>, which return <code>Coord</code> values that
preserve the compile-time static shape and stride information that the
previous <code>IndexList</code>-returning queries discarded.</p>
</li>
<li class="">
<p>Improved the short-axis GPU softmax kernel, reaching performance parity on
<code>[8, 4096, 1024, 24]</code>-style shapes (~3.1 ms).</p>
</li>
<li class="">
<p><code>max.nn.kernels.scatter_set_constant</code> now raises a <code>ValueError</code> at graph
construction time when <code>indices</code> doesn't have a statically-known inner
dimension of 2. Each <code>indices</code> row is a <code>(row, col)</code> coordinate pair; the
kernel previously read the second coordinate out of bounds for
<code>[num_indices, 1]</code>-shaped indices, silently scattering the fill value to a
heap-content-dependent location (or dropping the write entirely). The Mojo
kernel also now raises unconditionally on malformed index shapes instead of
only under <code>MODULAR_MAX_DEBUG_ASSERT_LEVEL</code>.</p>
</li>
<li class="">
<p>Improved SM100 (Blackwell) GEMM kernel performance:</p>
<ul>
<li class="">Added a cpasync + <code>mma.sync</code> pipelined GEMM kernel for small M and N
shapes, providing higher throughput than <code>gemv_splitk</code> for those cases
(for example, nearly 2x on <code>28x384x7168</code>).</li>
<li class="">Added a warp-specialized TMA epilogue warp that asynchronously loads
epilogue data into shared memory, improving output-pipeline throughput.</li>
<li class="">Added an experimental 1D residual bias epilogue (matmul + broadcast + add
fusion) that uses TMA to asynchronously load the bias tensor.</li>
<li class="">The Mojo SM100 FP4 matmul kernel is now used for small shapes (<code>m &lt;= 128</code>),
improving performance and supporting all fusion types on those shapes.</li>
<li class="">Enabled Programmatic Dependent Launch (PDL) for the SM100 (Blackwell)
FlashAttention-4 prefill kernel, letting back-to-back attention grids in a
stream overlap launch and prologue latency. This reduces per-launch overhead
most for shorter sequences (measured ~1.05x–1.5x faster on B200, bf16,
head_dim=128 across seq lengths 128–2048). On by default; disable with
<code>-D MHA_PDL=false</code>.</li>
</ul>
</li>
<li class="">
<p>Improved AMD MI355X GPU kernel performance</p>
<ul>
<li class="">Added FP8 MLA prefill and <code>HKMhaPrefill</code> long-context MHA prefill</li>
<li class="">Added 4-wave matmul and implicit-GEMM convolution kernels (FP8/BF16/FP16)
and native 3D implicit-GEMM convolution</li>
<li class="">Tuned MLA/MXFP4 decode including split-K</li>
<li class="">Overlapped Kimi K2.5 MXFP4 shared-expert compute with expert-parallel
communication on MI355</li>
<li class="">Fixed HK MHA prefill correctness for partial-K, odd-N, and depth-64
geometries that corrupted FLUX image generation</li>
</ul>
</li>
<li class="">
<p>Improved Blackwell (SM100) GPU kernel performance</p>
<ul>
<li class="">Added sparse MHA prefill and decode kernels and FP8 MHA prefill/decode
support</li>
<li class="">Added sparse MLA prefill kernel (<code>mo.mla.prefill.sparse.paged.fp8</code>)</li>
<li class="">Added fused grouped matmul + SwiGLU + NVFP4/MXFP8 quantization for Kimi K2.5</li>
<li class="">Enabled PDL for split-K MHA decode</li>
<li class="">Fixed an SM100 FP8 MoE decode regression in grouped GEMM</li>
<li class="">Improved FP8 grouped GEMM for non-aligned problem sizes</li>
<li class="">Made LayerNorm ~13% faster at FLUX/DiT-32B tensor shapes</li>
</ul>
</li>
<li class="">
<p>Improved Apple silicon support:</p>
<ul>
<li class="">Added a simdgroup-tiled matmul kernel for the Apple M5 GPU, bringing
neural-accelerator-backed matmul to the MAX framework. In-range MAX matmuls
(<code>m &gt;= 64</code>, <code>n &gt;= 64</code>, <code>k &gt;= 16</code>; ragged K supported) now use it: fp16/bf16
always, and fp32 a/b by default (accepting the simdgroup MMA's fp19
truncation). Set <code>MODULAR_APPLE_M5_ALLOW_LOSSY_F32_MATMUL=0</code> for the precise
naive fp32 path. An 8x8 <code>simdgroup_matrix</code> matmul path also covers Apple
M1-M4 GPUs, roughly 20x faster than the previous naive matmul on those GPUs
in local microbenchmarks.</li>
<li class="">Added a naive split-K decode attention kernel for Apple GPUs, opt-in behind
<code>MODULAR_ENABLE_APPLE_NAIVE_FA_DECODE</code> (default off). On Apple Metal,
token-generation attention otherwise falls back to the unfused
<code>mha_gpu_naive</code>; this adds a paged-KV-cache decode path supporting MHA and
GQA. It is a correctness-first implementation and not yet
performance-optimized.</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-breaking">Breaking changes<a href="https://docs.modular.com/releases/v26.4/#26-4-breaking" class="hash-link" aria-label="Direct link to Breaking changes" title="Direct link to Breaking changes" translate="no">​</a></h2>
<ul>
<li class="">
<p>Removed the <code>max.interfaces</code> top-level module. Pipeline request/context
types and helpers moved into <code>max.pipelines</code> (for example
<code>max.pipelines.request</code>, <code>max.pipelines.modeling</code>); <code>SchedulerResult</code>
moved to <code>max.serve</code>. No deprecation shim remains at the old paths.</p>
</li>
<li class="">
<p>KV cache management has moved from <code>max.kv_cache</code> to <code>max.pipelines.kv_cache</code>.
Update imports accordingly:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code># Before
from max.kv_cache import PagedKVCacheManager, DummyKVCache

# After
from max.pipelines.kv_cache import PagedKVCacheManager, DummyKVCache</code></pre></div></div>
<p>Deprecation shims with <code>DeprecationWarning</code> remain at the old path.</p>
</li>
<li class="">
<p>GPU and CPU diagnostic tooling has moved from <code>max.diagnostics</code> to
<code>max.profiler</code>: <code>max.diagnostics.gpu</code> → <code>max.profiler.gpu</code> and
<code>max.diagnostics.cpu</code> → <code>max.profiler.cpu</code>. Update imports accordingly.
Deprecation shims with <code>DeprecationWarning</code> remain at the old paths.</p>
</li>
<li class="">
<p>Removed support for speculative decoding with a standalone draft model. Use
<code>eagle</code>, <code>mtp</code>, or <code>dflash</code> drafters instead.</p>
</li>
<li class="">
<p>All Mojo custom ops must now declare their <code>ctx</code> parameter as <code>DeviceContext</code>
instead of <code>DeviceContextPtr</code>. The <code>DeviceContextPtr</code> type has been removed
from the Mojo standard library; multi-device ops should declare their variadic
context argument as <code>DeviceContextList[N]</code> (for details, see the corresponding
<a href="https://mojolang.org/releases/v1.0.0b2/#1-0-0-b2-gpu-programming" target="_blank" rel="noopener noreferrer" class="">Mojo v1.0.0b2 release notes</a>).</p>
</li>
<li class="">
<p><code>max/python/max/benchmark/benchmark_throughput.py</code>, deprecated in v0.26.3,
has been removed.</p>
</li>
<li class="">
<p>Removed the LMCache KV cache connector (use <code>local</code> or <code>tiered</code> connectors).</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-fixed">Fixes<a href="https://docs.modular.com/releases/v26.4/#26-4-fixed" class="hash-link" aria-label="Direct link to Fixes" title="Direct link to Fixes" translate="no">​</a></h2>
<ul>
<li class="">
<p>Fixed structured output (<code>response_format: json_schema</code> and grammar-guided
tool calling) intermittently emitting raw control characters inside JSON
string values on models that use a byte-level BPE (TikToken) tokenizer,
producing invalid JSON. The constrained-decoding adapter fed llguidance the
tokens' byte-&gt;unicode <em>surface</em> bytes (for example, a raw newline rendered as
<code>Ċ</code>) instead of their true bytes, so the grammar mask admitted control-char
tokens as legal string content. Token bytes are now recovered via the
tokenizer's <code>byte_decoder</code>, so raw control characters are correctly excluded.
Fast-tokenizer checkpoints were unaffected.</p>
</li>
<li class="">
<p>Fixed an expert-parallelism dispatch assertion (<code>Cannot dispatch EP kernel with N input tokens when the maximum tokens per rank is N-1</code>)
that fired whenever <code>--max-batch-input-tokens</code> wasn't evenly
divisible by the tensor-parallel degree. The EP per-rank cap now uses
ceiling division to match the ragged binning of <code>reducescatter</code> in
TP-attention + EP-MoE mode, so the largest shard fits in the
dispatch buffer. Affects DeepSeek-V3, Kimi-K2.5, MiniMax-M2, Qwen3,
and Step3.5 deployments configured with non-divisible batch sizes.</p>
</li>
<li class="">
<p><code>MODULAR_DEBUG=ir-output-dir=&lt;dir&gt;</code> (and the equivalent
<code>[max-debug] ir-output-dir = &lt;dir&gt;</code> config-file entry and
<code>InferenceSession.debug.ir_output_dir = &lt;dir&gt;</code> Python setter) now
actually dumps per-stage MLIR files to the configured directory. The
option was previously parsed but no compiler stage consulted it, so
users had to fall back to the legacy <code>MODULAR_MAX_TEMPS_DIR</code> env var.
Both spellings are now honored.</p>
</li>
<li class="">
<p>Fixed page-size=128 support in attention kernels when head depth is ≥ 256,
which previously produced incorrect results.</p>
</li>
<li class="">
<p>Fixed pixel-generation serve configs silently dropping denoising-cache flags
(for example TeaCache), so cache tuning options passed through recipes now
take effect.</p>
</li>
<li class="">
<p>Fixed Wan 2.2 image-to-video (I2V) producing a flat green frame when
conditioning inputs were misaligned across the dual-transformer MoE path.</p>
</li>
<li class="">
<p>Fixed a KV-cache host-buffer lifetime bug where <code>cache_lengths</code> and
<code>lut_tables</code> could be freed before asynchronous H2D copies finished,
causing intermittent corruption under offload or tiered-KV workloads.</p>
</li>
<li class="">
<p>Fixed an FP8 dynamic-quantization bug that mis-quantized near-zero groups on
NVIDIA GPUs (writing NaN into FP8 activations and the FP8 KV cache, surfacing
downstream as non-finite logits).</p>
</li>
<li class="">
<p>Fixed a KV cache offloading correctness bug that corrupted output for
multi-cache models (such as Gemma 4's interleaved sliding-window plus
global attention) when the <code>local</code> or <code>tiered</code> KV connector was enabled.</p>
</li>
<li class="">
<p>Fixed JSON <code>response_format</code> and tool-call grammars not being enforced for
Kimi K2.5 vision-language checkpoints.</p>
</li>
<li class="">
<p>Fixed an intermittent constrained-decoding correctness bug under EAGLE
speculative decoding.</p>
</li>
<li class="">
<p>Fixed <code>CreateChatCompletionRequest</code> rejecting explicit <code>null</code> values for
optional fields such as <code>tool_choice</code>, <code>tools</code>, and <code>response_format</code>.
OpenAI-compatible clients (LangChain, JS SDKs, anything that serializes
a dataclass with a <code>None</code> field) that emit <code>"tool_choice": null</code> instead
of omitting the key are now accepted, matching the behavior of other
OpenAI-compatible inference servers.</p>
</li>
<li class="">
<p>Fixed miscalculation of scratch space required by some models. The estimate
was wrong by a factor of <code>1/num_devices</code> because each device only needs
scratch for its own portion of the collective problem. For example, the fix
reduces the footprint for Kimi-K2.5 from 16 GB to 4 GB.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-4-mojo">Mojo language<a href="https://docs.modular.com/releases/v26.4/#26-4-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
see the <a href="https://mojolang.org/releases/" target="_blank" rel="noopener noreferrer" class="">Mojo release notes</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v26.3]]></title>
            <link>https://docs.modular.com/releases/v26.3/</link>
            <guid>https://docs.modular.com/releases/v26.3/</guid>
            <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-highlights">Highlights<a href="https://docs.modular.com/releases/v26.3/#26-3-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>MAX now supports <strong>video generation</strong> with Wan 2.1 / 2.2 diffusion
models, including image-to-video and video-to-video pipelines.</p>
</li>
<li class="">
<p>New API for <strong>multi-GPU model execution from Python</strong>: the
<a class="" href="https://docs.modular.com/max/api/python/generated/max.experimental.sharding/"><code>max.experimental.sharding</code></a>
module lets a single <code>Module.compile()</code> call distribute a model across a
<code>DeviceMesh</code> using <code>Replicated</code>, <code>Sharded</code>, and <code>Partial</code> placement
primitives. Gemma 3 ModuleV3 is the first multi-GPU model on this path.</p>
</li>
<li class="">
<p>The MAX NVFP4 grouped matmul kernel now <strong>outperforms FlashInfer on
B200</strong> across all tested decoding and prefill shapes for Kimi K2.5.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-docs">Documentation<a href="https://docs.modular.com/releases/v26.3/#26-3-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">Restructured the <a href="https://llm.modular.com/" target="_blank" rel="noopener noreferrer" class="">MAX LLM book</a> around how to
deploy a custom model with <code>max serve</code>.</li>
<li class="">Added new model developer guides covering
<a class="" href="https://docs.modular.com/max/develop/broadcasting/">broadcasting</a>,
<a class="" href="https://docs.modular.com/max/develop/indexing/">indexing</a>, and the
<a class="" href="https://docs.modular.com/max/develop/model-bringup-workflow/">model bring-up workflow</a>.</li>
<li class="">Added a <a class="" href="https://docs.modular.com/max/develop/graph/">graph overview</a> and a new
<a class="" href="https://docs.modular.com/max/develop/modules/">graph and modules guide</a>.</li>
<li class="">Added <a class="" href="https://docs.modular.com/max/develop/debugging/">model debugging guides</a> for accuracy, errors,
GPU, and tracing.</li>
<li class="">Updated the <a class="" href="https://docs.modular.com/max/serve/speculative-decoding/">speculative decoding</a> guide.</li>
<li class="">Updated the guide to
<a class="" href="https://docs.modular.com/max/develop/serve-custom-model-architectures/">serve custom models</a>.</li>
<li class="">Added API docs for
<a class="" href="https://docs.modular.com/max/api/python/pipelines.architectures/"><code>max.pipelines.architectures</code></a>.</li>
<li class="">Redesigned <a class="" href="https://docs.modular.com/max/rest-api/">REST API reference</a>, now built with Scalar.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-models">MAX models<a href="https://docs.modular.com/releases/v26.3/#26-3-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>The <code>residual_threshold</code> parameter for FLUX first-block cache (FBCache) is
now a per-request runtime parameter on <code>ImageProviderOptions</code>, allowing it
to be tuned without recompiling the model graph.</p>
</li>
<li class="">
<p>Added the Mamba state space model architecture.</p>
</li>
<li class="">
<p>Added the Step-3.5-Flash architecture.</p>
</li>
<li class="">
<p>Added the Qwen-Image and Qwen-Image-Edit text-to-image architectures.</p>
</li>
<li class="">
<p>Added the Z-Image and Z-Image-Turbo text-to-image architectures.</p>
</li>
<li class="">
<p><strong>MiniMax-M2 and MiniMax-M2.7:</strong></p>
<ul>
<li class="">Added MiniMax-M2 and MiniMax-M2.7 architecture support, including FP8
weights, the lightning-attention hybrid backbone, and 4×H100 multi-GPU
serving.</li>
<li class="">Enabled DP+EP execution paths for MiniMax MoE layers, with automatic
overlap scheduling and device-graph capture.</li>
<li class="">Added per-rank token-limit checks and reduced input-offset device round
trips on the MiniMax decode path.</li>
</ul>
</li>
<li class="">
<p><strong>Gemma 4 and Gemma 3 ModuleV3:</strong></p>
<ul>
<li class="">Added the Gemma 4 architecture (ModuleV2), including multimodal vision
support.</li>
<li class="">Added the Gemma 3 ModuleV3 implementation with multi-GPU support via
the DTensor / <code>DistributedTensorType</code> compile path.</li>
<li class="">Fixed token-offset and prompt-image alignment regressions in Gemma 4
multimodal prefill, plus assorted Gemma 3 ModuleV3 performance fixes.</li>
</ul>
</li>
<li class="">
<p><strong>Qwen3 and Qwen3-VL:</strong></p>
<ul>
<li class="">Added Qwen3 and Qwen3-VL architecture support, including the MoE variant
and multimodal vision input.</li>
</ul>
</li>
<li class="">
<p><strong>Wan video diffusion:</strong></p>
<ul>
<li class="">Fixed Wan 2.1 / 2.2 video diffusion pipelines silently running without
classifier-free guidance. The tokenizer gated negative-prompt tokenization
on <code>true_cfg_scale &gt; 1.0</code> (default <code>1.0</code>), so negative tokens were never
produced and the executor fell back to unguided generation even when
<code>guidance_scale &gt; 1.0</code> and a negative prompt were supplied. Wan now enables
classical CFG whenever <code>guidance_scale &gt; 1.0</code> and defaults an absent
negative prompt to the empty string, matching the diffusers baseline.</li>
<li class="">Added the UniPC multistep scheduler for Wan diffusion.</li>
<li class="">Added Wan image-to-video and video-to-video pipeline variants, plus
additional generation kwargs and prompt-handling fixes.</li>
</ul>
</li>
<li class="">
<p><strong>FLUX.2:</strong></p>
<ul>
<li class="">Added TaylorSeer denoising cache support to the FLUX.2 Klein pipeline,
enabling significant speedups for image-to-image generation by skipping
redundant transformer passes during the denoising loop.</li>
<li class="">Added TeaCache support to <code>DiffusionPipeline</code> as a peer of TaylorSeer.</li>
<li class="">Added FLUX.2 ModuleV2 pipeline, FLUX.2 Klein support, NVFP4 quantization,
aspect-ratio preserving image preprocessing, and BFL checkpoint weight
fixes.</li>
</ul>
</li>
<li class="">
<p><strong>Kimi K2.5 vision:</strong></p>
<ul>
<li class="">Improved Kimi K2.5 multimodal support, including vision encoder fixes
and tokenizer parity with the upstream model.</li>
</ul>
</li>
<li class="">
<p><strong>DeepSeek V3 and Kimi K2.5 distributed execution:</strong></p>
<ul>
<li class="">Improved tensor-parallel and expert-parallel execution paths for
DeepSeek V3 and Kimi K2.5, including subgraph deduplication, MoE dispatch
tuning, and reduced compile-time overhead.</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-max">MAX framework<a href="https://docs.modular.com/releases/v26.3/#26-3-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-max-serve">Inference server<a href="https://docs.modular.com/releases/v26.3/#26-3-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added periodic "still building/compiling" log messages during model
compilation so that long operations produce visible signs of progress.</p>
</li>
<li class="">
<p>Consolidated KV connector CLI flags (<code>--host-kvcache-swap-space-gb</code>,
<code>--disk-offload-dir</code>, <code>--disk-offload-max-gb</code>, <code>--disk-offload-direct-io</code>,
<code>--lmcache-config-file</code>) into the <code>--kv-connector-config</code> JSON dict.</p>
</li>
<li class="">
<p>Removed the <code>--allow-safetensors-weights-fp32-bf16-bidirectional-cast</code> CLI
flag. Float32 &lt;-&gt; bfloat16 safetensors weight casting is now unconditionally
enabled.</p>
</li>
<li class="">
<p>Added <code>--model-override</code> CLI flag for per-component <code>ModelManifest</code> overrides
(e.g. <code>--model-override transformer.quantization_encoding=float4_e2m1fnx2</code>),
enabling mixed quantization in diffusion pipelines.</p>
</li>
<li class="">
<p>Removed jump forward decoding (<code>compute_ff_tokens</code>) from structured output.
The bitmask constraint alone ensures valid structured output, matching the
approach used by vLLM and SGLang.</p>
</li>
<li class="">
<p>Added <code>json_object</code> response-format support to MAX Serve structured output
via <code>/v1/chat/completions</code>.</p>
</li>
<li class="">
<p>Improved error handling for image request failures in MAX Serve.</p>
</li>
<li class="">
<p>Added multi-step and overlap-scheduler support for structured output in the
<code>TextGenerationPipeline</code>. Extended tokenizer support to include TikToken-based
tokenizers, enabling structured output with Kimi K2.5.</p>
</li>
<li class="">
<p>Improved cached-token reporting, fixed cache hit/miss metrics to emit only
on context-encoding batches, moved a subset of telemetry from detailed to
basic, and added per-draft-position acceptance-rate logging for speculative
decoding.</p>
</li>
<li class="">
<p>Tightened the <code>MODULAR_MAX_SERVE_*</code> environment-variable prefix; unprefixed
overrides previously honored by <code>max-serve</code> no longer apply.</p>
</li>
<li class="">
<p>Added <code>min_p</code> and <code>top_k</code> sampling controls and additional
chat-completion kwargs to the OpenAI-compatible routes.</p>
</li>
<li class="">
<p><strong>Unified EAGLE speculative decoding:</strong></p>
<ul>
<li class="">Added unified EAGLE pipelines for Llama 3, DeepSeek V3 + MTP, and Kimi
K2.5, sharing a single PipelineModel.</li>
<li class="">Added support for <code>--num-speculative-tokens &gt; 1</code> across the unified EAGLE
Llama, DeepSeek+MTP, and Kimi+EAGLE paths.</li>
<li class="">Added overlap-scheduler support for unified EAGLE, including multi-GPU
DP setups (e.g. DP Kimi).</li>
<li class="">Enabled CUDA graphs for EAGLE and MTP.</li>
</ul>
</li>
<li class="">
<p><strong>Distributed KV transfer (dKV):</strong></p>
<ul>
<li class="">Added the <code>DKVConnector</code> with NIXL transfer support for the distributed
KV cache.</li>
<li class="">Unified KV connector configuration under <code>--kv-connector-config</code>.</li>
<li class="">Added EFA compatibility, disconnect support, parent-hash eviction, and
per-connector metrics for the dKV transfer engine.</li>
<li class="">Added a configurable decode-stall watchdog for 1P1D deployments.</li>
<li class="">Added disk-location support to the Python dKV client.</li>
</ul>
</li>
<li class="">
<p><strong>Heterogeneous serving and overlap scheduling:</strong></p>
<ul>
<li class="">Added two-phase prefill execution under the overlap scheduler for the
distributed-inference (DI) prefill role.</li>
<li class="">Auto-enabled overlap scheduling for DI pipeline roles and disabled
auto device-graph capture for prefill-only workers.</li>
<li class="">Added support for heterogeneous TP prefill / DP decode in MLA KV
transfer (e.g. <code>tp4</code> prefill into a DP decode pool).</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v26.3/#26-3-max-cli" class="hash-link" aria-label="Direct link to 26-3-max-cli" title="Direct link to 26-3-max-cli" translate="no">​</a></h3>
<ul>
<li class="">Added sweep benchmarking capabilities to <code>max benchmark</code>: iterate over
multiple concurrency and request-rate combinations, flush the prefix cache
between runs, and collect per-run structured JSON results.</li>
<li class="">Standardized the <code>--model</code> flag across <code>max serve</code>, <code>max generate</code>,
<code>max encode</code>, and <code>max warm-cache</code>.</li>
<li class="">Improved <code>max serve</code> CLI flag descriptions.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-max-python">Python API<a href="https://docs.modular.com/releases/v26.3/#26-3-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added <code>Model.release_captured_graph()</code>, which drops a previously captured
device graph identified by graph key (or per-device keys) and frees its
device-side working memory once any in-flight replay completes. Releasing a
key that was never captured is a no-op. Callers remain responsible for
dropping any output <code>Buffer</code> handles returned by the corresponding
<code>Model.capture()</code> call.</p>
</li>
<li class="">
<p>Added <code>ops.roi_align</code> (with <code>F.roi_align</code> functional wrapper) for ROI Align
pooling over NHWC inputs, with configurable spatial scale, sampling ratio,
alignment mode, and AVG/MAX pooling. Includes a matching MO eager handler.</p>
</li>
<li class="">
<p>Added MO eager handlers for <code>ConstantExternalOp</code>, <code>ConstantScalarOp</code>,
<code>ReduceRmsNormOp</code>, and <code>ReduceGroupNormOp</code>, so graphs with external
weights, scalar constants, RMS norm, or group norm run eagerly without
falling back to compilation.</p>
</li>
<li class="">
<p>Fixed tensor slicing with negative integer indices (e.g. <code>hidden[:, -1]</code>)
which previously raised a <code>RuntimeError</code> at compile time.</p>
</li>
<li class="">
<p>Fixed <code>ops.reshape</code> / <code>TensorValue.reshape</code> rejecting valid <code>-1</code> reshapes
on tensors whose leading dim is a symbolic sum-of-products (e.g.
<code>[(batch_size * num_steps) + total_seq_len, 1536]</code> reshaped to
<code>[-1, n_heads, head_dim]</code> with <code>n_heads * head_dim == 1536</code>). The inferred
dim now simplifies without requiring a <code>rebind</code>.</p>
</li>
<li class="">
<p>Setting <code>MODULAR_MAX_DEBUG_UNINITIALIZED_READ_CHECK=true</code> (or the
<code>max-debug.uninitialized-read-check</code> config key, or
<code>InferenceSession.debug.uninitialized_read_check = True</code>) enables detection
of uninitialized memory reads in Mojo kernels. <code>InferenceSession</code>
automatically enables the debug allocator poison and compiles kernels with
load-time poison checks for all float types. When a load matches a poison
pattern, the process aborts with a descriptive message.</p>
</li>
<li class="">
<p>Added support for the <code>bfloat16</code> data type on ARM CPU devices in MAX graphs.
Previously, <code>session.load()</code> raised a <code>ValueError</code> when a graph contained
bf16 tensors targeting an ARM CPU.</p>
</li>
<li class="">
<p>Added <code>DevicePlacementPolicy</code> (<code>Ignore</code>, <code>Warn</code>, <code>Error</code>) to <code>Graph</code> to
control behavior when CPU-only ops (<code>ops.scatter</code>, <code>ops.cumsum</code>,
<code>ops.nonzero</code>, <code>ops.tile</code>) receive GPU tensors. The default (<code>Warn</code>) emits a
<code>UserWarning</code> and falls back to CPU; <code>Error</code> raises <code>ValueError</code> instead.
<code>ops.cond</code> and <code>ops.while_loop</code> always raise <code>ValueError</code> for GPU predicates.</p>
</li>
<li class="">
<p>Fixed slow <code>axis=None</code> reductions (<code>mean</code>, <code>sum</code>, <code>prod</code>, <code>max</code>, <code>min</code>) in
<code>max.experimental.functional</code>. The previous implementation flattened the
tensor before reducing, serializing the work onto a single GPU block.
Reductions now iterate axis-by-axis to preserve parallelism.</p>
</li>
<li class="">
<p>Renamed the public quantization APIs from <code>Float8*</code> to <code>Quant*</code> (including
<code>Float8Config</code> → <code>QuantConfig</code>, <code>parse_float8_config()</code> →
<code>parse_quant_config()</code>, and the <code>quant</code> modules in <code>max.nn</code> and
<code>max.pipelines.lib</code>), reflecting that the config now covers FP8, NVFP4,
and MXFP4 quantization.</p>
</li>
<li class="">
<p><code>max.diagnostics.gpu.BackgroundRecorder</code>'s sampling interval can now be
configured.</p>
</li>
<li class="">
<p>Introduced <code>CPUMetrics</code> alongside the existing GPU diagnostics and open source
it under from <code>max.diagnostics</code>.</p>
</li>
<li class="">
<p>Added <code>Model.kernel_summaries</code> for inspecting compiled kernels through the
Python API.</p>
</li>
<li class="">
<p>Added a unified <code>DebugConfig</code> Python class (with nanobind bindings) and
exposed <code>DebugConfig</code> and <code>GraphDebugConfig</code> in <code>max.engine</code> and
<code>max.graph</code>.</p>
</li>
<li class="">
<p>Added a graph API for initializing and registering the runtime context
(<code>M::Context</code>) from Python.</p>
</li>
<li class="">
<p>Improved <code>max.experimental.functional.custom</code>: compiled custom-op kernels
are now cached, and eager-mode <code>F.custom</code> no longer recompiles on every
call.</p>
</li>
<li class="">
<p>Fixed <code>Module.compile()</code> when unrealized tensors are used as weights.</p>
</li>
<li class="">
<p>Added the <code>InputModality</code> enum for specifying model input types and
threaded it through the multimodal pipeline architectures.</p>
</li>
<li class="">
<p>Updated <code>Tensor.to()</code> and <code>Module.to()</code> to accept distributed device
targets, including <code>DeviceMapping</code> and <code>DeviceMesh</code>.</p>
</li>
<li class="">
<p><code>max.experimental.Tensor</code> is now distribution-aware: it carries a
tuple of per-shard storages, <code>driver.Buffer</code>s (realized) or graph
values (<code>TensorValue</code> / <code>BufferValue</code>, unrealized), paired with a
<code>DeviceMapping</code> that maps those local shards onto the
<code>DeviceMesh</code>.</p>
</li>
<li class="">
<p>Reworked <code>max.experimental.functional</code> from a single <code>functional.py</code>
into a <code>functional/</code> package, a new distribution-and mesh-aware
dispatch layer on top of the graph-compiler Python API, split cleanly
into three op categories: <code>creation_ops</code> (tensor factories), <code>spmd_ops</code>
(rule-based per-op SPMD dispatch), and <code>collective_ops</code>
(<code>allreduce_sum</code>, <code>allgather</code>, <code>reduce_scatter</code> etc., now applied per
device-group along a chosen mesh axis so they dispatch correctly on
multi-dimensional meshes, plus a <code>transfer_to</code> convenience op
between <code>DeviceMapping</code>s).</p>
</li>
<li class="">
<p>Added <code>max.experimental.sharding</code> with the core types for distributed
tensors (<code>DeviceMesh</code>; <code>DeviceMapping</code> with <code>PlacementMapping</code> and
<code>NamedMapping</code>; placement primitives <code>Replicated</code> / <code>Sharded</code> /
<code>Partial</code>; <code>DistributedTensorType</code> / <code>DistributedBufferType</code>;
<code>TensorLayout</code>), plus a <code>sharding.rules</code> submodule of pure
mapping-propagation rules (elementwise, matmul, reduction, shape,
conv, pooling) that, for each op, either error out or reshard inputs
to the proposed <code>DeviceMapping</code>s and derive the resulting output
<code>DeviceMapping</code>.</p>
</li>
<li class="">
<p><code>max.experimental.nn.Module.compile()</code> now accepts
<code>DistributedTensorType</code> symbolic inputs (not just <code>TensorType</code>), so
distributed models can be built via the graph-compilation path in
addition to running eagerly; <code>gemma3_modulev3</code> is the first multi-GPU
model wired up. DTensor support in MAX is still ongoing work and
these APIs may evolve.</p>
</li>
<li class="">
<p>Added new graph ops (with matching <code>max.experimental.functional</code> wrappers):
<code>scatter_max</code>, <code>scatter_min</code>, <code>scatter_mul</code>, <code>scatter_nd_max</code>,
<code>scatter_nd_min</code>, <code>scatter_nd_mul</code>, <code>non_maximum_suppression</code>,
<code>resize_linear</code>, <code>resize_nearest</code>, and <code>resize_bicubic</code>. The existing
<code>max.graph.ops.resize</code> now delegates to these for <code>BILINEAR</code>, <code>NEAREST</code>,
and <code>BICUBIC</code> interpolation modes. <code>max.graph.ops.pad</code> (and the functional
wrapper) also accepts <code>mode='reflect'</code> and <code>mode='edge'</code> in addition to
<code>mode='constant'</code>.</p>
</li>
<li class="">
<p>Expanded experimental eager-interpreter coverage so significantly more
graphs run end-to-end without falling back to compilation. Added handlers
for <code>gather</code>, <code>gather_nd</code>, <code>argmax</code>, <code>argmin</code>, <code>split</code>, <code>scatter</code>,
<code>scatter_nd</code>, <code>scatter_nd_add</code>, <code>scatter_add</code>, <code>scatter_max</code>, <code>scatter_min</code>,
<code>scatter_mul</code>, <code>scatter_nd_max</code>, <code>scatter_nd_min</code>, <code>scatter_nd_mul</code>, <code>tile</code>,
<code>band_part</code>, <code>top_k</code>, <code>bottom_k</code>, <code>nonzero</code>, <code>non_maximum_suppression</code>,
<code>pad</code> (constant on CPU/GPU; reflect and edge on CPU), <code>conv2d</code>,
<code>conv2d_transpose</code>, <code>max_pool2d</code>, <code>avg_pool2d</code> (floor and ceil mode),
<code>resize_linear</code>, <code>resize_nearest</code>, <code>resize_bicubic</code>, <code>mo.mutable.store</code>,
<code>mo.mutable.store.slice</code>, and the distributed collectives
<code>distributed.allreduce.sum</code>, <code>distributed.allgather</code>, <code>distributed.scatter</code>,
<code>distributed.broadcast</code>, and <code>distributed.reducescatter.sum</code>. Most run on
both CPU and GPU; CPU-only handlers are noted as such.</p>
</li>
<li class="">
<p>Rewrote the eager-interpreter <code>mo.mutable.store.slice</code> handler to write
slices via a device-side Mojo kernel instead of a host numpy round-trip.
GPU buffers no longer round-trip D→H→D on every call, and <code>bfloat16</code> and
<code>float8_*</code> dtypes are now supported (<code>float4_e2m1fn</code> remains unsupported).</p>
</li>
<li class="">
<p>Added defensive eager-interpreter handlers for <code>mo.shape.from_tensor</code>,
<code>mo.index.to_tensor</code>, <code>mo.buffer.create</code>, <code>mo.buffer.transfer</code>, and
<code>mo.gather_sum</code> so eager runs no longer crash if these internal ops survive
canonicalization.</p>
</li>
<li class="">
<p>Improved experimental eager-interpreter performance by enabling
multi-threaded CPU execution and removing unnecessary GPU device
synchronization between op dispatches.</p>
</li>
<li class="">
<p>Added <code>max.nn.StackedLinear</code> for QKV-style stacked projections, with a
fused (<code>stacked=True</code>) and an unfused (<code>stacked=False</code>) layout. Unfused
mode opts into a new <code>Module._omit_module_attr_name</code> flag, which drops
the wrapper's own attribute name from descendant weight FQNs, so a
<code>self.qkv_proj = StackedLinear(names=["q_proj", "k_proj", "v_proj"], stacked=False)</code> exposes weights at <code>self_attn.q_proj.weight</code> rather
than <code>self_attn.qkv_proj.q_proj.weight</code>. This lets HuggingFace
checkpoint names flow into models without per-architecture remapping
in their <code>weight_adapters.py</code>.</p>
</li>
<li class="">
<p><code>Module.compile()</code> now accepts a <code>custom_extensions</code> parameter for loading
custom Mojo kernel libraries at graph construction time, fixing validation
failures for kernels with struct-level parameters.</p>
</li>
<li class="">
<p>Fixed <code>torch.compile(fullgraph=True)</code> failing with an "Unsupported context
manager" error when accessing <code>CustomOpLibrary</code> ops inside the compiled
function. Ops are now eagerly compiled during library initialization.</p>
</li>
<li class="">
<p><strong>Runtime and device graph performance:</strong></p>
<ul>
<li class="">Reduced device-graph launch overhead for single-graph models.</li>
<li class="">Parallelized device-graph instantiation and moved instantiation off the
main execution threads.</li>
<li class="">Added parallel device-graph launches and a task-ID hint on AsyncRT
algorithms.</li>
<li class="">Added a GPU health check during <code>DeviceContext</code> initialization.</li>
<li class="">Added NaN/Inf detection at compiled-region boundaries.</li>
<li class="">Improved Metal driver support with custom statuses and Metal log capture
for Apple GPU print output.</li>
<li class="">Made <code>CPUDeviceContext</code> asynchronous and added <code>enqueue_cpu_function</code> /
<code>enqueue_cpu_range</code> helpers for CPU kernel execution.</li>
<li class="">Auto-enabled device-graph capture for DeepSeek V3, Kimi, and Kimi K2.5
serving paths.</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-custom-ops">Custom ops<a href="https://docs.modular.com/releases/v26.3/#26-3-custom-ops" class="hash-link" aria-label="Direct link to Custom ops" title="Direct link to Custom ops" translate="no">​</a></h3>
<ul>
<li class="">Added host-function and in-place memcpy custom ops, including
<code>mo.launch_host_func</code>, <code>mo.inplace_memcpy</code>, an <code>enqueueHostFunc</code> Mojo
binding on <code>DeviceStream</code>, and a <code>cuLaunchHostFunc</code> binding for the
CUDA device stream.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-max-kernels">MAX kernels<a href="https://docs.modular.com/releases/v26.3/#26-3-max-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added GPU kernel examples from the <em>Programming Massively Parallel Processors</em>
(PMPP) textbook covering reductions, scans, histograms, sorting, sparse
matrix operations, graph algorithms, convolutions, FlashAttention, and more.</p>
</li>
<li class="">
<p>Improved NVFP4 grouped matmul kernel performance, now outperforming FlashInfer
across all tested decoding and prefill shapes for Kimi K2.5 on B200.</p>
</li>
<li class="">
<p>Optimized GPU <code>layer_norm</code> kernels with SIMD reductions, gamma/beta
prefetch, and a <code>simd_width*2</code> warp tiling dispatch path.</p>
</li>
<li class="">
<p>Optimized GPU <code>pad_constant</code> kernel with SIMD vectorization (<code>simd_width=4</code>)
and added a kbench benchmark suite (<code>bench_pad</code>).</p>
</li>
<li class="">
<p>Improved GPU <code>topk</code> and <code>argsort</code> kernel performance by nearly 2x.</p>
</li>
<li class="">
<p>Optimized GPU <code>concat</code> with a flat-indexing kernel that avoids
multi-dimensional index decomposition, using 128-bit vectorized loads with
automatic fallback for unaligned shapes.</p>
</li>
<li class="">
<p>Optimized GPU <code>topk</code> stage-1 kernel with a per-thread register heap that
caches the top-8 elements during a single scan pass, eliminating redundant
global memory re-reads for the first 8 extraction iterations.</p>
</li>
<li class="">
<p>Moved <code>partial_simd_load</code> and <code>partial_simd_store</code> from
<code>buffer.buffer</code> to <code>linalg.utils</code> and removed the <code>buffer</code> package. Update
imports from <code>from buffer.buffer import ...</code> to
<code>from linalg.utils import ...</code>.</p>
</li>
<li class="">
<p><strong>Blackwell (SM100) GPU performance:</strong></p>
<ul>
<li class="">Enabled the Mojo SM100 GEMM by default.</li>
<li class="">Added MXFP4 and MXFP8 block-scaled matmul on SM100, plus a <code>KIND_MXF4</code>
execution path.</li>
<li class="">Added a general grouped block-scaled matmul dispatch and MXFP4 support
for the grouped path.</li>
<li class="">Enabled PDL for SM100 grouped NVFP4 / MXFP4 / MXFP8 GMM.</li>
<li class="">Improved the SM100 GEMV dispatcher and added GEMV split-K for GEMMs with
small <code>M</code> and <code>N</code>.</li>
<li class="">Increased the SM100 GEMM <code>C</code>-tile <code>N</code> dispatch up to 64.</li>
</ul>
</li>
<li class="">
<p><strong>AMD GPU performance:</strong></p>
<ul>
<li class="">Added B300 support, including device-agnostic default block counts for
allreduce and allgather.</li>
<li class="">Added a CDNA4 block-scaled MFMA wrapper.</li>
<li class="">Added MI355X TileTensor MHA (about +13% prefill at depth 128) and
TileTensor-based AMD attention kernels generally.</li>
<li class="">Always enabled the gfx950 MHA prefill kernel and modernized AMD MHA/MLA
decode with 16x16 MMA and FP8.</li>
<li class="">Added depth-512 paths for AMD RDNA GPUs and a 2-D convolution kernel for
RDNA 3+ GPUs.</li>
<li class="">Added MXFP4 matmul and grouped matmul support on AMD.</li>
</ul>
</li>
<li class="">
<p><strong>Attention and state-space kernels:</strong></p>
<ul>
<li class="">Added sparse MLA decode (with qbf16 / FP8 KV variants) for SM100.</li>
<li class="">Added speculative-decoding sequence-length folding with <code>numhead</code> for the
TP MLA decode dispatch.</li>
<li class="">Added gated delta-rule recurrence kernels for hybrid-attention models.</li>
</ul>
</li>
<li class="">
<p><strong>Expert-parallel (EP) kernels:</strong></p>
<ul>
<li class="">Added multi-device MO ops for EP dispatch and combine.</li>
<li class="">Added a grouped dynamic NVFP4 quantization kernel for MoE.</li>
<li class="">Added MXFP4 support to <code>ep.dispatch</code> and the
<code>mo.distributed.ep.dispatch.mxfp4</code> op.</li>
<li class="">Added a <code>skip_a2a</code> mode to EP dispatch and combine.</li>
<li class="">Fixed AMD GPU atomics in EP dispatch.</li>
</ul>
</li>
<li class="">
<p><strong>Collective communication kernels:</strong></p>
<ul>
<li class="">Unified the multimem and standard code paths in <code>ReduceScatter</code>.</li>
<li class="">Enabled PDL for allgather and updated <code>ReduceScatter</code> to use <code>with_PDL()</code>.</li>
<li class="">Launched allgather kernels in parallel and set the allgather block count
via a tuning table.</li>
<li class="">Added support for non-multiples of SIMD width in allreduce.</li>
</ul>
</li>
<li class="">
<p><strong>Fused transformer kernels:</strong></p>
<ul>
<li class="">Added a fused <code>rope_split_store</code> kernel and wired it into
<code>AttentionWithRope</code>.</li>
<li class="">Added a fused RMSNorm + RoPE GPU kernel and a graph-compiler fusion
pattern for <code>mo.reduce.rms_norm.RoPE</code>.</li>
<li class="">Added a GEMV + partial RMSNorm fusion path.</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-breaking">Breaking changes<a href="https://docs.modular.com/releases/v26.3/#26-3-breaking" class="hash-link" aria-label="Direct link to Breaking changes" title="Direct link to Breaking changes" translate="no">​</a></h2>
<ul>
<li class="">
<p>Removed individual KV connector CLI flags (<code>--host-kvcache-swap-space-gb</code>,
<code>--disk-offload-dir</code>, <code>--disk-offload-max-gb</code>, <code>--disk-offload-direct-io</code>,
<code>--lmcache-config-file</code>). Use <code>--kv-connector-config</code> with a JSON dict
instead.</p>
</li>
<li class="">
<p><code>max/python/max/benchmark/benchmark_throughput.py</code> has been deprecated and
will be removed in a future MAX release.</p>
</li>
<li class="">
<p>Removed <code>Dim</code> and <code>DimList</code> types from <code>buffer.dimlist</code>. Custom kernel code
using these types should migrate to <code>IntTuple</code> and <code>TileLayout</code> from the
<code>layout</code> package.</p>
</li>
<li class="">
<p>Removed <code>PreTrainedPipelineTokenizer</code>. Use the standard pipeline tokenizer
resolution path instead.</p>
</li>
<li class="">
<p>Moved <code>DenoisingCacheConfig</code> from <code>PipelineConfig</code> to
<code>PipelineRuntimeConfig</code>. Update call sites that constructed
<code>PipelineConfig(denoising_cache_config=...)</code> to set the field on
<code>PipelineRuntimeConfig</code> instead.</p>
</li>
<li class="">
<p>Replaced <code>FluxPipelineOutput</code> and <code>Flux2PipelineOutput</code> with a unified
<code>DiffusionPipelineOutput</code>. Code that imports the old output types must
switch to <code>DiffusionPipelineOutput</code>.</p>
</li>
<li class="">
<p><code>PipelineConfig</code> now expects a <code>models=ModelManifest(...)</code> configuration
for multi-component pipelines (transformer, VAE, text encoders, etc.).
Pipelines that previously passed individual model paths or configs at the
top level must migrate to a <code>ModelManifest</code>.</p>
</li>
<li class="">
<p><code>max-serve</code> now requires the <code>MODULAR_MAX_SERVE_*</code> prefix for environment
overrides. Unprefixed environment variables previously honored by
<code>max-serve</code> no longer apply.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-fixed">Fixed<a href="https://docs.modular.com/releases/v26.3/#26-3-fixed" class="hash-link" aria-label="Direct link to Fixed" title="Direct link to Fixed" translate="no">​</a></h2>
<ul>
<li class="">
<p>Fixed MAX tools aborting at startup with
<code>std::filesystem::filesystem_error</code> when <code>$HOME</code> is not traversable by the
running UID (common in containerized CI where the image's build-time UID
differs from the runtime UID). The config search now treats permission
errors as "not found" and falls through to the next candidate.
(<a href="https://github.com/modular/modular/issues/6412" target="_blank" rel="noopener noreferrer" class="">Issue #6412</a>)</p>
</li>
<li class="">
<p>Fixed <code>enqueue_fill()</code> taking O(N) HIP API calls for <code>float64</code> buffers on
AMD GPUs when the high and low 32-bit halves of the fill value differ (e.g.,
<code>2.0</code>), reducing the call count to O(log N).
(<a href="https://github.com/modular/modular/issues/6417" target="_blank" rel="noopener noreferrer" class="">Issue #6417</a>)</p>
</li>
<li class="">
<p>Fixed integer indexing into a graph tensor (e.g. <code>x[0]</code> on a <code>(2, 3)</code>
tensor) failing graph compilation with
<code>'mo.static.reshape' op input and output elements do not match</code>. A
reshape-through-slice optimization pattern was incorrectly rewriting
the slice + squeeze pattern produced by integer indexing, generating a
reshape whose element count did not match the input.
(<a href="https://github.com/modular/modular/issues/6440" target="_blank" rel="noopener noreferrer" class="">Issue #6440</a>)</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-3-mojo">Mojo language<a href="https://docs.modular.com/releases/v26.3/#26-3-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools, see the
<a href="https://mojolang.org/releases/" target="_blank" rel="noopener noreferrer" class="">Mojo release notes</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v26.2]]></title>
            <link>https://docs.modular.com/releases/v26.2/</link>
            <guid>https://docs.modular.com/releases/v26.2/</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-highlights">Highlights<a href="https://docs.modular.com/releases/v26.2/#26-2-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>MAX now supports <strong>image generation</strong> with FLUX diffusion models
(<code>FLUX.1-dev</code> and <code>FLUX.2-dev</code>), served through a new <code>/v1/responses</code> endpoint
with the <a href="https://www.openresponses.org/reference" target="_blank" rel="noopener noreferrer" class="">OpenResponses API</a>. See the
<a class="" href="https://docs.modular.com/max/inference/image-generation/">image generation guide</a> to get started.</p>
</li>
<li class="">
<p>Significant <strong>DeepSeek improvements</strong>: added support for DeepSeekV3.2 with
multi-latent attention, NVFP4 quantization support for DeepSeek-R1 (with
expert parallelism), and expert parallelism now supports more than 32 local
experts without requiring NVSHMEM for single-node deployments.</p>
</li>
<li class="">
<p>Major <strong>Blackwell (SM100) kernel optimizations</strong>, including
<a href="https://arxiv.org/abs/2602.10718" target="_blank" rel="noopener noreferrer" class="">SnapMLA</a> for MLA decode,
hardware-accelerated conv2d with TMA im2col for FLUX VAE, fused epilogues in
BF16 and FP8 matmul kernels, and FP8 MMA support for MLA prefill with
blockwise scaling.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-docs">Documentation<a href="https://docs.modular.com/releases/v26.2/#26-2-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>Refactored the <a class="" href="https://docs.modular.com/max/api/python/">MAX Python API reference</a> into a flat list
of module pages. Each summary page organizes APIs based on conceptual groups
instead of source file locations. All API members also include a direct link
to the source code on GitHub.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/develop/basic-ops/">Basic operations</a> to the model developer
guide, covering tensor arithmetic, shape manipulation, reductions, matrix
operations, activation functions, and random tensor generation.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/develop/pipelines/">Model pipeline</a> to the model developer
guide, explaining how to connect models to MAX's serving infrastructure with
inference pipelines that handle weight loading, KV cache management, request
batching, and tokenization.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/inference/image-generation/">Image generation</a> to the inference
guide, showing how to generate images from text prompts or transform existing
images using the <code>v1/responses</code> endpoint with FLUX models.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/environment-variables/">Environment variables</a> reference,
documenting all configurable MAX environment variables for server settings,
logging, telemetry, debugging, performance, and Hugging Face integration.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-models">MAX models<a href="https://docs.modular.com/releases/v26.2/#26-2-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added support for FLUX image generation models
(<code>black-forest-labs/FLUX.1-dev</code> and <code>FLUX.2-dev</code>). Supports fused graph
compilation, batched VAE decoding, GPU-side post-processing, and first-block
caching for repeated prompts.</p>
</li>
<li class="">
<p>Added support for Kimi vision-language models (<code>moonshotai/Kimi-K2.5</code> and
<code>Kimi-VL-A3B-Instruct</code>). Supports multi-GPU tensor parallelism, a custom
vision processor, learnable 2D position embeddings, and tiktoken tokenizer.</p>
</li>
<li class="">
<p>Added support for OLMo 3 models (<code>Olmo3ForCausalLM</code>), for example
<code>allenai/Olmo-3-7B-Instruct</code>.</p>
</li>
<li class="">
<p>Added support for Qwen3-MoE models (<code>Qwen3MoeForCausalLM</code>), for example
<code>Qwen/Qwen3-30B-A3B-Instruct</code>, with multi-GPU tensor parallelism and FP8
quantization support.</p>
</li>
<li class="">
<p>DeepSeek improvements:</p>
<ul>
<li class="">Added support for the DeepSeekV3.2 architecture with multi-latent attention
and fused FP8 paged KV cache.</li>
<li class="">Added NVFP4 quantization support for DeepSeek-R1, including with expert
parallelism.</li>
<li class="">Expert parallelism now supports more than 32 local experts and no longer
requires NVSHMEM for single-node deployments.</li>
<li class="">Improved memory estimation for NVFP4-quantized models and EP communication
buffers.</li>
<li class="">Added FP4 quantization support for the DeepSeek MTP speculative decoding
module.</li>
<li class="">Various fixes: decode-only mode, missing <code>rope_scaling</code> config,
DeepSeek-V2-Lite gather-index OOB, re-enabled multi-GPU TP for
DeepSeek-V2-Lite-Chat.</li>
</ul>
</li>
<li class="">
<p>Removed legacy Gemma 3 multimodal implementation and the
<code>MODULAR_MAX_DISABLE_GEMMA3_VISION</code> environment variable.</p>
</li>
<li class="">
<p>Fixed multi-GPU tensor parallelism for GPT-OSS MoE models.</p>
</li>
<li class="">
<p>Common MAX models like Qwen 2.5 can now run on AMD RDNA consumer GPUs.</p>
</li>
<li class="">
<p>Improved Mistral3 text encoder performance by compiling hidden-state selection
and eliminating redundant GPU transfers.</p>
</li>
<li class="">
<p>Fixed prompt validator for Qwen2.5-VL models.</p>
</li>
<li class="">
<p>Fixed audio generator pipeline to restore audio generation support.</p>
</li>
<li class="">
<p>Fixed multi-GPU NVFP4 inference for Llama3.</p>
</li>
<li class="">
<p>Fixed Idefics3 chat template image placeholder ordering.</p>
</li>
<li class="">
<p>Added MXFP4 quantization support for GPT-OSS models (such as
<code>openai/gpt-oss-20b</code>).</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-max">MAX framework<a href="https://docs.modular.com/releases/v26.2/#26-2-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">
<p>Upgraded the bundled <code>libnvptxcompiler</code> from CUDA 12.9 to CUDA 13.1, which
requires NVIDIA GPU driver 580 or higher. This brings the latest bug fixes and
performance improvements from NVIDIA's PTX compiler, as well as fully
supporting new hardware like the DGX Spark and Jetson Thor.</p>
<p>To use MAX and Mojo with older NVIDIA drivers and
hardware, you can set the <code>MODULAR_NVPTX_COMPILER_PATH</code> environment
variable to point to a system <code>ptxas</code> binary, instead of using the bundled
<code>libnvptxcompiler</code> version.</p>
<p>The Mojo <code>DeviceContext()</code> constructor now checks NVIDIA driver compatibility
at creation time and provides a clear error message when the driver version
is too old, matching the behavior of the Python <code>Accelerator()</code> API.</p>
</li>
<li class="">
<p>Runtime GPU errors now include a Python source traceback, showing where
the failing operation was defined in your graph-building code. Build with
<code>MODULAR_MAX_DEBUG=True</code> to enable source note collection; when source notes
aren't available, error messages include a hint about how to enable them.</p>
</li>
<li class="">
<p>Added <code>MODULAR_DEBUG_DEVICE_ALLOCATOR</code> environment variable for debugging
GPU memory issues. Set to <code>uninitialized-poison</code> to fill buffers with
sentinel values (qNaN for floats, <code>0xCD</code> for others) to detect use of
uninitialized data, or <code>out-of-bounds</code> to enable redzone checks for
buffer overflows. Accepts a comma-separated list for multiple options.</p>
</li>
<li class="">
<p>Fixed a memory leak in CUDA graph execution where output buffers were not
freed between replays, causing GPU memory to grow over time during
sustained inference.</p>
</li>
<li class="">
<p>Fixed compilation cache misses when cross-compiling GPTQ and LoRA models
on machines without a GPU. Weight dtype casting now skips the actual data
conversion in virtual device mode, because only compilation metadata is
needed.</p>
</li>
<li class="">
<p>Enabled peer-to-peer device memory access for AMD HIP multi-GPU
configurations, enabling direct GPU-to-GPU memory transfers on AMD
hardware.</p>
</li>
<li class="">
<p>Fixed multi-GPU communication silently falling back to a slower transport on
systems where <code>rdma-core</code> is installed without dev packages (common in
production containers).</p>
</li>
<li class="">
<p>Fixed multi-GPU broadcast operations failing with "Broadcast currently
requires P2P access between GPUs," due to a regression in peer-to-peer
device access initialization.</p>
</li>
<li class="">
<p>Improved Hugging Face model downloads: gated repo errors now surface
clearly instead of showing a misleading "check the repo name" messages.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-max-serve">Inference server<a href="https://docs.modular.com/releases/v26.2/#26-2-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added image generation support via a new <code>/v1/responses</code> endpoint implementing
the <a href="https://www.openresponses.org/reference" target="_blank" rel="noopener noreferrer" class="">OpenResponses</a> API standard.
Enable it by adding <code>responses</code> to <code>MAX_SERVE_API_TYPES</code> (for example,
<code>MAX_SERVE_API_TYPES='["openai","responses"]'</code>). Currently supports FLUX
diffusion models. For more information, see the
<a class="" href="https://docs.modular.com/max/inference/image-generation/">image generation guide</a>.</p>
</li>
<li class="">
<p>Added <code>output_format</code> parameter to image generation requests, allowing clients
to choose JPEG, PNG, or WEBP output per request (default remains JPEG).</p>
</li>
<li class="">
<p>Overlap scheduling is now auto-enabled for select model architectures like
<code>LlamaForCausalLM_Legacy</code>, and is compatible with prefix caching. This reduces
CPU overhead by overlapping Python host code with GPU kernel execution. It's
currently incompatible with some features such as structured outputs and CPU
models. It's still experimental and you can disable it with
<code>--no-enable-overlap-scheduler --force</code>.</p>
</li>
<li class="">
<p>Speculative decoding improvements:</p>
<ul>
<li class="">Added typical-acceptance rejection sampling.</li>
<li class="">Added <code>rejection-sampling-strategy</code> option (<code>greedy</code> or <code>residual</code>) for
speculative decoding. Defaults to <code>residual</code>; use <code>greedy</code> for models
that pass hidden states.</li>
<li class="">Applied repetition/frequency/presence penalty sampling in EAGLE.</li>
<li class="">Enabled weight sharing between MTP draft and main model to reduce memory.</li>
<li class="">Added support for chunked prefill with EAGLE and MTP speculative decoding.</li>
<li class="">Fixed batch context length calculation for draft models.</li>
<li class="">Fixed Eagle penalty inputs being unconditionally applied.</li>
</ul>
</li>
<li class="">
<p>EAGLE speculative decoding now reports the draft token acceptance rate in
scheduler metrics output.</p>
</li>
<li class="">
<p>Added KV cache offloading: KV cache blocks can now spill from GPU to CPU
memory and disk when GPU memory is full, enabling larger effective cache
capacity and warm restarts. Includes
<a href="https://github.com/LMCache/LMCache" target="_blank" rel="noopener noreferrer" class="">LMCache</a> integration for sharing
KV cache across model instances via external storage (CPU, disk, Redis),
with multi-GPU tensor parallelism support.</p>
</li>
<li class="">
<p>CUDA graph capture is now auto-enabled for Llama models when
<code>max_batch_size</code> is set, reducing per-token latency. You can opt out with
<code>--no-device-graph-capture --force</code>.</p>
</li>
<li class="">
<p>Added FP8 quantization support for the KV cache, reducing KV cache memory
usage. Configure via <code>--kv-cache-format float8_e4m3fn</code> (also supports
<code>float32</code> and <code>bfloat16</code>).</p>
</li>
<li class="">
<p>Added configurable batch scheduling strategy for text generation via the
<code>MAX_SERVE_BATCH_PRIORITY</code> environment variable. It defines how the
scheduler prioritizes between prefill (context encoding) and decode
(token generation) when constructing batches. Options: <code>prefill_first</code>
(minimize time-to-first-token), <code>decode_first</code> (minimize inter-token
latency), <code>balanced</code> (adaptive based on global queue state), or
<code>per_replica</code> (each replica decides independently; default).</p>
</li>
<li class="">
<p>Diffusion models can now specify a default <code>num_inference_steps</code> per
architecture.</p>
</li>
<li class="">
<p>Added <code>--first-block-caching</code> flag to enable first-block caching (FBCache) for
diffusion models like FLUX, and <code>--residual-threshold</code> for the TaylorSeer
caching strategy. Both are configurable via <code>max serve</code> and <code>max generate</code>.</p>
</li>
<li class="">
<p>Enabled <code>logprobs</code> in chat completion responses, returning per-token
log probabilities.</p>
</li>
<li class="">
<p>Non-streaming requests are now cancelled when the client disconnects,
preventing zombie requests from consuming KV cache memory.</p>
</li>
<li class="">
<p>Improved streaming performance by buffering generated tokens and
detokenizing them in batches rather than one at a time, reducing CPU
overhead and improving GPU utilization.</p>
</li>
<li class="">
<p>Improved multi-GPU AllReduce performance by launching per-device
kernels in parallel async tasks instead of sequentially.</p>
</li>
<li class="">
<p>Fixed a server hang when a model worker process crashes before it finishes
initializing.</p>
</li>
<li class="">
<p>Fixed per-request seed handling in TopK/TopP sampling. Seeds are now
correctly applied per request instead of using a single seed for the
entire batch.</p>
</li>
<li class="">
<p>Fixed KV cache blocks not being released after offline text generation
(<code>generate()</code> / <code>generate_async()</code>), which could cause block exhaustion
during sustained inference.</p>
</li>
<li class="">
<p>Fixed three resource leaks in the disaggregated inference decode scheduler: KV
cache blocks leaked on request cancellation, replica load-balancing counter
drift over time, and a <code>KeyError</code> crash on stale prefill responses arriving
after cancellation.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v26.2/#26-2-max-cli" class="hash-link" aria-label="Direct link to 26-2-max-cli" title="Direct link to 26-2-max-cli" translate="no">​</a></h3>
<ul>
<li class="">Added the <code>--device-graph-capture</code> flag to enable CUDA graph capture for
serving, reducing per-token latency by replaying recorded GPU kernel launches.
Auto-enabled for Llama and DeepSeek V3; opt out with
<code>--no-device-graph-capture --force</code>.</li>
<li class="">Added the <code>--debug-verify-replay</code> flag to run eager launch-trace verification
before device graph replay, for debugging CUDA graph correctness issues.</li>
<li class="">Added the <code>--kv-cache-format</code> flag to set the KV cache data type at runtime.
Accepts <code>float32</code>, <code>bfloat16</code>, or <code>float8_e4m3fn</code> for FP8 quantized caching.</li>
<li class="">Added the <code>--lmcache-config-file</code> flag to enable
<a href="https://github.com/LMCache/LMCache" target="_blank" rel="noopener noreferrer" class="">LMCache</a>-based external KV cache
tiering. Point it at an LMCache YAML config to share KV cache blocks across
model instances via CPU, disk, or remote storage.</li>
<li class="">Added the <code>--reasoning-parser</code> flag to <code>max serve</code> to enable extraction of
model thinking/reasoning content into a separate <code>reasoning</code> field on the
OpenAI API response. Currently supports Kimi K2.5 (<code>kimi-k2</code>), with a
registry for adding additional parsers.</li>
<li class="">Added the <code>--rejection-sampling-strategy</code> flag to select the rejection
sampling method for speculative decoding. Options: <code>greedy</code>, <code>residual</code>
(default for standalone), or <code>typical-acceptance</code> (default for EAGLE/MTP).
Use <code>greedy</code> for models that pass hidden states.</li>
<li class=""><code>max benchmark</code> now uses the model's default temperature when none is
specified.</li>
<li class=""><code>max benchmark</code> no longer overrides <code>top_p</code> unless the user provides a value.</li>
<li class="">Removed the <code>--cache-strategy</code> flag.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-max-python">Python API<a href="https://docs.modular.com/releases/v26.2/#26-2-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p><code>Tensor.constant()</code> is deprecated. Use the <code>Tensor(data, dtype=..., device=...)</code> constructor directly, matching PyTorch's <code>torch.tensor()</code>
semantics. For example, replace <code>Tensor.constant([1.0, 2.0])</code> with
<code>Tensor([1.0, 2.0])</code>. <code>Tensor.constant()</code> will be removed in a future
release.</p>
</li>
<li class="">
<p><code>DeviceEvent</code> now accepts an <code>enable_timing=True</code> parameter to enable GPU
event timing. Use <code>start.elapsed_time(end)</code> to measure elapsed GPU time in
milliseconds between two timing-enabled events.</p>
</li>
<li class="">
<p>Added the <code>prod</code> op for computing the product of elements along an axis,
available as <code>max.graph.ops.prod</code>, <code>max.experimental.functional.prod</code>, and
<code>Tensor.prod()</code>.</p>
</li>
<li class="">
<p><code>Device.stats</code> now includes <code>graph_mem_reserved</code> and <code>graph_mem_used</code> fields
for device graph memory observability.</p>
</li>
<li class="">
<p><code>Module.compile()</code> now validates weight names, dtypes, and shapes before
loading, surfacing mismatches as Python errors instead of runtime
crashes during asynchronous host-to-device transfers.</p>
</li>
<li class="">
<p><code>InferenceSession</code> now automatically includes the CPU in its device list,
removing the need to manually add it when graphs include host-side values.</p>
</li>
<li class="">
<p>Added <code>max.graph.ops.broadcast</code> for distributed broadcast across devices.
Raises <code>ValueError</code> when <code>signal_buffers</code> is empty.</p>
</li>
<li class="">
<p>Added manual synchronization API (<code>DevicePinnedBuffer</code>, <code>DeviceEvent</code>) for
controlling buffer readiness and reducing stream synchronization overhead.</p>
</li>
<li class="">
<p><code>Tensor.cast()</code> is now idempotent for same-dtype casts.</p>
</li>
<li class="">
<p>Added <code>F.cond</code> to the experimental functional API for conditional execution.</p>
</li>
<li class="">
<p>Added fast path for <code>Tensor.to(device)</code> in eager mode.</p>
</li>
<li class="">
<p>Added <code>Dim</code>-based scalar dimension API to <code>Module.compile()</code>.</p>
</li>
<li class="">
<p><code>Module</code> is now device-aware via <code>to()</code> for unified device placement.</p>
</li>
<li class="">
<p><code>Module.load_state_dict()</code> now validates weight attribute names.</p>
</li>
<li class="">
<p>Algebraic dims and graph/custom op construction now works without an explicit
context manager, by using a global MLIR context. Threadpool-backed MAX paths
now scope worker-thread MLIR usage to the default context automatically.</p>
</li>
<li class="">
<p>Renamed <code>Float8Config</code> to <code>QuantConfig</code> (and related types/functions)
to reflect that the config now covers FP8, NVFP4, and MXFP4 quantization.</p>
</li>
<li class="">
<p>Renamed related public Python quantization APIs from <code>Float8*</code> names to
<code>Quant*</code> names, including <code>parse_float8_config()</code> to
<code>parse_quant_config()</code>, and the public <code>quant</code> modules in <code>max.nn</code> and
<code>max.pipelines.lib</code>.</p>
</li>
<li class="">
<p><code>max.diagnostics.gpu.BackgroundRecorder</code>'s sampling interval can now be
configured.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-breaking">Breaking changes<a href="https://docs.modular.com/releases/v26.2/#26-2-breaking" class="hash-link" aria-label="Direct link to Breaking changes" title="Direct link to Breaking changes" translate="no">​</a></h3>
<ul>
<li class="">
<p>Reorganized <code>max.nn</code> namespace. The graph-based neural network API has
been restored as the default <code>max.nn</code> namespace (previously located under
<code>max.nn.legacy</code>). The eager module API has moved from <code>max.nn</code> to
<code>max.nn.module_v3</code>. Additionally, <code>max.tensor</code>, <code>max.functional</code>, and
<code>max.random</code> have moved back under <code>max.experimental</code>
(<code>max.experimental.tensor</code>, <code>max.experimental.functional</code>,
<code>max.experimental.random</code>). Update imports accordingly.</p>
</li>
<li class="">
<p>Moved experimental APIs under <code>max.experimental</code>. Two additional packages
have moved under the <code>max.experimental</code> namespace to co-locate all
experimental APIs:</p>
<ul>
<li class="">
<p><code>max.torch</code> is now <code>max.experimental.torch</code>. Update imports from
<code>from max.torch import CustomOpLibrary, graph_op</code> to
<code>from max.experimental.torch import CustomOpLibrary, graph_op</code>.</p>
</li>
<li class="">
<p><code>max.nn.module_v3</code> is now <code>max.experimental.nn</code> (the <code>v3</code> suffix has been
dropped). Update imports from
<code>from max.nn.module_v3 import Module, Linear</code> to
<code>from max.experimental.nn import Module, Linear</code>.</p>
</li>
</ul>
</li>
<li class="">
<p>Removed <code>PipelineConfig.max_length</code>. The <code>max_length</code> parameter now resides at
the model configuration level as <code>MAXModelConfig.max_length</code> (accessible as
<code>config.model.max_length</code>). This change correctly places the parameter at the
model level since it describes model capacity (maximum sequence length the
model can process), not pipeline runtime behavior. Update all configurations
and code to use <code>model.max_length</code> instead of the removed <code>max_length</code> field
at the pipeline level.</p>
</li>
<li class="">
<p><code>PipelineModel</code> no longer accepts the <code>encoding</code> parameter. The
<code>encoding</code> parameter has been removed from <code>PipelineModel.__init__</code> and all
subclasses. The encoding is now automatically inferred from
<code>pipeline_config.model.quantization_encoding</code>. This change eliminates
redundant parameter passing and ensures a single source of truth for
quantization encoding configuration.</p>
</li>
<li class="">
<p>Device-graph APIs now require explicit caller-provided graph keys for
capture/replay/verification. Update calls from
<code>model.capture(*inputs)</code>, <code>model.replay(*inputs)</code>, and
<code>model.debug_verify_replay(*inputs)</code> to
<code>model.capture(graph_key, *inputs)</code>, <code>model.replay(graph_key, *inputs)</code>,
and <code>model.debug_verify_replay(graph_key, *inputs)</code>.</p>
</li>
<li class="">
<p>Removed <code>q_max_seq_len</code> from <code>KVCacheParams</code>; accepted via graph capture
instead.</p>
</li>
<li class="">
<p><code>MAXBaseModel</code> now uses <code>extra=forbid</code> and <code>strict=True</code>; configs with
unknown fields will be rejected.</p>
</li>
<li class="">
<p>Replaced <code>disable_auto_sync</code>/<code>mark_as_ready</code> with <code>DevicePinnedBuffer</code> and
<code>DeviceEvent</code> for pinned memory management.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-max-kernels">MAX kernels<a href="https://docs.modular.com/releases/v26.2/#26-2-max-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>Blackwell (SM100) GPU performance</strong>:</p>
<ul>
<li class="">Optimized Attention on SM100 by skipping unnecessary softmax
corrections when the row maximum change is small.</li>
<li class="">Fused epilogue into SM100 BF16 and FP8 matmul kernels.</li>
<li class="">Improved SM100 FP8 matmul dispatch for small M shapes (M &lt;= 128).</li>
<li class="">Fixed matmul kernel dispatch on SM100.</li>
<li class="">Added SM100 hardware-accelerated conv2d with TMA im2col and fused residual
epilogue for FLUX VAE.</li>
<li class="">Added batched BF16 matmul support for SM100.</li>
<li class="">Added <a href="https://arxiv.org/abs/2602.10718" target="_blank" rel="noopener noreferrer" class="">SnapMLA</a> implementation for
SM100 MLA decode.</li>
<li class="">Added FP8 tensorwise and block-scale MLA decode for SM100/B200.</li>
<li class="">Added FP8 MMA support for MLA prefill with blockwise scaling and K RoPE.</li>
<li class="">Enabled MLA attention for SM100 GPUs.</li>
<li class="">Enabled 64x256 N split MMA for B200 MLA decode (long context).</li>
<li class="">Used TMA for KV scale loads in attention kernels (SM100).</li>
</ul>
</li>
<li class="">
<p><strong>AMD GPU kernel improvements</strong>:</p>
<ul>
<li class="">Tuned and optimized GEMV split-K BF16 dispatch and kernel for AMD GPUs.</li>
<li class="">Enabled FP8 GEMV kernel on AMD GPUs.</li>
<li class="">Reduced K buffer bank conflicts in MHA prefill on AMD via swizzle.</li>
<li class="">Integrated AMD pingpong kernel with FP8 dispatch and fixed TP &gt; 1.</li>
<li class="">Fixed out-of-bounds masking and depths &gt; 256 on AMD RDNA GPUs.</li>
<li class="">Enabled rocSHMEM GDA backend with TCP bootstrap for multi-node AMD EP.</li>
</ul>
</li>
<li class="">
<p><strong>Grouped matmul improvements</strong> (SM100):</p>
<ul>
<li class="">Added MMA_N=64 support for 1D1D block-scaled grouped matmul.</li>
<li class="">Added 2SM support to structured 1D1D grouped matmul kernel.</li>
<li class="">Enabled swapAB for block-scaled grouped matmul and block-scaled matmul on
SM100.</li>
<li class="">Added tensor scale factor to block-scaled 1D1D grouped matmul.</li>
<li class="">Added bf16 scales support to blockwise FP8 grouped matmul.</li>
</ul>
</li>
<li class="">
<p><strong>DeepSeek kernel optimizations</strong>:</p>
<ul>
<li class="">Added BF16 MLA prefill/decode mega-kernel.</li>
<li class="">Enabled BF16 graph execution path for Multi-Latent Attention.</li>
<li class="">Enabled fused QKV projection for latent attention with RoPE.</li>
<li class="">Fused RoPE and RMSNorm into MLA custom ops.</li>
<li class="">Fused epilogue operations in DeepSeek BF16 matmul kernels.</li>
<li class="">Added fused dispatch and combine kernels for expert parallelism.</li>
<li class="">Enabled Mojo BF16 matmul kernels and FP4 kernels for DeepSeek shapes.</li>
<li class="">Fixed blockwise FP8 batched matmul for non-row-major layouts.</li>
</ul>
</li>
<li class="">
<p><strong>Multi-GPU distributed ops</strong>:</p>
<ul>
<li class="">Added fused allreduce + RMSNorm + FP8 kernel with residual path and 2-stage
allreduce for tensor-parallel workloads.</li>
<li class="">Added distributed scatter graph op for multi-GPU DP&gt;1 inference.</li>
<li class="">Fixed and optimized broadcast kernel for BF16/FP16 with multimem on GPU.</li>
<li class="">Fixed and optimized 2-stage broadcast kernel for multi-GPU.</li>
</ul>
</li>
<li class="">
<p><strong>FLUX kernel improvements</strong>: Autotuned cuDNN convolution algorithm selection
and cached results. Added multi-block GroupNorm GPU kernel. Enabled
high-performance Mojo matmul kernels for FLUX.2. Fixed grouped conv2d on GPU
incorrectly ignoring the <code>num_groups</code> parameter.</p>
</li>
<li class="">
<p><code>kbench</code> now runs benchmarks via shared library (<code>.so</code>) by default, reusing
persistent workers and CUDA contexts instead of spawning subprocesses.
Benchmark execution phase is ~10x faster (for example, 4.25 h → 0.4 h on a
tuning workload). Falls back to subprocess mode when profiling or using custom
exec wrappers.</p>
</li>
<li class="">
<p>Added MXFP4 dequant and matmul kernels.</p>
</li>
<li class="">
<p>Optimized FP4 matmul dispatch for Llama-style shapes and added FP4 GEMM
dispatch configs for additional shape coverage.</p>
</li>
<li class="">
<p>Used asynchronous FP4 quantization kernel for improved throughput.</p>
</li>
<li class="">
<p>Optimized Hopper matmul for M=256 and small M shapes via swapAB.</p>
</li>
<li class="">
<p>Improved GEMV kernel performance. Integrated Flash Infer TopK kernel for
improved sampling performance.</p>
</li>
<li class="">
<p>Improved layer normalization kernel performance.</p>
</li>
<li class="">
<p>Added FP8 support to FlashMLA decode kernel.</p>
</li>
<li class="">
<p>Fixed FP8 cast lambda epilogue in matmul.</p>
</li>
<li class="">
<p>Fixed NaN in MLA decode split-K kernel with causal masking.</p>
</li>
<li class="">
<p>Fixed warpgroup deadlock in MLA decode that could cause hangs on DeepSeek
models.</p>
</li>
<li class="">
<p>Fixed incorrect MoE expert routing caused by bitonic sort merge direction bug.</p>
</li>
<li class="">
<p>Fixed int8 matmul dispatch on ARM64.</p>
</li>
<li class="">
<p>Fixed Metal buffer tracking for sub-buffers and tensor slices on Apple
Silicon.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-2-mojo">Mojo language<a href="https://docs.modular.com/releases/v26.2/#26-2-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
including all GPU programming and <code>Layout</code>/<code>LayoutTensor</code> changes, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v26.1]]></title>
            <link>https://docs.modular.com/releases/v26.1/</link>
            <guid>https://docs.modular.com/releases/v26.1/</guid>
            <pubDate>Thu, 29 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-highlights">Highlights<a href="https://docs.modular.com/releases/v26.1/#26-1-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<p>The eager-style <a class="" href="https://docs.modular.com/max/api/python/tensor/#max.tensor.Tensor"><code>Tensor</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Module/"><code>Module</code></a> APIs are
now the primary API for model development, providing a PyTorch-like development
experience:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>from max import functional as F
from max.tensor import Tensor
from max.dtype import DType

x = Tensor.constant([1.0, -2.0, 3.0, -4.0, 5.0], dtype=DType.float16)
y = F.relu(x)
print(y)
# Tensor([1 0 3 0 5], dtype=DType.float16, device=Device(type=gpu,id=0))</code></pre></div></div>
<p>If you want explicit control over the graph structure, you can
still build models with the
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/"><code>Graph</code></a> APIs.</p>
<p>For more details, see the <a class="" href="https://docs.modular.com/max/develop/">model developer guide</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-docs">Documentation<a href="https://docs.modular.com/releases/v26.1/#26-1-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>The fully refactored <a href="https://llm.modular.com/" target="_blank" rel="noopener noreferrer" class="">MAX LLM book</a> is now designed
so the code you write in each exercise incrementally builds upon the last one,
until you've built an executable GPT-2 model with the MAX Python API.</p>
</li>
<li class="">
<p>New model developer guide introduces <a class="" href="https://docs.modular.com/max/develop/">eager-style
programming</a>, <a class="" href="https://docs.modular.com/max/develop/tensors/">tensor APIs</a>, and <a class="" href="https://docs.modular.com/max/develop/dtypes/">data
types</a>. Much more is coming soon.</p>
</li>
<li class="">
<p>New guide to <a class="" href="https://docs.modular.com/max/gpu-system-profiling/">profile MAX on GPUs with <code>nsys</code></a>.</p>
</li>
<li class="">
<p>Extended
<a href="https://github.com/modular/modular/tree/main/max/kernels/benchmarks/autotune#kbench-a-benchmarking-toolkit-for-mojo-kernels" target="_blank" rel="noopener noreferrer" class="">documentation for <code>kbench</code></a>,
a Python tool to benchmark, autotune, and analyze MAX kernel performance.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-models">MAX models<a href="https://docs.modular.com/releases/v26.1/#26-1-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p><a href="https://builds.modular.com/models/gemma-3-it/27B" target="_blank" rel="noopener noreferrer" class="">Gemma3</a> now supports
vision input (multimodal) in the 12B and 27B variants, including support for
local file paths and structured output. Learn more in the <a class="" href="https://docs.modular.com/max/inference/image-to-text/">image to text
guide</a>.</p>
</li>
<li class="">
<p>Added <code>Qwen/Qwen3-VL-4B-Instruct</code> and <code>Qwen/Qwen3-VL-2B-Instruct</code>
model architectures.</p>
</li>
<li class="">
<p>Removed Llama 3.2 Vision (<code>Llama-3.2-11B-Vision-Instruct</code>) architecture
support. Use other vision models such as Pixtral, InternVL, Qwen2.5-VL, and
Gemma3.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-max">MAX framework<a href="https://docs.modular.com/releases/v26.1/#26-1-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">All Python wheels are now hosted at <code>https://whl.modular.com/nightly/simple/</code>.
If using <code>uv</code>, change <code>--index-url</code> to <code>--index</code>, and if using <code>pip</code>, change
to <code>--extra-index-url</code>. For precise commands, see the
<a class="" href="https://docs.modular.com/max/packages/#install">install guide</a>.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-max-serve">Inference server<a href="https://docs.modular.com/releases/v26.1/#26-1-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Improved scheduling to achieve higher KVCache utilization and batch sizes. By
default, MAX now schedules a context encoding (CE) request only if KVCache
memory is less than 95% full <em>after</em> allocating blocks for that request or if
no active requests exist. You can adjust this watermark value (<code>0.95</code>) with
<a class="" href="https://docs.modular.com/max/cli/serve/#--kvcache-ce-watermark-kvcache_ce_watermark"><code>--kvcache-ce-watermark</code></a>.
Beware that increasing it causes more preemptions.</p>
</li>
<li class="">
<p>When running models with data-parallelism (DP), the semantics of max batch
size has changed. For example, when specifying <code>--data-parallel-degree 8</code> and
<code>--max-batch-size 32</code> it previously meant that each data-parallel replica
could have at most 4 requests for an aggregate max batch size of 32. We
changed this so that now the CLI flag specifies the max batch size per
replica. This means the aggregate max batch size of the above values is
8*32=256 requests. This aligns with vLLM and other inference engines.</p>
</li>
<li class="">
<p><code>--max-ce-batch-size</code> is now deprecated. The cap on batch size is now uniform
between context encoding and token generation phases of text generation. Use
<code>--max-batch-size</code> instead.</p>
</li>
<li class="">
<p>The API server now returns chunked tokens from the model worker, reducing
overhead and significantly improving throughput for small models and
decode-heavy workloads.</p>
</li>
<li class="">
<p>Server stats collection (<code>collect_server_stats</code>) is now enabled by default for
serving benchmarks.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v26.1/#26-1-max-cli" class="hash-link" aria-label="Direct link to 26-1-max-cli" title="Direct link to 26-1-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p>The <code>max generate</code> command now applies the model's chat template internally
when using <code>--prompt</code>. This more closely aligns with how users typically
prompt a model for testing and ensures special tokens are properly filtered
from output.</p>
</li>
<li class="">
<p>Added tracing flags to <code>max benchmark</code> for <code>nsys</code> profiling:</p>
<ul>
<li class=""><code>--trace</code>: Enable tracing of the benchmark run (currently NVIDIA GPUs only)</li>
<li class=""><code>--trace-file</code>: Path to save the trace file</li>
<li class=""><code>--trace-session</code>: Optional session name for tracing</li>
</ul>
<p>Requires the server to be run under <code>nsys launch</code>. Using
<code>--gpu-profiling detailed</code> is recommended.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-max-python">Python API<a href="https://docs.modular.com/releases/v26.1/#26-1-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>The eager-style <a class="" href="https://docs.modular.com/max/api/python/tensor/#max.tensor.Tensor"><code>Tensor</code></a> APIs are
now the primary API for model development, providing a PyTorch-like
development experience.</p>
<p>We moved the eager-style tensor APIs out of <code>experimental</code> and reorganized the
<code>max.nn</code> module to make the eager module system the primary API
(<code>nn.module_v3</code> is now <code>nn.module</code>).</p>
<p>The previous <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn</code></a> components are still available for
backward compatibility in <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.legacy</code></a>.</p>
</li>
<li class="">
<p>Renamed <code>max.driver.Tensor</code> to
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Buffer"><code>max.driver.Buffer</code></a> to clarify
that it represents a low-level memory buffer, not a tensor. The
<a class="" href="https://docs.modular.com/max/api/python/tensor/#max.tensor.Tensor"><code>max.tensor.Tensor</code></a> class remains
the primary tensor type.</p>
</li>
<li class="">
<p>Added <code>forward()</code> method to
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Module/"><code>Module</code></a> to compute the
output—it behaves the same as invoking the object as a callable (the
<code>__call__()</code> method).</p>
</li>
<li class="">
<p><code>accelerator_count()</code> now returns a non-zero value when called on an Apple
silicon system. This means you can use this code:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>device = CPU() if accelerator_count() == 0 else Accelerator()</code></pre></div></div>
<p>And it defaults to using the available Apple silicon GPU. As a consequence,
MAX graphs should in most cases be dispatched to run on Apple silicon GPUs.
Note that most MAX models do not yet work on Apple silicon GPUs due to
missing hardware-specific kernel pathways and other support, but this is an
important step towards enabling MAX more broadly on Apple silicon GPUs.</p>
</li>
<li class="">
<p>Added <code>max.nn.module.rope</code> containing rotary embedding implementations,
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.RotaryEmbedding/"><code>RotaryEmbedding</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/nn/"><code>TransposedRotaryEmbedding</code></a>.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/pipelines.lib.interfaces/#max.pipelines.lib.interfaces.ArchConfig"><code>ArchConfig</code></a>
and <code>ArchConfigWithKVCache</code>. Going forward, models that register with the MAX
architecture registry must define a config that implements this protocol</p>
</li>
<li class="">
<p>Added <code>ops.complex.mul</code> for multiplying complex-valued tensors</p>
</li>
<li class="">
<p>Added <code>calculate_virtual_device_count()</code>,
<code>calculate_virtual_device_count_from_cli()</code>, <code>load_max_buffer()</code> to
<a class="" href="https://docs.modular.com/max/api/python/driver/"><code>max.driver</code></a>.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.TokenBuffer"><code>TokenBuffer</code></a>
for token management.</p>
</li>
<li class="">
<p>Renamed <code>prefill_chunk_size</code> to <code>max_batch_input_tokens</code>
and <code>max_batch_context_length</code> to <code>max_batch_total_tokens</code>
in <a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.PipelineConfig/"><code>PipelineConfig</code></a>
and <code>TTSConfig</code> classes to better reflect their purpose in batch memory
management.</p>
<p>The corresponding CLI flags have also been renamed:
<code>--prefill-chunk-size</code> is now <code>--max-batch-input-tokens</code> and
<code>--max-batch-context-length</code> is now <code>--max-batch-total-tokens</code>.</p>
</li>
<li class="">
<p>Fixed <code>max.driver.Buffer.to(stream)</code> to not copy (it return reference to
the same tensor) when the stream is on the same device, even for GPU-pinned
host memory.</p>
</li>
<li class="">
<p>Removed deprecated <code>max.nn</code> convolution classes: <code>Conv2dV1</code>, <code>Conv1DV1</code>,
<code>Conv3DV1</code>. Use <code>Conv2d</code>, <code>Conv1D</code>, <code>Conv3D</code> instead.</p>
</li>
<li class="">
<p>Removed deprecated <code>max.nn</code> layer classes: <code>LinearV1</code>, <code>QLinearV1</code>,
<code>GPTQLinearV1</code>, <code>MLPV1</code>, <code>EmbeddingV1</code>, <code>LayerNormV1</code>, <code>RMSNormV1</code>. Use
<code>Linear</code>, <code>GPTQLinear</code>, <code>MLP</code>, <code>Embedding</code>, <code>LayerNorm</code>, <code>RMSNorm</code> instead.</p>
</li>
<li class="">
<p>Removed <code>max.engine.MojoValue</code></p>
</li>
<li class="">
<p>Removed the deprecated <code>custom_ops_path</code> parameter from
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession.load"><code>InferenceSession.load()</code></a>.
Instead use the <code>custom_extensions</code> parameter.</p>
</li>
<li class="">
<p>Added <code>graph.ops.shard_and_stack()</code></p>
</li>
<li class="">
<p>Removed unused <code>graph.weights.PytorchWeights</code></p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-max-kernels">MAX kernels<a href="https://docs.modular.com/releases/v26.1/#26-1-max-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">
<p>Improved performance for Hopper Matmul when using skinny M shapes. In
particular when M is between 2 and 64, we see a significant performance boost
for specific shapes ranging between 10 - 40%.</p>
</li>
<li class="">
<p>Added swapAB optimization to Hopper Matmul, performs B x A and does a
transposed
write to C. This helps when you need more granularity in the M dimension.</p>
</li>
<li class="">
<p>Refined <code>create_stream</code> API: all streams are now non-blocking (<code>blocking</code>
argument has been removed). Explicitly use <code>DeviceEvent</code> and <code>synchronize()</code>
wherever necessary.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-1-mojo">Mojo language<a href="https://docs.modular.com/releases/v26.1/#26-1-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
including all GPU programming and <code>Layout</code>/<code>LayoutTensor</code> changes, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.7]]></title>
            <link>https://docs.modular.com/releases/v25.7/</link>
            <guid>https://docs.modular.com/releases/v25.7/</guid>
            <pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-highlights">Highlights<a href="https://docs.modular.com/releases/v25.7/#25-7-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>The MAX Python API is now <a href="https://github.com/modular/modular/tree/main/max/python/max" target="_blank" rel="noopener noreferrer" class="">fully open-sourced on
GitHub</a>!</p>
<p>As we expand our <a href="https://builds.modular.com/?category=models" target="_blank" rel="noopener noreferrer" class="">model
repository</a>, we're making
significant progress on these APIs to simplify the effort to build
production-ready GenAI models in Python. Some APIs are still experimental,
but you can <a href="https://llm.modular.com/" target="_blank" rel="noopener noreferrer" class="">build an LLM with it today</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-docs">Documentation<a href="https://docs.modular.com/releases/v25.7/#25-7-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>New online book to
<a href="https://llm.modular.com/" target="_blank" rel="noopener noreferrer" class="">build an LLM from scratch with MAX</a>, using our
<strong>experimental model APIs</strong>. This is a guided lesson to building GPT-2 with
our Python API, explaining each component of the transformer model along the
way. Like the Python APIs, the book is a work in progress—please
<a href="https://github.com/modular/max-llm-book/issues" target="_blank" rel="noopener noreferrer" class="">report any issues in GitHub</a>.</p>
</li>
<li class="">
<p>All the planned parts of <a href="https://puzzles.modular.com/" target="_blank" rel="noopener noreferrer" class="">GPU Puzzles</a> are now
complete! Support for Apple silicon GPUs is also making <a href="https://puzzles.modular.com/howto.html#gpu-support-matrix" target="_blank" rel="noopener noreferrer" class="">steady
progress</a>.</p>
</li>
<li class="">
<p>Tutorials on docs.modular.com are now integrated into the
<a class="" href="https://docs.modular.com/max/intro/">Guides</a> section, indicated with a book icon in the left
navigation.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/cli/"><code>max</code> CLI docs</a> are now generated from
<a href="https://github.com/modular/modular/blob/modular/v25.7/max/python/max/entrypoints/pipelines.py" target="_blank" rel="noopener noreferrer" class="">the CLI source</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-models">MAX models<a href="https://docs.modular.com/releases/v25.7/#25-7-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">Gemma3 now supports logprobs.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-max">MAX framework<a href="https://docs.modular.com/releases/v25.7/#25-7-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">Added support for bfloat16 models running on GPUs with ARM-based CPU hosts,
such as Grace Hopper (GH200) and Grace Blackwell (GB200).</li>
<li class="">Updated minimum NVIDIA GPU driver requirement to 580.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v25.7/#25-7-max-cli" class="hash-link" aria-label="Direct link to 25-7-max-cli" title="Direct link to 25-7-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/cli/benchmark/"><code>max benchmark</code></a> can now run LoRA benchmarking for
supported models and target modules.</p>
</li>
<li class="">
<p><code>max benchmark --collect-gpu-stats</code> can now collect AMD
GPU statistics.</p>
</li>
<li class="">
<p><code>max serve --do-penalties</code> was renamed to <code>--enable-penalties</code> and enabled by
default. To disable penalties, you can specify
<a class="" href="https://docs.modular.com/max/cli/serve/#--enable-penalties---no-enable-penalties"><code>--no-enable-penalties</code></a></p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-max-python">Python API<a href="https://docs.modular.com/releases/v25.7/#25-7-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added support for Python 3.14.</p>
</li>
<li class="">
<p>Removed support for Python 3.9.</p>
</li>
<li class="">
<p>All MAX Python API modules are now <strong>open-sourced</strong>. In addition to those
previously released, we've added <code>driver</code>, <code>dtype</code>, <code>engine</code>, <code>experimental</code>,
<code>interfaces</code>, <code>kv_cache</code>, <code>mlir</code>, <code>nn</code>, <code>profiler</code>, <code>support</code>, <code>torch</code>, and
more <a href="https://github.com/modular/modular/tree/main/max/python/max" target="_blank" rel="noopener noreferrer" class="">in our GitHub
repo</a>.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/profiler/"><code>max.profiler</code></a> module with the
<a class="" href="https://docs.modular.com/max/api/python/profiler/#max.profiler.Tracer"><code>Tracer</code></a> class to create and
manage profiling spans based on runtime conditions, and the
[`@traced()] decorator to profile a whole function.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/diagnostics.gpu/"><code>max.diagnostics.gpu</code></a> APIs to expose
common GPU statistics as might be reported by <code>nvidia-smi</code> or <code>rocm-smi</code>.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/kv_cache/"><code>max.kv_cache</code></a> package, which provides
APIs to manage key-value caches used in transformer models. Not to be confused
with the existing <a class="" href="https://docs.modular.com/max/api/python/nn.kv_cache/"><code>max.nn.kv_cache</code></a> package
that includes kernels for KV caching.</p>
</li>
<li class="">
<p>Removed the <code>KVCacheManager</code> class and combined it with the single
<a class="" href="https://docs.modular.com/max/api/python/generated/max.kv_cache.PagedKVCacheManager/"><code>PagedKVCacheManager</code></a>
implementation. During merger, <code>prefetch()</code> was renamed <code>maybe_reserve()</code>.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.kv_cache.DummyKVCache/"><code>NullKVCacheManager</code></a>
for compile-only mode, which avoids GPU memory allocation when compiling
models without a physical GPU present.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/kv_cache/"><code>ResetPrefixCacheBackend</code></a>
and
<a class="" href="https://docs.modular.com/max/api/python/kv_cache/"><code>ResetPrefixCacheFrontend</code></a>
classes for coordinating prefix cache resets between frontend and backend
components.</p>
</li>
<li class="">
<p>Added more APIs for text-to-speech (TTS) models such as
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.AudioGenerationInputs"><code>AudioGenerationInputs</code></a>
and
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.AudioGenerationOutput"><code>AudioGenerationOutput</code></a></p>
</li>
<li class="">
<p>Changed
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.LoRAConfig/#max.pipelines.LoRAConfig.max_num_loras"><code>LoRAConfig.max_num_loras</code></a>
default to <code>1</code> (was <code>100</code>).</p>
</li>
<li class="">
<p>New <a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.RequestID"><code>RequestID</code></a> class
replaces previous type alias to provide better type safety and consistency
across the API.</p>
</li>
<li class="">
<p>Removed <code>InputContext</code> and replaced it with the modality-output specific
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.TextGenerationContext"><code>TextGenerationContext</code></a>
and
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.EmbeddingsContext"><code>EmbeddingsContext</code></a>.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.ImageMetadata"><code>ImageMetadata</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.VLMTextGenerationContext"><code>VLMTextGenerationContext</code></a>.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.comm</code></a> with <code>Allreduce</code> and
<code>Signals</code> for peer-to-peer communication in allreduce.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.gather"><code>ops.gather()</code></a> no longer
has a default <code>axis</code>, it must be specified explicitly (better matching PyTorch
and NumPy).</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/#max.graph.Graph.add_subgraph"><code>Graph.add_subgraph()</code></a>
has been updated to take a <code>devices</code> argument. This allows subgraphs to take
advantage of device-aware work scheduling.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-max-mojo">Mojo API<a href="https://docs.modular.com/releases/v25.7/#25-7-max-mojo" class="hash-link" aria-label="Direct link to Mojo API" title="Direct link to Mojo API" translate="no">​</a></h3>
<ul>
<li class="">Renamed the <code>tensor_internal</code> package to <code>tensor</code> and removed the
previous <code>tensor</code> stub—the API behaves the same but the <a class="" href="https://docs.modular.com/max/api/kernels/extensibility/tensor/">Mojo <code>tensor</code>
docs</a> moved.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-7-mojo">Mojo language<a href="https://docs.modular.com/releases/v25.7/#25-7-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
including all GPU programming and <code>Layout</code>/<code>LayoutTensor</code> changes, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.6.1]]></title>
            <link>https://docs.modular.com/releases/v25.6.1/</link>
            <guid>https://docs.modular.com/releases/v25.6.1/</guid>
            <pubDate>Fri, 10 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Fixes a latency regression due to a top-k algorithm change and a couple]]></description>
            <content:encoded><![CDATA[<p>Fixes a latency regression due to a top-k algorithm change and a couple
other benchmarking bugs.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.6]]></title>
            <link>https://docs.modular.com/releases/v25.6/</link>
            <guid>https://docs.modular.com/releases/v25.6/</guid>
            <pubDate>Mon, 22 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-highlights">Highlights<a href="https://docs.modular.com/releases/v25.6/#25-6-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>MAX delivers <strong>state-of-the-art performance on NVIDIA Blackwell</strong> (B200)!</p>
<p>We've been describing our Blackwell bring-up over a series of blog posts, and
we recently published
<a href="https://www.modular.com/blog/matrix-multiplication-on-blackwell-part-4---breaking-sota" target="_blank" rel="noopener noreferrer" class="">Part 4: Breaking SOTA</a>,
in which we share our latest matmul benchmarks compared to NVIDIA's cuBLAS
library.</p>
</li>
<li class="">
<p>MAX provides <strong>industry-leading performance on AMD MI355X</strong>!</p>
<p>In a matter of weeks, we got MAX running on the brand new MI255X system and
have already produced early benchmarks that go head-to-head with Blackwell.
If you have access to an MI355X, you can try it yourself today by following
our <a class="" href="https://docs.modular.com/max/get-started/">quickstart guide</a>.</p>
</li>
<li class="">
<p>Benchmarking endpoints is easier than ever before the new <a class="" href="https://docs.modular.com/max/cli/benchmark/"><code>max benchmark</code></a> command, which accepts YAML
configuration files so you can easily share and reproduce your benchmarks.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-docs">Documentation<a href="https://docs.modular.com/releases/v25.6/#25-6-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>Our new <a class="" href="https://docs.modular.com/max/get-started/">quickstart guide</a> lets you pick the model
architecture and size you want, and then shows you how to deploy it and run
our open-source benchmarking script, all from the <code>max</code> CLI.</p>
</li>
<li class="">
<p>We updated and simplified the <a class="" href="https://docs.modular.com/max/deploy/benchmark/">benchmarking
tutorial</a> to use the new <code>max benchmark</code>
command.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-models">MAX models<a href="https://docs.modular.com/releases/v25.6/#25-6-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">Added the
<a href="https://github.com/modular/modular/tree/modular/v25.6.0/max/pipelines/architectures/gpt_oss" target="_blank" rel="noopener noreferrer" class="">gpt-oss</a>
model architecture (GPU, bfloat16).
<a href="https://builds.modular.com/models/gpt-oss-20b-BF16/20B" target="_blank" rel="noopener noreferrer" class="">Try GPT-OSS now</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-max">MAX framework<a href="https://docs.modular.com/releases/v25.6/#25-6-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added device-aware work scheduling for AsyncRT: work items can now specify a
<code>deviceHint</code> to route execution to specific worker threads based on device
affinity, improving multi-device performance.</p>
</li>
<li class="">
<p>Improved code quality by enabling large set of RUFF lints, including
<a href="https://docs.astral.sh/ruff/rules/#flake8-annotations-ann" target="_blank" rel="noopener noreferrer" class="">flake8-annotations (ANN)</a>
which now enforces Python type annotations for new contributions.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-max-serve">Inference server<a href="https://docs.modular.com/releases/v25.6/#25-6-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added support for data parallelism in Llama models. To enable this feature,
use the <code>--data-parallel-degree</code> option:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max serve --model $MODEL_ID --data-parallel-degree 2 --devices gpu:0,1</code></pre></div></div>
</li>
<li class="">
<p>Metrics for each context encoding and token generation batch are now logged
to the console periodically. We can override the default frequency (3 seconds)
of such logs via setting the <code>MAX_SERVE_SCHEDULER_STATS_LOG_INTERVAL_S</code> flag.
For example, setting <code>MAX_SERVE_SCHEDULER_STATS_LOG_INTERVAL_S=0</code> will log
metrics for all batches.</p>
</li>
<li class="">
<p>Improved error messages when pulling a model that requires more RAM than
what's available or when there won't be enough RAM left for the KV cache.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v25.6/#25-6-max-cli" class="hash-link" aria-label="Direct link to 25-6-max-cli" title="Direct link to 25-6-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added the <code>max benchmark</code> subcommand that runs a suite of benchmarks and
collects performance metrics on a model server. This command provides
convenient packaging/installation for our open-source
<a href="https://github.com/modular/modular/tree/main/benchmark#benchmark-max" target="_blank" rel="noopener noreferrer" class=""><code>benchmark_serving.py</code></a>
script and accepts all the same options.</p>
</li>
<li class="">
<p>Added <code>--chat-template</code> to the CLI for passing a custom chat templates
defined in Jinja2 template files.</p>
</li>
<li class="">
<p>Renamed the <code>--allow-safetensors-weights-float32-to-bfloat16-cast</code> flag to
<code>--allow-safetensors-weights-fp32-bf6-bidirectional-cast</code>, which supports
automatic bidirectional dtype casts when needed.</p>
</li>
<li class="">
<p>The <code>max generate</code> command now supports <code>--top-k</code>, <code>--temperature</code>, and
<code>--seed</code> flags.</p>
</li>
<li class="">
<p>Changed <code>--num-warmups</code> behavior. Previously, it ran the model on the prompt
<code>N</code> times, generating until reaching a stop condition each time. Now it runs
the model for <code>N</code> steps, generating <code>N</code> new tokens as a warmup.</p>
</li>
<li class="">
<p>Added the <code>--model</code> option as a preferred alternative to <code>--model-path</code>. They
behave the same.</p>
</li>
<li class="">
<p>Deprecated <code>--pad-to-multiple-of</code>.</p>
</li>
<li class="">
<p>Removed the previously deprecated <code>--model-name</code>. Use <code>--served-model-name</code>
instead.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-max-python">Python API<a href="https://docs.modular.com/releases/v25.6/#25-6-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Removed the previously deprecated <code>KVCacheStrategy.CONTINUOUS</code> and all
associated classes (including <code>ContinuousBatchingKVCacheManager</code>).</p>
</li>
<li class="">
<p>Added <code>ops.fence</code>, a pure
identity operation that prevents the async runtime from reordering operations
across it. This operation is essential for implementing cross-device
synchronization.</p>
</li>
<li class="">
<p>Removed <code>PipelineConfig.max_new_tokens</code>. Use
<a class="" href="https://docs.modular.com/max/api/python/pipelines/#max.pipelines.SamplingParams"><code>SamplingParams.max_new_tokens</code></a>
instead.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.SamplingParams.logits_processors"><code>logits_processor</code></a>
to
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.SamplingParams"><code>SamplingParams</code></a>
for updating logits in-place during each step of token generation.</p>
</li>
<li class="">
<p>Added <code>generate()</code> to
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.TextGenerationPipeline/"><code>TextGenerationPipeline</code></a>
and
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.lib.StandaloneSpeculativeDecodingPipeline/"><code>StandaloneSpeculativeDecodingPipeline</code></a>,
a convenience method for getting text generations. <code>generate_async()</code> is
available for getting streamed outputs.</p>
</li>
<li class="">
<p>Renamed the <code>target_num_new_tokens</code> configuration parameter to
<code>prefill_chunk_size</code>
in
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.PipelineConfig/"><code>PipelineConfig</code></a>
and <code>TTSConfig</code> classes to better reflect its role in chunked prefill
operations.</p>
</li>
<li class="">
<p>Fixed <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.range"><code>ops.range</code></a> to respect
the <code>dtype</code> parameter when using <a class="" href="https://docs.modular.com/max/api/python/graph/"><code>Dim</code></a> objects as
inputs. Previously, the dtype was ignored and defaulted to int64.</p>
</li>
<li class="">
<p>Made the <code>devices</code> argument in
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession"><code>InferenceSession()</code></a>
required. To maintain the previous default behavior, use
<code>InferenceSession(devices=[CPU()])</code>.</p>
</li>
<li class="">
<p>Added an optional <code>logging</code> argument to
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession"><code>InferenceSession()</code></a>.
When set to <code>"op"</code>, this option enables operation launch output to stderr.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.lora</code></a>, providing
Low-Rank Adaptation (LoRA) support for parameter-efficient fine-tuning of
neural network models.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.moe</code></a>, implementing
Mixture of Experts (MoE) layers for scalable model architectures.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.sampling</code></a>,
containing advanced sampling methods including MinP and rejection sampling
techniques.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn.hooks</code></a>, providing
debugging and inspection hooks for neural network layers.</p>
</li>
<li class="">
<p>Added attention submodules
<a class="" href="https://docs.modular.com/max/api/python/nn.attention/"><code>max.nn.attention.mask_config</code></a>,
<a class="" href="https://docs.modular.com/max/api/python/nn.attention/"><code>max.nn.attention.multihead_attention</code></a>,
and
<a class="" href="https://docs.modular.com/max/api/python/nn.attention/"><code>max.nn.attention.multi_latent_attention</code></a>
for comprehensive attention mechanism configuration and implementation.</p>
</li>
<li class="">
<p>Moved some Mojo-related functionality to a new top-level <code>mojo</code> Python
namespace. Specifically, <code>max.mojo</code> (previously used for Mojo-Python interop),
some of <code>max.support</code>, and <code>max.entrypoints.mojo</code> now live under the <code>mojo</code>
namespace and are provided in the new <a href="https://mojolang.org/docs/manual/install#whats-included" target="_blank" rel="noopener noreferrer" class=""><code>mojo</code>
package</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-kernels">MAX kernels<a href="https://docs.modular.com/releases/v25.6/#25-6-kernels" class="hash-link" aria-label="Direct link to MAX kernels" title="Direct link to MAX kernels" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added a leaky ReLU activation function kernel.</p>
</li>
<li class="">
<p>Added a specialized <a class="" href="https://docs.modular.com/max/api/kernels/nn/normalization/rms_norm/">RMS norm</a>
function kernel for the common case of <code>cols=128</code>, <code>bfloat16</code>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-6-mojo">Mojo language<a href="https://docs.modular.com/releases/v25.6/#25-6-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
including all GPU programming changes, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.5]]></title>
            <link>https://docs.modular.com/releases/v25.5/</link>
            <guid>https://docs.modular.com/releases/v25.5/</guid>
            <pubDate>Tue, 05 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-highlights">Highlights<a href="https://docs.modular.com/releases/v25.5/#25-5-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>OpenAI-compatible batch API</strong>: The <a class="" href="https://docs.modular.com/max/rest-api/"><code>/v1/batches</code>
API</a> is now available with
<a class="" href="https://docs.modular.com/mammoth/">Mammoth</a>.</p>
<p>We recently announced a <a href="https://www.modular.com/blog/sf-compute" target="_blank" rel="noopener noreferrer" class="">partnership with SF
Compute</a> to make this API available
through their dynamic GPU pricing marketplace. Their Large Scale Inference
Batch API looks different from the <code>/v1/batches</code> API in Mammoth because it's
a superset.</p>
</li>
<li class="">
<p><strong>New <code>mojo</code> Conda package</strong>: For Mojo-specific projects that run on CPUs and
GPUs, you can now install the bare essentials with the <code>mojo</code> Conda package
that's less than 900 MB on disk. For example, this now works:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>pixi add mojo</code></pre></div></div>
<p>The <code>mojo</code> Python package is not available for pip/uv yet.</p>
<p>For a complete model-development and serving toolkit, you should still install
the <code>modular</code> package (which includes <code>mojo</code> as a dependency).</p>
</li>
<li class="">
<p><strong>Open-source graph APIs</strong>: We've added the <code>max.graph</code> Python APIs to our
<a href="https://github.com/modular/modular/tree/modular/v25.5.0/max/graph" target="_blank" rel="noopener noreferrer" class="">GitHub repo</a>.
We've made great strides in recent months to simplify these APIs that help you
build high-performance models you can
<a class="" href="https://docs.modular.com/max/develop/serve-custom-model-architectures/">serve with MAX</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-docs">Documentation<a href="https://docs.modular.com/releases/v25.5/#25-5-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>New
<a class="" href="https://docs.modular.com/max/develop/serve-custom-model-architectures/">Serve custom model architectures tutorial</a>,
with
<a href="https://github.com/modular/modular/tree/main/max/examples/custom-models" target="_blank" rel="noopener noreferrer" class="">example code on GitHub</a>.</p>
</li>
<li class="">
<p>New guide for <a class="" href="https://docs.modular.com/max/serve/lora-adapters/">using LoRA adapters with MAX</a>.</p>
</li>
<li class="">
<p>Updated the <a class="" href="https://docs.modular.com/max/deploy/local-to-cloud/">Deploy Llama 3 on GPU
tutorial</a> with instructions using
AMD MI300X (on Azure).</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/pixi/">Pixi basics</a>, which is where we redirect all the now-removed
Magic docs (see our <a href="https://forum.modular.com/t/migrating-from-magic-to-pixi/1530" target="_blank" rel="noopener noreferrer" class="">announcement migrating Magic to
Pixi</a>).</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-models">MAX models<a href="https://docs.modular.com/releases/v25.5/#25-5-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">Added support for
<a href="https://github.com/modular/modular/tree/modular/v25.5.0/max/pipelines/architectures/idefics3" target="_blank" rel="noopener noreferrer" class="">Idefics3</a>
model.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-max">MAX framework<a href="https://docs.modular.com/releases/v25.5/#25-5-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<ul>
<li class="">
<p>Removed all <code>torch</code> package dependencies.</p>
<ul>
<li class="">
<p>Reduces the total installation size of <code>modular</code> (including dependencies)
from 2.2 GB for CPUs and 6.5 GB for GPUs <strong>down to 1.5 GB</strong>, for all Python
packages. Conda packages pull additional system dependencies so sizes may
vary, but one example brings the size down from 9.8 GB to 2.0 GB.</p>
</li>
<li class="">
<p><code>pip install</code> no longer requires the <code>--extra-index-url https://download.pytorch.org/whl/cpu</code> option (which was to avoid installing
the GPU version of <code>torch</code> that has a lot of CUDA dependencies).</p>
</li>
<li class="">
<p><code>uv pip install</code> no longer requires the <code>--index-strategy unsafe-best-match</code>
option (which was to avoid package resolution issues with the above
<code>--extra-index-url</code> option).</p>
</li>
</ul>
</li>
<li class="">
<p>Removed HuggingFace fallback for model pipelines not natively supported in
MAX (<code>PipelineEngine.HUGGINGFACE</code>), because it's almost never used and it
creates significant tech debt.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-max-serve">Inference server<a href="https://docs.modular.com/releases/v25.5/#25-5-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/rest-api/#GET/health"><code>/health</code> endpoint</a> for service
readiness checks, used by tools like lm-eval to determine when the service is
ready to accept requests.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/serve/prefix-caching/">Prefix caching</a> now uses a Mojo token hashing
operation. Previously we used the <code>hash()</code> method from the Python stdlib.
However, this resulted in noticeable CPU overhead and reduced GPU utilization.
In this release, we migrated the token hashing operation to an accelerated
Mojo implementation.</p>
</li>
<li class="">
<p>Re-implemented the OpenAI API's <code>logprobs</code> and <code>echo</code> request
parameters to eliminate an expensive device transfer.
The <code>--enable-echo</code> flag, which previously incurred a significant performance
penalty, is now 9-12x faster.</p>
</li>
<li class="">
<p>Added support for <code>file://</code> URIs in image inputs for multimodal models. Local
file access is controlled via the <code>MAX_SERVE_ALLOWED_IMAGE_ROOTS</code> environment
variable, which specifies a list of allowed root directories. Files are read
asynchronously using aiofiles for better performance under high load.</p>
</li>
<li class="">
<p>Improved <a class="" href="https://docs.modular.com/max/serve/function-calling/">function calling</a> (tool use) to more
reliably extract JSON tool calling responses for Llama models in an
OpenAI-compatible format.</p>
</li>
<li class="">
<p>Switched from XGrammar to
<a href="https://github.com/guidance-ai/llguidance" target="_blank" rel="noopener noreferrer" class="">llguidance</a> for generating
structured output (constrained decoding).</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v25.5/#25-5-max-cli" class="hash-link" aria-label="Direct link to 25-5-max-cli" title="Direct link to 25-5-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added <code>--vision-config-overrides</code> CLI option to override
vision model configuration parameters. For example, to decrease InternVL's
maximum dynamic patches from 12 to 6:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max serve --model-path OpenGVLab/InternVL3-38B-Instruct \
  --vision-config-overrides '{"max_dynamic_patch": 6}'</code></pre></div></div>
</li>
<li class="">
<p>Removed <code>--ignore-eos</code> CLI argument. The full set of OpenAI chat and
completion sampling parameters are now supported in the http requests. As
such, the parameter can just be set via the http payload.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-max-python">Python API<a href="https://docs.modular.com/releases/v25.5/#25-5-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/interfaces/"><code>max.interfaces</code></a> module. This module
should serve as a relatively import free module to hold all shared interfaces
across the MAX stack. Slowly we will be moving common interfaces to this
module. So far, we've moved the following from <code>max.pipelines.core</code>:</p>
<ul>
<li class="">
<p>Moved <code>TextGenerationStatus</code>, <code>TextResponse</code>, <code>TextGenerationResponse</code>,
<code>InputContext</code>, and <code>PipelineTask</code> into <code>max.interfaces</code>.</p>
</li>
<li class="">
<p>Moved all <code>TokenGeneratorRequest</code>-prefixed objects into <code>max.interfaces</code>
and renamed with the <code>TextGenerationRequest</code> prefix.</p>
</li>
<li class="">
<p>Moved <code>TextGenerationStatus</code> to
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.GenerationStatus"><code>GenerationStatus</code></a>.</p>
</li>
<li class="">
<p>Moved <code>TextResponse</code> and <code>TextGenerationResponse</code> to
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.TextGenerationOutput"><code>TextGenerationOutput</code></a>.</p>
</li>
<li class="">
<p>Moved <code>EmbeddingsResponse</code> to
<a class="" href="https://docs.modular.com/max/api/python/interfaces/#max.interfaces.EmbeddingsOutput"><code>EmbeddingsOutput</code></a>.</p>
</li>
</ul>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.scatter_nd"><code>ops.scatter_nd</code></a>
operation for scattering updates into a tensor at specified indices.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.avg_pool2d"><code>ops.avg_pool2d</code></a>
and <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.max_pool2d"><code>ops.max_pool2d</code></a>.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/torch/#max.torch.graph_op"><code>max.torch.graph_op</code></a>
interface to make it simple to embed larger MAX computations and models inside
PyTorch. These can use <code>max.nn</code> modules internally and may be used within
<code>torch.nn</code> modules, allowing the use of MAX subcomponents for access to our
high performance graph compiler and Mojo kernel library.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>import torch
import numpy as np
import max
from max.dtype import DType
from max.graph import ops

@max.torch.graph_op
def max_grayscale(pic: max.graph.TensorValue):
    scaled = pic.cast(DType.float32) * np.array([0.21, 0.71, 0.07])
    grayscaled = ops.sum(scaled, axis=-1).cast(pic.dtype)
    # max reductions don't remove the dimension, need to squeeze
    return ops.squeeze(grayscaled, axis=-1)

@torch.compile
def grayscale(pic: torch.Tensor):
    output = pic.new_empty(pic.shape[:-1])  # Remove color channel dimension
    max_grayscale(output, pic)  # Call as destination-passing style
    return output

img = (torch.rand(64, 64, 3, device=device) * 255).to(torch.uint8)
result = grayscale(img)</code></pre></div></div>
</li>
<li class="">
<p>Moved <code>AlgebraicDim</code>, <code>Dim</code>, <code>StaticDim</code>, and <code>SymbolicDim</code> out of <code>max.type</code>
and into <a class="" href="https://docs.modular.com/max/api/python/graph/"><code>max.graph.dim</code></a>. You can still import
them directly from <code>max.graph</code>.</p>
</li>
<li class="">
<p>Moved <code>Shape</code> out of <code>max.type</code> and into
<a class="" href="https://docs.modular.com/max/api/python/graph/"><code>max.graph.shape</code></a>. You can still import it
directly from <code>max.graph</code>.</p>
</li>
<li class="">
<p>Removed the ability to pass Python objects into models and have them returned
as Mojo <code>PythonObject</code> types in the kernels.</p>
</li>
<li class="">
<p>Removed <code>RandomWeights</code>.</p>
</li>
<li class="">
<p>Removed <code>Model.execute_legacy()</code>. Instead use the
standard <a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.execute"><code>execute()</code></a> or
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.__call"><code>__call__()</code></a> methods.</p>
</li>
<li class="">
<p>Removed TorchScript-related helper functions and APIs, including support for
<code>.pt</code> TorchScript files in custom extensions.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-5-mojo">Mojo language<a href="https://docs.modular.com/releases/v25.5/#25-5-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools,
including all GPU programming changes, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.4]]></title>
            <link>https://docs.modular.com/releases/v25.4/</link>
            <guid>https://docs.modular.com/releases/v25.4/</guid>
            <pubDate>Wed, 18 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-highlights">Highlights<a href="https://docs.modular.com/releases/v25.4/#25-4-highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>AMD GPUs are officially supported!</strong></p>
<p>You can now deploy MAX with acceleration on AMD MI300X and MI325X GPUs, using
the same code and container that works on NVIDIA GPUs. For the first time, you
can build portable, high-performance GenAI deployments that run on any
platform without vendor lock-in or platform-specific optimizations.</p>
<p>For more details, including benchmarks, see our
<a href="https://www.modular.com/blog/modular-x-amd-unleashing-ai-performance-on-amd-gpus" target="_blank" rel="noopener noreferrer" class="">Modular + AMD blog post</a>.</p>
</li>
<li class="">
<p><strong>Now accepting GPU kernel contributions</strong></p>
<p>Last month, we open-sourced the code for the CPU and GPU kernels that power
the MAX framework, and now we're accepting contributions! For information
about how to contribute and the sort of kernels most interesting to us, see
the
<a href="https://github.com/modular/modular/blob/main/max/kernels/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">MAX AI kernels contributing guide</a>.</p>
</li>
<li class="">
<p><strong>Preview: Mojo interoperability from Python</strong></p>
<p>This release includes an early version of a new Python-to-Mojo
interoperability API. You can now write just the performance-critical parts
your code in Mojo and call it from Python just like you're importing another
Python library. Check out our docs to <a href="https://mojolang.org/docs/manual/python/mojo-from-python" target="_blank" rel="noopener noreferrer" class="">call Mojo from
Python</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-docs">Documentation<a href="https://docs.modular.com/releases/v25.4/#25-4-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<p>We've redesigned <a href="https://builds.modular.com/" target="_blank" rel="noopener noreferrer" class="">builds.modular.com</a> and
<a href="https://docs.modular.com/" target="_blank" rel="noopener noreferrer" class="">docs.modular.com</a> with a unified top navigation bar
that so you can more easily discover all the available docs and code resources.</p>
<p>New docs:</p>
<ul>
<li class="">
<p><a href="https://puzzles.modular.com/introduction.html" target="_blank" rel="noopener noreferrer" class="">GPU Puzzles</a>: Several
new puzzles, including: 1D convolution op, softmax op, attention op,
embedding op, kernel fusion, custom backward pass, GPU functional programming
patterns, and warp fundamentals.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/coding-assistants/">Using AI coding assistants guide</a>: Learn how to use
large language models (LLMs) and coding assistants (such as Cursor and Claude
Code) to accelerate your development with Modular.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/build-an-mlp-block/">Build an MLP block as a graph module tutorial</a>:
Learn how to create reusable <code>Module</code> components in your MAX graphs.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/custom-kernels-pytorch/">Write custom ops for PyTorch
tutorial</a> (Beta feature): Learn to write
high-performance GPU kernels for your PyTorch models with Mojo.</p>
</li>
<li class="">
<p><a href="https://github.com/modular/modular/blob/main/max/docs/kernel-profiling.md" target="_blank" rel="noopener noreferrer" class="">Profile MAX kernel performance</a>:
Learn how to set up Nsight Compute to profile your Mojo-based kernels on
NVIDIA GPUs.</p>
</li>
</ul>
<p>Major updates:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/build-custom-ops/">Build custom ops for GPUs tutorial</a>:
Now includes how to write hardware-specific functions for CPUs and GPUs.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/custom-ops-matmul/">Optimize a matrix multiply custom op
tutorial</a>: Migrated from a Recipe with
revisions to help you improve the performance of your GPU custom ops.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-models">MAX models<a href="https://docs.modular.com/releases/v25.4/#25-4-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added the OLMo 2 model architecture
(<a href="https://github.com/modular/modular/tree/modular/v25.4.0/max/pipelines/architectures/olmo2" target="_blank" rel="noopener noreferrer" class=""><code>olmo2</code></a>).</p>
<p><a href="https://builds.modular.com/models/OLMo-2-1124/7B" target="_blank" rel="noopener noreferrer" class="">Try OLMo 2 now</a>.</p>
</li>
<li class="">
<p>Added Google's Gemma 3 multimodal model architecture
(<a href="https://github.com/modular/modular/tree/modular/v25.4.0/max/pipelines/architectures/gemma3" target="_blank" rel="noopener noreferrer" class=""><code>gemma3multimodal</code></a>).</p>
<p><a href="https://builds.modular.com/models/gemma-3-it/1B" target="_blank" rel="noopener noreferrer" class="">Try Gemma3 now</a>.</p>
</li>
<li class="">
<p>Added the Qwen 3 model architecture
(<a href="https://github.com/modular/modular/tree/modular/v25.4.0/max/pipelines/architectures/qwen3" target="_blank" rel="noopener noreferrer" class=""><code>qwen3</code></a>).</p>
<p><a href="https://builds.modular.com/models/Qwen3/1.7B" target="_blank" rel="noopener noreferrer" class="">Try Qwen3 now</a>.</p>
</li>
<li class="">
<p>Added the InternVL3 model architecture
(<a href="https://github.com/modular/modular/tree/modular/v25.4.0/max/pipelines/architectures/internvl" target="_blank" rel="noopener noreferrer" class=""><code>internvl</code></a>).
This is still a work in progress.</p>
</li>
<li class="">
<p>GGUF quantized Llamas (q4_0, q4_k, and q6_k) are now supported with paged
KVCache strategy.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-max">MAX framework<a href="https://docs.modular.com/releases/v25.4/#25-4-max" class="hash-link" aria-label="Direct link to MAX framework" title="Direct link to MAX framework" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-max-serve">Inference server<a href="https://docs.modular.com/releases/v25.4/#25-4-max-serve" class="hash-link" aria-label="Direct link to Inference server" title="Direct link to Inference server" translate="no">​</a></h3>
<ul>
<li class="">
<p>Inflight batching no longer requires chunked prefill.</p>
</li>
<li class="">
<p>Expanded token sampling logic, including top_k, min_p, min_new_tokens,
temperature.</p>
</li>
<li class="">
<p>Extended sampling configuration to be per-request, e.g. different requests
can ask for different sampling hyperparameters.</p>
</li>
<li class="">
<p>Removed support for TorchScript and torch MLIR models.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v25.4/#25-4-max-cli" class="hash-link" aria-label="Direct link to 25-4-max-cli" title="Direct link to 25-4-max-cli" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added the <code>--use-subgraphs</code> flag to <code>max generate</code> to allow for the use of
subgraphs in the model.</p>
</li>
<li class="">
<p>Added the <code>--port</code> option to specify the port number with the <code>max serve</code>
command.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-max-python">Python API<a href="https://docs.modular.com/releases/v25.4/#25-4-max-python" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Lots of new APIs in the <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn</code></a> package.</p>
</li>
<li class="">
<p>Added <code>max.mojo.importer</code> module to import Mojo code into Python. See the docs
for
<a href="https://mojolang.org/docs/manual/python/mojo-from-python" target="_blank" rel="noopener noreferrer" class="">calling Mojo from Python</a>.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/#max.graph.Graph.add_subgraph"><code>Graph.add_subgraph()</code></a>
to allow for the addition of a subgraph to a graph.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Module/#max.nn.Module.build_subgraph"><code>Module.build_subgraph()</code></a>
to allow for the creation of a subgraph for a layer that inherits from
<code>Module</code>.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.call"><code>call</code></a> op
which allows for the execution of a subgraph.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.fold"><code>fold</code></a> op for
combining sliding blocks into a larger tensor.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.KernelLibrary/"><code>KernelLibrary</code></a>
as an argument type for the
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/"><code>Graph</code></a> constructor.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.quantization.QuantizationConfig/"><code>QuantizationConfig</code></a>
to specify quantization parameters for ops such as
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.qmatmul"><code>qmatmul()</code></a>.</p>
</li>
<li class="">
<p>Added the <code>strict</code> argument to the
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Module/#max.nn.Module.load_state_dict"><code>Module.load_state_dict()</code></a>
method. When <code>strict=True</code> (default), an error is raised if the <code>state_dict</code>
contains unused keys. When <code>strict=False</code>, extra keys are ignored. This helps
model developers identify missing implementations in their models.</p>
</li>
<li class="">
<p>Added audio generator APIs for text-to-speech models (such as
<code>AudioGenerator</code>,
<code>PipelineAudioTokenizer</code>,
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.TTSContext/"><code>TTSContext</code></a>,
and others). This is still a work in progress.</p>
</li>
<li class="">
<p>The
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.masked_scatter"><code>ops.masked_scatter()</code></a>
function now requires naming the <code>out_dim</code> explicitly as it is data-dependent.
For example:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>ops.masked_scatter(
    inputs_embeds, video_mask, video_embeds, out_dim="unmasked_inputs"
)</code></pre></div></div>
</li>
<li class="">
<p>Deprecated the <code>CONTINUOUS</code> KVCache strategy
(<code>KVCacheStrategy</code>).
Please use <code>PAGED</code> KVCache strategy instead.</p>
</li>
<li class="">
<p>Removed the <code>Settings</code> argument from
<a class="" href="https://docs.modular.com/max/api/python/entrypoints/#max.entrypoints.llm.LLM"><code>LLM</code></a> constructor. The
server is now automatically configured in the background without consuming an
HTTP port.</p>
</li>
<li class="">
<p>Removed <code>Graph.unique_symbolic_dim()</code>.</p>
</li>
<li class="">
<p>Removed <code>max_to_torch_type()</code> and <code>torch_to_max_type()</code> and replaced them with
<a class="" href="https://docs.modular.com/max/api/python/dtype/#max.dtype.DType.to_torch"><code>DType.to_torch()</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/dtype/#max.dtype.DType.from_torch"><code>DType.from_torch()</code></a>,
respectively. This aligns with the corresponding NumPy methods.</p>
</li>
<li class="">
<p>Removed <code>stats_report</code> property and <code>reset_stats_report</code> method from
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession"><code>InferenceSession</code></a>. This
functionality was primarily used for internal PyTorch debugging and is no
longer needed.</p>
</li>
<li class="">
<p>Removed the naive KVCache (<code>nn.kv_cache.naive_cache</code>).</p>
</li>
<li class="">
<p>Removed <code>nn.attention</code> and <code>nn.naive_attention_with_rope</code>.</p>
</li>
<li class="">
<p>Renamed <code>ops.select</code> to
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.where"><code>ops.where</code></a>. This matches the
name of the similar operation in torch and numpy.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-max-mojo">Mojo API<a href="https://docs.modular.com/releases/v25.4/#25-4-max-mojo" class="hash-link" aria-label="Direct link to Mojo API" title="Direct link to Mojo API" translate="no">​</a></h3>
<ul>
<li class="">
<p><a href="https://mojolang.org/docs/layout/layout_tensor/LayoutTensor/" target="_blank" rel="noopener noreferrer" class=""><code>LayoutTensor</code></a>
now has a
<code>size</code> method to get the total number of elements.</p>
</li>
<li class="">
<p>Following our <a class="" href="https://docs.modular.com/releases/#25-3-engine-mojo-api">previous deprecation</a> of
the Mojo <code>max.driver</code>, <code>max.graph</code> and <code>max.engine</code> APIs, we've removed them
from the package and API docs.</p>
</li>
</ul>
<p>As a result, we've also removed Mojo <code>max.tensor</code> APIs (including <code>Tensor</code>,
<code>TensorShape</code>, and <code>TensorSpec</code>). You can replace any use with
<a href="https://mojolang.org/docs/layout/layout_tensor/LayoutTensor/" target="_blank" rel="noopener noreferrer" class=""><code>LayoutTensor</code></a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-custom-ops">Custom ops<a href="https://docs.modular.com/releases/v25.4/#25-4-custom-ops" class="hash-link" aria-label="Direct link to Custom ops" title="Direct link to Custom ops" translate="no">​</a></h3>
<ul>
<li class="">
<p>Improved error messages when custom op parameters are provided with values
that don't have the proper type.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.custom"><code>ops.custom()</code></a> function
now requires a <code>device</code> argument to specify where the operation should
execute. This avoids the need for custom ops to infer their execution device,
which can be error-prone.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/torch/"><code>max.torch</code></a> module with the
<code>CustomOpLibrary</code> class for using custom Mojo kernels from PyTorch. For
example, with a custom <code>grayscale</code> operation written in Mojo:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>@register("grayscale")
struct Grayscale:
    @staticmethod
    fn execute[
        # The kind of device this is running on: "cpu" or "gpu"
        target: StaticString,
    ](
        img_out: OutputTensor[dtype = DType.uint8, rank=2],
        img_in: InputTensor[dtype = DType.uint8, rank=3],
        ctx: DeviceContextPtr,
    ) raises:
        ...</code></pre></div></div>
<p>You can load it with PyTorch like so:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>from max.torch import CustomOpLibrary

op_library = CustomOpLibrary("path/to/custom.mojopkg")

@torch.compile(backend=backend)
def grayscale(pic):
    result = pic.new_empty(pic.shape[:-1])
    op_library.grayscale(result, pic)
    return result

img = (torch.rand(64, 64, 3) * 255).to(torch.uint8)
result = grayscale(img)</code></pre></div></div>
<p>See our</p>
<p><a class="" href="https://docs.modular.com/max/develop/custom-kernels-pytorch/">tutorial to write custom ops for PyTorch</a>,
and our</p>
<p><a href="https://github.com/modular/modular/tree/main/max/examples/pytorch_custom_ops" target="_blank" rel="noopener noreferrer" class="">PyTorch custom operation examples</a>,
which range from a very basic "hello world" to the replacement of a layer in a
full model.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-gpu-programming">GPU programming<a href="https://docs.modular.com/releases/v25.4/#25-4-gpu-programming" class="hash-link" aria-label="Direct link to GPU programming" title="Direct link to GPU programming" translate="no">​</a></h3>
<ul>
<li class="">
<p>Full support for AMD CDNA3 datacenter GPUs is now available! Specifically,
MI300X and MI325X.</p>
</li>
<li class="">
<p>Added initial support for programming on AMD RDNA3 consumer GPUs. Basic tuning
parameters have been specified for AMD Radeon 780m integrated GPUs. (AMD RDNA3
support is for GPU programming only; AI models are still missing some GPU
kernels for this architecture.) For details, see the
<a class="" href="https://docs.modular.com/max/packages/#gpu-compatibility">GPU requirements</a>.</p>
</li>
<li class="">
<p>Now accepting CPU and GPU kernel contributions. See the
<a href="https://github.com/modular/modular/blob/main/max/kernels/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">MAX AI kernels contributing guide</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-4-mojo">Mojo language<a href="https://docs.modular.com/releases/v25.4/#25-4-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<p>For all the updates to the Mojo language, standard library, and tools, see the
<a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.3]]></title>
            <link>https://docs.modular.com/releases/v25.3/</link>
            <guid>https://docs.modular.com/releases/v25.3/</guid>
            <pubDate>Tue, 06 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[✨ Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-highlights">✨ Highlights<a href="https://docs.modular.com/releases/v25.3/#25-3-highlights" class="hash-link" aria-label="Direct link to ✨ Highlights" title="Direct link to ✨ Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>You can now <strong>install Modular APIs and tools with pip</strong>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>pip install modular \
  --index-url https://download.pytorch.org/whl/cpu</code></pre></div></div>
<p>This installs the <code>max</code> CLI, <code>max</code> Python library, <code>mojo</code> CLI, and Mojo
libraries. However, the Mojo LSP and debugger are currently not included.</p>
<p>We use the <code>--index-url</code> argument to ensure that <code>torch</code> installs its CPU
dependencies only, thus avoiding a lot of unnecessary GPU packages. This is a
temporary workaround until we can remove our dependency on <code>torch</code>.</p>
</li>
<li class="">
<p>We <strong>open-sourced the MAX AI kernels</strong> and the rest of the <strong>Mojo standard
library</strong>!</p>
</li>
</ul>
<p>The
<a href="https://mojolang.org/docs/lib#max-ai-kernels-library" target="_blank" rel="noopener noreferrer" class="">MAX AI kernels library</a>
is a new Mojo API for writing high-performance and portable programs across CPU
and GPU, but it's also
<a href="https://github.com/modular/modular/tree/main/max/kernels/src" target="_blank" rel="noopener noreferrer" class="">the source code for our CPU/GPU kernels</a>.
You can now see the Mojo code we use in MAX to power GenAI workloads on CPUs and
GPUs.</p>
<p>Just like the Mojo standard library, these kernels are open source under the
Apache 2.0 License with LLVM exceptions. Plus, the rest of the Mojo standard
library is also <a href="https://github.com/modular/modular/tree/main/mojo/std/src" target="_blank" rel="noopener noreferrer" class="">now open source in
GitHub</a>.</p>
<ul>
<li class="">
<p><strong>Learn to program GPUs</strong> with
<a href="https://puzzles.modular.com/" target="_blank" rel="noopener noreferrer" class="">Mojo GPU Puzzles</a>!</p>
<p>This is a brand new site that offers a hands-on guide to mastering GPU
programming with Mojo. Starting from basic concepts, you'll learn step-by-step
how to program for GPUs by solving increasingly challenging puzzles.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-docs">Documentation<a href="https://docs.modular.com/releases/v25.3/#25-3-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<p>We've restructured the documentation to unify MAX and Mojo documentation
under the Modular Platform. We believe this improves content discovery with a
simplified navigation and helps unify the platform story as a whole.</p>
<p>We've also added the following new docs:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/rest-api/">REST API reference</a>: Although it's not a new API (our
serving library has supported OpenAI APIs for the last few versions), this
now shows precisely which endpoints and body parameters we support.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/serve/speculative-decoding/">Speculative decoding</a>: An introduction to
using speculative decoding to reduce latency for LLMs. This feature is still
in development.</p>
</li>
<li class="">
<p>Offline inference: An introduction to our
Python API for running inference with an LLM locally (without sending requests
to a serving endpoint).</p>
</li>
<li class="">
<p><a href="https://mojolang.org/docs/manual/layout/layouts" target="_blank" rel="noopener noreferrer" class="">Introduction to layouts</a>:
A guide to working
with dense multidimensional arrays on CPUs and GPUs, using new Mojo <code>layout</code>
types that abstract-away complex memory layout patterns.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-max-cli"><code>max</code> CLI<a href="https://docs.modular.com/releases/v25.3/#25-3-max-cli" class="hash-link" aria-label="Direct link to 25-3-max-cli" title="Direct link to 25-3-max-cli" translate="no">​</a></h2>
<ul>
<li class="">
<p>Renamed the <code>max-pipelines</code> CLI tool to <code>max</code>. We recommend re-installing
it as shown in the <a class="" href="https://docs.modular.com/max/cli/"><code>max</code> CLI docs</a>.</p>
</li>
<li class="">
<p>Remove previously deprecated <code>--use-gpu</code>, <code>--serialized_model_path</code>,
<code>--save_to_serialized_model_path</code>, <code>--max_cache_batch_size</code> and
<code>--huggingface-repo-id</code> options.</p>
</li>
<li class="">
<p>Move <code>InputContext</code>, <code>TextContext</code>, and <code>TextAndVisionContext</code> from
<code>max.pipelines</code> to <code>max.pipelines.context</code>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-models">MAX models<a href="https://docs.modular.com/releases/v25.3/#25-3-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added <code>Llama4ForConditionalGeneration</code> support, featuring new MoE layers.
Currently, it is limited to text inputs. Run the model by calling:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max generate --model-path meta-llama/Llama-4-Scout-17B-16E-Instruct --devices 0,1,2,3</code></pre></div></div>
</li>
<li class="">
<p>Added support for running text generations using the Mistral 3 24B model. Run
the model with:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max generate --model-path mistralai/Mistral-Small-3.1-24B-Instruct-2503 --devices 0</code></pre></div></div>
</li>
<li class="">
<p>Fixed empty textual outputs for certain Mistral models
(<a href="https://github.com/modular/modular/issues/4193" target="_blank" rel="noopener noreferrer" class="">MAX issue 4193</a>).</p>
</li>
<li class="">
<p>Added support for loading a custom pipeline architecture by module. Using
<code>--custom-architectures=folder/path/to/import:my_module</code> will lead to loading
architectures from the file. The architectures must be exposed via an
<code>ARCHITECTURES</code> variable in the file. Once loaded, a model can be run using
the new architectures. The flag can be specified multiple times to load more
modules.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-serve">MAX Serve<a href="https://docs.modular.com/releases/v25.3/#25-3-serve" class="hash-link" aria-label="Direct link to MAX Serve" title="Direct link to MAX Serve" translate="no">​</a></h2>
<ul>
<li class="">
<p>Moved from radix trie to hash based prefix caching implementation which has
smaller CPU overheads. This improves performance particularly in workloads
with high cache reuse rates.</p>
</li>
<li class="">
<p>Added experimental support for offloading KVCache to host memory via the
<code>--enable-kvcache-swapping-to-host</code> and <code>--host-kvcache-swap-space-gb</code> flags.
This allows for superior KVCache reuse through prefix caching in workloads
where the reusable KVCache amount exceeds GPU VRAM.</p>
</li>
<li class="">
<p>Fixed the <code>usage.prompt_tokens</code> field in the OpenAI API Usage Info response.
Previously this field was always set to Null, but now it correctly
contains the number of prompt tokens in the request.</p>
</li>
<li class="">
<p>Switched from Python Multiprocessing Queue to ZeroMQ. This reduces latencies
between frontend server process and model worker process related to
networking.</p>
</li>
<li class="">
<p>Stray model workers on Linux now terminate more reliably when the parent
process is killed.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-engine">MAX Engine &amp; Graph<a href="https://docs.modular.com/releases/v25.3/#25-3-engine" class="hash-link" aria-label="Direct link to MAX Engine &amp; Graph" title="Direct link to MAX Engine &amp; Graph" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-engine-python-api">Python API<a href="https://docs.modular.com/releases/v25.3/#25-3-engine-python-api" class="hash-link" aria-label="Direct link to Python API" title="Direct link to Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>We now raise an error if there's a mismatch between the expected device of a
weight on a graph and the device of the actual tensor data specified in
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession.load"><code>InferenceSession.load()</code></a>.</p>
</li>
<li class="">
<p>Removed <code>output_device</code> argument from
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.execute"><code>Model.execute()</code></a>.</p>
</li>
<li class="">
<p>Removed the <code>copy_inputs_to_device</code> argument in
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.execute"><code>Model.execute</code></a> to improve
predictability of the API. Now <code>execute()</code> raises a <code>TypeError</code> if arguments
are passed whose devices don't match the model.</p>
</li>
<li class="">
<p>Swapped the order of the <code>dtype</code> and <code>shape</code> fields of
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor"><code>driver.Tensor</code></a>. Previously, the
arguments are ordered as <code>(shape, dtype)</code>. They are now swapped to
<code>(dtype, shape)</code> to be in line with other tensor-like types.</p>
</li>
<li class="">
<p>Replaced some instances of
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor.zeros"><code>Tensor.zeros</code></a>
with <code>Tensor.__init__</code> when the engine did not depend on the tensor being zero
initialized. This elides the unnecessary memset to provide a minor performance
improvement.</p>
</li>
<li class="">
<p>Added a new experimental
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor.inplace_copy_from"><code>Tensor.inplace_copy_from()</code></a>.
This allows users to copy the contents of one <code>Tensor</code> into another.</p>
</li>
<li class="">
<p>Made the default behavior of
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Weight/"><code>Weight</code></a> as expecting the
initial allocation on host. A transfer is then inserted to the target device
and this value is returned when weights generate an MLIR value. This is done
due to current conservative ownership around external weights.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.irfft"><code>irfft</code></a> op, which
computes the inverse real fast fourier transform (FFT).</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.argmax"><code>argmax</code></a> op,
which returns the index of the maximum value in an array or sequence.</p>
</li>
<li class="">
<p>Added the <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>GroupNorm</code></a> layer.</p>
</li>
<li class="">
<p>Switched layer names so that <code>max.nn</code> layers that are implemented with the
deprecated <code>Layer</code> class are marked as "V1", and layers that are implemented
with the new <a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Module/"><code>max.nn.Module</code></a>
are the default. That is, <code>max.nn.LinearV2</code> is now
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Linear/"><code>max.nn.Linear</code></a>, and the
previous <code>max.nn.Linear</code> is now
<code>max.nn.LinearV1</code>.</p>
</li>
<li class="">
<p>DeviceRefs in types/layers are in general expected to be explicit rather than
implicit.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-engine-mojo-api">Mojo API<a href="https://docs.modular.com/releases/v25.3/#25-3-engine-mojo-api" class="hash-link" aria-label="Direct link to Mojo API" title="Direct link to Mojo API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Removed some functionality from
<a class="" href="https://docs.modular.com/max/api/kernels/extensibility/tensor/tensor/Tensor/"><code>tensor.Tensor</code></a>:</p>
<ul>
<li class="">Serializing <code>Tensor</code> to disk (<code>Tensor.tofile(path)</code> and
<code>Tensor.save(path)</code>).</li>
<li class="">Reading the serialized data back from disk (<code>Tensor.load(path)</code> and
<code>Tensor.fromfile(path)</code>.</li>
<li class=""><code>rand</code> and <code>randn</code> methods have been removed. Use the ones in the Mojo
standard library if you still need access for constructing a new <code>Tensor</code>
with random elements based on a particular <code>TensorShape</code>.</li>
</ul>
</li>
<li class="">
<p><strong>Deprecated the Mojo Driver, Graph, and Engine APIs</strong></p>
<p>These APIs are not currently used internally. Instead, we build graphs using
the Python APIs, and our engineering efforts have been focused on making that
experience as robust and user-friendly as possible. As a result, the Mojo
versions of these APIs have not kept pace with new features and language
improvements. These APIs will be open sourced for the community before being
removed.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-custom-ops">Custom ops API<a href="https://docs.modular.com/releases/v25.3/#25-3-custom-ops" class="hash-link" aria-label="Direct link to Custom ops API" title="Direct link to Custom ops API" translate="no">​</a></h3>
<ul>
<li class="">
<p>You can now pass Mojo source package paths as
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/"><code>Graph</code></a> custom extensions. The
Mojo code will be compiled automatically, no need to run <code>mojo package</code>
manually as a prior step. Previously, only pre-compiled <code>.mojopkg</code> paths were
accepted, requiring the Mojo code to be built as a prerequisite step before
running a <code>Graph</code> with a custom op.</p>
<p>Given a project structure like:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>project
|-- main.py
\-- kernels
    |-- __init__.mojo
    \-- my_custom_op.mojo</code></pre></div></div>
<p>You can construct a <code>Graph</code> in <code>main.py</code> using Mojo custom op kernels simply
using:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>g = Graph(
  ...,
  custom_extensions = [Path(__file__).parent / "kernels"]
)</code></pre></div></div>
<p>A change to your Mojo source code defining a custom op will be reflected
immediately the next time the <code>Graph</code> is constructed.</p>
</li>
<li class="">
<p>New
<a href="https://github.com/modular/modular/tree/main/max/examples/custom_ops" target="_blank" rel="noopener noreferrer" class="">image_pipeline example</a>
that demonstrates sequencing custom ops together which modify an image,
leaving data on the GPU for each op, before writing it back to CPU and disk.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-kernels">Kernels<a href="https://docs.modular.com/releases/v25.3/#25-3-kernels" class="hash-link" aria-label="Direct link to Kernels" title="Direct link to Kernels" translate="no">​</a></h2>
<ul>
<li class="">More compute overlap is now enabled for Hopper GPUs. This allows finer-grained
scheduling of kernel operations by analyzing producer-consumer patterns within
a compute kernel. As a result, there is more kernel compute overlap,
especially for compute-heavy kernels with data-dependent execution paths.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-gpu-programming">GPU programming<a href="https://docs.modular.com/releases/v25.3/#25-3-gpu-programming" class="hash-link" aria-label="Direct link to GPU programming" title="Direct link to GPU programming" translate="no">​</a></h2>
<ul>
<li class="">
<p>CUDA driver requirement reduced to version 12.4 and the NVIDIA driver to be
version 550. Requiring these earlier driver versions allows MAX to be more
easily deployed on AWS and GCP, since these are the default versions used by
those cloud providers.</p>
</li>
<li class="">
<p>Added support for programming NVIDIA Jetson Orin GPUs (<code>sm_87</code>).</p>
</li>
</ul>
<p>Also see the
<a href="https://mojolang.org/releases#gpu-changes" target="_blank" rel="noopener noreferrer" class="">Mojo changelog of GPU changes</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-3-mojo">Mojo language<a href="https://docs.modular.com/releases/v25.3/#25-3-mojo" class="hash-link" aria-label="Direct link to Mojo language" title="Direct link to Mojo language" translate="no">​</a></h2>
<ul>
<li class="">
<p>We recently open-sourced the rest of the Mojo standard library, including the
<code>algorithm</code>, <code>benchmark</code>, <code>buffer</code>, <code>compile</code>, <code>complex</code>, <code>gpu</code>, and <code>layout</code>
packages. <a href="https://github.com/modular/modular/tree/main/mojo/std/src" target="_blank" rel="noopener noreferrer" class="">See it all in
GitHub</a>.</p>
</li>
<li class="">
<p>We've also open sourced <a href="https://github.com/modular/modular/tree/main/max/kernels/src" target="_blank" rel="noopener noreferrer" class="">all our MAX AI
kernels</a>.
This new library includes <code>kv_cache</code>, <code>layout</code>, <code>linalg</code>, <code>nn</code>, <code>nvml</code>, and
<code>quantization</code>.</p>
</li>
</ul>
<p>For all the updates to the Mojo language, standard library, and tools, see the
<a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.2]]></title>
            <link>https://docs.modular.com/releases/v25.2/</link>
            <guid>https://docs.modular.com/releases/v25.2/</guid>
            <pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[✨ Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-highlights">✨ Highlights<a href="https://docs.modular.com/releases/v25.2/#25-2-highlights" class="hash-link" aria-label="Direct link to ✨ Highlights" title="Direct link to ✨ Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>Support for NVIDIA Hopper GPUs</strong></p>
<p>MAX has been optimized to run on Hopper GPUs. For more information on MAX and
NVIDIA's hardware, see the <a class="" href="https://docs.modular.com/max/container/#recommended-cloud-instances">MAX
container</a> documentation.</p>
</li>
<li class="">
<p><strong>Multi-GPU support</strong></p>
<p>MAX uses tensor parallelism to distribute work across multiple GPUs so you can
run LLMs like
<a href="https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct" target="_blank" rel="noopener noreferrer" class=""><code>Llama-3.3-70B-Instruct</code></a>,
even with long context window.</p>
</li>
<li class="">
<p><strong>Expanded library of MAX models</strong></p>
<p>We're rapidly growing our library of base model architectures that MAX can
accelerate with MAX Serve (including <code>Phi3ForCausalLM</code>, <code>OlmoForCausalLM</code>,
and <code>GraniteForCausalLM</code>). We also now support <code>GTPQ</code> for the Llama models.
For more information, check out our <a href="https://builds.modular.com/?category=models" target="_blank" rel="noopener noreferrer" class="">MAX model
repository</a>.</p>
</li>
<li class="">
<p><strong>Advanced E2E optimizations for long context window</strong></p>
<p>In flight batching, chunked prefill, and copy-on-write optimize the execution
for prefix heavy and long context window scenario.</p>
</li>
<li class="">
<p><strong>GPU programming with Mojo</strong></p>
<p>Lots of new APIs are now available to enable both low-level GPU programming
and abstracted programming patterns that simplify the code required to write
GPU kernels for your AI models.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-serve">MAX Serve<a href="https://docs.modular.com/releases/v25.2/#25-2-serve" class="hash-link" aria-label="Direct link to MAX Serve" title="Direct link to MAX Serve" translate="no">​</a></h2>
<ul>
<li class="">
<p>Extended MAX Serve batch scheduling to account for the prefix cache. The
scheduler can now create larger batches when many prompt tokens are already
cached, improving throughput up to 10% in some benchmarks.</p>
</li>
<li class="">
<p>Added support for in-flight batching, allowing token generation requests to be
scheduled alongside context encoding requests to reduce inter-token latency.
This behavior can be controlled by CLI argument <code>--enable-in-flight-batch</code>.</p>
</li>
<li class="">
<p>Added support for copy-on-write on KV blocks when using PagedAttention with
Prefix Caching. This improves the prefix cache hit rate and prefill
performance in some scenarios.</p>
</li>
<li class="">
<p>MAX Serve now supports <code>transformers</code> v.4.49.0, with a patch
to avoid graph breaks when using <code>torch.compile()</code> on Llama models.</p>
</li>
<li class="">
<p>Added support for recording HTTP traffic out to a file for diagnostics or
later
replay.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-models">MAX models<a href="https://docs.modular.com/releases/v25.2/#25-2-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added support for executing <code>LlamaForCausalLM</code> architecture models on multiple
GPUs. The model uses tensor parallelism automatically when passing multiple
device IDs to the <code>--devices</code> CLI argument. Try running
<a href="https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct" target="_blank" rel="noopener noreferrer" class=""><code>meta-llama/Llama-3.3-70B-Instruct</code></a>
on 4 GPUs with the following example:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate --model-path=meta-llama/Llama-3.3-70B-Instruct \
  --quantization-encoding bfloat16 \
  --devices gpu:0,1,2,3 \
  --prompt="Design a
    self-sustaining colony on Neptune's moon Triton with a myth/science
    fusion name, three quantum tech breakthroughs, one ethical debate, a
    neon-lit cultural ritual, and a hidden flaw—presented in bullet points."</code></pre></div></div>
</li>
<li class="">
<p>Added support for the <code>Phi3ForCausalLM</code> model architecture (such as
<a href="https://huggingface.co/microsoft/phi-4" target="_blank" rel="noopener noreferrer" class=""><code>microsoft/phi-4</code></a>). For example:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path microsoft/phi-4 \
  --prompt "Write bubble sort in mojo"</code></pre></div></div>
</li>
<li class="">
<p>Added support for the <code>OlmoForCausalLM</code> model architecture (such as
<a href="https://huggingface.co/allenai/OLMo-1B-0724-hf" target="_blank" rel="noopener noreferrer" class=""><code>allenai/OLMo-1B-0724-hf</code></a>).
For example:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path allenai/OLMo-1B-0724-hf \
  --prompt "Write bubble sort in mojo"</code></pre></div></div>
</li>
<li class="">
<p>Added support for the <code>GraniteForCausalLM</code> model architecture (such as
<a href="https://huggingface.co/ibm-granite/granite-3.1-8b-instruct" target="_blank" rel="noopener noreferrer" class=""><code>ibm-granite/granite-3.1-8b-instruct</code></a>).
For example:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path ibm-granite/granite-3.1-8b-instruct \
  --prompt "Write bubble sort in mojo"</code></pre></div></div>
</li>
<li class="">
<p>Added support for:</p>
<ul>
<li class=""><a href="https://huggingface.co/microsoft/Phi-3.5-mini-instruct" target="_blank" rel="noopener noreferrer" class=""><code>microsoft/Phi-3.5-mini-instruct</code></a></li>
<li class=""><a href="https://huggingface.co/microsoft/phi-4" target="_blank" rel="noopener noreferrer" class=""><code>microsoft/phi-4</code></a></li>
<li class=""><a href="https://huggingface.co/LGAI-EXAONE/EXAONE-3.0-7.8B-Instruct" target="_blank" rel="noopener noreferrer" class=""><code>LGAI-EXAONE/EXAONE-3.0-7.8B-Instruct</code></a></li>
<li class=""><a href="https://huggingface.co/LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct" target="_blank" rel="noopener noreferrer" class=""><code>LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct</code></a></li>
</ul>
</li>
<li class="">
<p>We now support GPTQ quantization for models that run on the GPU. This is
handled transparently when the model weights are specified. For example, this
runs Llama 3.1 8B using int4-quantized GPTQ weights:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path hugging-quants/Meta-Llama-3.1-8B-Instruct-GPTQ-INT4 \
  --prompt "Why is the sky blue?" \
  --max-batch-size 1 \
  --max-length 10000</code></pre></div></div>
<p>This reduces the total memory consumption of this model from ~16 GB to ~5 GB,
allowing the model to fit in the RAM smaller GPUs.</p>
</li>
<li class="">
<p>Model weights are now downloaded in parallel.</p>
</li>
<li class="">
<p>Added constraints on whitespace during <a class="" href="https://docs.modular.com/max/serve/structured-output/">Structured
Output</a>. This reduces tokens counts and improves
model adherence.</p>
</li>
<li class="">
<p>Added jump ahead decoding during Structured Output. This auto-completes tokens
when a singular path forward is identified, improving single completion times
by up to ~20% for long prompts.</p>
</li>
<li class="">
<p>In the event of an unhandled exception, we now use the standard Python
traceback format instead of using pretty-printed Rich tracebacks.</p>
</li>
<li class="">
<p>We now need to explicitly import <code>LLM</code> from
<a class="" href="https://docs.modular.com/max/api/python/entrypoints/"><code>max.entrypoints.llm</code></a> rather than the previous
<code>max.entrypoints</code> import.</p>
</li>
<li class="">
<p>The <code>max.pipelines.dataprocessing.tokenizer</code> and
<code>max.pipelines.dataprocessing.gguf_utils</code> modules have been removed.</p>
</li>
<li class="">
<p>The previously deprecated <code>PipelineConfig.architecture</code> field and its
corresponding <code>--architecture</code> CLI argument have been removed.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-pipelines-cli"><code>max-pipelines</code> CLI<a href="https://docs.modular.com/releases/v25.2/#25-2-pipelines-cli" class="hash-link" aria-label="Direct link to 25-2-pipelines-cli" title="Direct link to 25-2-pipelines-cli" translate="no">​</a></h2>
<ul>
<li class="">
<p>The <code>--devices</code> CLI argument now supports a comma-separated list of GPU IDs
prefixed with <code>gpu:</code> like <code>--devices=gpu:0,1,2,3</code>. We no longer support the
previous <code>--devices=gpu-&lt;N&gt;</code> format.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate --model-path=meta-llama/Llama-3.3-70B-Instruct \
  --quantization-encoding bfloat16 \
  --devices gpu:0,1,2,3 \
  --prompt="Design a self-sustaining colony on Neptune's moon Triton with a myth/science fusion name, three quantum tech breakthroughs, one ethical debate, a neon-lit cultural ritual, and a hidden flaw—presented in bullet points."</code></pre></div></div>
</li>
<li class="">
<p>Removed <code>--huggingface-repo-id</code>
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.PipelineConfig/">PipelineConfig</a>
option and CLI argument in favor of <code>--model-path</code>.</p>
</li>
<li class="">
<p>We consolidated <code>--model-path</code> and <code>-weight-path</code>. Valid <code>--weight-path</code>
values now override <code>--model-path</code>, which handles both local and remote
(Hugging Face) cases. If we cannot derive the weights from the
<code>--weight-path</code>, we now fall back to the <code>--model-path</code>, which you must set
explicitly.</p>
</li>
<li class="">
<p>Added <code>--huggingface-revision</code> option, to allow selecting a non-default branch
or a specific commit in a Hugging Face model repository.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-engine">MAX Engine<a href="https://docs.modular.com/releases/v25.2/#25-2-engine" class="hash-link" aria-label="Direct link to MAX Engine" title="Direct link to MAX Engine" translate="no">​</a></h2>
<ul>
<li class="">
<p>The MAX graph compiler now has kernel caching. This is a significant
improvement to our compilation pipeline. Here are some of the highlights:</p>
</li>
<li class="">
<p>Up to 28% faster compilation times when making iterative changes to models</p>
</li>
<li class="">
<p>Improved caching between different but similar models (up to 27% faster)</p>
</li>
<li class="">
<p>Lays foundation for future caching optimizations</p>
</li>
</ul>
<p>What does this mean for you? Faster development cycles! When you're working on
model pipelines and making changes to the graph, the graph compiler will now
intelligently reuse kernels that haven't changed, significantly reducing
compilation times.</p>
<p>The improvements are particularly noticeable during iterative development, with
compilation times dropping from ~80s to ~57s in some cases of compiling
Llama3.1-8B for 4 GPUs. Even when compiling different models from the same
family (like Llama/Granite variants), you'll see significant speedups on
subsequent compilations.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-driver">Driver APIs<a href="https://docs.modular.com/releases/v25.2/#25-2-driver" class="hash-link" aria-label="Direct link to Driver APIs" title="Direct link to Driver APIs" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added <code>Accelerator.can_access(other: Device) -&gt; bool</code> method to check if one
device can directly access memory of another device.</p>
</li>
<li class="">
<p>Fixed a bug in <code>max.driver.tensor.load_max_tensor()</code> for <code>bfloat16</code> dtype,
which would cause an error about mmap size being too large.</p>
</li>
<li class="">
<p><code>max.driver.Tensor.item()</code> now works on any single-element tensor (previously
restricted to rank-0 tensors).</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Device.synchronize"><code>Device.synchronize()</code></a>,
which ensures all operations on the device complete before returning.</p>
</li>
<li class="">
<p>Removed <code>MojoCallContextPtr</code> in favor of <code>DeviceContextPtr</code>.
<code>MojoCallContextPtr</code> only contained a <code>DeviceContextPtr</code>, so this change
directly exposes the <code>DeviceContextPtr</code>. Custom ops using <code>MojoCallContextPtr</code>
now directly take a <code>DeviceContextPtr</code> argument:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>    @staticmethod
    fn execute[
        type: DType, rank: Int
    ](
        output: OutputTensor[type=type, rank=rank],
        input: InputTensor[type=type, rank=rank],
        ctx: MojoCallContextPtr,
    ):</code></pre></div></div>
<p>becomes</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>    @staticmethod
    fn execute[
        type: DType, rank: Int
    ](
        output: OutputTensor[type=type, rank=rank],
        input: InputTensor[type=type, rank=rank],
        ctx: DeviceContextPtr,
    ):</code></pre></div></div>
</li>
<li class="">
<p>You can now skip compiling a GPU kernel first before enqueueing it, and pass
a function directly to <code>ctx.enqueue_function[func](...)</code>:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>fn func():
    print("Hello from GPU")

@register("custom_op")
struct CustomOp:

    @staticmethod
    fn execute(ctx: DeviceContextPtr) raises:
        var dev_ctx = ctx.get_device_context()
        dev_ctx.enqueue_function[func](grid_dim=1, block_dim=1)</code></pre></div></div>
<p>However, if you're reusing the same function and parameters multiple times,
this incurs some overhead of around 50-500 nanoseconds per enqueue. So you
can still compile the function first and pass it to <code>ctx.enqueue_function</code>
in this scenario:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>var compiled_func = ctx.compile_function[func]()
# Multiple kernel launches with the same function/parameters
ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)
ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)</code></pre></div></div>
</li>
<li class="">
<p>Changed <code>Accelerator</code> and <code>CPU</code> from factory methods that created <code>Device</code>
objects in Python (which were accelerators and CPUs in the C++ implementation)
to actual Python types. This change elevates the <code>Accelerator</code> and <code>CPU</code> type
concepts to Python, making them types rather than methods.</p>
<p>This allows type annotations in Python. For example, a list of accelerators
used to be defined like this:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>graph_devices: list[DeviceRef]</code></pre></div></div>
<p>Now it can be defined like this:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>graph_devices: list[Accelerator]</code></pre></div></div>
</li>
<li class="">
<p>Elementwise operations (e.g. <code>__add__</code>) have been removed from <code>Tensor</code> (that
is, <code>tensor_internal.Tensor</code>). This <code>Tensor</code> type is being phased out; please
reduce usage in favor of <code>LayoutTensor</code>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-graph">Graph APIs<a href="https://docs.modular.com/releases/v25.2/#25-2-graph" class="hash-link" aria-label="Direct link to Graph APIs" title="Direct link to Graph APIs" translate="no">​</a></h2>
<ul>
<li class="">
<p>The <code>nn</code> package is now <a class="" href="https://docs.modular.com/max/api/python/nn/"><code>max.nn</code></a>.</p>
</li>
<li class="">
<p>Added <a class="" href="https://docs.modular.com/max/api/python/graph/#max.graphs.ops.chunk"><code>ops.chunk</code></a>) to support
chunking tensors along an axis.</p>
</li>
<li class="">
<p>Added support for while loops with
<a class="" href="https://docs.modular.com/max/api/python/graph/#max.graphs.ops.while_loop"><code>ops.while_loop</code></a>.</p>
</li>
<li class="">
<p>Added support for conditional execution with
<a class="" href="https://docs.modular.com/max/api/python/graph/#max.graph.ops.cond"><code>ops.cond</code></a>.</p>
</li>
<li class="">
<p>Added axis reduction overloads for
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.min"><code>ops.min</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.max"><code>ops.max</code></a>. For example;
<code>ops.min(tensor, axis=-1)</code>.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.gelu"><code>gelu()</code></a> function now
accepts
an <code>approximate</code> keyword. The keyword controls the <code>gelu</code> approximation with
<code>none</code>, <code>tanh</code>, and <code>fast</code> approximations accepted.</p>
</li>
<li class="">
<p>Removed the <code>roundeven()</code> operation from the Python API. The
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.round"><code>round()</code></a> operation now has
the same behavior as <code>roundeven()</code>, so there is no need for both to exist.</p>
</li>
<li class="">
<p>Added helpers to create analogous tensors from buffer types and vice versa.</p>
</li>
<li class="">
<p>Added <code>max.nn.Module</code>, a base class for writing layers and constructing
networks of layers (e.g. using <code>max.nn.Sequential</code>). Currently, this class
supports graph building by ensuring that all weight names are unique and
systematically generated. This class also supports managing the weight values
with the <code>module.state_dict()</code> and <code>module.load_state_dict()</code> methods. More
functionality and documentation will be added in future releases.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-custom-ops">Custom ops<a href="https://docs.modular.com/releases/v25.2/#25-2-custom-ops" class="hash-link" aria-label="Direct link to Custom ops" title="Direct link to Custom ops" translate="no">​</a></h2>
<ul>
<li class="">
<p>Changes have been made to the way that custom ops are registered: rather
than using the <code>num_dps_outputs</code> attribute on <code>@compiler.register</code> to specify
the number of outputs, that number is now inferred from the signature of the
custom operation. Inputs to the operation now use the <code>InputTensor</code> type and
outputs from the operation use <code>OutputTensor</code>, instead of the previous
<code>ManagedTensorSlice</code> for both. This eliminates the need for a manual
<code>num_dps_outputs</code> attribute, and makes it safer to work with these inputs and
outputs by preventing accidental writes to input tensors. The new interface
looks something like the following:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>```mojo
@compiler.register("add_one_custom")
struct AddOneCustom:
    @staticmethod
    fn execute[
        target: StringLiteral,
    ](
        out: OutputTensor,
        x: InputTensor[type = out.type, rank = out.rank],
        ctx: DeviceContextPtr,
    ) raises:
        @parameter
        @always_inline
        fn elementwise_add_one[
            width: Int
        ](idx: IndexList[x.rank]) -&gt; SIMD[x.type, width]:
            return x.load[width](idx) + 1

        foreach[elementwise_add_one, target=target](out, ctx)
```</code></pre></div></div>
</li>
<li class="">
<p>The <code>foreach</code> function now <code>raises</code> to be able to handle errors within an
elementwise calculation.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-hopper-kernels">Hopper kernels<a href="https://docs.modular.com/releases/v25.2/#25-2-hopper-kernels" class="hash-link" aria-label="Direct link to Hopper kernels" title="Direct link to Hopper kernels" translate="no">​</a></h2>
<p>State-of-the-Art Kernels in Mojo for H100/H200 GPUs</p>
<ul>
<li class="">
<p><strong>Hopper Architecture Matrix Multiplication Kernels</strong>: The implementation
achieved performance comparable to NVIDIA's highly optimized cuBLAS library.
These kernels take full advantage of the Tensor Cores in Hopper architecture
GPUs to accelerate the fundamental matrix multiplication operations that
underpin deep learning workloads.</p>
</li>
<li class="">
<p><strong>Multi-GPU AllReduce Implementation</strong>: The AllReduce operation is critical
for
distributed inference across multiple GPUs, as it efficiently aggregates
gradients. The Mojo implementation surpassed NVIDIA's NCCL library in
performance benchmarks. This improvement reduces communication overhead during
distributed inference.</p>
</li>
<li class="">
<p><strong>MAX Attention Kernel with Flash Attention 3:</strong> This implementation
incorporates the latest Flash Attention 3 algorithm and extends it, which
significantly accelerates the computation of attention mechanisms in
transformer models. The MAX attention kernel optimizes memory access patterns
and computational steps, reducing both the memory footprint and execution time
of attention operations. This is particularly important for LLMs where
attention calculations represent a substantial portion of the computational
workload.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-gpu-programming">GPU programming<a href="https://docs.modular.com/releases/v25.2/#25-2-gpu-programming" class="hash-link" aria-label="Direct link to GPU programming" title="Direct link to GPU programming" translate="no">​</a></h2>
<ul>
<li class="">Added the Mojo <code>max.driver</code> API to enable dispatching
GPU functions from Mojo.</li>
</ul>
<p>Check out <a href="https://github.com/modular/modular/tree/main/mojo/examples/gpu-functions" target="_blank" rel="noopener noreferrer" class="">examples for GPU programming in
Mojo</a>,
which use this new API.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-mojo">Mojo<a href="https://docs.modular.com/releases/v25.2/#25-2-mojo" class="hash-link" aria-label="Direct link to Mojo" title="Direct link to Mojo" translate="no">​</a></h2>
<p>Mojo is a crucial component of the MAX stack that enables all of MAX's
performance-oriented code across hardware. For all the updates to the Mojo
language, standard library, and tools, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-2-documentation">Documentation<a href="https://docs.modular.com/releases/v25.2/#25-2-documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<p>New examples for writing custom ops:</p>
<ul>
<li class="">
<p><a href="https://github.com/modular/modular/blob/main/max/examples/custom_ops/kernels/fused_attention.mojo" target="_blank" rel="noopener noreferrer" class=""><code>fused_attention</code></a>
demonstrates complex GPU programming using MAX abstractions for a
practical use in AI model development.</p>
</li>
<li class="">
<p><a href="https://github.com/modular/modular/blob/main/max/examples/custom_ops/kernels/matrix_multiplication.mojo" target="_blank" rel="noopener noreferrer" class=""><code>matrix_multiplication</code></a>
includes a series of progressive optimizations for matrix multiplications
on GPUs.</p>
</li>
<li class="">
<p><a href="https://github.com/modular/modular/blob/main/max/examples/custom_ops/kernels/histogram.mojo" target="_blank" rel="noopener noreferrer" class=""><code>histogram</code></a>
shows how to implement the histogram pattern as a custom op.</p>
</li>
<li class="">
<p>New
<a href="https://github.com/modular/modular/tree/main/mojo/examples/gpu-functions" target="_blank" rel="noopener noreferrer" class="">examples for GPU programming in Mojo</a>
using the new MAX Driver API</p>
<ul>
<li class="">These use a Mojo programming model that should look familiar to CUDA C
programmers, showing how to define and dispatch GPU functions within a
single Mojo file. These examples recreate the first three samples from the
popular textbook
<a href="https://www.amazon.com/Programming-Massively-Parallel-Processors-Hands/dp/0323912311" target="_blank" rel="noopener noreferrer" class="">"Programming Massively Parallel Processors"</a>,
showing how basic concepts translate from CUDA into Mojo. Additionally, a
Mandelbrot set calculation example that parallels a similar one in the
existing custom ops examples.</li>
</ul>
</li>
<li class="">
<p>New <a class="" href="https://docs.modular.com/max/container/">MAX containers</a> available. For
more information on the base and full MAX containers, see <a class="" href="https://docs.modular.com/max/container/#container-contents">Container
contents</a>.</p>
</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.1.1]]></title>
            <link>https://docs.modular.com/releases/v25.1.1/</link>
            <guid>https://docs.modular.com/releases/v25.1.1/</guid>
            <pubDate>Wed, 19 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Fix performance issues in autoregressive models with paged attention]]></description>
            <content:encoded><![CDATA[<p>Fix performance issues in autoregressive models with paged attention
by setting sensible default values for <code>--max-num-steps</code> that are
platform-specific.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v25.1]]></title>
            <link>https://docs.modular.com/releases/v25.1/</link>
            <guid>https://docs.modular.com/releases/v25.1/</guid>
            <pubDate>Thu, 13 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[✨ Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-highlights">✨ Highlights<a href="https://docs.modular.com/releases/v25.1/#25-1-highlights" class="hash-link" aria-label="Direct link to ✨ Highlights" title="Direct link to ✨ Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>Custom ops for GPUs</strong></p>
<p>Our new custom op API allows you to extend MAX Engine with new graph
operations written in Mojo that execute on either CPU or GPU, providing full
composability and extensibility for your models. See more in the section
about <a href="https://docs.modular.com/releases/v25.1/#25-1-gpus" class="">GPU programming</a>.</p>
</li>
<li class="">
<p><strong>Enhanced support for agentic workflows</strong></p>
<p>MAX Serve now supports function calling, which allows you to instruct your
model to interact with other systems, such as retrieve data and execute
external tasks.
<a class="" href="https://docs.modular.com/max/serve/function-calling/">Learn more about function calling and tool use</a>.</p>
<p>MAX Serve now supports structured output (also known as constrained decoding)
for MAX models on GPU. This allows you to enforce the output format from a
model using an input schema that defines the output structure.
<a class="" href="https://docs.modular.com/max/serve/structured-output/">Learn more about structured output</a>.</p>
</li>
<li class="">
<p><strong>Extended model architecture support</strong></p>
<ul>
<li class="">
<p>MAX Serve now supports multimodal models that take both text and image
inputs. For example, see <a class="" href="https://docs.modular.com/max/develop/deploy-llama-vision/">how to deploy Llama 3.2
Vision</a>.</p>
</li>
<li class="">
<p>MAX Serve now supports text embedding models. Learn how to <a class="" href="https://docs.modular.com/max/develop/run-embeddings-with-max-serve/">deploy a text
embedding model</a>.</p>
</li>
</ul>
</li>
<li class="">
<p><strong>New <code>max-pipelines</code> CLI tool</strong></p>
<p>Instead of cloning our GitHub repo to access our latest GenAI models, you can
instead install the <code>max-pipelines</code> CLI tool and quickly run an inference or
deploy an endpoint.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-docs">Documentation<a href="https://docs.modular.com/releases/v25.1/#25-1-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<p>New tutorials:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/build-custom-ops/">Build custom ops for GPUs</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/deploy-serverless-cloud-run/">Serverless GPU inference on Google Cloud
Run</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/deploy-llama-vision/">Generate image descriptions with Llama 3.2
Vision</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/run-embeddings-with-max-serve/">Deploy a text embedding model</a></p>
</li>
</ul>
<p>Other docs:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/serve/function-calling/">Function calling and tool use</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/serve/structured-output/">Structured output</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/serve/prefix-caching/">Prefix caching with PagedAttention</a></p>
</li>
<li class="">
<p><code>max-pipelines</code> CLI</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-serve">MAX Serve<a href="https://docs.modular.com/releases/v25.1/#25-1-serve" class="hash-link" aria-label="Direct link to MAX Serve" title="Direct link to MAX Serve" translate="no">​</a></h2>
<ul>
<li class="">
<p>The <code>/v1/completions</code> REST endpoint now supports:</p>
<ul>
<li class="">
<p>Pre-tokenized prompts.</p>
</li>
<li class="">
<p>Image inputs for multimodal models such as <code>Llama-3.2-11B-Vision-Instruct</code>.
For an example, see <a class="" href="https://docs.modular.com/max/develop/deploy-llama-vision/">how to generate image
descriptions with Llama 3.2 Vision</a>.</p>
</li>
</ul>
<p><strong>Known issue:</strong> You might receive faulty results because some parts of the
text prompt get ignored for certain input combinations. We've identified
the problem and will have a fix in a subsequent nightly
release.</p>
<ul>
<li class="">
<p>Function calling and tool use, which allows you to instruct your
model to interact with other systems, such as retrieve data and execute
external tasks. <a class="" href="https://docs.modular.com/max/serve/function-calling/">Learn more about function calling and tool
use</a>.</p>
</li>
<li class="">
<p>Structured output (also known as constrained decoding), which allows you to
enforce the output format from a model using a JSON schema and the
<code>response_format</code> field. To enable constrained decoding pass
<code>--enable-structured-output</code> when running the server. However, this feature
currently works for MAX models on GPU only (support for PyTorch models and
CPU is in progress). <a class="" href="https://docs.modular.com/max/serve/structured-output/">Learn more about structured
output</a>.</p>
</li>
</ul>
</li>
<li class="">
<p>Added support for the <code>/v1/embeddings</code> API endpoint, allowing you to generate
vector representations using embedding models. See how to <a class="" href="https://docs.modular.com/max/develop/run-embeddings-with-max-serve/">deploy a text
embedding model</a>.</p>
</li>
<li class="">
<p>Max Serve can evict requests when the number of available pages in the
PagedAttention KVCache is limited. Before, the KV manager would throw an OOM
error when a batch that cannot fit in the cache was scheduled.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-max-models">MAX models<a href="https://docs.modular.com/releases/v25.1/#25-1-max-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added the <code>max-pipelines</code> CLI tool that simplifies the
process to run inference with GenAI models (specified with a Hugging Face repo
ID) and deploy them to a local endpoint with MAX Serve.</p>
<p>Previously, running or serving these models required cloning the
<a href="https://github.com/modular/max" target="_blank" rel="noopener noreferrer" class="">modular/max</a> GitHub repo and then running
commands such as <code>magic run llama3</code>.</p>
<p>These model-specific commands like <code>llama3</code> and <code>replit</code> commands have been
removed. They're now standardized and subsumed by flags like
<code>--model-path</code> in the <code>max-pipelines</code> tool. Arguments such as
<code>--max-length</code> and <code>--weight-path</code> are also still supported by
<code>max-pipelines</code>.</p>
<p>To view a list of supported model architectures from Hugging Face, run
<code>max-pipelines list</code>.</p>
</li>
<li class="">
<p>Added support for PagedAttention, which improves memory efficiency by
partitioning the KV cache into smaller blocks, reducing fragmentation and
enabling larger inference batches. You can enable it with
<code>--cache-strategy=paged</code> and <code>--kv-cache-page-size</code> with a value that's a
multiple of 128.</p>
</li>
<li class="">
<p>Added support for prefix caching in all cases where PagedAttention is
supported. This allows for more efficient usage of KVCache and improved
prefill performance for workloads with common prefixes. You can enable it by
setting <code>--enable-prefix-caching</code>. For more information, see
<a class="" href="https://docs.modular.com/max/serve/prefix-caching/">Prefix caching with PagedAttention</a>.</p>
</li>
<li class="">
<p>Batch size and max length are now inferred from available memory and the HF
Models' default values for max length, respectively. If a configuration leads
to an OOM, then we provide recommendations (to the best of our ability) to the
user to fit the model into memory.</p>
</li>
<li class="">
<p>Added support for heterogeneous KV caches for multi-modal models, such as
Llama Vision, which cache different KV states for self and cross attention
layers.</p>
</li>
<li class="">
<p>Added support for embedding models, starting with MPNet. For example:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path=sentence-transformers/all-mpnet-base-v2 \
  --prompt="Encode this sentence."</code></pre></div></div>
<p>Also see <a class="" href="https://docs.modular.com/max/develop/run-embeddings-with-max-serve/">how to deploy a text
embedding model</a>.</p>
</li>
<li class="">
<p>Added support for image and text multimodal models:</p>
<ul>
<li class="">
<p><code>max-pipelines generate</code> now accepts image input with <code>--image_url</code>.</p>
</li>
<li class="">
<p>Added an experimental Pixtral pipeline you can run as follows:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path=mistral-community/pixtral-12b \
  --prompt="What is in this image? [IMG]" \
  --image_url=http://picsum.photos/1024/1024</code></pre></div></div>
<p>The pipeline is automatically used for all models implementing the
<code>LlavaForConditionalGeneration</code> architecture.</p>
<p>The implementation currently has a limit of one image. We plan support an
arbitrary number of images of mixed sizes soon.</p>
</li>
<li class="">
<p>Added an experimental Llama Vision pipeline you can run as follows:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path=meta-llama/Llama-3.2-11B-Vision-Instruct \
  --prompt="&lt;|image|&gt;&lt;|begin_of_text|&gt;What is in this image?" \
  --image_url=http://picsum.photos/1024/1024</code></pre></div></div>
<p>The pipeline is automatically used for all models implementing the
<code>MllamaForConditionalGeneration</code> architecture.</p>
<p>Note: This model is gated and requires that you set the
<a href="https://huggingface.co/docs/huggingface_hub/en/package_reference/environment_variables#hftoken" target="_blank" rel="noopener noreferrer" class=""><code>HF_TOKEN</code></a>
environment variable. See
<a href="https://huggingface.co/meta-llama/Llama-3.2-11B-Vision-Instruct" target="_blank" rel="noopener noreferrer" class="">Llama-3.2-11B-Vision-Instruct</a>.</p>
</li>
<li class="">
<p>See <a class="" href="https://docs.modular.com/max/develop/deploy-llama-vision/">how to generate image
descriptions with Llama 3.2 Vision</a>.</p>
</li>
</ul>
</li>
<li class="">
<p>Added support for the <code>Qwen2ForCausalLM</code> model architecture (such as
<code>Qwen/Qwen2.5-7B-Instruct</code>). For example:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>max-pipelines generate \
  --model-path=Qwen/Qwen2.5-7B-Instruct \
  --prompt="Write bubble sort in python" \
  --quantization-encoding bfloat16</code></pre></div></div>
</li>
<li class="">
<p>Added support for offline batched inference for text-based LLMs, allowing you
to load a model and run inference with a batch of inputs directly from Python,
instead of relying on an HTTP interface. For an example, see
<a href="https://github.com/modular/modular/blob/modular/v26.1/max/examples/offline-inference/basic.py" target="_blank" rel="noopener noreferrer" class=""><code>examples/offline-inference/basic.py</code></a>.</p>
</li>
<li class="">
<p>The <code>--max-cache-batch-size</code> flag has been deprecated in favor of
<code>--max-batch-size</code>. Using <code>--max-cache-batch-size</code> now emits a deprecation
warning and will stop working in a future release.</p>
</li>
<li class="">
<p>The <code>--use-gpu</code> flag has been deprecated in favor of <code>--devices=cpu</code>,
<code>--devices=gpu</code>, or <code>--devices=gpu-0,gpu-1,...</code>. If the device isn't
specified, the model runs on the first available GPU, or CPU if no GPUs are
available.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-engine">MAX Engine<a href="https://docs.modular.com/releases/v25.1/#25-1-engine" class="hash-link" aria-label="Direct link to MAX Engine" title="Direct link to MAX Engine" translate="no">​</a></h2>
<ul>
<li class="">
<p>Improved internal kernel compilation speed 1.5 - 4X across different models.</p>
<p>We've revamped our GPU compilation process so that all kernels in a program
are compiled together into a single LLVM module, then split into separate
kernels afterward. This ensures shared code between kernel entry points is
only compiled once. For example, we observe a 3.7x speed up for Llama3.1-8b
GPU startup time.</p>
</li>
<li class="">
<p>Improved initial model execution speed on NVIDIA GPUs.</p>
<p>Instead of compiling to PTX and performing just-in-time compilation during
runtime, we now generate CUBIN binaries directly. While this increases
initial compilation time, it significantly improves execution speed.</p>
</li>
<li class="">
<p>The kernels have been further tuned for performance on NVIDIA A100 GPUs.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-graph">Graph APIs<a href="https://docs.modular.com/releases/v25.1/#25-1-graph" class="hash-link" aria-label="Direct link to Graph APIs" title="Direct link to Graph APIs" translate="no">​</a></h3>
<ul>
<li class="">
<p>You can now write custom operations (ops) in Mojo, and add them to a graph
constructed in Python, using
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.custom"><code>custom()</code></a> and
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.inplace_custom"><code>inplace_custom()</code></a>.</p>
<p>For more detail, see the section below about <a href="https://docs.modular.com/releases/v25.1/#25-1-gpus" class="">GPU programming</a>.</p>
</li>
<li class="">
<p>Cached compiled MAX graphs that make use of custom operations now get
invalidated when the implementation of the custom operations change.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/#max.graph.Graph.add_weight"><code>Graph.add_weight()</code></a>
now takes an explicit <code>device</code> argument. This enables explicitly passing
GPU-resident weights to
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession.load"><code>session.load()</code></a>
via the weights registry to initialize the model.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Weight/"><code>max.graph.Weight</code></a> now inherits
from <code>TensorValue</code>, allowing you to call <code>weight.cast()</code> or <code>weight.T</code>. As
such, the
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/#max.graph.TensorValue"><code>TensorValue</code></a>
no longer accepts <code>Weight</code> for the <code>value</code> argument.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-pipelines">Pipeline APIs<a href="https://docs.modular.com/releases/v25.1/#25-1-pipelines" class="hash-link" aria-label="Direct link to Pipeline APIs" title="Direct link to Pipeline APIs" translate="no">​</a></h3>
<ul>
<li class="">
<p><code>TextTokenizer.new_context()</code>
now supports tool definitions passed through its <code>request</code> argument (via
<code>TokenGeneratorRequest.tools</code>).</p>
<ul>
<li class="">It also now supports JSON schemas passed through its <code>request</code> argument (via
<a class="" href="https://docs.modular.com/max/api/python/pipelines.lib.interfaces/#max.pipelines.interfaces.TokenGeneratorRequest.response_format"><code>TokenGeneratorRequest.response_format</code></a>).</li>
</ul>
</li>
<li class="">
<p>Removed the default <code>num_steps</code> value for
<a class="" href="https://docs.modular.com/max/api/python/pipelines.lib.interfaces/#max.pipelines.interfaces.TokenGenerator.next_token"><code>TokenGenerator.next_token()</code></a>,
ensuring users pass a value, reducing the potential for silent errors.</p>
</li>
<li class="">
<p><code>KVCacheStrategy</code>
now defaults to <code>MODEL_DEFAULT</code>.</p>
<p>As opposed to the previous setting which always used the "continuous" caching
strategy, KV caching strategy is now defaulted on an architecture-specific
basis to ensure the most optimized caching strategy is used.</p>
</li>
<li class="">
<p>The
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Linear/"><code>Linear</code></a>
layer now has a <code>create()</code> class method that automatically creates
specializations of <code>Linear</code> for non-quantized, k-quant, or GPTQ layers.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.nn.Conv1D/"><code>nn.Conv1D</code></a>
for audio models like Whisper.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-gpus">GPU programming<a href="https://docs.modular.com/releases/v25.1/#25-1-gpus" class="hash-link" aria-label="Direct link to GPU programming" title="Direct link to GPU programming" translate="no">​</a></h3>
<p>This release includes all new APIs to program on GPUs. The way to write code
for GPUs is to create custom operations with GPU functions that you can load
into a MAX graph. This foundational API includes a few key components:</p>
<ul>
<li class="">
<p>Mojo APIs to write custom op functions:</p>
<ul>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/mojo-decorators/compiler-register/"><code>@compiler.register</code></a>
decorator is applied to a Mojo struct that implements a custom op in an
<code>execute()</code> function—for either CPU or GPU—and a <code>shape()</code> function that
defines the custom op's output tensor.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/kernels/extensibility/tensor/"><code>max.tensor</code></a> package adds
essential Mojo APIs for writing custom ops, such as:</p>
<ul>
<li class="">
<p>The
<a class="" href="https://docs.modular.com/max/api/kernels/extensibility/tensor/managed_tensor_slice/foreach/"><code>foreach()</code></a>
function, which efficiently executes an element-wise computation in
parallel on either a GPU or CPU.</p>
</li>
<li class="">
<p>The
<a class="" href="https://docs.modular.com/max/api/kernels/extensibility/tensor/managed_tensor_slice/ManagedTensorSlice/"><code>ManagedTensorSlice</code></a>
type defines the input and output tensors for the custom op.</p>
</li>
</ul>
</li>
</ul>
</li>
<li class="">
<p>Python APIs to load custom ops into a model:</p>
<ul>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.custom"><code>custom()</code></a> and
<code>inplace_custom()</code>
functions allow you to add the previously-defined Mojo custom op to a MAX
graph written in Python.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession"><code>InferenceSession</code></a>
constructor accepts the custom op implementation as a
<a href="https://mojolang.org/docs/manual/packages#mojo-packages" target="_blank" rel="noopener noreferrer" class="">Mojo package</a> in
the <code>custom_extensions</code> argument.</p>
</li>
</ul>
</li>
</ul>
<p>For more detail, see the <a class="" href="https://docs.modular.com/max/develop/build-custom-ops/">tutorial to build custom ops for
GPUs</a>.</p>
<p>Additionally, we've added a new
<a href="https://mojolang.org/docs/std/gpu/" target="_blank" rel="noopener noreferrer" class=""><code>gpu</code> package</a> to the Mojo standard library
that provides low-level programming constructs for working with GPUs. These APIs
let you do things that you can't currently do with the high-level <code>foreach()</code>
abstraction above. The Mojo <code>gpu</code> APIs allow you to manually manage interaction
between the CPU host and GPU device, manage memory between devices, synchronize
threads, and more. For some examples, see
<a href="https://github.com/modular/modular/blob/main/max/examples/custom_ops/kernels/vector_addition.mojo" target="_blank" rel="noopener noreferrer" class=""><code>vector_addition.mojo</code></a>
and
<a href="https://github.com/modular/modular/blob/main/max/examples/custom_ops/kernels/top_k.mojo" target="_blank" rel="noopener noreferrer" class=""><code>top_k.mojo</code></a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-1-mojo">Mojo<a href="https://docs.modular.com/releases/v25.1/#25-1-mojo" class="hash-link" aria-label="Direct link to Mojo" title="Direct link to Mojo" translate="no">​</a></h2>
<p>Mojo is a crucial component of the MAX stack that enables all of MAX's
performance-oriented code across hardware. For all the updates to the Mojo
language, standard library, and tools, see the <a href="https://mojolang.org/releases" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.6]]></title>
            <link>https://docs.modular.com/releases/v24.6/</link>
            <guid>https://docs.modular.com/releases/v24.6/</guid>
            <pubDate>Tue, 17 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This is a huge update that offers a first look at our serving library for]]></description>
            <content:encoded><![CDATA[<p>This is a huge update that offers a first look at our serving library for
MAX on GPUs!</p>
<p>Also check out our
<a href="https://www.modular.com/blog/introducing-max-24-6-a-gpu-native-generative-ai-platform" target="_blank" rel="noopener noreferrer" class="">blog post introducing MAX 24.6</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-highlights">✨ Highlights<a href="https://docs.modular.com/releases/v24.6/#24-6-highlights" class="hash-link" aria-label="Direct link to ✨ Highlights" title="Direct link to ✨ Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p><strong>MAX Engine on GPUs preview</strong></p>
<p>We're excited to share a preview of MAX Engine on GPUs. We've created a few
tutorials that demonstrate MAX's ability to run GenAI models with our
next-generation MAX graph compiler on NVIDIA GPU architectures (including
A100, A10, L4, and L40 GPUs). You can experience it today by <a class="" href="https://docs.modular.com/max/deploy/local-to-cloud/">deploying
Llama 3 on an A100 GPU</a>.</p>
</li>
<li class="">
<p><strong>MAX Serve preview</strong></p>
<p>This release also includes an all-new serving interface called MAX
Serve. It's a Python-based serving layer that supports both
native MAX models when you want a high-performance deployment, and
off-the-shelf PyTorch LLMs from Hugging Face when you want to explore and
experiment—all with GPU support. It provides an OpenAI-compatible REST
endpoint for inference requests, and a Prometheus-compatible metrics
endpoint. You can use a <code>magic</code> command to start a local server , or use our
ready-to-deploy MAX container to start an endpoint in the cloud. Try it now
<a class="" href="https://docs.modular.com/max/deploy/local-to-cloud/">with an LLM from Hugging Face</a>.</p>
</li>
<li class="">
<p><strong>Upgraded MAX models</strong></p>
<p>As we continue to build our Python-based MAX Graph API that allows you to
build high-performance GenAI models, we've made a ton of performance
improvements to the existing models and added a few new models to our GitHub
repo. All the Python-based MAX models now support GPUs and broad model
architectures. For example,
<a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures/llama3" target="_blank" rel="noopener noreferrer" class=""><code>llama3</code></a>
adds compatibility for the LlamaForCausalLM family, which includes over
20,000 model variants and weights on Hugging Face.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-docs">Documentation<a href="https://docs.modular.com/releases/v24.6/#24-6-docs" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<p>New tutorials:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/deploy/local-to-cloud/">Deploy Llama 3 on GPU with MAX
Serve</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/deploy-max-serve-on-kubernetes/">Deploy Llama 3.1 on GPU-powered Kubernetes
clusters</a></p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/develop/get-started-with-max-graph-in-python/">Get started with MAX Graph in
Python</a></p>
</li>
</ul>
<p>Other new docs:</p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/container/">MAX container</a></p>
</li>
<li class="">
<p><a href="https://github.com/modular/modular/tree/main/benchmark" target="_blank" rel="noopener noreferrer" class="">Benchmark MAX
Serve</a></p>
</li>
</ul>
<p>Also, our documentation is now available for <strong>MAX nightly builds</strong>! If you're
building with a nightly
release, you can
switch to see the nightly docs using a toggle to the right of the search bar.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-serve">MAX Serve<a href="https://docs.modular.com/releases/v24.6/#24-6-serve" class="hash-link" aria-label="Direct link to MAX Serve" title="Direct link to MAX Serve" translate="no">​</a></h2>
<p>This release includes a preview of our Python-based serving library called MAX
Serve. It simplifies the process to deploy your own inference
server with consistent and reliable performance.</p>
<p>MAX Serve currently includes the following features:</p>
<ul>
<li class="">
<p>Deploys locally and to the cloud with our <a class="" href="https://docs.modular.com/max/container/">MAX container
image</a>, or with the <code>magic</code> CLI.</p>
</li>
<li class="">
<p>An OpenAI-compatible server with streaming <code>/chat/completion</code> and
<code>/completion</code> endpoints for LLM inference requests.</p>
</li>
<li class="">
<p>Prometheus-compatible <a class="" href="https://docs.modular.com/max/container/#metrics">metrics endpoint</a> with LLM
KPIs (TTFT and ITL) for monitoring and evaluating performance.</p>
</li>
<li class="">
<p>Supports most <code>TextGeneration</code> Hugging Face Hub models.</p>
</li>
<li class="">
<p>Multiprocess HTTP/model worker architecture to maximize CPU core utilization
by distributing multiple incoming requests across multiple processes, ensuring
both high throughput and responsiveness.</p>
</li>
<li class="">
<p>Continuous heterogeneous batching to combine multiple incoming requests into
a single inference (no waiting to fill a batch size) and improve total
throughput.</p>
</li>
</ul>
<p>There's much more still in the works for MAX Serve, but you can try it today
with our tutorials to <a class="" href="https://docs.modular.com/max/deploy/local-to-cloud/">Deploy Llama 3 on GPU with MAX
Serve</a>.</p>
<p><strong>Known issues:</strong></p>
<ul>
<li class="">
<p>While this release is enough to support typical chatbot applications,
this release does not yet support the function-calling portion of the
OpenAI API specification needed to enable robust agentic workflows.</p>
</li>
<li class="">
<p>Sampling is still limited and doesn't currently respect temperature or
other sampling-related API request input.</p>
</li>
<li class="">
<p>Structured generation is not supported.</p>
</li>
<li class="">
<p>Support for multi-modal models is still nascent.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-models">MAX models<a href="https://docs.modular.com/releases/v24.6/#24-6-models" class="hash-link" aria-label="Direct link to MAX models" title="Direct link to MAX models" translate="no">​</a></h2>
<p>All of our Python-based GenAI
<a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures" target="_blank" rel="noopener noreferrer" class="">models on GitHub</a>
now support GPUs!</p>
<p>As we add more models, we're also building a robust set of libraries and
infrastructure that make it easier to build and deploy a growing library of
LLMs. Some of which is available in a new
<a class="" href="https://docs.modular.com/max/api/python/pipelines/"><code>max.pipelines</code></a> package and some of it is alongside
the
<a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures" target="_blank" rel="noopener noreferrer" class="">models on GitHub</a>.
Here are just some of the highlights:</p>
<ul>
<li class="">
<p>Deep integration with the Hugging Face ecosystem for a quick-to-deploy
experience, such as using HF Model Hub tools to fetch config files, support
for weights in <a href="https://github.com/huggingface/safetensors" target="_blank" rel="noopener noreferrer" class="">safetensor</a>
format, support for HF tokenizers, and more. (We also support GGUF weight
formats.)</p>
</li>
<li class="">
<p>Expanded set of model abstractions for use by different LLM architectures:</p>
<ul>
<li class="">
<p>Attention layers (including highly optimized implementations with
configurable masking, like
<a href="https://github.com/modular/modular/tree/main/max/nn/attention/attention_with_rope.py" target="_blank" rel="noopener noreferrer" class=""><code>AttentionWithRope</code></a>).
The optimized attention layers include variants that accept an attention
mask. More memory-efficient variants that don't take a mask instead take a
"mask functor" argument to the kernel, which implements masking without
materializing a mask by computing a mask value from input coordinates on the
fly.</p>
</li>
<li class="">
<p>Transformers such as
<a href="https://github.com/modular/modular/tree/main/max/nn/transformer/transformer.py" target="_blank" rel="noopener noreferrer" class=""><code>Transformer</code> and <code>TransformerBlock</code></a>.
These include an initial implementation of ragged tensors—tensors for which
each dimension can have a different size, avoiding the use of padding tokens
by flattening a batch of sequences of differing lengths.</p>
</li>
<li class="">
<p>Common layers such as
<a href="https://github.com/modular/modular/tree/main/max/nn/norm/rms_norm.py" target="_blank" rel="noopener noreferrer" class=""><code>RMSNorm</code></a>,
<a href="https://github.com/modular/modular/tree/main/max/nn/embedding.py" target="_blank" rel="noopener noreferrer" class=""><code>Embedding</code></a>,
and
<a href="https://github.com/modular/modular/tree/main/max/nn/sequential.py" target="_blank" rel="noopener noreferrer" class=""><code>Sequential</code></a>.</p>
</li>
<li class="">
<p>KV cache management helpers, like
<code>ContinuousBatchingKVCacheManager</code>.</p>
</li>
<li class="">
<p>Low-level wrappers over optimized kernels like
<a href="https://github.com/modular/modular/tree/main/max/nn/kernels.py" target="_blank" rel="noopener noreferrer" class=""><code>fused_qk_ragged_rope</code></a>.
These are custom fused kernels that update the KV cache in place. Although
they are custom, they reuse the underlying kernel implementation by passing
in lambda functions used to retrieve inputs and write to outputs in place.</p>
</li>
</ul>
</li>
<li class="">
<p>Added generalized interfaces for text generation such as
<a class="" href="https://docs.modular.com/max/api/python/pipelines.lib.interfaces/#max.pipelines.interfaces.TokenGenerator"><code>TokenGenerator</code></a>
and <a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.PipelineModel/"><code>PipelineModel</code></a>,
which provide modularity within the models and serving infrastructure. Also
added a plug-in mechanism
(<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.lib.registry.PipelineRegistry/"><code>PipelineRegistry</code></a>)
to more quickly define new models, tokenizers, and other reusable components.
For example, anything that conforms to
<a class="" href="https://docs.modular.com/max/api/python/pipelines.lib.interfaces/#max.pipelines.interfaces.TokenGenerator"><code>TokenGenerator</code></a>
can be served using the LLM infrastructure within MAX Serve. We then used this
interface to create the following:</p>
<ul>
<li class="">
<p>An optimized
<a class="" href="https://docs.modular.com/max/api/python/generated/max.pipelines.TextGenerationPipeline/"><code>TextGenerationPipeline</code></a>
that can be combined with any compatible graph and has powerful performance
features like graph-based multi-step scheduling, sampling, KV cache
management, ragged tensor support, and more.</p>
</li>
<li class="">
<p>A generic
<code>HFTextGenerationPipeline</code>
that can run any Hugging Face model for which we don't yet have an optimized
implementation in eager mode.</p>
</li>
</ul>
</li>
<li class="">
<p>Models now accept weights via a weights registry, which is passed to the
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession.load"><code>session.load()</code></a>
method's <code>weights_registry</code> argument. The decoupling of weights and model
architecture allows implementing all of the different fine-tunes for a given
model with the same graph. Furthermore, because the underlying design is
decoupled, we can later expose the ability to compile a model once and swap
weights out on the fly, without re-compiling the model.</p>
</li>
<li class="">
<p>Added generic implementations of common kernels, which allow you to plug-in
different batching strategies (ragged or padded), KV cache management
approaches (continuous batching), masking (causal, sliding window, etc.), and
position encoding (RoPE or ALIBI) without having to re-write any kernel code.
(More about this in a future release.)</p>
</li>
<li class="">
<p>Multi-step scheduling to run multiple token-generation steps on GPU before
synchronizing to the CPU.</p>
</li>
</ul>
<p><strong>Updated models:</strong></p>
<ul>
<li class="">Significant performance upgrades for
<a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures/llama3" target="_blank" rel="noopener noreferrer" class="">Llama 3</a>,
and expanded compatibility with the <code>LlamaForCausalLM</code> models family. For
example, it also supports Llama 3.2 1B and 3B text models.</li>
</ul>
<p><strong>New models:</strong></p>
<ul>
<li class="">
<p><a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures/mistral" target="_blank" rel="noopener noreferrer" class="">Mistral NeMo</a>
(and other <code>MistralForCausalLM</code> models)</p>
</li>
<li class="">
<p><a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures/replit" target="_blank" rel="noopener noreferrer" class="">Replit Code V1.5 3B</a></p>
</li>
</ul>
<p><strong>Known issues:</strong></p>
<ul>
<li class="">
<p>The Q4 quantized models currently work on CPU only.</p>
</li>
<li class="">
<p>Using a large setting for <code>top-k</code> with the Llama 3.1 model may lead to
segmentation faults for certain workloads when run on NVIDIA GPUs. This should
be resolved in the latest nightly MAX builds.</p>
</li>
<li class="">
<p>The models currently use a smaller default context window than the
<code>max_seq_len</code> specified in the Hugging Face configuration files for a given
model. This can be manually adjusted by setting the <code>--max-length</code> parameter
to the desired context length when serving a model.</p>
</li>
<li class="">
<p>Some variants of the supported core models (like <code>LlamaForCausalLM</code> with
different number of heads, head sizes, etc.) might not be fully optimized yet.
We plan to fully generalize our implementations in a future release.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-engine">MAX Engine<a href="https://docs.modular.com/releases/v24.6/#24-6-engine" class="hash-link" aria-label="Direct link to MAX Engine" title="Direct link to MAX Engine" translate="no">​</a></h2>
<p>MAX Engine includes a lot of the
core infrastructure that enables MAX to accelerate AI models on any hardware,
such as the graph compiler, runtime, kernels, and the APIs to interact with it
all, and it all works without external dependencies such as PyTorch or CUDA.</p>
<p>This release includes a bunch of performance upgrades to our graph compiler and
runtime. We've added support for NVIDIA GPU architectures (including A100, A10,
L4, and L40 GPUs), and built out new infrastructure so we can quickly add
support for other GPU hardware.</p>
<p><strong>Engine API changes:</strong></p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession"><code>InferenceSession</code></a>
now accepts a <code>custom_extensions</code> constructor argument, same as <code>load()</code>, to
specify model extension libraries.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model"><code>Model</code></a> object is now callable
to run an inference.</p>
</li>
</ul>
<p><strong>Breaking changes</strong>:</p>
<ul>
<li class=""><code>Model.execute()</code> signature changed to support GPUs.
<ul>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.execute"><code>execute()</code></a> function
currently doesn't accept keyword arguments. Instead you can pass tensors as
a <a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor"><code>driver.Tensor</code></a>, <code>int</code>,
<code>float</code>, <code>bool</code>,
<a href="https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.generic" target="_blank" rel="noopener noreferrer" class=""><code>np.generic</code></a>,
or <a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.DLPackArray"><code>DLPackArray</code></a>
(<a href="https://github.com/dmlc/dlpack" target="_blank" rel="noopener noreferrer" class="">DLPack</a>). Note that both PyTorch and NumPy
arrays implement the DLPack protocol, which means you can also pass either
of those types to <code>execute()</code>.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.Model.execute_legacy"><code>execute_legacy()</code></a>
preserves the semantics of <code>execute()</code> with support for keyword arguments to
help with migration, but will be removed in a future release.
<code>execute_legacy()</code> doesn't support GPUs.</p>
</li>
<li class="">
<p>Calling <code>execute()</code> with positional arguments still works the same.</p>
</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-driver-api">Driver APIs<a href="https://docs.modular.com/releases/v24.6/#24-6-driver-api" class="hash-link" aria-label="Direct link to Driver APIs" title="Direct link to Driver APIs" translate="no">​</a></h3>
<p>MAX Driver (the <a class="" href="https://docs.modular.com/max/api/python/driver/"><code>max.driver</code></a> module) is a new
component of MAX Engine that's still a work in progress. It provides primitives
for working with heterogeneous hardware systems (GPUs and CPUs), such as to
allocate on-device memory, transfer data between host and device, query device
stats, and more. It's a foundation on which other components of MAX Engine
operate (for example, <code>InferenceEngine</code> now uses
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor"><code>driver.Tensor</code></a> to handle model
inputs and outputs).</p>
<p><strong>Driver API changes:</strong></p>
<ul>
<li class="">
<p>Added <code>CUDA()</code> device to open an NVIDIA GPU.</p>
</li>
<li class="">
<p>Added support for fp16 and bfloat16 dtypes.</p>
</li>
<li class="">
<p>Expanded functionality for <code>max.driver.Device</code>, with new class methods and
properties. We are still working on building this out to support more
accelerator features.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor"><code>driver.Tensor</code></a> (and the
<code>InferenceSession.load()</code> argument <code>weights_registry</code> ) now supports zero-copy
interoperability with NumPy arrays and PyTorch tensors, using
<a href="https://github.com/dmlc/dlpack" target="_blank" rel="noopener noreferrer" class="">DLPack</a> /
<a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.DLPackArray"><code>DLPackArray</code></a>.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/driver/#max.driver.Tensor"><code>driver.Tensor</code></a> has new methods,
such as <code>from_dlpack()</code>, <code>element_size()</code> , <code>to()</code>, <code>to_numpy()</code>, <code>view()</code>,
<code>zeros()</code>, and more.</p>
</li>
</ul>
<p>MAX Driver APIs are still changing rapidly and not yet ready for general use.
We'll publish more documentation in a future release.</p>
<p><strong>Known issues:</strong></p>
<ul>
<li class="">
<p>MAX Driver is currently limited to managing just one NVIDIA GPU at a time (it
does not yet support multi-GPU). It also does not yet support remote devices.</p>
</li>
<li class="">
<p>DLPack support is not complete. For example, streams are not yet supported.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-graph-compiler">Graph compiler<a href="https://docs.modular.com/releases/v24.6/#24-6-graph-compiler" class="hash-link" aria-label="Direct link to Graph compiler" title="Direct link to Graph compiler" translate="no">​</a></h3>
<p>When you load a model into MAX Engine, the graph compiler is the component that
inspects and optimizes all graph operations (ops) to deliver the best run time
performance on each device.</p>
<p>This release includes various graph compiler improvements:</p>
<ul>
<li class="">
<p>Major extensions to support NVIDIA GPUs (and other devices in the future),
including async copies and caching of JIT'd kernels.</p>
</li>
<li class="">
<p>The runtime now performs scheduling to enable GPU compute overlap with the
CPU.</p>
</li>
<li class="">
<p>New transformations to the Mojo kernels to enable a number of optimizations,
including specialization on tensor dimensions, specialization on target
hardware, specialization on non-tensor dimension input to kernels, automatic
kernel fusion between operators, and more.</p>
</li>
<li class="">
<p>New algebraic simplifications and algorithms for ops such as horizontal
fusion of matrix multiplications.</p>
</li>
<li class="">
<p>New CPU-side primitives for device management that are automatically
transformed and optimized to reduce overhead (MAX does not need to use things
like CUDA Graphs).</p>
</li>
<li class="">
<p>Updated memory planning to preallocate device memory (hoist computation from
inference runtime to initialization time) and reduce per-inference overhead.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-graph-api">Graph APIs<a href="https://docs.modular.com/releases/v24.6/#24-6-graph-api" class="hash-link" aria-label="Direct link to Graph APIs" title="Direct link to Graph APIs" translate="no">​</a></h3>
<p>The graph compiler is also exposed through the MAX Graph APIs (the
<a class="" href="https://docs.modular.com/max/api/python/graph/"><code>max.graph</code></a> package), which allow you to build
high-performance GenAI models in Python.</p>
<p><strong>Graph API changes:</strong></p>
<ul>
<li class="">
<p>Python stack traces from model execution failures now include a trace to the
original op-creation, allowing for easier debugging during development.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/graph/"><code>max.graph</code></a> APIs now include preliminary support
for symbolic algebraic expressions using
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.AlgebraicDim/"><code>AlgebraicDim</code></a>, enabling
more powerful support for checked dynamic shapes. This allows <code>-Dim("x") - 4</code>.
Furthermore, the algebraic expressions simplify to a canonical form, so that
for example <code>-Dim("x") - 4 == -(Dim("x") + 4)</code> holds.</p>
</li>
<li class="">
<p>More advanced dtype promotion now allows
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/"><code>TensorValue</code></a>
math operators to just work when used with NumPy arrays and
python primitives.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/"><code>TensorValue</code></a>
has new methods, such as <code>broadcast_to()</code>, <code>cast()</code>,
<code>flatten()</code>, <code>permute()</code>, and more.</p>
</li>
<li class="">
<p>Added
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.BufferValue/"><code>BufferValue</code></a>,
which allows for device-resident tensors that are read and
mutated within the graph.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/dtype/#max.dtype.DType"><code>DType</code></a> has new methods/properties,
<code>align</code>, <code>size_in_bytes</code>, and <code>is_float()</code>.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Value/"><code>Value</code></a> constructor
accepts more types for <code>value</code>.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/"><code>TensorValue</code></a>
constructor accepts more types for <code>value</code>.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/#max.graph.TensorValue.rebind"><code>TensorValue.rebind()</code></a>
accepts a new <code>message</code> argument.</p>
</li>
</ul>
<p><strong>Breaking changes:</strong></p>
<ul>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Graph/#max.graph.Graph.add_weight"><code>Graph.add_weight()</code></a>
now accepts
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Weight/#max.graph.Weight"><code>Weight</code></a> and
returns <a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.TensorValue/"><code>TensorValue</code></a>.
<a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Weight/#max.graph.Weight"><code>Weight</code></a> is
essentially a named placeholder for a tensor that knows its name, dtype,
shape, and optionally device and quantization encoding. <code>Graph.add_weight()</code>
stages an op in the graph that is populated by a named weight in the weights
registry passed to <code>session.load</code>.</p>
</li>
<li class="">
<p>The <a class="" href="https://docs.modular.com/max/api/python/generated/max.graph.Weight/#max.graph.Weight"><code>Weight</code></a>
constructor
arguments changed; added <code>align</code> , <code>dtype</code> , and <code>shape</code>; removed <code>assign</code> ,
<code>filepath</code>, <code>offset</code>, and <code>value</code>.</p>
</li>
<li class="">
<p>The <code>ops.scalar()</code> method was removed along with the <code>is_static()</code> and
<code>is_symbolic()</code> methods from all <code>graph.type</code> objects.</p>
<ul>
<li class="">
<p>Instead of <code>ops.scalar()</code>, use
<a class="" href="https://docs.modular.com/max/api/python/graph.ops/#max.graph.ops.constant"><code>ops.constant()</code></a>.</p>
</li>
<li class="">
<p>Instead of <code>is_static()</code> and <code>is_symbolic()</code>, use
<code>isinstance(dim, SymbolicDim)</code> and <code>isinstance(dim, StaticDim)</code>.</p>
</li>
</ul>
</li>
</ul>
<p>The MAX Graph APIs are not ready for general use but you can <a class="" href="https://docs.modular.com/max/develop/get-started-with-max-graph-in-python/">experiment with
it now by following this
tutorial</a>. We'll add more
documentation when we finish some API redesigns.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-custom-ops">Custom op registration<a href="https://docs.modular.com/releases/v24.6/#24-6-custom-ops" class="hash-link" aria-label="Direct link to Custom op registration" title="Direct link to Custom op registration" translate="no">​</a></h3>
<p>Although the APIs to write custom operators (ops) isn't ready for general use,
this release includes a significant redesign that lays the groundwork. You
might notice some associated APIs in this release and more APIs in the
nightlies, so here's a little about the work in progress:</p>
<ul>
<li class="">
<p>The custom op APIs will allow you to extend MAX Engine with new ops written
in Mojo, providing full composability and extensibility for your models. It's
the exact same API we use to write MAX Engine's built-in ops such as <code>matmul</code>.
That means your custom ops can benefit from all our compiler optimization
features such as kernel fusion—your ops are treated the same as all the ops
included "in the box."</p>
</li>
<li class="">
<p>The new API requires far less adornment at the definition site to enable the
MAX model compiler to optimize custom ops along with the rest of the graph
(compared to our previous version that used <code>NDBuffer</code>).</p>
</li>
<li class="">
<p>Custom ops support "destination passing style" for tensors.</p>
</li>
<li class="">
<p>The design composes on top of Mojo's powerful meta programming, as well as
the kernel libraries abstractions for composable kernels.</p>
</li>
</ul>
<p>We'll publish more documentation when the custom op API is ready for general
use. Check out the MAX repo's <code>nightly</code> branch to see the latest <a href="https://github.com/modular/modular/tree/main/max/examples/custom_ops" target="_blank" rel="noopener noreferrer" class="">custom op
examples</a>.</p>
<p><strong>Known issues:</strong></p>
<ul>
<li class="">Custom ops don't have type or lifetime checking. They also don't reason about
mutability. Expect lots of sharp corners and segfaults if you hold them wrong
while we improve this!</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-kernels">Numeric kernels<a href="https://docs.modular.com/releases/v24.6/#24-6-kernels" class="hash-link" aria-label="Direct link to Numeric kernels" title="Direct link to Numeric kernels" translate="no">​</a></h3>
<p>The GPU kernels for MAX Engine are built from the ground up in Mojo with no
dependencies on external vendor code or libraries. This release includes the
following kernel improvements:</p>
<ul>
<li class="">
<p>AttenGen: a novel way to express attention pattern that's able to express
different attention masks, score functions, as well as caching strategies.</p>
</li>
<li class="">
<p>State-of-the-art matrix multiplication algorithms with optimizations such as
the following:</p>
<ul>
<li class="">
<p>Pipelining and double-buffering to overlap data transfer and computation
and to hide memory access latency (for both global and shared memory).</p>
</li>
<li class="">
<p>Thread swizzling to avoid shared memory bank conflicts associated with
tensor core layouts.</p>
</li>
<li class="">
<p>Block swizzling to increase L2 cache locality.</p>
</li>
</ul>
</li>
<li class="">
<p>SplitK/StreamK GEMM algorithms: divides the computation along the shared K
dimension into smaller matrices which can then be executed independently on
streaming multiprocessors (such as CUDA cores). These algorithms are ideal for
matrices with large K dimension but small M dimension.</p>
</li>
<li class="">
<p>Large context length MHA: uses SplitK/StreamK to implement the attention
mechanism and eliminate the need of a huge score matrix, which drastically
reduces memory usage/traffic to enable large context length.</p>
</li>
<li class="">
<p>DualGemm: accelerates the multi-layer perceptron (MLP) layers where the
left-hand side (LHS) is shared between two matrix multiplications.</p>
</li>
</ul>
<p><strong>Known issues:</strong></p>
<ul>
<li class="">
<p>The MAX kernels are optimized for bfloat16 on GPUs.</p>
</li>
<li class="">
<p>Convolution on GPU is not performance optimized yet.</p>
</li>
<li class="">
<p>Although v24.6 technically runs on H100, it doesn't include
performance-optimized kernels for that device yet and it isn't recommended.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-6-mojo">Mojo<a href="https://docs.modular.com/releases/v24.6/#24-6-mojo" class="hash-link" aria-label="Direct link to Mojo" title="Direct link to Mojo" translate="no">​</a></h2>
<p>Mojo is a crucial component of the MAX stack that enables all of MAX's
performance-oriented code across hardware. For all the updates to the Mojo
language, standard library, and tools, see the <a href="https://mojolang.org/releases#v246-2024-12-17" target="_blank" rel="noopener noreferrer" class="">Mojo
changelog</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.5]]></title>
            <link>https://docs.modular.com/releases/v24.5/</link>
            <guid>https://docs.modular.com/releases/v24.5/</guid>
            <pubDate>Fri, 13 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[✨ Highlights]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-highlights">✨ Highlights<a href="https://docs.modular.com/releases/v24.5/#-highlights" class="hash-link" aria-label="Direct link to ✨ Highlights" title="Direct link to ✨ Highlights" translate="no">​</a></h2>
<ul>
<li class="">
<p>Mojo and MAX are magical! We've created a new package and virtual environment
manager, <code>magic</code>, for MAX and Mojo.</p>
</li>
<li class="">
<p>New
<a href="https://github.com/modular/modular/tree/main/max/pipelines/architectures" target="_blank" rel="noopener noreferrer" class="">Llama3.1 pipeline</a>
built with the new MAX Graph Python API.</p>
</li>
<li class="">
<p>We have not one, but two new Python APIs that we're introducing in this
release:</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="️-new">⭐️ New<a href="https://docs.modular.com/releases/v24.5/#%EF%B8%8F-new" class="hash-link" aria-label="Direct link to ⭐️ New" title="Direct link to ⭐️ New" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added <code>repeat_interleave</code> graph op.</p>
</li>
<li class="">
<p>Added caching for MAX graph models.
This means that graph compilation is cached and the executable model is
retrieved from cache on the 2nd and subsequent runs.
Note that the model cache is architecture specific and isn't portable across
different targets.</p>
</li>
<li class="">
<p>Support for Python 3.12.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-graph-python-api">MAX Graph Python API<a href="https://docs.modular.com/releases/v24.5/#max-graph-python-api" class="hash-link" aria-label="Direct link to MAX Graph Python API" title="Direct link to MAX Graph Python API" translate="no">​</a></h3>
<p>This Python API
will ultimately provide the same low-level programming interface for
high-performance inference graphs as the Mojo API. As with the Mojo API, it's an
API for graph-building only, and it does not implement support for training.</p>
<p>You can take a look at how the API works in the
<a class="" href="https://docs.modular.com/max/api/python/graph/">MAX Graph Python API reference</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-driver-python-api">MAX Driver Python API<a href="https://docs.modular.com/releases/v24.5/#max-driver-python-api" class="hash-link" aria-label="Direct link to MAX Driver Python API" title="Direct link to MAX Driver Python API" translate="no">​</a></h3>
<p>The MAX Driver API allows you to interact with devices (such as CPUs and GPUs)
and allocate memory directly onto them. With this API, you interact with
this memory as tensors.</p>
<p>Note that this API is still under development, with support for non-host
devices, such as GPUs, planned for a future release.</p>
<p>To learn more, check out the
<a class="" href="https://docs.modular.com/max/api/python/driver/">MAX Driver Python APIreference</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-c-api">MAX C API<a href="https://docs.modular.com/releases/v24.5/#max-c-api" class="hash-link" aria-label="Direct link to MAX C API" title="Direct link to MAX C API" translate="no">​</a></h3>
<p>New APIs for adding torch metadata libraries:</p>
<ul>
<li class=""><code>M_setTorchMetadataLibraryPath</code></li>
<li class=""><code>M_setTorchMetadataLibraryPtr</code></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-changed">🦋 Changed<a href="https://docs.modular.com/releases/v24.5/#-changed" class="hash-link" aria-label="Direct link to 🦋 Changed" title="Direct link to 🦋 Changed" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-engine-performance">MAX Engine performance<a href="https://docs.modular.com/releases/v24.5/#max-engine-performance" class="hash-link" aria-label="Direct link to MAX Engine performance" title="Direct link to MAX Engine performance" translate="no">​</a></h3>
<ul>
<li class="">Compared to v24.4, MAX Engine v24.5 generates tokens for Llama an average of
15%-48% faster.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-c-api-1">MAX C API<a href="https://docs.modular.com/releases/v24.5/#max-c-api-1" class="hash-link" aria-label="Direct link to MAX C API" title="Direct link to MAX C API" translate="no">​</a></h3>
<p>Simplified the API for adding torch library paths, which now only takes one path
per API call, but can be called multiple times to add paths to the config:</p>
<ul>
<li class=""><code>M_setTorchLibraries</code> -&gt; <code>M_setTorchLibraryPath</code></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="️-deprecated">⚠️ Deprecated<a href="https://docs.modular.com/releases/v24.5/#%EF%B8%8F-deprecated" class="hash-link" aria-label="Direct link to ⚠️ Deprecated" title="Direct link to ⚠️ Deprecated" translate="no">​</a></h2>
<ul>
<li class="">The <code>max</code> command line tool is no longer supported and will be removed
in a future release.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-removed">❌ Removed<a href="https://docs.modular.com/releases/v24.5/#-removed" class="hash-link" aria-label="Direct link to ❌ Removed" title="Direct link to ❌ Removed" translate="no">​</a></h2>
<ul>
<li class="">Dropped support for Ubuntu 20.04. If you're using Ubuntu, we currently
support Ubuntu 22.04 LTS only.</li>
<li class="">Dropped support for Python 3.8.</li>
<li class="">Removed built-in PyTorch libraries from the max package. See the
<a class="" href="https://docs.modular.com/max/faq/">FAQ</a> for information on supported torch versions.</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.4]]></title>
            <link>https://docs.modular.com/releases/v24.4/</link>
            <guid>https://docs.modular.com/releases/v24.4/</guid>
            <pubDate>Fri, 07 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[🔥 Legendary]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-legendary">🔥 Legendary<a href="https://docs.modular.com/releases/v24.4/#-legendary" class="hash-link" aria-label="Direct link to 🔥 Legendary" title="Direct link to 🔥 Legendary" translate="no">​</a></h2>
<ul>
<li class="">
<p>MAX is now available on macOS! <a class="" href="https://docs.modular.com/max/">Try it now</a>.</p>
</li>
<li class="">
<p>New quantization APIs for MAX Graph. You can now build high-performance
graphs in Mojo that use the latest quantization techniques, enabling even
faster performance and more system compatibility for large models.</p>
<p>Learn more in the guide to <a class="" href="https://docs.modular.com/max/graph/quantize/">quantize your graph weights</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="️-new">⭐️ New<a href="https://docs.modular.com/releases/v24.4/#%EF%B8%8F-new" class="hash-link" aria-label="Direct link to ⭐️ New" title="Direct link to ⭐️ New" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-mojo-apis">MAX Mojo APIs<a href="https://docs.modular.com/releases/v24.4/#max-mojo-apis" class="hash-link" aria-label="Direct link to MAX Mojo APIs" title="Direct link to MAX Mojo APIs" translate="no">​</a></h3>
<ul>
<li class="">
<p>Added AI pipeline examples in the <code>max</code> repo, with Mojo implementations for
common transformer layers, including quantization support.</p>
<ul>
<li class="">
<p>New Llama3 pipeline built with MAX Graph.</p>
</li>
<li class="">
<p>New Replit Code pipeline built with MAX Graph.</p>
</li>
<li class="">
<p>New TinyStories pipeline (based on TinyLlama) that offers a simple demo of
the MAX Graph quantization API.</p>
</li>
</ul>
</li>
<li class="">
<p>Added <code>max.graph.checkpoint</code> package
to save and load model weights.</p>
<p>All weights are stored in a
<code>TensorDict</code>.
You can save and load a <code>TensorDict</code> to disk with
<code>save()</code> and
<code>load()</code> functions.</p>
</li>
<li class="">
<p>Added MAX Graph quantization APIs:</p>
<ul>
<li class="">Added quantization encodings
<code>BFloat16Encoding</code>,
<code>Q4_0Encoding</code>,
<code>Q4_KEncoding</code>,
and
<code>Q6_KEncoding</code>.</li>
<li class="">Added the
<code>QuantizationEncoding</code>
trait so you can build custom quantization encodings.</li>
<li class="">Added <code>Graph.quantize()</code>
to create a quantized tensor node.</li>
<li class="">Added <code>qmatmul()</code> to
perform matrix-multiplication with a float32 and a quantized matrix.</li>
</ul>
</li>
<li class="">
<p>Added some MAX Graph ops:</p>
<ul>
<li class=""><code>avg_pool()</code></li>
<li class=""><code>max_pool()</code></li>
<li class=""><code>conv2d()</code></li>
<li class=""><code>conv3d()</code></li>
<li class=""><code>layer_norm()</code></li>
<li class=""><code>tile()</code></li>
<li class=""><code>select()</code></li>
</ul>
</li>
<li class="">
<p>Added a <code>layer()</code> context
manager and
<code>current_layer()</code>
function to aid in debugging during graph construction. For example:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>with graph.layer("foo"):
    with graph.layer("bar"):
        print(graph.current_layer())  # prints "foo.bar"
        x = graph.constant[DType.int64](1)
        graph.output(x)</code></pre></div></div>
<p>This adds a path <code>foo.bar</code> to the added nodes, which will
be reported during errors.</p>
</li>
<li class="">
<p>Added
<code>format_system_stack()</code>
function to format the stack trace, which we use to print better error
messages from <code>error()</code>.</p>
</li>
<li class="">
<p>Added
<code>TensorMap.keys()</code> to
get all the tensor key names.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-c-api">MAX C API<a href="https://docs.modular.com/releases/v24.4/#max-c-api" class="hash-link" aria-label="Direct link to MAX C API" title="Direct link to MAX C API" translate="no">​</a></h3>
<p>Miscellaneous new APIs:</p>
<ul>
<li class=""><code>M_cloneCompileConfig()</code></li>
<li class=""><code>M_copyAsyncTensorMap()</code></li>
<li class=""><code>M_tensorMapKeys()</code> and <code>M_deleteTensorMapKeys()</code></li>
<li class=""><code>M_setTorchLibraries()</code></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-changed">🦋 Changed<a href="https://docs.modular.com/releases/v24.4/#-changed" class="hash-link" aria-label="Direct link to 🦋 Changed" title="Direct link to 🦋 Changed" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-mojo-api">MAX Mojo API<a href="https://docs.modular.com/releases/v24.4/#max-mojo-api" class="hash-link" aria-label="Direct link to MAX Mojo API" title="Direct link to MAX Mojo API" translate="no">​</a></h3>
<ul>
<li class="">
<p><code>EngineNumpyView.data()</code>
and <code>EngineTensorView.data()</code>
functions that return a type-erased pointer were renamed to <code>unsafe_ptr()</code>.</p>
</li>
<li class="">
<p><code>TensorMap</code> now conforms
to <code>CollectionElement</code> trait to be copyable and movable.</p>
</li>
<li class="">
<p><code>custom_nv()</code> was removed, and its functionality moved into
<code>custom()</code> as a function
overload, so it can now output a list of tensor symbols.</p>
</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.3]]></title>
            <link>https://docs.modular.com/releases/v24.3/</link>
            <guid>https://docs.modular.com/releases/v24.3/</guid>
            <pubDate>Thu, 02 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[🔥 Legendary]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-legendary">🔥 Legendary<a href="https://docs.modular.com/releases/v24.3/#-legendary" class="hash-link" aria-label="Direct link to 🔥 Legendary" title="Direct link to 🔥 Legendary" translate="no">​</a></h2>
<ul>
<li class="">
<p>You can now write custom ops for your models with Mojo!</p>
<p>Learn more about <a class="" href="https://docs.modular.com/max/develop/custom-ops/">MAX extensibility</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-changed">🦋 Changed<a href="https://docs.modular.com/releases/v24.3/#-changed" class="hash-link" aria-label="Direct link to 🦋 Changed" title="Direct link to 🦋 Changed" translate="no">​</a></h2>
<ul>
<li class="">
<p>Added support for named dynamic dimensions. This means you can specify when
two
or more dimensions in your model's input are dynamic but their sizes at run
time must match each other. By specifying each of these dimension sizes with a
name (instead of using <code>None</code> to indicate a dynamic size), the MAX Engine
compiler can perform additional optimizations. See the notes below for the
corresponding API changes that support named dimensions.</p>
</li>
<li class="">
<p>Simplified all the APIs to load input specs for models, making them more
consistent.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-engine-performance">MAX Engine performance<a href="https://docs.modular.com/releases/v24.3/#max-engine-performance" class="hash-link" aria-label="Direct link to MAX Engine performance" title="Direct link to MAX Engine performance" translate="no">​</a></h3>
<ul>
<li class="">Compared to v24.2, MAX Engine v24.3 shows an average speedup of 10% on PyTorch
models, and an average 20% speedup on dynamically quantized ONNX transformers.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-graph-api">MAX Graph API<a href="https://docs.modular.com/releases/v24.3/#max-graph-api" class="hash-link" aria-label="Direct link to MAX Graph API" title="Direct link to MAX Graph API" translate="no">​</a></h3>
<p>The <code>max.graph</code> APIs are still changing
rapidly, but starting to stabilize.</p>
<ul>
<li class="">
<p><code>AnyMoType</code> renamed to <code>Type</code>,
<code>MOTensor</code> renamed to
<code>TensorType</code>, and <code>MOList</code>
renamed to <code>ListType</code>.</p>
</li>
<li class="">
<p>Removed <code>ElementType</code> in favor of using <code>DType</code>.</p>
</li>
<li class="">
<p>Removed <code>TypeTuple</code> in favor of using <code>List[Type]</code>.</p>
</li>
<li class="">
<p>Removed the <code>Module</code> type so you can now start building a graph by directly
instantiating a <code>Graph</code>.</p>
</li>
<li class="">
<p>Some new ops in <code>max.ops</code>, including
support for custom ops.</p>
<p>See how to <a class="" href="https://docs.modular.com/max/develop/build-custom-ops/">create a custom op in MAX
Graph</a>.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-engine-python-api">MAX Engine Python API<a href="https://docs.modular.com/releases/v24.3/#max-engine-python-api" class="hash-link" aria-label="Direct link to MAX Engine Python API" title="Direct link to MAX Engine Python API" translate="no">​</a></h3>
<ul>
<li class="">
<p>Redesigned
<a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.InferenceSession.load"><code>InferenceSession.load()</code></a>
to replace the confusing <code>options</code> argument with a <code>custom_ops_path</code> argument.</p>
<p>As a result, <code>CommonLoadOptions</code>, <code>TorchLoadOptions</code>, and
<code>TensorFlowLoadOptions</code> have all been removed.</p>
</li>
<li class="">
<p><a class="" href="https://docs.modular.com/max/api/python/engine/#max.engine.TorchInputSpec"><code>TorchInputSpec</code></a>
now supports named dynamic dimensions (previously, dynamic dimension sizes
could be specified only as <code>None</code>). This lets you tell MAX which dynamic
dimensions are required to have the same size, which helps MAX better optimize
your model.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-engine-mojo-api">MAX Engine Mojo API<a href="https://docs.modular.com/releases/v24.3/#max-engine-mojo-api" class="hash-link" aria-label="Direct link to MAX Engine Mojo API" title="Direct link to MAX Engine Mojo API" translate="no">​</a></h3>
<ul>
<li class="">
<p><code>InferenceSession.load_model()</code> was renamed to
<code>load()</code>.</p>
</li>
<li class="">
<p>Redesigned
<code>InferenceSession.load()</code>
to replace the confusing <code>config</code> argument with a <code>custom_ops_path</code> argument
for use when <a class="" href="https://docs.modular.com/max/develop/build-custom-ops/">loading a custom op</a>, and an
<code>input_specs</code> argument for use when loading TorchScript models.</p>
<p>Doing so removed <code>LoadOptions</code> and introduced the new
<code>InputSpec</code> type to define
the input shape/type of a model (instead of <code>LoadOptions</code>).</p>
</li>
<li class="">
<p>New <code>ShapeElement</code>
type to allow for named dynamic dimensions (in <code>InputSpec</code>).</p>
</li>
<li class="">
<p><code>max.engine.engine</code> module was renamed to
<code>max.engine.info</code>.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="max-engine-c-api">MAX Engine C API<a href="https://docs.modular.com/releases/v24.3/#max-engine-c-api" class="hash-link" aria-label="Direct link to MAX Engine C API" title="Direct link to MAX Engine C API" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://docs.modular.com/max/api/c/pytorch/config/#m_newtorchinputspec"><code>M_newTorchInputSpec()</code></a>
now supports named dynamic dimensions (via new <code>dimNames</code> argument).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-removed">❌ Removed<a href="https://docs.modular.com/releases/v24.3/#-removed" class="hash-link" aria-label="Direct link to ❌ Removed" title="Direct link to ❌ Removed" translate="no">​</a></h2>
<ul>
<li class="">
<p>Removed TensorFlow support in the MAX SDK, so you can no longer load a
TensorFlow SavedModel for inference. However, TensorFlow is still available
for enterprise customers.</p>
<p>We removed TensorFlow because industry-wide TensorFlow usage has declined
significantly, especially for the latest AI innovations. Removing TensorFlow
also cuts our package size by over 50% and accelerates the development of
other customer-requested features. If you have a production use-case for a
TensorFlow model, please <a href="https://www.modular.com/request-demo" target="_blank" rel="noopener noreferrer" class="">contact us</a>.</p>
</li>
<li class="">
<p>Removed the Python <code>CommonLoadOptions</code>, <code>TorchLoadOptions</code>, and
<code>TensorFlowLoadOptions</code> classes. See note above about
<code>InferenceSession.load()</code> changes.</p>
</li>
<li class="">
<p>Removed the Mojo <code>LoadOptions</code> type. See the note above about
<code>InferenceSession.load()</code> changes.</p>
</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.2.1]]></title>
            <link>https://docs.modular.com/releases/v24.2.1/</link>
            <guid>https://docs.modular.com/releases/v24.2.1/</guid>
            <pubDate>Thu, 11 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[- You can now import more MAX Graph functions from max.graph.ops instead of]]></description>
            <content:encoded><![CDATA[<ul>
<li class="">
<p>You can now import more MAX Graph functions from <code>max.graph.ops</code> instead of
using <code>max.graph.ops.elementwise</code>. For example:</p>
<div class="language-mojo codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:rgb(238, 240, 244);--prism-color:rgb(38, 44, 48)"><div class="codeBlockContent_QJqH"><pre class="codeBlockBg"><code>from max.graph import ops

var relu = ops.relu(matmul)</code></pre></div></div>
</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MAX v24.2]]></title>
            <link>https://docs.modular.com/releases/v24.2/</link>
            <guid>https://docs.modular.com/releases/v24.2/</guid>
            <pubDate>Thu, 28 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[- MAX Engine now supports TorchScript models with dynamic input shapes.]]></description>
            <content:encoded><![CDATA[<ul>
<li class="">
<p>MAX Engine now supports TorchScript models with dynamic input shapes.</p>
<p>No matter what the input shapes are, you still need to specify the input
specs for all TorchScript models.</p>
</li>
<li class="">
<p>The Mojo standard library is now open source!</p>
<p>Read more about it in <a href="https://www.modular.com/blog/the-next-big-step-in-mojo-open-source" target="_blank" rel="noopener noreferrer" class="">this blog
post</a>.</p>
</li>
<li class="">
<p>And, of course, lots of Mojo updates, including implicit traits, support for
keyword arguments in Python calls, a new <code>List</code> type (previously
<code>DynamicVector</code>), some refactoring that might break your code, and much more.</p>
<p>For details, see the
<a href="https://mojolang.org/releases#v242-2024-03-28" target="_blank" rel="noopener noreferrer" class="">Mojo changelog</a>.</p>
</li>
</ul>]]></content:encoded>
        </item>
    </channel>
</rss>