第 1 课
← 返回系列列表

MiniMax-H3 架构拆解:一条 5 秒带声音的视频,背后是哪些模型在干活

MiniMax-H3 × DGX Spark — 六期原理实战

134GB 权重不是单个模型,是一组模型的合体:text encoder 63G + 33B DiT 62G + 双 VAE 10G。本期把流水线一个个拆开看。

下载视频 (MP4)

MiniMax-H3 架构拆解 一条 5 秒带声音的视频,背后是哪些模型在干活

T AGENT 开发纪实 · EP30 · MiniMax-H3 六期原理课 ①
"134GB 权重" 不是单个模型,是一组模型的合体:text encoder 63G + 33B 参数的 DiT 62G + 双 VAE 10G。本期把它们一个个拆开看。
权重总账
134GB
DiT 参数
33B
层 DiT block
50
端到端耗时
5s→20min

💡 本节要点:MiniMax-H3 六期原理课 ①:一条 5 秒带声音的视频 = text encoder(63G)+ 双 VAE(10G)+ 33B DiT(62G)——134GB 是一组模型的合体

起点问题

四个问题:134GB 到底是什么?

设计决策

三段式全链路:编码 → 去噪 → 解码

text encoder 63G 提示词 → 文本条件 text_dim 5120 → 双 VAE 10G 视频/音频 → latent 压缩 4×(patch 1,2,2) → 33B DiT 62G 50 层,latent 空间 去噪 20 步 → 双输出头 video 96 + audio 32 去噪完的 latent 一分为二 → VAE 解码 latent → 像素 + 波形 768×448@24fps
- 🎯 · latent 空间扩散 · 不在像素空间干活:视频 latent 24 通道、音频 32 通道,patch (1,2,2) 空间压缩 4 倍——算力和内存省一个量级。
- 🧩 · 一次前向管多模态 · 视频/音频/文本 token 打包成一个 packed sequence,DiT 一次前向同时生成画面和声音的条件。
- ⚡ · CFG-distilled · 每去噪步只做一次前向(对照扩散需要两次),省一半算力——速度换的是蒸馏过的质量。

💡 本节要点:设计决策:三段式全链路——text encoder(条件)→ 双 VAE(压缩)→ DiT(latent 去噪)→ 双输出头 → VAE 解码;扩散在 latent 空间做,不在像素空间

核心代码 1 · 模型配置

从配置看规模:一个 33B 参数的宽模型

@dataclass
class MiniMaxH3DiTArchConfig:
    num_layers: int = 50            # 50 层 DiT block
    token_refiner_num_layers: int = 2   # 文本精炼 2 层
    hidden_size: int = 5376         # 每层宽度
    num_attention_heads: int = 56
    attention_head_dim: int = 128   # 56 × 128 = 7168 投影
    ffn_hidden_size: int = 14336    # FFN ≈ 2.7× 宽度
    latents_dim: int = 24           # 视频 latent 通道
    audio_latents_dim: int = 32     # 音频 latent 通道
    patch_size: tuple[int,int,int] = (1, 2, 2)  # 空间压缩 2×2
    text_dim: int = 5120            # 文本条件维度
    time_embed_dim: int = 2688      # 时间步嵌入

规模推演: hidden 5376 是"宽"模型风格(对比常见 4096),FFN 14336 接近 3 倍宽度。50 层 × 每层 qkv+fc1+fc2 三个大矩阵 → 权重约 33.1B 参数,BF16 下恰好 ~62GB,和磁盘实测一致。

💡 本节要点:核心代码 1:MiniMaxH3DiTArchConfig——50 层 / hidden 5376 / 56 heads×128 / ffn 14336 / latents 24+32 / patch (1,2,2) / text_dim 5120

核心代码 2 · 多模态打包

packed sequence:三种 token 拼成一次前向

