执行摘要
- 一句话:修复 Hunyuan3D-2 DiT 模型 checkpoint 参数名映射
- 推荐动作:该 PR 值得精读,尤其是
param_names_mapping 的设计模式(正则替换 + merge_info)可复用于其他 DiT 或 Flux 系列模型。建议后续增加参数映射的单元测试,覆盖主要 checkpoint 变体。
功能与动机
Loading the official Hunyuan3D‑2 DiT checkpoint with the existing mapping fails with an unsupported “new parameter” error for fused text attention weights, for example: ValueError: New parameter 'double_blocks.10.txt_attn.qkv.weight' is not supported. Similar issues show up for single‑stream blocks when the checkpoint uses separate proj_out / attn.to_out projections instead of the packed linear2 layout used by Hunyuan3D2DiT.
实现拆解
-
添加模型前缀去除规则:在映射字典开头添加 r"^model\.(.*)$" → r"\1",以兼容官方 safetensors 中可能存在的 model. 前缀。
-
MLP 线性层重命名:将 double_blocks 中索引为 0 和 2 的 MLP 层(分别对应 fc_in 和 fc_out)映射为内部使用的命名方式,例如 double_blocks.0.img_mlp.0.* → double_blocks.0.img_mlp.fc_in.*。
-
Double-stream QKV 融合:将 separate Q/K/V 投影(如 to_q、q_proj、query 等变体)映射到 fused qkv 张量,并指定合并索引(0、1、2)和合并数量(3)。
-
Double-stream out-projection 映射:将各种 out-projection 命名(to_out.0、to_add_out.0)统一映射到内部 proj 张量,并保留 weight/bias 后缀。
-
Q/K norm 别名与 weight→scale 转换:将 norm_q/norm_k 映射为 norm.query_norm / norm.key_norm,并将 HuggingFace 风格的 .weight 转换为内部使用的 .scale。
-
Single-stream 块处理:支持 single_transformer_blocks 和 single_blocks 两种导出命名,并将 attn 中的 Q/K/V 及 MLP 第一层(proj_mlp/mlp_fc1)打包到 linear1(merge_index 0-3),out-projection 映射到 linear2,norm 规则与 double-stream 类似。
对应的实现全部在 python/sglang/multimodal_gen/configs/models/dits/hunyuan3d.py 中完成。
关键文件:
python/sglang/multimodal_gen/configs/models/dits/hunyuan3d.py(模块 参数映射;类别 source;类型 data-contract): 核心变更文件,扩展了 param_names_mapping 字典以支持 Hunyuan3D-2 DiT 官方 checkpoint 参数名映射。
关键符号:未识别
关键源码片段
python/sglang/multimodal_gen/configs/models/dits/hunyuan3d.py
核心变更文件,扩展了 param_names_mapping 字典以支持 Hunyuan3D-2 DiT 官方 checkpoint 参数名映射。
# SPDX-License-Identifier: Apache-2.0
from dataclasses import dataclass, field
from sglang.multimodal_gen.configs.models.dits.base import DiTArchConfig, DiTConfig
@dataclass
class Hunyuan3DDiTArchConfig(DiTArchConfig):
"""Architecture config for Hunyuan3D DiT (Flux-style for Hunyuan3D-2.0)."""
param_names_mapping: dict = field(
default_factory=lambda: {
# 去除官方 safetensors 中可能存在的 "model." 前缀 , 使后续规则无需重复匹配
r"^model\.(.*)$": r"\1",
# Double-stream MLP 层重命名 ( 索引 0 -> fc_in, 2 -> fc_out)
r"^(double_blocks\.\d+\.img_mlp)\.0\.(.*)$": r"\1.fc_in.\2",
r"^(double_blocks\.\d+\.img_mlp)\.2\.(.*)$": r"\1.fc_out.\2",
r"^(double_blocks\.\d+\.txt_mlp)\.0\.(.*)$": r"\1.fc_in.\2",
r"^(double_blocks\.\d+\.txt_mlp)\.2\.(.*)$": r"\1.fc_out.\2",
# Double-stream attention: 将 split 的 Q/K/V 融合成 fused qkv, 并指定合并索引和数量
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.(?:to_q|q_proj|query)\.(.*)$": (
r"\1.qkv.\2", 0, 3),
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.(?:to_k|k_proj|key)\.(.*)$": (
r"\1.qkv.\2", 1, 3),
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.(?:to_v|v_proj|value)\.(.*)$": (
r"\1.qkv.\2", 2, 3),
# Double-stream out-projection: 多种命名统一到 proj
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.to_out(?:\.0)?\.(weight|bias)$": r"\1.proj.\2",
r"^(double_blocks\.\d+\.txt_attn)\.to_add_out(?:\.0)?\.(weight|bias)$": r"\1.proj.\2",
# Q/K norm 别名 + HF "weight" -> 内部 "scale"
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.norm_q\.(.*)$": r"\1.norm.query_norm.\2",
r"^(double_blocks\.\d+\.(?:txt_attn|img_attn))\.norm_k\.(.*)$": r"\1.norm.key_norm.\2",
r"^(.*norm\.query_norm)\.weight$": r"\1.scale",
r"^(.*norm\.key_norm)\.weight$": r"\1.scale",
# Single-stream: 支持两种导出命名 , QKV+MLP 打包进 linear1, out-proj 进 linear2
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.(?:to_q|q_proj|query)\.(.*)$": (
r"single_blocks.\1.linear1.\2", 0, 4),
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.(?:to_k|k_proj|key)\.(.*)$": (
r"single_blocks.\1.linear1.\2", 1, 4),
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.(?:to_v|v_proj|value)\.(.*)$": (
r"single_blocks.\1.linear1.\2", 2, 4),
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.(?:proj_mlp|mlp_fc1)\.(.*)$": (
r"single_blocks.\1.linear1.\2", 3, 4),
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.(?:proj_out|out_proj)(?:\.0)?\.(weight|bias)$": r"single_blocks.\1.linear2.\2",
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.to_out(?:\.0)?\.(weight|bias)$": r"single_blocks.\1.linear2.\2",
# Single-stream norm 映射
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.norm_q\.(.*)$": r"single_blocks.\1.norm.query_norm.\2",
r"^(?:single_blocks|single_transformer_blocks)\.(\d+)\.attn\.norm_k\.(.*)$": r"single_blocks.\1.norm.key_norm.\2",
}
)
in_channels: int = 64
hidden_size: int = 1024
num_attention_heads: int = 16
num_layers: int = 16
num_single_layers: int = 32
mlp_ratio: float = 4.0
context_in_dim: int = 1536
axes_dim: tuple[int, ...] = (64,)
theta: int = 10000
qkv_bias: bool = True
guidance_embed: bool = False
time_factor: float = 1000.0
def __post_init__(self) -> None:
if self.num_channels_latents == 0:
self.num_channels_latents = self.in_channels
super().__post_init__()
@dataclass
class Hunyuan3DDiTConfig(DiTConfig):
"""DiT configuration for Hunyuan3D shape generation (Flux-style)."""
arch_config: Hunyuan3DDiTArchConfig = field(default_factory=Hunyuan3DDiTArchConfig)
subfolder: str = "hunyuan3d-dit-v2-0"
评论区精华
无实质性讨论,PR 由 maintainer mickqian 直接批准。
风险与影响
- 风险:
- 正则覆盖不足:若 checkpoint 中存在未考虑到的命名模式(如其他的 prefix 或 MLP 层索引),仍可能加载失败。
- 正则顺序冲突:多个规则可能匹配同一参数名,顺序敏感,后续维护时需小心。
- 无测试覆盖:未增加专门的参数映射测试,回归风险依赖人工验证。
- 影响范围局限:仅影响权重加载路径,不影响运行时推理,因此性能风险低。
- 影响:对依赖 Hunyuan3D-2 DiT 模型的用户,此修复使其能正常加载官方权重,解锁模型使用。对系统无性能影响,代码改动集中。对团队维护而言,映射规则需持续对齐官方导出的命名变化。
- 风险标记:缺少测试覆盖, 正则冲突风险, 仅支持特定 checkpoint 命名
关联脉络
- PR #22289 [Bugfix] multimodal_gen(hunyuan3d): honor config precisions for delight/paint: 同属 Hunyuan3D 模型族的 bugfix,但关注精度配置而非参数映射,属于该模型在不同方面的修复。
参与讨论