This tiny model is intended for debugging. It is randomly initialized using the configuration adapted from MiniMaxAI/MiniMax-H3.

This retains the root T2VA component topology from the pinned source. MiniMax-H3 also publishes FL2VA and Ref2VA component trees; they are separate workflows and are not silently substituted for the root pipeline.

  • The conditioner reads hidden_states[50], so the tiny text encoder keeps 51 layers.
  • The text attention head dimension is 32. The vision tower has two layers, and the diffusion transformer and VAE decoder retain four repeated layers each; the seven-stage audio decoder remains present.
  • Audio decoder width stays 128 because the released seven-stage decoder requires it.
File path Size
audio_vae/diffusion_pytorch_model.safetensors 66.7MB
text_encoder/model.safetensors 21.4MB
transformer/diffusion_pytorch_model.safetensors 0.9MB
transformer_ref/diffusion_pytorch_model.safetensors 0.9MB
vae/diffusion_pytorch_model.safetensors 5.5MB

Example usage:

  • Transformers (✅ verified)
import torch
from diffusers import ModularPipeline

model_id = "tiny-random/minimax-h3"
device = 'cuda' if torch.cuda.is_available() else 'cpu'
pipe = ModularPipeline.from_pretrained(model_id, workflow='t2va')
pipe.load_components(dtype=torch.bfloat16)
if device == 'cuda':
    pipe.to(device)

outputs = pipe(
    prompt='A red fox trotting through a snowy pine forest',
    num_frames=124,
    height=64,
    width=64,
    num_inference_steps=2,
    generator=torch.Generator(device=device).manual_seed(42),
    output=['videos', 'audio', 'sampling_rate'],
)
print(type(outputs['videos'][0]), getattr(outputs['videos'][0], 'shape', None))
print(type(outputs['audio'][0]), getattr(outputs['audio'][0], 'shape', None), outputs['sampling_rate'])

Codes to create this repo (✅ verified):

Click to expand
import json
import shutil
from pathlib import Path

import torch
from diffusers import (
    AutoencoderKLMiniMaxH3,
    AutoencoderKLMiniMaxH3Audio,
    MiniMaxH3Blocks,
    MiniMaxH3Scheduler,
    MiniMaxH3Transformer3DModel,
)
from huggingface_hub import hf_hub_download
from transformers import AutoConfig, Qwen3VLForConditionalGeneration

source_model_id = "MiniMaxAI/MiniMax-H3"
save_folder = "/tmp/tiny-random/minimax-h3"
revision = '42ed227ee7df40d41602854ae760620d6eb651fe'

def save_json(path, obj):
    Path(path).parent.mkdir(parents=True, exist_ok=True)
    with open(path, 'w', encoding='utf-8') as f:
        json.dump(obj, f, indent=2, ensure_ascii=False)

def init_weights(model):
    torch.manual_seed(42)
    model = model.cpu()
    with torch.no_grad():
        for name, p in sorted(model.named_parameters()):
            torch.nn.init.normal_(p, 0, 0.1)

torch.set_default_dtype(torch.bfloat16)
text_dim = 32
Path(save_folder).mkdir(parents=True, exist_ok=True)

# These JSON assets are public API files, not generated artifacts.  Copy them
# byte-for-byte rather than round-tripping through save_pretrained().
for subfolder, names in {
    'tokenizer': ('merges.txt', 'tokenizer.json', 'tokenizer_config.json', 'vocab.json'),
    'processor': ('chat_template.json', 'merges.txt', 'preprocessor_config.json', 'tokenizer.json', 'tokenizer_config.json', 'video_preprocessor_config.json', 'vocab.json'),
}.items():
    destination = Path(save_folder) / subfolder
    destination.mkdir(parents=True, exist_ok=True)
    for name in names:
        shutil.copy2(
            hf_hub_download(source_model_id, filename=f'{subfolder}/{name}', repo_type='model', revision=revision),
            destination / name,
        )

with open(hf_hub_download(source_model_id, filename='text_encoder/config.json', repo_type='model', revision=revision), 'r', encoding='utf-8') as f:
    config = json.load(f)