# _embed:把三种模态拼成一个 packed sequence
视频 token:  x        [T_v, 24]   ← video VAE latent + patch 投影
音频 token:  audio_x  [T_a, 32]   ← audio VAE latent
文本 token:  prompt   [T_t, 5120] ← text encoder 条件
                ↓ 按顺序拼接
    packed:  [T_v + T_a + T_t, 5376]   ← 一次 DiT 前向
    cu_seqlens = [0, T_v, T_v+T_a, T_v+T_a+T_t]
    # 注意力按 cu_seqlens 分段,视频/音频/文本互不串扰

为什么这样设计: 多模态一次前向 → 去噪时画面和声音共享同一套条件(文本、时间步),一个 DiT 同时生成 96 维视频 latent 和 32 维音频 latent——这是"5 秒视频自带声音"的来源。

注:代价:变长序列需要变长注意力内核 → 埋下 FA4 编译失败的坑(Step 8 / EP32 展开)。
💡 本节要点:核心代码 2:packed sequence——视频 latent + 音频 latent + 文本 embedding 拼成一个序列,cu_seqlens 分段,注意力不跨文档

核心代码 3 · DiT block 内部

每个 block:AdaLN 调制 + 3D RoPE + 门控残差

class MiniMaxH3DiTBlock(nn.Module):
    # AdaLN:每 block 出 6 个调制向量(3 模态 × 6 组)
    shift_msa, scale_msa, gate_msa, \
    shift_mlp, scale_mlp, gate_mlp = self.adaln_proj(t_emb)

    residual = x
    h = self.norm1(x)
    h = _modulate_scale_shift(h, shift_msa, scale_msa, idx)  # x*(1+s)+shift
    h = self.attn(h, rope_freqs=rope_freqs, ...)             # 3D RoPE 96/128 维
    x = _modulate_gate(residual, gate_msa, h, idx)           # x + gate*h

    residual = x
    h = self.norm2(x)                                        # 同样走一遍 MLP
    h = self.mlp(h)
    return _modulate_gate(residual, gate_mlp, h, idx)

理解: 时间步 + 文本条件通过 AdaLN 变成每个 block 的 shift/scale/gate——这就是"条件怎么控制生成"。3D RoPE 把 (t, h, w) 位置编码进注意力,所以视频知道每一帧该长什么样。

💡 本节要点:核心代码 3:MiniMaxH3DiTBlock——AdaLN 出 6 个调制向量(shift/scale/gate × attn/mlp)+ 3D RoPE(t,h,w 旋转 96/128 维)+ gated residual

理解型踩坑 ① · 账单之谜

text encoder 比主模型还大——文本条件是"大模型级"的

组件 大小 参数/形态 角色
text_encoder/ 63 GiB 30B+ 级文本模型 提示词 → 5120 维文本条件
transformer/ 62 GiB 33.1B 参数(BF16) 50 层 DiT 去噪主体
video_vae/ 9.8 GiB 视频压缩器 像素 ↔ 24 通道 latent
audio_vae/ 578 MiB 音频压缩器 波形 ↔ 32 通道 latent
▌ text encoder · 63 GiB
▌ DiT · 62 GiB
▌ 双 VAE · 10.4 GiB
认知反转: "文生视频"的大头不在"视频模型",而在"文本模型"。134GB 里文本条件占了近一半——这也是 128GB 设备装 134GB 权重时最头痛的部分(EP31 的 FP8 量化正是从这 63GB 开始省的)。
> 💡 本节要点:踩坑 1:134GB 账单之谜——text encoder(63G)比主 DiT(62G)还大;video VAE 9.8G + audio VAE 578M;文本条件是'大模型级'的

理解型踩坑 ② · 变长序列的代价

打包的代价:变长注意力内核编不出来

视频/音频/文本 打包成变长序列 → FlashAttention-4 CuTe 变长内核 → SM121 编译失败 → 换 PyTorch SDPA 按 cu_seqlens 分段
架构性坑: packed 设计(Step 5)换来一次前向多模态,代价是注意力必须支持"一条序列里多段文档"。FA4 的 CuTe 变长内核在 GB10 上编不出来——这不是配置问题,是架构选择撞上了硬件限制。
修复思路: SDPA 的 _sdpa_varlen_attention 按 cu_seqlens 逐段做注意力,语义完全等价、可编译。性能略降,但正确性不妥协。完整排障链放 EP32/33。

