Diffusers
Safetensors
English
motionbricks
modular-diffusers
motion-generation
motion-inbetweening
soma
Instructions to use OzzyGT/motionbricks_soma_diffusers with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use OzzyGT/motionbricks_soma_diffusers with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("OzzyGT/motionbricks_soma_diffusers", 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
Download root_model/root_motionbricks.py from OzzyGT/motionbricks_soma_diffusers: direct link, hf CLI and curl.
- Browser
- Download file 20.2 kB
-
https://huggingface.co/OzzyGT/motionbricks_soma_diffusers/resolve/main/root_model/root_motionbricks.py
- Command line
-
hf download hf://OzzyGT/motionbricks_soma_diffusers/root_model/root_motionbricks.py
-
curl -L -o root_motionbricks.py https://huggingface.co/OzzyGT/motionbricks_soma_diffusers/resolve/main/root_model/root_motionbricks.py
20.2 kB
| # Copyright 2026 The HuggingFace Team. All rights reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| from dataclasses import dataclass | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from diffusers.configuration_utils import ConfigMixin, register_to_config | |
| from diffusers.models.attention import AttentionMixin, AttentionModuleMixin | |
| from diffusers.models.attention_dispatch import dispatch_attention_fn | |
| from diffusers.models.modeling_utils import ModelMixin | |
| from diffusers.utils import BaseOutput | |
| class MotionBricksMLP(nn.Module): | |
| """Two linear layers, each followed by LeakyReLU(0.01), then a linear projection.""" | |
| def __init__(self, in_features: int, hidden_features: int, out_features: int): | |
| super().__init__() | |
| self.layers = nn.ModuleList( | |
| [nn.Linear(in_features, hidden_features), nn.Linear(hidden_features, hidden_features)] | |
| ) | |
| self.proj_out = nn.Linear(hidden_features, out_features) | |
| def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: | |
| for layer in self.layers: | |
| hidden_states = F.leaky_relu(layer(hidden_states), 0.01) | |
| return self.proj_out(hidden_states) | |
| class MotionBricksAttnProcessor: | |
| _attention_backend = None | |
| _parallel_config = None | |
| def __call__( | |
| self, | |
| attn: "MotionBricksAttention", | |
| hidden_states: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| ) -> torch.Tensor: | |
| batch_size, seq_len, _ = hidden_states.shape | |
| shape = (batch_size, seq_len, attn.heads, -1) | |
| query = attn.to_q(hidden_states).view(shape) | |
| key = attn.to_k(hidden_states).view(shape) | |
| value = attn.to_v(hidden_states).view(shape) | |
| hidden_states = dispatch_attention_fn( | |
| query, | |
| key, | |
| value, | |
| attn_mask=attention_mask, | |
| backend=self._attention_backend, | |
| parallel_config=self._parallel_config, | |
| ) | |
| hidden_states = hidden_states.flatten(2, 3).to(query.dtype) | |
| return attn.to_out[0](hidden_states) | |
| class MotionBricksAttention(nn.Module, AttentionModuleMixin): | |
| """Multi-head self-attention. `attention_mask` is a boolean `(batch_size, 1, 1, seq_len)` mask of the keys to | |
| attend to.""" | |
| _default_processor_cls = MotionBricksAttnProcessor | |
| _available_processors = [MotionBricksAttnProcessor] | |
| def __init__(self, dim: int, heads: int): | |
| super().__init__() | |
| self.heads = heads | |
| self.to_q = nn.Linear(dim, dim) | |
| self.to_k = nn.Linear(dim, dim) | |
| self.to_v = nn.Linear(dim, dim) | |
| self.to_out = nn.ModuleList([nn.Linear(dim, dim), nn.Dropout(0.0)]) | |
| self.set_processor(MotionBricksAttnProcessor()) | |
| def forward(self, hidden_states: torch.Tensor, attention_mask: torch.Tensor | None = None) -> torch.Tensor: | |
| return self.processor(self, hidden_states, attention_mask) | |
| class MotionBricksTransformerLayer(nn.Module): | |
| """Post-norm transformer encoder layer with a ReLU feed-forward.""" | |
| def __init__(self, dim: int, heads: int, ff_dim: int): | |
| super().__init__() | |
| self.attn = MotionBricksAttention(dim, heads) | |
| self.norm1 = nn.LayerNorm(dim) | |
| self.ff_in = nn.Linear(dim, ff_dim) | |
| self.ff_out = nn.Linear(ff_dim, dim) | |
| self.norm2 = nn.LayerNorm(dim) | |
| def forward(self, hidden_states: torch.Tensor, attention_mask: torch.Tensor | None = None) -> torch.Tensor: | |
| hidden_states = self.norm1(hidden_states + self.attn(hidden_states, attention_mask)) | |
| return self.norm2(hidden_states + self.ff_out(F.relu(self.ff_in(hidden_states)))) | |
| def key_mask(num_tokens: torch.Tensor, max_tokens: int, prefix: int = 0) -> torch.Tensor: | |
| """Boolean `(batch_size, 1, 1, prefix + max_tokens)` attention mask: the `prefix` positions, then the first | |
| `num_tokens` of `max_tokens` token positions.""" | |
| positions = torch.arange(max_tokens, device=num_tokens.device) | |
| valid = positions[None] < num_tokens[:, None] | |
| valid = F.pad(valid, (prefix, 0), value=True) | |
| return valid[:, None, None] | |
| class MotionBricksConv1d(nn.Conv1d): | |
| """Stride-1 `nn.Conv1d` computed as one matrix product over the shifted inputs, faster than cuDNN at these | |
| sizes.""" | |
| def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: | |
| kernel, dilation, padding = self.kernel_size[0], self.dilation[0], self.padding[0] | |
| length = hidden_states.shape[-1] | |
| if kernel > 1: | |
| padded = F.pad(hidden_states, (padding, padding)) | |
| shifted = [padded[..., i * dilation : i * dilation + length] for i in range(kernel)] | |
| hidden_states = torch.stack(shifted, dim=2).flatten(1, 2) | |
| weight = self.weight.reshape(self.out_channels, -1) | |
| return torch.matmul(weight, hidden_states) + self.bias[:, None] | |
| class MotionBricksResnetBlock(nn.Module): | |
| def __init__(self, channels: int, dilation: int): | |
| super().__init__() | |
| self.conv1 = MotionBricksConv1d(channels, channels, 3, padding=dilation, dilation=dilation) | |
| self.conv2 = MotionBricksConv1d(channels, channels, 1) | |
| def forward(self, hidden_states: torch.Tensor, mask: torch.Tensor) -> torch.Tensor: | |
| residual = hidden_states * mask | |
| hidden_states = self.conv1(F.relu(residual) * mask) | |
| hidden_states = self.conv2(F.relu(hidden_states) * mask) | |
| return (hidden_states + residual) * mask | |
| class MotionBricksUpBlock(nn.Module): | |
| def __init__(self, channels: int, depth: int, dilation_growth_rate: int): | |
| super().__init__() | |
| dilations = [dilation_growth_rate**i for i in reversed(range(depth))] | |
| self.resnets = nn.ModuleList([MotionBricksResnetBlock(channels, dilation) for dilation in dilations]) | |
| self.conv = MotionBricksConv1d(channels, channels, 3, padding=1) | |
| class MotionBricksConditionedDecoder(nn.Module): | |
| """Dilated 1D convolution decoder that upsamples tokens to frames, conditioned on per-frame targets and | |
| external features.""" | |
| def __init__( | |
| self, | |
| in_channels: int, | |
| out_channels: int, | |
| target_channels: int, | |
| external_channels: int, | |
| width: int = 512, | |
| depth: int = 4, | |
| dilation_growth_rate: int = 3, | |
| num_tokens: int = 16, | |
| num_frames: int = 64, | |
| ): | |
| super().__init__() | |
| self.width = width | |
| self.num_frames = num_frames | |
| lengths = [num_tokens, num_tokens * 2] | |
| self.conv_in = MotionBricksConv1d(in_channels, width, 3, padding=1) | |
| self.target_projections = nn.ModuleList( | |
| [nn.Linear(target_channels, width * length // num_frames) for length in lengths] | |
| ) | |
| self.external_projections = nn.ModuleList( | |
| [nn.Linear(width + external_channels * num_frames // length, width) for length in lengths] | |
| ) | |
| self.up_blocks = nn.ModuleList([MotionBricksUpBlock(width, depth, dilation_growth_rate) for _ in lengths]) | |
| self.conv_mid = MotionBricksConv1d(width, width, 3, padding=1) | |
| self.conv_out = MotionBricksConv1d(width, out_channels, 3, padding=1) | |
| def forward( | |
| self, | |
| hidden_states: torch.Tensor, | |
| token_mask: torch.Tensor, | |
| target: torch.Tensor, | |
| target_mask: torch.Tensor, | |
| external: torch.Tensor, | |
| ) -> torch.Tensor: | |
| """ | |
| Args: | |
| hidden_states: `(batch_size, in_channels, num_tokens)` token features. | |
| token_mask: `(batch_size, num_tokens)` float mask of the valid tokens. | |
| target: `(batch_size, num_frames, target_channels)` per-frame targets. | |
| target_mask: `(batch_size, num_frames)` boolean mask of the frames with a target. | |
| external: `(batch_size, num_frames, external_channels)` per-frame conditioning. | |
| Returns: | |
| `(batch_size, out_channels, num_frames)` frame features. | |
| """ | |
| batch_size = hidden_states.shape[0] | |
| mask = token_mask[:, None] | |
| hidden_states = F.relu(self.conv_in(hidden_states * mask)) | |
| for block, target_projection, external_projection in zip( | |
| self.up_blocks, self.target_projections, self.external_projections | |
| ): | |
| length = hidden_states.shape[-1] | |
| projected = F.relu(target_projection(target)) | |
| grouped = hidden_states.transpose(1, 2).reshape(batch_size, self.num_frames, -1) | |
| grouped = torch.where(target_mask[..., None], projected, grouped) | |
| grouped = grouped.reshape(batch_size, length, self.width) | |
| conditioned = torch.cat([grouped, external.reshape(batch_size, length, -1)], dim=-1) | |
| hidden_states = F.relu(external_projection(conditioned).transpose(1, 2)) | |
| for resnet in block.resnets: | |
| hidden_states = resnet(hidden_states, mask) | |
| hidden_states = F.interpolate(hidden_states, scale_factor=2, mode="nearest") | |
| mask = mask.repeat_interleave(2, dim=-1) | |
| hidden_states = block.conv(hidden_states * mask) | |
| hidden_states = F.relu(self.conv_mid(hidden_states * mask)) * mask | |
| return self.conv_out(hidden_states) * mask | |
| class MotionBricksRootOutput(BaseOutput): | |
| """ | |
| Args: | |
| num_tokens (`torch.LongTensor` of shape `(batch_size,)`): | |
| The chosen motion length in tokens; the motion spans `num_tokens * frames_per_token` frames. | |
| root (`torch.Tensor` of shape `(batch_size, num_frames, 5)`): | |
| The normalized global root of every frame: position, then cosine and sine of the heading. | |
| """ | |
| num_tokens: torch.LongTensor | |
| root: torch.Tensor | |
| class MotionBricksRootModel(ModelMixin, ConfigMixin, AttentionMixin): | |
| """Chooses the length of a transition and predicts its root trajectory from `context_frames` context poses and | |
| `target_frames` target poses. Stores the normalization statistics of the guide features as buffers.""" | |
| _no_split_modules = ["MotionBricksTransformerLayer", "MotionBricksConditionedDecoder"] | |
| _repeated_blocks = ["MotionBricksTransformerLayer"] | |
| _skip_layerwise_casting_patterns = ["norm", "embed"] | |
| def __init__( | |
| self, | |
| pose_dim: int = 268, | |
| global_root_dim: int = 5, | |
| local_root_dim: int = 4, | |
| pose_embed_dim: int = 256, | |
| root_embed_dim: int = 64, | |
| hidden_dim: int = 512, | |
| num_heads: int = 16, | |
| ff_dim: int = 2048, | |
| num_shared_layers: int = 6, | |
| num_token_layers: int = 2, | |
| context_frames: int = 4, | |
| target_frames: int = 4, | |
| frames_per_token: int = 4, | |
| min_tokens: int = 6, | |
| max_tokens: int = 16, | |
| decoder_depth: int = 4, | |
| decoder_dilation_growth_rate: int = 3, | |
| ): | |
| super().__init__() | |
| guide_frames = context_frames + target_frames | |
| num_lengths = max_tokens - min_tokens + 1 | |
| guide_dim = pose_embed_dim + 2 * root_embed_dim | |
| self.pose_proj = nn.Linear(pose_dim, pose_embed_dim) | |
| self.local_root_proj = nn.Linear(local_root_dim, root_embed_dim) | |
| self.global_root_proj = nn.Linear(global_root_dim, root_embed_dim) | |
| self.missing_pose_embed = nn.Parameter(torch.zeros(pose_embed_dim)) | |
| self.missing_local_root_embed = nn.Parameter(torch.zeros(root_embed_dim)) | |
| self.missing_global_root_embed = nn.Parameter(torch.zeros(root_embed_dim)) | |
| self.context_proj = MotionBricksMLP(guide_dim, hidden_dim, hidden_dim) | |
| self.target_proj = MotionBricksMLP(guide_dim, hidden_dim, hidden_dim) | |
| self.guide_position_embed = nn.Parameter(torch.zeros(guide_frames, hidden_dim)) | |
| # Index num_lengths + 1 asks for a prediction; the length classes are min_tokens..max_tokens and one unused. | |
| self.length_query_embed = nn.Embedding(num_lengths + 2, hidden_dim) | |
| self.shared_layers = nn.ModuleList( | |
| [MotionBricksTransformerLayer(hidden_dim, num_heads, ff_dim) for _ in range(num_shared_layers)] | |
| ) | |
| self.length_head = nn.Linear(hidden_dim, num_lengths + 1) | |
| self.length_embed = nn.Embedding(num_lengths + 1, hidden_dim) | |
| self.token_position_embed = nn.Parameter(torch.zeros(max_tokens, hidden_dim)) | |
| self.token_layers = nn.ModuleList( | |
| [MotionBricksTransformerLayer(hidden_dim, num_heads, ff_dim) for _ in range(num_token_layers)] | |
| ) | |
| self.missing_frame_embed = nn.Parameter(torch.zeros(hidden_dim)) | |
| self.decoder = MotionBricksConditionedDecoder( | |
| hidden_dim, | |
| global_root_dim, | |
| target_channels=global_root_dim, | |
| external_channels=hidden_dim, | |
| width=hidden_dim, | |
| depth=decoder_depth, | |
| dilation_growth_rate=decoder_dilation_growth_rate, | |
| num_tokens=max_tokens, | |
| num_frames=max_tokens * frames_per_token, | |
| ) | |
| self.register_buffer("global_root_mean", torch.zeros(global_root_dim)) | |
| self.register_buffer("global_root_std", torch.ones(global_root_dim)) | |
| self.register_buffer("local_root_mean", torch.zeros(local_root_dim)) | |
| self.register_buffer("local_root_std", torch.ones(local_root_dim)) | |
| self.register_buffer("pose_mean", torch.zeros(pose_dim)) | |
| self.register_buffer("pose_std", torch.ones(pose_dim)) | |
| def _statistics(self, value: torch.Tensor, name: str) -> tuple[torch.Tensor, torch.Tensor]: | |
| # The buffers can sit on another device while the model is offloaded. | |
| mean, std = getattr(self, f"{name}_mean"), getattr(self, f"{name}_std") | |
| return mean.to(value.device, value.dtype), std.to(value.device, value.dtype) | |
| def normalize(self, value: torch.Tensor, name: str) -> torch.Tensor: | |
| """Normalize `global_root`, `local_root` or `pose` features with this model's statistics.""" | |
| mean, std = self._statistics(value, name) | |
| return (value - mean) / std | |
| def denormalize(self, value: torch.Tensor, name: str) -> torch.Tensor: | |
| mean, std = self._statistics(value, name) | |
| return value * std + mean | |
| def place_guides(self, guides: torch.Tensor, num_tokens: torch.Tensor, fill) -> torch.Tensor: | |
| """Place `(batch_size, guide_frames, ...)` guide values on the frame timeline: the context poses at the start | |
| and the target poses at the last frames of the chosen length. Other frames hold `fill`.""" | |
| config = self.config | |
| shape = (guides.shape[0], config.max_tokens * config.frames_per_token, *guides.shape[2:]) | |
| if isinstance(fill, torch.Tensor): | |
| timeline = fill.to(guides.dtype).expand(shape).clone() | |
| else: | |
| timeline = torch.full(shape, fill, dtype=guides.dtype, device=guides.device) | |
| timeline[:, : config.context_frames] = guides[:, : config.context_frames] | |
| end = num_tokens * config.frames_per_token | |
| frames = end[:, None] - config.target_frames + torch.arange(config.target_frames, device=end.device) | |
| batch = torch.arange(guides.shape[0], device=guides.device)[:, None] | |
| timeline[batch, frames] = guides[:, config.context_frames :] | |
| return timeline | |
| def forward( | |
| self, | |
| global_root: torch.Tensor, | |
| local_root: torch.Tensor, | |
| pose: torch.Tensor, | |
| has_global_root: torch.Tensor, | |
| has_local_root: torch.Tensor, | |
| has_pose: torch.Tensor, | |
| allowed_num_tokens: torch.Tensor, | |
| return_dict: bool = True, | |
| ) -> MotionBricksRootOutput | tuple: | |
| """ | |
| Args: | |
| global_root (`torch.Tensor` of shape `(batch_size, guide_frames, global_root_dim)`): | |
| Normalized global root of the guide poses. | |
| local_root (`torch.Tensor` of shape `(batch_size, guide_frames, local_root_dim)`): | |
| Normalized local root of the guide poses. | |
| pose (`torch.Tensor` of shape `(batch_size, guide_frames, pose_dim)`): | |
| Normalized pose features of the guide poses. | |
| has_global_root (`torch.BoolTensor` of shape `(batch_size, guide_frames)`): | |
| Which guide poses have a global root. | |
| has_local_root (`torch.BoolTensor` of shape `(batch_size, guide_frames)`): | |
| Which guide poses have a local root. | |
| has_pose (`torch.BoolTensor` of shape `(batch_size, guide_frames)`): | |
| Which guide poses have pose features. | |
| allowed_num_tokens (`torch.BoolTensor` of shape `(batch_size, max_tokens - min_tokens + 1)`): | |
| The lengths the model may choose, from `min_tokens`. | |
| return_dict (`bool`, defaults to `True`): | |
| Whether to return a `MotionBricksRootOutput` instead of a tuple. | |
| Returns: | |
| `MotionBricksRootOutput` or `tuple`: The chosen length and the normalized root; a tuple of the two when | |
| `return_dict` is `False`. | |
| """ | |
| config = self.config | |
| has_pose_f = has_pose[..., None].to(pose.dtype) | |
| has_local_f = has_local_root[..., None].to(pose.dtype) | |
| has_global_f = has_global_root[..., None].to(pose.dtype) | |
| pose_embeds = self.pose_proj(pose) * has_pose_f + self.missing_pose_embed * (1 - has_pose_f) | |
| local_embeds = self.local_root_proj(local_root) * has_local_f + self.missing_local_root_embed * ( | |
| 1 - has_local_f | |
| ) | |
| global_embeds = self.global_root_proj(global_root) * has_global_f + self.missing_global_root_embed * ( | |
| 1 - has_global_f | |
| ) | |
| guides = torch.cat([pose_embeds, local_embeds, global_embeds], dim=-1) | |
| guides = torch.cat( | |
| [ | |
| self.context_proj(guides[:, : config.context_frames]), | |
| self.target_proj(guides[:, config.context_frames :]), | |
| ], | |
| dim=1, | |
| ) | |
| positioned = guides + self.guide_position_embed | |
| batch_size = guides.shape[0] | |
| num_lengths = config.max_tokens - config.min_tokens + 1 | |
| query = self.length_query_embed(torch.full((batch_size, 1), num_lengths + 1, device=guides.device)) | |
| hidden_states = torch.cat([query, positioned], dim=1) | |
| for layer in self.shared_layers: | |
| hidden_states = layer(hidden_states) | |
| logits = self.length_head(hidden_states[:, 0]) | |
| allowed = F.pad(allowed_num_tokens, (0, 1), value=False) | |
| length = logits.masked_fill(~allowed, float("-inf")).argmax(dim=-1) | |
| num_tokens = length + config.min_tokens | |
| tokens = self.token_position_embed.expand(batch_size, -1, -1) | |
| hidden_states = torch.cat([self.length_embed(length)[:, None], positioned, tokens], dim=1) | |
| mask = key_mask(num_tokens, config.max_tokens, prefix=1 + guides.shape[1]) | |
| for layer in self.token_layers: | |
| hidden_states = layer(hidden_states, mask) | |
| tokens = hidden_states[:, -config.max_tokens :] | |
| has_guide = has_pose | has_local_root | has_global_root | |
| frame_guides = torch.where(has_guide[..., None], guides, self.missing_frame_embed) | |
| external = self.place_guides(frame_guides, num_tokens, fill=self.missing_frame_embed) | |
| target = self.place_guides(global_root, num_tokens, fill=0) | |
| target_mask = self.place_guides(has_global_root, num_tokens, fill=False) | |
| token_mask = (torch.arange(config.max_tokens, device=num_tokens.device)[None] < num_tokens[:, None]).to( | |
| tokens.dtype | |
| ) | |
| root = self.decoder(tokens.transpose(1, 2), token_mask, target, target_mask, external).transpose(1, 2) | |
| if not return_dict: | |
| return (num_tokens, root) | |
| return MotionBricksRootOutput(num_tokens=num_tokens, root=root) | |