# MiniMax-H3 conditions on hidden_states[50], so keep >50 layers with a tiny width.
config['text_config'].update({
    'head_dim': 32,
    'hidden_size': text_dim,
    'intermediate_size': 64,
    'num_attention_heads': 1,
    'num_key_value_heads': 1,
    'num_hidden_layers': 51,
    'tie_word_embeddings': False,
})
config['text_config']['rope_scaling']['mrope_section'] = [8, 4, 4]
config['vision_config'].update({
    'depth': 2,
    'hidden_size': 64,
    'intermediate_size': 128,
    'num_heads': 2,
    'out_hidden_size': text_dim,
    'deepstack_visual_indexes': [],
})
config['tie_word_embeddings'] = False
save_json(f'{save_folder}/text_encoder/config.json', config)
text_encoder = Qwen3VLForConditionalGeneration(
    AutoConfig.from_pretrained(f'{save_folder}/text_encoder')
).to(torch.bfloat16)
init_weights(text_encoder)
text_encoder.save_pretrained(f'{save_folder}/text_encoder')

# attention_head_dim must cover 2 * 3 * rope_freq_dim rotary channels.
transformer_kwargs = dict(
    num_attention_heads=2,
    attention_head_dim=32,
    hidden_size=64,
    num_layers=4,
    num_refiner_layers=2,
    ffn_dim=128,
    in_channels=8,
    audio_in_channels=8,
    patch_size=(1, 2, 2),
    text_dim=text_dim,
    freq_dim=64,
    time_embed_hidden_dim=64,
    time_embed_dim=32,
    rope_freq_dim=4,
)
for subfolder in ('transformer', 'transformer_ref'):
    transformer = MiniMaxH3Transformer3DModel(**transformer_kwargs)
    init_weights(transformer)
    transformer.save_pretrained(f'{save_folder}/{subfolder}')

with open(hf_hub_download(source_model_id, filename='vae/config.json', repo_type='model', revision=revision), 'r', encoding='utf-8') as f:
    vae_config = json.load(f)
vae_config.update({
    'latent_channels': 8,
    'block_out_channels': [32, 32, 32, 64, 64, 64],
    'layers_per_block': 1,
    'spatial_downsample_factors': [2, 2, 2, 2, 1, 1],
    'temporal_downsample_factors': [1, 2, 2, 1, 1, 1],
    'norm_num_groups': 8,
    'decoder_num_layers': 4,
    'decoder_num_attention_heads': 2,
    'decoder_attention_head_dim': 32,
    'decoder_num_register_tokens': 2,
    'decoder_ffn_mult': 2,
    'latents_mean': [0.0] * 8,
    'latents_std': [1.0] * 8,
})
save_json(f'{save_folder}/vae/config.json', vae_config)
vae = AutoencoderKLMiniMaxH3.from_config(
    AutoencoderKLMiniMaxH3.load_config(f'{save_folder}/vae')
)
init_weights(vae)
vae.save_pretrained(f'{save_folder}/vae')

# Keep hop length 800 (=32000/40Hz). decoder_dim must stay >= 128 for 7 upsample stages.
with open(hf_hub_download(source_model_id, filename='audio_vae/config.json', repo_type='model', revision=revision), 'r', encoding='utf-8') as f:
    audio_config = json.load(f)
audio_config.update({
    'encoder_dim': 32,
    'latent_dim': 128,
    'latent_channels': 8,
    'num_attention_heads': 4,
    'decoder_dim': 128,
    'latents_mean': [0.0] * 8,
    'latents_std': [1.0] * 8,
})
save_json(f'{save_folder}/audio_vae/config.json', audio_config)
audio_vae = AutoencoderKLMiniMaxH3Audio.from_config(
    AutoencoderKLMiniMaxH3Audio.load_config(f'{save_folder}/audio_vae')
)
init_weights(audio_vae)
audio_vae.save_pretrained(f'{save_folder}/audio_vae')

MiniMaxH3Scheduler.from_pretrained(source_model_id, subfolder='scheduler', revision=revision).save_pretrained(
    f'{save_folder}/scheduler'
)
MiniMaxH3Scheduler.from_pretrained(source_model_id, subfolder='audio_scheduler', revision=revision).save_pretrained(
    f'{save_folder}/audio_scheduler'
)

