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 pose_decoder/decoder_motionbricks.py from OzzyGT/motionbricks_soma_diffusers: direct link, hf CLI and curl.
- Browser
- Download file 10.2 kB
-
https://huggingface.co/OzzyGT/motionbricks_soma_diffusers/resolve/main/pose_decoder/decoder_motionbricks.py
- Command line
-
hf download hf://OzzyGT/motionbricks_soma_diffusers/pose_decoder/decoder_motionbricks.py
-
curl -L -o decoder_motionbricks.py https://huggingface.co/OzzyGT/motionbricks_soma_diffusers/resolve/main/pose_decoder/decoder_motionbricks.py
10.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.modeling_utils import ModelMixin | |
| from diffusers.utils import BaseOutput | |
| 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 MotionBricksPoseDecoderOutput(BaseOutput): | |
| """ | |
| Args: | |
| features (`torch.Tensor` of shape `(batch_size, num_frames, feature_dim)`): | |
| The normalized features of every frame. | |
| """ | |
| features: torch.Tensor | |
| class MotionBricksPoseDecoder(ModelMixin, ConfigMixin): | |
| """Decoder of the pose VQ-VAE: looks up the codes of every token and decodes them to normalized frame features, | |
| conditioned on the given poses and the root velocity. | |
| The features of a frame are the local root (heading rate, ground velocity, height) followed by the body: joint | |
| positions relative to the root, 6D global rotations, joint velocities and foot contacts. Their normalization | |
| statistics and the neutral joint positions of the skeleton are stored as buffers. | |
| """ | |
| _no_split_modules = ["MotionBricksConditionedDecoder"] | |
| _repeated_blocks = ["MotionBricksResnetBlock"] | |
| def __init__( | |
| self, | |
| num_heads_codebook: int = 5, | |
| codebook_size: int = 16, | |
| code_embed_dim: int = 32, | |
| pose_dim: int = 268, | |
| velocity_dim: int = 2, | |
| feature_dim: int = 365, | |
| num_joints: int = 30, | |
| width: int = 512, | |
| depth: int = 4, | |
| dilation_growth_rate: int = 3, | |
| frames_per_token: int = 4, | |
| max_tokens: int = 16, | |
| ): | |
| super().__init__() | |
| self.codebook = nn.Parameter(torch.zeros(num_heads_codebook, codebook_size, code_embed_dim)) | |
| self.decoder = MotionBricksConditionedDecoder( | |
| num_heads_codebook * code_embed_dim, | |
| feature_dim, | |
| target_channels=pose_dim, | |
| external_channels=velocity_dim, | |
| width=width, | |
| depth=depth, | |
| dilation_growth_rate=dilation_growth_rate, | |
| num_tokens=max_tokens, | |
| num_frames=max_tokens * frames_per_token, | |
| ) | |
| self.register_buffer("feature_mean", torch.zeros(feature_dim)) | |
| self.register_buffer("feature_std", torch.ones(feature_dim)) | |
| self.register_buffer("neutral_joints", torch.zeros(num_joints, 3)) | |
| def denormalize(self, features: torch.Tensor) -> torch.Tensor: | |
| # The buffers can sit on another device while the model is offloaded. | |
| std = self.feature_std.to(features.device, features.dtype) | |
| return features * std + self.feature_mean.to(features.device, features.dtype) | |
| def forward( | |
| self, | |
| codes: torch.LongTensor, | |
| num_tokens: torch.Tensor, | |
| pose: torch.Tensor, | |
| has_pose: torch.Tensor, | |
| velocity: torch.Tensor, | |
| return_dict: bool = True, | |
| ) -> MotionBricksPoseDecoderOutput | tuple: | |
| """ | |
| Args: | |
| codes (`torch.LongTensor` of shape `(batch_size, max_tokens, num_heads_codebook)`): | |
| The pose code of every token and head. | |
| num_tokens (`torch.LongTensor` of shape `(batch_size,)`): | |
| The motion length in tokens. | |
| pose (`torch.Tensor` of shape `(batch_size, num_frames, pose_dim)`): | |
| Normalized pose features on the frame timeline. | |
| has_pose (`torch.BoolTensor` of shape `(batch_size, num_frames)`): | |
| The frames whose pose is given. | |
| velocity (`torch.Tensor` of shape `(batch_size, num_frames, velocity_dim)`): | |
| Normalized ground velocity of the root. | |
| return_dict (`bool`, defaults to `True`): | |
| Whether to return a `MotionBricksPoseDecoderOutput` instead of a tuple. | |
| Returns: | |
| `MotionBricksPoseDecoderOutput` or `tuple`: The normalized frame features; a one-element tuple when | |
| `return_dict` is `False`. | |
| """ | |
| heads = torch.arange(self.config.num_heads_codebook, device=codes.device) | |
| embeds = self.codebook[heads, codes].flatten(2) | |
| token_mask = (torch.arange(codes.shape[1], device=codes.device)[None] < num_tokens[:, None]).to(embeds.dtype) | |
| features = self.decoder(embeds.transpose(1, 2), token_mask, pose, has_pose, velocity).transpose(1, 2) | |
| if not return_dict: | |
| return (features,) | |
| return MotionBricksPoseDecoderOutput(features=features) | |