motionbricks_soma_custom_blocks / modular_blocks_motionbricks.py
OzzyGT's picture
OzzyGT HF Staff
add blocks
25496a5
Raw History Blame Contribute Delete
3.68 kB
# Copyright 2026 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0. See the LICENSE file in this repository.
from dataclasses import replace
from diffusers.modular_pipelines import ModularPipeline, SequentialPipelineBlocks
from diffusers.modular_pipelines.modular_pipeline_utils import OutputParam
from diffusers.utils.dynamic_modules_utils import get_class_from_dynamic_module
from .decoders import MotionBricksDecodeStep, MotionBricksPostprocessStep
from .encoders import MotionBricksGuidesStep
from .generation import MotionBricksPoseTokensStep, MotionBricksRootStep
# The remote-code loader only copies modules imported here directly, so the shared helpers are imported too.
from .motion_utils import encode_guides # noqa: F401
class MotionBricksBlocks(SequentialPipelineBlocks):
"""Motion in-betweening with NVIDIA MotionBricks on the SOMA skeleton.
Every component loads from `components_repo`, one subfolder per component, and so does its code, which requires
`trust_components_code=True`.
"""
model_name = "motionbricks"
block_classes = [
MotionBricksGuidesStep(),
MotionBricksRootStep(),
MotionBricksPoseTokensStep(),
MotionBricksDecodeStep(),
MotionBricksPostprocessStep(),
]
block_names = ["guides", "root", "pose_tokens", "decode", "postprocess"]
_requirements = {"diffusers": ">=0.41.0"}
def __init__(self, components_repo=None, components_revision=None, trust_components_code=False):
super().__init__()
self.components_repo = components_repo
self.components_revision = components_revision
self.component_types = {}
if components_repo is None:
return
if not trust_components_code:
raise ValueError("Set `trust_components_code=True` to load the model code from the components repository")
index = ModularPipeline.load_config(str(components_repo), revision=components_revision)
for spec in super().expected_components:
module_name, class_name, _ = index[spec.name]
self.component_types[spec.name] = get_class_from_dynamic_module(
str(components_repo),
subfolder=spec.name,
module_file=f"{module_name}.py",
class_name=class_name,
revision=components_revision,
trust_remote_code=True,
)
@property
def expected_components(self):
if self.components_repo is None:
return super().expected_components
return [
replace(
spec,
type_hint=self.component_types.get(spec.name, spec.type_hint),
pretrained_model_name_or_path=str(self.components_repo),
subfolder=spec.name,
revision=self.components_revision,
)
for spec in super().expected_components
]
@property
def description(self) -> str:
return (
"Generates the transition from the last poses of a context motion to target poses, choosing its length "
"among the allowed ones."
)
@property
def outputs(self):
return [
OutputParam(
"motion",
type_hint=list,
description="One SOMA30 motion dict per batch item, 30 FPS, meters, +Y up.",
),
OutputParam(
"placed_target",
type_hint=list,
description="`target` as used, one dict per batch item, moved by `target_offset` and `target_turn`.",
),
]