for index_name in ('model_index.json', 'modular_model_index.json'):
    index = json.load(open(hf_hub_download(source_model_id, filename=index_name, repo_type='model', revision=revision), encoding='utf-8'))
    for value in index.values():
        if isinstance(value, list) and len(value) >= 3 and isinstance(value[2], dict):
            value[2]['pretrained_model_name_or_path'] = save_folder
    save_json(f'{save_folder}/{index_name}', index)

pipe = MiniMaxH3Blocks().init_pipeline(save_folder)
pipe.load_components(dtype=torch.bfloat16)
pipe.save_pretrained(save_folder, safe_serialization=True, overwrite_modular_index=True)
torch.set_default_dtype(torch.float32)
print(pipe)

Printing the model:

Click to expand
MiniMaxH3ModularPipeline {
  "_blocks_class_name": "MiniMaxH3Blocks",
  "_class_name": "MiniMaxH3ModularPipeline",
  "_diffusers_version": "0.40.0.dev0",
  "audio_scheduler": [
    "diffusers",
    "MiniMaxH3Scheduler",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "audio_scheduler",
      "type_hint": [
        "diffusers",
        "MiniMaxH3Scheduler"
      ],
      "variant": null
    }
  ],
  "audio_vae": [
    "diffusers",
    "AutoencoderKLMiniMaxH3Audio",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "audio_vae",
      "type_hint": [
        "diffusers",
        "AutoencoderKLMiniMaxH3Audio"
      ],
      "variant": null
    }
  ],
  "canvas_max_pixels": 1032192,
  "canvas_short_edge": 768,
  "processor": [
    "transformers",
    "Qwen3VLProcessor",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "processor",
      "type_hint": [
        "transformers",
        "Qwen3VLProcessor"
      ],
      "variant": null
    }
  ],
  "reference_image_short_edge": 2048,
  "scheduler": [
    "diffusers",
    "MiniMaxH3Scheduler",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "scheduler",
      "type_hint": [
        "diffusers",
        "MiniMaxH3Scheduler"
      ],
      "variant": null
    }
  ],
  "text_encoder": [
    "transformers",
    "Qwen3VLForConditionalGeneration",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "text_encoder",
      "type_hint": [
        "transformers",
        "Qwen3VLForConditionalGeneration"
      ],
      "variant": null
    }
  ],
  "tokenizer": [
    "transformers",
    "Qwen2Tokenizer",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "tokenizer",
      "type_hint": [
        "transformers",
        "Qwen2Tokenizer"
      ],
      "variant": null
    }
  ],
  "transformer": [
    "diffusers",
    "MiniMaxH3Transformer3DModel",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "transformer",
      "type_hint": [
        "diffusers",
        "MiniMaxH3Transformer3DModel"
      ],
      "variant": null
    }
  ],
  "transformer_ref": [
    "diffusers",
    "MiniMaxH3Transformer3DModel",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "transformer_ref",
      "type_hint": [
        "diffusers",
        "MiniMaxH3Transformer3DModel"
      ],
      "variant": null
    }
  ],
  "vae": [
    "diffusers",
    "AutoencoderKLMiniMaxH3",
    {
      "pretrained_model_name_or_path": "./tmp/tiny-random/minimax-h3",
      "revision": null,
      "subfolder": "vae",
      "type_hint": [
        "diffusers",
        "AutoencoderKLMiniMaxH3"
      ],
      "variant": null
    }
  ]
}

Test environment:

  • diffusers: 0.40.0.dev0
  • huggingface_hub: 1.27.0
  • safetensors: 0.8.0
  • tokenizers: 0.23.0rc0
  • torch: 2.13.0+cu126
  • transformers: 5.15.0.dev0

Change log:

  • 2026-10-23: Initial version.

This repo is generated by GPT-6.1-Sol

Downloads last month
152
Safetensors
Model size
417k params
Tensor type
F32
·
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for tiny-random/minimax-h3

Finetuned
(199)
this model

Collection including tiny-random/minimax-h3