注:这个坑的教训:多模态打包是有代价的——架构每省一次前向,推理后端就多一个必须支持的特性。
💡 本节要点:踩坑 2:packed 变长序列的代价——三种 token 打包 → 变长注意力 → FlashAttention-4 的 CuTe 变长内核在 SM121 编译失败 → 必须换 SDPA

理解型踩坑 ③ · 扩散的"慢"

5 秒视频等 20 分钟:注意力是 O(T²) 的

请求 帧数 相对帧数 端到端耗时 相对耗时
2s demo 56 298s
5s demo 124 2.2× 1235s 4.0×
- 20 步扩散 · 每步一次完整前向(CFG-distilled 已省一半)——20 步 × 全序列。
- O(T²) 注意力 · 帧数翻倍 → 注意力矩阵 4 倍。视频扩散的序列比语言模型长一个量级。
- 不是机器慢 · GPU 满载 92-95%、温度余量充足——慢是数学决定的,换更好的硬件只缩常数。
推论: 2s→5s 帧数 2.2×、耗时 4.0× 的超线性增长是架构性成本——10s 外推约 55-70 分钟,且内存是硬约束(EP35 基准展开)。
> 💡 本节要点:踩坑 3:扩散的'慢'是架构性的——CFG-distilled 已省一半,但 attention O(T²):帧数 2.2× → 耗时 4.0×(2s→298s、5s→1235s)

横向话题 · 开源组件

架构代码从哪来:vLLM-Omni 的开源栈

验证数据 · 架构实测

拆解账本 + 生成基准:数字都对得上

33.1B
DiT 参数(BF16 = 62GB)
89.17 GB
模型加载内存(532s)
7.75s
平均每去噪步耗时
4.0×
帧数 2.2× → 耗时 4.0×
| 验证项 | 结果 |
|---|---|
| 模型加载 | 89.1659 GiB / 532.257s(shard 加载 154.75s,13/13 shards) |
| 2s T2VA 请求 | 154.956s 端到端(mean denoising step 7.748s) |
| 5s T2VA 请求 | ~1235s 端到端;124 帧 H.264 软编 55s(无 NVENC) |
| 产物校验 | 768×448@24fps,H.264 + AAC 32kHz stereo,full decode 通过 |

注:口径:加载 89.17 GiB 是模型参数内存;请求后 worker 分配 92,957 MiB——134GB 原始权重靠 FP8 量化压下来(EP31 讲实现)。
💡 本节要点:验证:134GB 拆解(text 63G / DiT 62G / 双 VAE 10G);模型加载 89.17 GiB / 532s;2s→298s、5s→1235s;124 帧软编 55s

总结

"文生视频"不是一个模型,是一整条流水线

—— text encoder 63G + 33B DiT 62G + 双 VAE 10G,文本条件是大头
134GB 拆解
—— 编码(VAE 压缩 4×)→ 去噪(50 层 DiT in latent)→ 解码(双输出头)
三段式架构
—— 视频/音频/文本一次前向,cu_seqlens 分段,声音画面同源
packed 多模态
—— 20 步 × O(T²) 注意力:5s 要 20 分钟,不是机器不行
慢是架构性的

理解了流水线,下一个问题就来了: 128GB 到底怎么装下 134GB?
- 📐 · EP30 · 模型原理 · 本期:流水线拆解 ✅
- 🧮 · EP31 · 量化原理 · 下期:在线动态 FP8——从 63GB 文本条件开始省
- 🖥️ · EP32 · 硬件适配 · 预告:GB10 统一内存与 SM121 的四个"不支持"
本期证据:patches/minimax_h3_transformer.py(架构代码)· 本地权重目录实测(134GB 拆解)· docs/RESULTS.md · generation-benchmark.md
💡 本节要点:总结:134GB 拆解 → 三段式架构 → packed 多模态 → 扩散超线性慢;下期 EP31:128GB 怎么装下 134GB——在线动态 FP8 量化原理

在线动态 FP8 量化:128GB 怎么装下 134GB 权重 →