Compare commits

...
Author SHA1 Message Date
SolitaryThinkerandClaude Opus 4.6 83fd2e058c [feat] Migrate SD35 SamplingParam subclass to profile-based defaults
Replace SD35SamplingParam subclass with a profile-based configuration
approach. This introduces the PipelineProfile registry infrastructure
and migrates SD35 as the first model to use it, enabling a cleaner
separation between model defaults and the base SamplingParam class.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:36:14 -07:00
6 changed files with 116 additions and 39 deletions
+42 -10
View File
@@ -103,17 +103,49 @@ class SamplingParam:
self.__post_init__()
@classmethod
def from_pretrained(cls, model_path: str) -> "SamplingParam":
from fastvideo.registry import get_sampling_param_cls_for_name
sampling_cls = get_sampling_param_cls_for_name(model_path)
if sampling_cls is not None:
sampling_param: SamplingParam = sampling_cls()
else:
logger.warning("Couldn't find an optimal sampling param for %s. Using the default sampling param.",
model_path)
sampling_param = cls()
def _from_profile(
cls,
profile_name: str,
) -> "SamplingParam":
"""Create a ``SamplingParam`` with profile defaults applied.
return sampling_param
Looks up *profile_name* in the central profile registry,
creates a base ``SamplingParam()``, then delegates to
:meth:`update` so that ``__post_init__`` is called and
derived fields stay consistent.
"""
from fastvideo.configs.sample.profiles import get_profile
profile = get_profile(profile_name)
if profile is None:
raise ValueError(f"Unknown profile: {profile_name}")
instance = cls()
instance.update(profile.defaults)
return instance
@classmethod
def from_pretrained(cls, model_path: str) -> "SamplingParam":
from fastvideo.registry import _get_config_info
config_info = _get_config_info(model_path, raise_on_missing=False)
if config_info is None:
logger.warning(
"Couldn't find an optimal sampling param "
"for %s. Using the default sampling param.",
model_path,
)
return cls()
# Profile-based path (preferred for new migrations).
if config_info.default_profile is not None:
return cls._from_profile(config_info.default_profile)
# Legacy path: use the registered subclass directly.
if config_info.sampling_param_cls is not None:
return config_info.sampling_param_cls()
return cls()
@staticmethod
def add_cli_args(parser: Any) -> Any:
+33
View File
@@ -0,0 +1,33 @@
# SPDX-License-Identifier: Apache-2.0
"""Pipeline profile registry for SamplingParam defaults.
A *profile* is a named collection of default field values that can be
applied to a base ``SamplingParam`` instance, replacing the need for
model-specific ``SamplingParam`` subclasses.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
@dataclass
class PipelineProfile:
"""Named set of default overrides for SamplingParam."""
name: str
defaults: dict[str, Any]
_PROFILE_REGISTRY: dict[str, PipelineProfile] = {}
def register_profile(profile: PipelineProfile) -> None:
"""Register a profile by name."""
_PROFILE_REGISTRY[profile.name] = profile
def get_profile(name: str) -> PipelineProfile | None:
"""Look up a profile by name."""
return _PROFILE_REGISTRY.get(name)
+4 -24
View File
@@ -1,25 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
from dataclasses import dataclass
from fastvideo.configs.sample.base import SamplingParam
@dataclass
class SD35SamplingParam(SamplingParam):
prompt: str | None = "a photo of a cat"
negative_prompt: str = ""
num_videos_per_prompt: int = 1
seed: int = 0
num_frames: int = 1
height: int = 512
width: int = 512
fps: int = 1
num_inference_steps: int = 28
guidance_scale: float = 6.0
# SD35 sampling defaults have been migrated to profile-based
# configuration. See fastvideo/pipelines/basic/sd35/profiles.py
# and use SamplingParam.from_pretrained(
# "stabilityai/stable-diffusion-3.5-medium") instead.
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: Apache-2.0
"""Pipeline profiles for Stable Diffusion 3.5 model family.
Each profile defines default sampling parameters that differ from the
base ``SamplingParam`` defaults.
"""
from fastvideo.configs.sample.profiles import (
PipelineProfile,
register_profile,
)
SD35_MEDIUM = PipelineProfile(
name="sd35_medium",
defaults={
"negative_prompt": "",
"num_videos_per_prompt": 1,
"seed": 0,
"num_frames": 1,
"height": 512,
"width": 512,
"fps": 1,
"num_inference_steps": 28,
"guidance_scale": 6.0,
},
)
register_profile(SD35_MEDIUM)
+6 -3
View File
@@ -83,8 +83,6 @@ from fastvideo.configs.sample.wan import (
WanT2V_14B_SamplingParam,
WanT2V_1_3B_SamplingParam,
)
from fastvideo.configs.sample.sd35 import SD35SamplingParam
from fastvideo.fastvideo_args import WorkloadType
from fastvideo.logger import init_logger
from fastvideo.utils import (maybe_download_model_index, verify_model_config_and_directory)
@@ -138,6 +136,7 @@ class ConfigInfo:
sampling_param_cls: type[SamplingParam] | None
pipeline_config_cls: type[PipelineConfig]
workload_types: tuple[WorkloadType, ...]
default_profile: str | None = None
# The central registry mapping a model name to its configuration information
@@ -156,6 +155,7 @@ def register_configs(
workload_types: tuple[WorkloadType, ...],
hf_model_paths: list[str] | None = None,
model_detectors: list[Callable[[str], bool]] | None = None,
default_profile: str | None = None,
) -> None:
"""Register config classes for a model family.
@@ -168,6 +168,7 @@ def register_configs(
sampling_param_cls=sampling_param_cls,
pipeline_config_cls=pipeline_config_cls,
workload_types=workload_types,
default_profile=default_profile,
)
if hf_model_paths:
@@ -624,8 +625,9 @@ def _register_configs() -> None:
)
# SD3.5
import fastvideo.pipelines.basic.sd35.profiles # noqa: F401
register_configs(
sampling_param_cls=SD35SamplingParam,
sampling_param_cls=None,
pipeline_config_cls=SD35Config,
workload_types=(WorkloadType.T2I, ),
hf_model_paths=[
@@ -638,6 +640,7 @@ def _register_configs() -> None:
"stabilityai__stable-diffusion-3.5-medium",
)),
],
default_profile="sd35_medium",
)
+3 -2
View File
@@ -6,7 +6,7 @@ import os
import pytest
import torch
from fastvideo.configs.sample.sd35 import SD35SamplingParam
from fastvideo.configs.sample.base import SamplingParam
from fastvideo.logger import init_logger
from fastvideo.tests.ssim.inference_similarity_utils import (
run_text_to_video_similarity_test,
@@ -60,7 +60,8 @@ SD35_PARAMS = {
"neg_prompt": "lowres, blurry",
}
_SD35_FULL_QUALITY_DEFAULTS = SD35SamplingParam()
_SD35_FULL_QUALITY_DEFAULTS = SamplingParam.from_pretrained(
"stabilityai/stable-diffusion-3.5-medium")
SD35_FULL_QUALITY_PARAMS = {
"num_gpus": 1,
"model_path": SD35_MODEL_PATH,