Image-Text-to-Video
Diffusers
Safetensors
text-to-video
image-to-video
video-to-video
text-to-audio-video
image-to-audio-video
image-text-to-audio-video
video-to-audio-video
audio-to-audio-video
audio-video-generation
multimodal
synchronized-audio-video
reference-to-audio-video
Instructions to use MiniMaxAI/MiniMax-H3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use MiniMaxAI/MiniMax-H3 with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("MiniMaxAI/MiniMax-H3", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
| # SPDX-License-Identifier: Apache-2.0 | |
| # Attention module for the MiniMax H3 visual VAE (inference-only bundle). | |
| import os | |
| import torch | |
| import torch.nn as nn | |
| import torch.distributed as dist | |
| from typing import Optional | |
| from diffusers.utils import logging | |
| from .parallel import all_to_all_4D, get_parallel_state | |
| from .func import apply_rotary_pos_emb | |
| from .flash import flash_attn | |
| logger = logging.get_logger(__name__) # pylint: disable=invalid-name | |
| def _env_flag(name, default="0"): | |
| value = os.environ.get(name, default) | |
| return str(value).strip().lower() in ("1", "true", "yes", "on") | |
| def _vit_norm_input(module, hidden_states): | |
| if _env_flag("MINIMAX_H3_VAE_DECODER_VIT_FP32_NORM", "1"): | |
| return hidden_states.float() | |
| weight = getattr(module, "weight", None) | |
| return hidden_states.to(getattr(weight, "dtype", hidden_states.dtype)) | |
| def maybe_checkpoint(owner, function, *args): | |
| if owner.training and getattr(owner, "gradient_checkpointing", False): | |
| raise NotImplementedError( | |
| "gradient checkpointing is not supported in this inference-only bundle" | |
| ) | |
| return function(*args) | |
| class Attention(nn.Module): | |
| def __init__( | |
| self, | |
| heads, | |
| dim_head, | |
| embed_dim: Optional[int] = None, | |
| qk_norm_type: Optional[str] = None, | |
| qk_norm_affine: bool = False, | |
| bias: bool = True, | |
| out_bias: Optional[bool] = None, | |
| eps: float = 1e-5, | |
| **kwargs, | |
| ): | |
| super().__init__() | |
| self.dim_head = dim_head | |
| self.heads = heads | |
| self.attn_inner_dim = dim_head * heads | |
| self.embed_dim = embed_dim if embed_dim is not None else self.attn_inner_dim | |
| out_bias = out_bias if out_bias is not None else bias | |
| if qk_norm_type is None: | |
| self.norm_q = None | |
| self.norm_k = None | |
| elif qk_norm_type == "layer_norm": | |
| self.norm_q = nn.LayerNorm( | |
| dim_head, eps=eps, elementwise_affine=qk_norm_affine | |
| ) | |
| self.norm_k = nn.LayerNorm( | |
| dim_head, eps=eps, elementwise_affine=qk_norm_affine | |
| ) | |
| elif qk_norm_type == "rms_norm": | |
| self.norm_q = nn.RMSNorm( | |
| dim_head, eps=eps, elementwise_affine=qk_norm_affine | |
| ) | |
| self.norm_k = nn.RMSNorm( | |
| dim_head, eps=eps, elementwise_affine=qk_norm_affine | |
| ) | |
| else: | |
| raise ValueError( | |
| f"unknown qk_norm_type: {qk_norm_type}. Should be None,'layer_norm','rms_norm'" | |
| ) | |
| self.to_qkv = nn.Linear(self.embed_dim, self.attn_inner_dim * 3, bias=bias) | |
| self.to_out = nn.Linear(self.attn_inner_dim, self.embed_dim, bias=out_bias) | |
| self.spatial_parallel = get_parallel_state().get("sp_enabled", False) | |
| state = get_parallel_state() | |
| sp_size = state.get("sp_size", 1) | |
| tp_size = state.get("tp_size", 1) | |
| parallel_size = sp_size * tp_size | |
| if parallel_size > 1 and self.heads % parallel_size != 0: | |
| raise ValueError( | |
| f"num_heads {self.heads} must be divisible by sp_size * tp_size ({sp_size} * {tp_size} = {parallel_size})" | |
| ) | |
| if len(kwargs) > 0 and (not dist.is_initialized() or dist.get_rank() == 0): | |
| logger.warning(f"Unused kwargs: {kwargs}") | |
| def _perform_attention(self, query, key, value, pack_info): | |
| cu_seqlens = pack_info.get("cu_seqlens", None) | |
| mask_mod = pack_info.get("mask_mod", None) | |
| block_sparse = pack_info.get("block_sparse", None) | |
| if cu_seqlens is not None: | |
| raise NotImplementedError( | |
| "varlen attention is not supported in this inference-only bundle" | |
| ) | |
| if mask_mod is not None: | |
| hidden_states = flash_attn( | |
| query, | |
| key, | |
| value, | |
| mask_mod=mask_mod, | |
| block_sparse=block_sparse, | |
| ) | |
| else: | |
| hidden_states = flash_attn( | |
| query, | |
| key, | |
| value, | |
| ) | |
| return hidden_states | |
| def perform_attention(self, query, key, value, pack_info={}): | |
| return self._perform_attention(query, key, value, pack_info) | |
| def forward( | |
| self, | |
| hidden_states: torch.Tensor, | |
| rotary_pos_emb: Optional[torch.Tensor] = None, | |
| pack_info: dict = {}, | |
| ) -> torch.Tensor: | |
| batch_size, seq_len, _ = hidden_states.shape | |
| qkv = self.to_qkv(hidden_states) | |
| qkv = qkv.view(batch_size, seq_len, -1, 3 * self.dim_head) | |
| query, key, value = torch.chunk(qkv, 3, dim=-1) | |
| if self.spatial_parallel: | |
| local_process_group = get_parallel_state()["sp_process_group"] | |
| query = all_to_all_4D(query, 2, 1, group=local_process_group) | |
| key = all_to_all_4D(key, 2, 1, group=local_process_group) | |
| value = all_to_all_4D(value, 2, 1, group=local_process_group) | |
| if self.norm_q is not None: | |
| query = self.norm_q(_vit_norm_input(self.norm_q, query)).to(query.dtype) | |
| if self.norm_k is not None: | |
| key = self.norm_k(_vit_norm_input(self.norm_k, key)).to(key.dtype) | |
| if rotary_pos_emb is not None: | |
| query = apply_rotary_pos_emb(query, rotary_pos_emb) | |
| key = apply_rotary_pos_emb(key, rotary_pos_emb) | |
| hidden_states = self.perform_attention(query, key, value, pack_info) | |
| if self.spatial_parallel: | |
| hidden_states = all_to_all_4D(hidden_states, 1, 2, group=local_process_group) | |
| hidden_states = hidden_states.reshape(batch_size, seq_len, -1) | |
| hidden_states = self.to_out(hidden_states) | |
| return hidden_states | |