When to Use SSMs in Production
Opening Scenario: The Genomics Startup Decision
A genomics startup is building a model to predict gene expression from raw DNA sequences. Each input is a chromosome segment: 500,000 to 2,000,000 base pairs. They have benchmarked three approaches:
Option 1 - Transformer with chunking: Split the sequence into 4K-base-pair windows with 1K overlap, process each window, combine results. Training takes 3 weeks on 32 A100s. The model cannot reason across chunk boundaries. Accuracy for long-range regulatory predictions: 61%.
Option 2 - Hyena + Mamba hybrid (HyenaDNA, Nguyen et al., 2023): Process full chromosomes as single sequences. Training takes 2 weeks on 8 A100s. The model captures full long-range dependencies. Accuracy for long-range regulatory predictions: 78%.
Option 3 - Mamba fine-tuned from a pre-trained checkpoint: Start from Mamba-130M, adapt to the DNA tokenization, fine-tune on genomics data. Training takes 3 days on 4 A100s. Accuracy for long-range regulatory predictions: 73%.
The startup chose Option 3 and improved to 76% with additional training. The architectural fit - O(n) compute over million-length sequences without chunking - made the difference. This is not a case where a cleverer transformer could have won. The architecture's ability to process the full sequence was the enabling factor.
This lesson covers the domains and deployment scenarios where SSMs have a genuine advantage, and the practical engineering of deploying Mamba-based models in production.
Where SSMs Win: The Key Use Cases
1. Long Audio Processing
Raw audio waveforms are extremely long sequences. A 1-minute audio clip at 16kHz is 960,000 samples. At 44.1kHz (CD quality), it is 2.6 million samples.
Transformer-based audio models (like AudioLM, MusicGen) handle this by either:
- Downsampling to a lower-resolution latent space (lossy, limits quality)
- Processing in short chunks (breaks temporal coherence)
- Using extremely expensive multi-GPU setups for even moderate-length audio
Mamba-based audio models (Mamba-Audio, SSM-based TTS systems) can process full waveforms as single sequences at O(n) cost. This enables:
- Higher-quality speech synthesis by conditioning on longer context
- Better music generation with coherent long-range structure
- Real-time audio processing with O(1) inference state (new samples arrive continuously, state updates incrementally)
The streaming case is particularly compelling. A real-time transcription system using Mamba processes each audio frame with a constant-size state update. No KV cache grows. Memory usage is fixed at model load time, never changing as the conversation continues. This is architecturally impossible with a standard transformer.
2. Genomics and Bioinformatics
DNA sequences exhibit long-range dependencies spanning thousands to millions of base pairs. Regulatory elements (enhancers, promoters, silencers) can be hundreds of kilobases from the genes they regulate. Transformer models, limited to 4K-32K token windows, cannot model these dependencies directly.
Key SSM results in genomics:
- HyenaDNA (Nguyen et al., NeurIPS 2023): SSM-based model trained on full chromosomes (up to 1M base pairs). Outperforms transformer models at all sequence lengths on regulatory variant prediction benchmarks.
- Evo (Nguyen et al., 2024, Arc Institute): 7B parameter SSM trained on 2.7T nucleotides of DNA. Processes 131K base pair context. Achieves zero-shot functional prediction across species and modalities.
3. Time Series and Streaming Data
Financial markets, IoT sensor networks, network monitoring, and similar domains generate continuous streams of data where:
- Sequences are unbounded in length (a trading session, a sensor deployment)
- New data arrives continuously
- Memory must not grow with time
The SSM's recurrent inference is a perfect architectural match. Each new data point triggers a constant-cost state update. The model's "memory" of past data is encoded in the fixed-size hidden state - which is exactly the behavior you want for streaming applications.
4. Long-Document Summarization and Analysis
For tasks where the goal is to understand the overall pattern or theme of a long document rather than retrieve specific facts verbatim, SSMs compete well. Legal document classification, scientific paper analysis, earnings call summary - tasks where the input is long but the output requires global understanding.
The key distinction from retrieval tasks: summarization requires compressing many tokens into a short output. SSMs' built-in compression is an asset here, not a limitation. The hidden state naturally aggregates document-level information.
5. Memory-Constrained Deployment
Edge devices, mobile applications, and cost-sensitive cloud deployments cannot afford growing KV caches. A Mamba model's fixed memory footprint enables:
- Deploying language model capabilities on devices with 4-8GB RAM
- Long-session chatbots without OOM risk (conversations can extend indefinitely without cache eviction)
- Predictable latency profiles (no slowdown as context grows)
The Streaming Inference Pattern
Streaming inference is one of Mamba's most compelling production patterns. Here is a production-quality streaming implementation:
import torch
import torch.nn as nn
from typing import Iterator, Optional
from dataclasses import dataclass
@dataclass
class MambaInferenceState:
"""
The complete recurrent state for Mamba inference.
This is ALL that needs to persist between tokens - no KV cache.
"""
conv_states: list # List of [batch, d_inner, d_conv-1] tensors (one per layer)
ssm_states: list # List of [batch, d_inner, d_state] tensors (one per layer)
@property
def memory_bytes(self) -> int:
"""Calculate total state memory in bytes."""
total = 0
for s in self.conv_states + self.ssm_states:
total += s.numel() * s.element_size()
return total
@property
def memory_mb(self) -> float:
return self.memory_bytes / 1e6
class MambaStreamingInferenceEngine:
"""
Production streaming inference engine for Mamba models.
Key properties:
- O(1) memory per new token (state doesn't grow)
- Constant latency per token regardless of conversation length
- Thread-safe state management
"""
def __init__(self, model, tokenizer, device: str = "cuda"):
self.model = model
self.tokenizer = tokenizer
self.device = device
self.model.eval()
def initialize_state(self, batch_size: int = 1) -> MambaInferenceState:
"""Create fresh hidden state (zero-initialized)."""
conv_states = []
ssm_states = []
for layer in self.model.layers:
# Each layer needs its conv state and SSM state
d_inner = layer.mamba.d_inner
d_state = layer.mamba.d_state
d_conv = layer.mamba.d_conv
conv_states.append(
torch.zeros(batch_size, d_inner, d_conv - 1,
device=self.device, dtype=torch.float16)
)
ssm_states.append(
torch.zeros(batch_size, d_inner, d_state,
device=self.device, dtype=torch.float16)
)
return MambaInferenceState(conv_states=conv_states, ssm_states=ssm_states)
def process_prompt(
self,
prompt: str,
state: Optional[MambaInferenceState] = None,
) -> tuple[torch.Tensor, MambaInferenceState]:
"""
Process a prompt (prefill phase).
Returns (logits for last token, updated state).
Note: Mamba can process the full prompt in parallel during prefill
using the convolutional mode. This is fast even for long prompts.
"""
if state is None:
state = self.initialize_state()
tokens = self.tokenizer(prompt, return_tensors="pt").input_ids.to(self.device)
with torch.no_grad():
output = self.model(
input_ids=tokens,
cache_params=state,
use_cache=True,
)
# Return the logits for the final position and the updated state
return output.logits[:, -1, :], output.cache_params
def generate_stream(
self,
prompt: str,
max_new_tokens: int = 500,
temperature: float = 0.7,
top_p: float = 0.9,
state: Optional[MambaInferenceState] = None,
) -> Iterator[str]:
"""
Stream generated tokens one by one.
Yields: decoded token strings as they are generated.
Perfect for real-time display or audio TTS streaming.
Memory usage is fixed at `state.memory_mb` MB throughout.
"""
# Process the prompt
logits, state = self.process_prompt(prompt, state)
generated_tokens = []
for step in range(max_new_tokens):
# Sample next token
if temperature > 0:
probs = torch.softmax(logits / temperature, dim=-1)
# Top-p sampling
sorted_probs, sorted_idx = torch.sort(probs, descending=True)
cumsum = torch.cumsum(sorted_probs, dim=-1)
# Remove tokens with cumulative prob above threshold
sorted_probs[cumsum - sorted_probs > top_p] = 0
sorted_probs /= sorted_probs.sum()
next_token_idx = torch.multinomial(sorted_probs, 1)
next_token = sorted_idx.gather(-1, next_token_idx)
else:
next_token = logits.argmax(dim=-1, keepdim=True)
generated_tokens.append(next_token.item())
# Check for EOS
if next_token.item() == self.tokenizer.eos_token_id:
break
# Yield decoded token
token_str = self.tokenizer.decode([next_token.item()])
yield token_str
# Update state with the new token - O(1) operation
with torch.no_grad():
output = self.model(
input_ids=next_token.unsqueeze(0),
cache_params=state,
use_cache=True,
)
logits = output.logits[:, -1, :]
state = output.cache_params
# State memory is CONSTANT throughout - verify if needed:
if step == 0 or step == 100:
print(f"State memory at step {step}: {state.memory_mb:.1f} MB")
# Usage example
def demo_streaming():
from transformers import AutoTokenizer, MambaForCausalLM
model = MambaForCausalLM.from_pretrained(
"state-spaces/mamba-2.8b-hf",
torch_dtype=torch.float16,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("state-spaces/mamba-2.8b-hf")
engine = MambaStreamingInferenceEngine(model, tokenizer)
print("Generating response (streaming):\n")
for token in engine.generate_stream(
"Explain the theory of relativity in simple terms:",
max_new_tokens=300,
):
print(token, end="", flush=True)
print("\n")
Multi-Turn Conversations with Persistent State
One of the most interesting properties of Mamba for production is persistent conversation state:
class MambaChatSession:
"""
Multi-turn conversation with Mamba.
The hidden state accumulates the entire conversation history.
No explicit conversation history management needed - the state IS the history.
Contrast with transformers: you must pass the full conversation text
(or the KV cache) at each turn, growing quadratically in cost.
"""
def __init__(self, engine: MambaStreamingInferenceEngine):
self.engine = engine
self.state = engine.initialize_state()
self.turn_count = 0
self.memory_log = []
def chat(self, user_message: str) -> str:
"""
Process one turn of conversation.
The model's state already contains all previous turns.
"""
self.turn_count += 1
# Format the message
formatted_input = f"User: {user_message}\nAssistant: "
# Process this turn (state updated in place)
response_tokens = []
logits, self.state = self.engine.process_prompt(formatted_input, self.state)
# Generate response
for token in self.engine.generate_stream(
"", # Already processed in prefill
max_new_tokens=200,
state=self.state,
):
response_tokens.append(token)
# Log memory (stays constant regardless of conversation length)
self.memory_log.append({
"turn": self.turn_count,
"state_memory_mb": self.state.memory_mb,
})
return "".join(response_tokens)
def print_memory_profile(self):
"""Show that memory stays constant across turns."""
print("\nMemory profile across conversation turns:")
for entry in self.memory_log:
bar = "=" * int(entry["state_memory_mb"])
print(f"Turn {entry['turn']:>3}: {entry['state_memory_mb']:.1f} MB [{bar}]")
print("\n(Memory is constant regardless of conversation length)")
Model Availability on HuggingFace
# Available Mamba models on HuggingFace (as of 2024-2025)
MAMBA_MODELS = {
# Original Mamba (Mamba-1)
"state-spaces/mamba-130m-hf": "130M params, base model",
"state-spaces/mamba-370m-hf": "370M params, base model",
"state-spaces/mamba-790m-hf": "790M params, base model",
"state-spaces/mamba-1.4b-hf": "1.4B params, base model",
"state-spaces/mamba-2.8b-hf": "2.8B params, base model",
# Mamba-2 (improved with SSD)
"state-spaces/mamba2-130m": "130M params, Mamba-2 architecture",
"state-spaces/mamba2-370m": "370M params, Mamba-2 architecture",
"state-spaces/mamba2-2.7b": "2.7B params, Mamba-2 architecture",
# Falcon Mamba (7B scale pure SSM)
"tiiuae/falcon-mamba-7b": "7B params, Falcon pre-training",
"tiiuae/falcon-mamba-7b-instruct": "7B params, instruction-tuned",
# Hybrid models
"ai21labs/Jamba-v0.1": "52B total / 12B active, hybrid, 256K context",
"ai21labs/Jamba-1.5-mini": "12B active, Jamba-1.5, 256K context",
"ai21labs/Jamba-1.5-large": "94B total / 52B active, 256K context",
}
# Loading pattern for any Mamba model
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
def load_mamba_model(model_id: str, **kwargs):
"""Standard loading pattern for Mamba models."""
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16, # bfloat16 is often better than float16 for Mamba
device_map="auto",
**kwargs,
)
return tokenizer, model
Fine-Tuning SSMs
Fine-tuning Mamba follows the same patterns as transformer fine-tuning, with a few important differences:
from transformers import (
AutoTokenizer,
MambaForCausalLM,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling,
)
from peft import LoraConfig, get_peft_model, TaskType
from datasets import load_dataset
import torch
def finetune_mamba_lora(
model_id: str = "state-spaces/mamba-2.8b-hf",
dataset_name: str = "your-dataset",
output_dir: str = "./mamba-finetuned",
):
"""Fine-tune Mamba with LoRA (efficient parameter updates)."""
# Load base model
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = MambaForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# LoRA config for Mamba - target the projection layers
# Note: Mamba does NOT have q_proj, k_proj, v_proj (no attention)
# Target the in_proj, out_proj, and x_proj layers instead
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16,
lora_alpha=32,
lora_dropout=0.05,
# Mamba-specific target modules (different from transformer!)
target_modules=[
"in_proj", # Input projection
"out_proj", # Output projection
"x_proj", # SSM parameter projection
"dt_proj", # Delta projection
],
bias="none",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Typical output: trainable params: ~4M (0.14% of 2.8B)
# Training arguments - note differences from transformer fine-tuning
training_args = TrainingArguments(
output_dir=output_dir,
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=3e-4, # Higher LR works for Mamba vs transformers (2e-5 typical)
warmup_ratio=0.1,
lr_scheduler_type="cosine",
bf16=True,
logging_steps=50,
save_strategy="epoch",
# Mamba-specific: no need for gradient checkpointing as much
# (no KV cache = less activation memory)
gradient_checkpointing=False,
)
# Data preparation (same as transformer)
dataset = load_dataset(dataset_name, split="train")
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True,
max_length=2048, # Can use longer sequences with Mamba efficiently
padding=False,
)
tokenized_dataset = dataset.map(tokenize_function, batched=True)
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=data_collator,
)
trainer.train()
trainer.save_model(output_dir)
return model, tokenizer
:::tip Mamba Hyperparameter Differences vs Transformers Mamba models respond differently to hyperparameters than transformers:
- Learning rate: Mamba can use higher LRs (1e-4 to 3e-4) during fine-tuning vs transformers (1e-5 to 5e-5)
- Batch size: Larger batches (4-16 with gradient accumulation) improve training stability
- LoRA targets: Target
in_proj,out_proj,x_proj,dt_proj- NOT attention projection names - Sequence length: Using longer sequences (2K-8K) during fine-tuning makes better use of Mamba's long-range capability :::
Production Architecture Patterns
Pattern 1: Long-Document Processing Pipeline
import asyncio
from typing import List
from concurrent.futures import ThreadPoolExecutor
class MambaDocumentProcessor:
"""
Async document processing pipeline using Mamba.
Processes full documents without chunking.
"""
def __init__(self, model, tokenizer, max_input_tokens: int = 100_000):
self.model = model
self.tokenizer = tokenizer
self.max_input_tokens = max_input_tokens
self.executor = ThreadPoolExecutor(max_workers=4)
async def process_document(
self,
document: str,
task: str = "summarize",
) -> str:
"""Process a single document asynchronously."""
loop = asyncio.get_event_loop()
# Run model inference in thread pool (GPU-bound)
result = await loop.run_in_executor(
self.executor,
self._process_sync,
document,
task,
)
return result
def _process_sync(self, document: str, task: str) -> str:
prompts = {
"summarize": f"Summarize the following document in 3-5 bullet points:\n\n{document}\n\nSummary:",
"classify": f"Classify this document:\n\n{document}\n\nCategory:",
"extract": f"Extract the key entities from:\n\n{document}\n\nEntities:",
}
prompt = prompts.get(task, prompts["summarize"])
inputs = self.tokenizer(
prompt,
return_tensors="pt",
truncation=True,
max_length=self.max_input_tokens,
).to(self.model.device)
token_count = inputs["input_ids"].shape[1]
print(f"Processing {token_count:,} tokens")
with torch.no_grad():
outputs = self.model.generate(
**inputs,
max_new_tokens=500,
do_sample=False,
)
new_tokens = outputs[0][inputs["input_ids"].shape[1]:]
return self.tokenizer.decode(new_tokens, skip_special_tokens=True)
async def process_batch(self, documents: List[str], task: str = "summarize") -> List[str]:
"""Process multiple documents concurrently."""
tasks = [self.process_document(doc, task) for doc in documents]
results = await asyncio.gather(*tasks)
return results
Pattern 2: Streaming Audio Transcription
class MambaAudioTranscriber:
"""
Real-time audio transcription using an SSM-based model.
Key property: state stays the same size whether 1 second or 1 hour of audio.
"""
def __init__(self, audio_ssm_model, sample_rate: int = 16000):
self.model = audio_ssm_model
self.sample_rate = sample_rate
self.chunk_size = sample_rate // 10 # 100ms chunks
self.state = None # Persistent SSM state
self.buffer = []
def start_session(self):
"""Initialize the SSM state for a new transcription session."""
self.state = self.model.initialize_state()
self.buffer = []
print(f"Session started. State memory: {self.state.memory_mb:.1f} MB")
print("This does not grow - even after 1 hour of audio.")
def process_audio_chunk(self, audio_samples: torch.Tensor) -> str:
"""
Process one chunk of audio (100ms).
Updates the persistent state in-place.
Returns any newly detected words/tokens.
"""
# Update SSM state with new audio
output, self.state = self.model.forward_recurrent(
audio_samples, self.state
)
# Decode output (model-specific)
text = self.model.decode_output(output)
return text
def stop_session(self) -> str:
"""End session and get final output."""
# Final state processing
final_output = self.model.finalize(self.state)
self.state = None
return final_output
Future Outlook: Will SSMs Overtake Transformers?
The honest assessment as of 2025:
SSMs are firmly established as the right architecture for specific domains: genomics, long-form audio, streaming data, and any application where sequence length makes transformers impractical.
Hybrids are the near-term consensus for general-purpose language models. Every frontier lab researching alternatives to pure transformers has converged on some form of attention + SSM hybrid. RecurrentGemma, Jamba, Zamba, and Griffin all point in this direction.
Pure transformers remain dominant at frontier scale. GPT-4, Claude 3, Llama 3 70B, and their successors are all transformer-based. The training infrastructure, optimization techniques, and model understanding built up over the transformer era create enormous inertia. Switching to a fundamentally different architecture at 100B+ scale carries significant research and engineering risk.
The open question: Can SSMs match transformers at frontier scale with equivalent training compute? This is unknown because no well-resourced frontier lab has publicly committed to training a 70B+ pure SSM with the same data and compute as competing transformers. Until such a comparison exists, the question is open.
Common Mistakes
:::danger Not Understanding That SSM Fine-Tuning Targets Are Different
The most common error when adapting a LoRA fine-tuning script from transformers to Mamba: specifying target_modules=["q_proj", "k_proj", "v_proj", "o_proj"] - Mamba has none of these. Mamba's projectable modules are in_proj, out_proj, x_proj, and dt_proj. Using transformer LoRA targets on Mamba either crashes or applies LoRA to no modules at all (silently training nothing), resulting in a model that doesn't improve.
:::
:::warning Ignoring the Qualitative Recall Limitation in Production Deploying Mamba for tasks that require precise verbatim retrieval - "quote the exact sentence from the document," "what is the specific API endpoint mentioned," "reproduce the error message exactly" - will produce confident but inaccurate outputs. The model may paraphrase, rearrange, or subtly alter the retrieved information because its compressed state doesn't preserve verbatim content. Monitor recall tasks specifically when deploying Mamba-based pipelines. :::
:::warning Benchmark-Driven Architecture Selection The most common mistake in model selection: picking Mamba because it "looks better on benchmarks" without testing your specific task. Standard benchmarks (HellaSwag, MMLU, ARC) measure broad capability. Your application may be a retrieval-heavy task where Mamba significantly underperforms, or a long-context summarization task where Mamba significantly outperforms. Always run your task-specific benchmarks before committing to an architecture. :::
Interview Q&A
Q1: For what production use cases would you choose a Mamba-based model over a transformer?
Three clear wins for Mamba in production: (1) Long audio processing - raw waveforms at 16kHz-44kHz create sequences of hundreds of thousands of samples; Mamba processes these at O(n) cost with constant inference memory, while transformers require expensive chunking or downsampling; (2) Genomics and bioinformatics - DNA sequences with regulatory dependencies spanning millions of base pairs require full-sequence processing that transformer context windows cannot accommodate; (3) Streaming applications - any system where inputs arrive continuously and state must not grow over time (live transcription, IoT monitoring, real-time analytics). The architectural properties match the problem exactly: O(1) memory update per new token, constant latency regardless of history length.
Q2: How does streaming inference with Mamba differ from streaming inference with a transformer?
A transformer's streaming inference requires maintaining a KV cache that grows by n_layers × 2 × n_heads × head_dim elements per new token. After 100K tokens, the cache is ~50GB for a 7B model. Memory grows until you hit a limit and must truncate or evict context. Mamba's streaming inference maintains a fixed hidden state - n_layers × d_inner × d_state elements. This is ~16-33MB for a 7B model and never grows. Processing the 100,000th token costs exactly the same memory and compute as processing the 10th token. This enables perpetual sessions without cache management, predictable memory profiles for capacity planning, and deployment on memory-constrained devices.
Q3: How do you fine-tune a Mamba model with LoRA? What target modules should you use?
Fine-tuning Mamba with LoRA follows the same process as transformers (using the PEFT library) but requires different target_modules. Mamba has no attention projection matrices (no Q, K, V, O proj). Instead, target: in_proj (input expansion projection), out_proj (output projection), x_proj (projects to SSM parameters B, C, delta), and dt_proj (delta step size projection). These are the parameter-rich layers where LoRA adaptation is most impactful. Typical LoRA rank for Mamba fine-tuning is r=16, with learning rates around 1e-4 to 3e-4 - notably higher than the 1e-5 to 5e-5 used for transformer fine-tuning. The higher LR reflects that SSM parameter updates translate differently to output quality changes than attention updates.
Q4: What is the realistic outlook for SSMs vs transformers over the next 3 years?
The most defensible prediction: hybrids become standard for new medium-scale (7B-30B) models, while frontier-scale models remain transformer-based until a well-resourced lab demonstrates comparable results at 70B+ with equivalent training. SSMs are firmly established for specialized domains (genomics, audio, signals) where their architectural properties provide clear advantages. The wildcard is hardware: current GPUs are optimized for the matrix multiplications that attention uses heavily. If hardware specifically optimized for the parallel scan algorithm emerges (similar to how FlashAttention made attention faster through kernel optimization), SSMs could become competitive or dominant more quickly. The architecturally interesting question - whether compression-based sequence models can match retrieval-based sequence models at scale - remains genuinely open.
Q5: How do you monitor the performance of a Mamba-based model in production?
Monitor three categories specific to SSM deployments: (1) Recall quality: Track hallucination rates on retrieval-type queries using automated metrics (ROUGE-Recall, exact match on specific information extraction tasks). Compare against baseline. Mamba's compressed state can cause subtle recall errors that look plausible but are factually wrong. (2) State divergence: For long-running sessions, track output coherence over time using perplexity on a held-out validation set. If the accumulated state becomes noisy (due to rare input distributions), generation quality can degrade. Reset state periodically for very long sessions. (3) Throughput monitoring: Mamba's constant-cost inference means throughput should be stable regardless of sequence length. If throughput is degrading, the issue is elsewhere (batching, I/O, preprocessing) - not the model. This stable throughput profile is itself a useful diagnostic signal.
:::tip 🎮 Interactive Playground
Visualize this concept: Try the Mamba State Space Model demo on the EngineersOfAI Playground - no code required.
:::
