Add Pika H3 Flex (MiniMax-H3 plus the released fl2va/ref2va rank-128 adapters) as a FastVideo model family: registry/config/presets, bucket geometry with tiered reference sizing, automatic adapter selection and manifest validation, the fixed six-forward re-noise sampler, T2VA/I2VA/L2VA/FL2VA/Ref2VA pipeline support, an example, docs, and CPU unit tests. GPU end-to-end validation is still pending. This change does not add PDD, VSA, or new kernel paths.
1502 lines
60 KiB
Python
1502 lines
60 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
"""
|
|
Central registry for FastVideo pipelines and model configuration discovery.
|
|
|
|
This module mirrors the organization of sglang's registry while keeping
|
|
FastVideo's legacy behavior and mappings intact.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
import os
|
|
from collections.abc import Callable
|
|
from functools import lru_cache
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from fastvideo.configs.pipelines.base import PipelineConfig
|
|
from fastvideo.configs.pipelines.cosmos import CosmosConfig
|
|
from fastvideo.configs.pipelines.cosmos2_5 import (
|
|
Cosmos25Config,
|
|
Cosmos25_14BConfig,
|
|
)
|
|
from fastvideo.configs.pipelines.hunyuan import FastHunyuanConfig, HunyuanConfig
|
|
from fastvideo.configs.pipelines.gen3c import Gen3CConfig
|
|
from fastvideo.configs.pipelines.helios import HeliosPipelineConfig
|
|
from fastvideo.configs.pipelines.hunyuan15 import (Hunyuan15T2V480PConfig, Hunyuan15I2V480PStepDistilledConfig,
|
|
Hunyuan15T2V720PConfig, Hunyuan15I2V720PConfig,
|
|
Hunyuan15SR1080PConfig)
|
|
from fastvideo.configs.pipelines.hyworld import HYWorldConfig
|
|
from fastvideo.configs.pipelines.kandinsky5 import Kandinsky5I2VConfig, Kandinsky5T2VConfig
|
|
from fastvideo.configs.pipelines.kandinsky6 import Kandinsky6TI2VAConfig
|
|
from fastvideo.configs.pipelines.kandinsky6_sr import Kandinsky6SRPipelineConfig
|
|
from fastvideo.configs.pipelines.lingbot_video import LingBotVideoT2VConfig
|
|
from fastvideo.configs.pipelines.lingbotworld import LingBotWorldI2V480PConfig
|
|
from fastvideo.configs.pipelines.lingbotworld2 import LingBotWorld2CausalFastI2V480PConfig
|
|
from fastvideo.configs.pipelines.lingbotworld_fast import LingBotWorldFastI2V480PConfig
|
|
from fastvideo.pipelines.basic.ltx2.pipeline_configs import LTX2T2VConfig
|
|
from fastvideo.configs.pipelines.flux_2 import (
|
|
Flux2KleinPipelineConfig,
|
|
Flux2PipelineConfig,
|
|
)
|
|
from fastvideo.configs.pipelines.matrixgame2 import MatrixGame2I2V480PConfig
|
|
from fastvideo.configs.pipelines.matrixgame3 import MatrixGame3I2V720PConfig
|
|
from fastvideo.configs.pipelines.minimax_h3 import MiniMaxH3PipelineConfig
|
|
from fastvideo.configs.pipelines.pika_h3_flex import PikaH3FlexPipelineConfig
|
|
from fastvideo.configs.pipelines.mmaudio import (
|
|
MMAudioLarge44kV2PipelineConfig,
|
|
MMAudioLarge44kV2AConfig,
|
|
MMAudioMedium44kV2AConfig,
|
|
MMAudioSmall16kV2AConfig,
|
|
MMAudioSmall44kV2AConfig,
|
|
MMAudioV2AConfig,
|
|
)
|
|
from fastvideo.models.wan import pipeline_config as wan_pipeline_config
|
|
from fastvideo.models.wan.definition import WAN_MODEL_DEFINITIONS, WanModelDefinition
|
|
from fastvideo.configs.pipelines.flux import FluxPipelineConfig
|
|
from fastvideo.configs.pipelines.sd35 import SD35Config
|
|
from fastvideo.configs.pipelines.stable_audio import (StableAudioOpenSmallConfig, StableAudioT2AConfig)
|
|
from fastvideo.configs.pipelines.qwen_image21 import QwenImage21PipelineConfig
|
|
from fastvideo.api.sampling_param import SamplingParam
|
|
from fastvideo.api.matrixgame2 import MatrixGame2SamplingParam
|
|
from fastvideo.api.matrixgame3 import MatrixGame3SamplingParam
|
|
from fastvideo.api.flux import FluxSamplingParam
|
|
from fastvideo.api.pika_h3_flex import PikaH3FlexSamplingParam
|
|
|
|
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)
|
|
|
|
logger = init_logger(__name__)
|
|
|
|
if TYPE_CHECKING:
|
|
from fastvideo.pipelines.composed_pipeline_base import ComposedPipelineBase
|
|
from fastvideo.pipelines.pipeline_registry import PipelineType
|
|
|
|
# --- Part 1: Pipeline Discovery ---
|
|
|
|
_PIPELINE_REGISTRY: dict[str, dict[str, type[ComposedPipelineBase]]] = {}
|
|
|
|
# Registry for pipeline configuration classes (for single-file weights without
|
|
# model_index.json). Maps pipeline_class_name -> (PipelineConfig, SamplingParam)
|
|
_PIPELINE_CONFIG_REGISTRY: dict[str, tuple[type[PipelineConfig], type[SamplingParam]]] = {}
|
|
|
|
|
|
def _discover_and_register_pipelines() -> None:
|
|
if _PIPELINE_REGISTRY:
|
|
return
|
|
|
|
from fastvideo.pipelines.pipeline_registry import import_pipeline_classes
|
|
|
|
pipeline_classes = import_pipeline_classes()
|
|
for pipeline_type, pipeline_dict in pipeline_classes.items():
|
|
_PIPELINE_REGISTRY[pipeline_type] = pipeline_dict
|
|
for pipeline_cls in pipeline_dict.values():
|
|
if pipeline_cls is None:
|
|
continue
|
|
if hasattr(pipeline_cls, "pipeline_config_cls") and hasattr(pipeline_cls, "sampling_params_cls"):
|
|
_PIPELINE_CONFIG_REGISTRY[pipeline_cls.__name__] = (
|
|
pipeline_cls.pipeline_config_cls,
|
|
pipeline_cls.sampling_params_cls,
|
|
)
|
|
|
|
|
|
def get_pipeline_config_classes(pipeline_class_name: str) -> tuple[type[PipelineConfig], type[SamplingParam]] | None:
|
|
_discover_and_register_pipelines()
|
|
return _PIPELINE_CONFIG_REGISTRY.get(pipeline_class_name)
|
|
|
|
|
|
# --- Part 2: Config Registration ---
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class ConfigInfo:
|
|
"""Encapsulates sampling + pipeline config classes for a model family."""
|
|
|
|
sampling_param_cls: type[SamplingParam] | None
|
|
pipeline_config_cls: type[PipelineConfig]
|
|
workload_types: tuple[WorkloadType, ...]
|
|
model_family: str | None = None
|
|
default_preset: str | None = None
|
|
# When set, overrides the model_index `_class_name` for pipeline resolution.
|
|
# Lets a model family map to a specific pipeline class by path/detector
|
|
# (e.g. a T2V and I2V checkpoint that share a `_class_name`).
|
|
pipeline_cls_name: str | None = None
|
|
|
|
|
|
# The central registry mapping a model name to its configuration information
|
|
_CONFIG_REGISTRY: dict[str, ConfigInfo] = {}
|
|
|
|
# Mappings from Hugging Face model paths to our internal model names
|
|
_MODEL_HF_PATH_TO_NAME: dict[str, str] = {}
|
|
|
|
# Detectors to identify model families from paths or class names
|
|
_MODEL_NAME_DETECTORS: list[tuple[str, Callable[[str], bool]]] = []
|
|
|
|
|
|
def register_configs(
|
|
sampling_param_cls: type[SamplingParam] | None,
|
|
pipeline_config_cls: type[PipelineConfig],
|
|
workload_types: tuple[WorkloadType, ...],
|
|
hf_model_paths: list[str] | None = None,
|
|
model_detectors: list[Callable[[str], bool]] | None = None,
|
|
model_family: str | None = None,
|
|
default_preset: str | None = None,
|
|
pipeline_cls_name: str | None = None,
|
|
) -> None:
|
|
"""Register config classes for a model family.
|
|
|
|
workload_types declares which UI workload options this config supports.
|
|
Use () for configs not exposed as workload options.
|
|
"""
|
|
model_id = str(len(_CONFIG_REGISTRY))
|
|
|
|
_CONFIG_REGISTRY[model_id] = ConfigInfo(
|
|
sampling_param_cls=sampling_param_cls,
|
|
pipeline_config_cls=pipeline_config_cls,
|
|
workload_types=workload_types,
|
|
model_family=model_family,
|
|
default_preset=default_preset,
|
|
pipeline_cls_name=pipeline_cls_name,
|
|
)
|
|
|
|
if hf_model_paths:
|
|
for path in hf_model_paths:
|
|
if path in _MODEL_HF_PATH_TO_NAME:
|
|
logger.warning("Model path '%s' is already mapped to '%s' and will be overwritten by '%s'.", path,
|
|
_MODEL_HF_PATH_TO_NAME[path], model_id)
|
|
_MODEL_HF_PATH_TO_NAME[path] = model_id
|
|
|
|
if model_detectors:
|
|
for detector in model_detectors:
|
|
_MODEL_NAME_DETECTORS.append((model_id, detector))
|
|
|
|
|
|
def get_model_short_name(model_id: str) -> str:
|
|
if "/" in model_id:
|
|
return model_id.split("/")[-1]
|
|
return model_id
|
|
|
|
|
|
def _longest_common_substring_length(left: str, right: str) -> int:
|
|
"""Length of the longest substring shared by ``left`` and ``right``."""
|
|
if not left or not right:
|
|
return 0
|
|
previous = [0] * (len(right) + 1)
|
|
longest = 0
|
|
for left_char in left:
|
|
current = [0] * (len(right) + 1)
|
|
for index, right_char in enumerate(right, start=1):
|
|
if left_char == right_char:
|
|
current[index] = previous[index - 1] + 1
|
|
longest = max(longest, current[index])
|
|
previous = current
|
|
return longest
|
|
|
|
|
|
def _pattern_specificity(model_id: str, path_lower: str) -> int:
|
|
"""How specifically ``path_lower`` points at ``model_id``: the longest
|
|
substring it shares with any of the model's registered HF paths (short
|
|
names). Unlike plain containment this still scores truncated or
|
|
re-hyphenated local directory names (e.g. ``ltx-2.3-distilled``). An
|
|
entry registered only through detectors scores 0."""
|
|
return max((_longest_common_substring_length(path_lower, get_model_short_name(registered_path.lower()))
|
|
for registered_path, mapped_id in _MODEL_HF_PATH_TO_NAME.items() if mapped_id == model_id),
|
|
default=0)
|
|
|
|
|
|
def _resolve_class_name(config: dict[str, Any]) -> str | None:
|
|
"""Read `_class_name` from a model_index.json/component config dict.
|
|
|
|
Usually a plain string, but some exports write it in the diffusers
|
|
`[library, class]` 2-element form instead -- unwrap that form to the bare
|
|
class name.
|
|
"""
|
|
class_name = config.get("_class_name")
|
|
if isinstance(class_name, list | tuple):
|
|
return class_name[-1] if class_name else None
|
|
return class_name
|
|
|
|
|
|
def _get_config_info(
|
|
model_path: str,
|
|
*,
|
|
raise_on_missing: bool = True,
|
|
revision: str | None = None,
|
|
allow_remote: bool = True,
|
|
) -> ConfigInfo | None:
|
|
# Normalize only the lookup key; keep the real path for manifest IO and detectors.
|
|
lookup_path = model_path.rstrip("/") or model_path
|
|
parts = lookup_path.split("/")
|
|
# Standard Hugging Face cache layout: models--{org}--{name}/snapshots/{revision}.
|
|
if len(parts) >= 3 and parts[-2] == "snapshots" and parts[-3].startswith("models--"):
|
|
lookup_path = parts[-3][len("models--"):].replace("--", "/", 1)
|
|
|
|
# 1. Exact match
|
|
if lookup_path in _MODEL_HF_PATH_TO_NAME:
|
|
model_id = _MODEL_HF_PATH_TO_NAME[lookup_path]
|
|
logger.debug("Resolved model path '%s' from exact path match.", model_path)
|
|
return _CONFIG_REGISTRY.get(model_id)
|
|
|
|
# 2. Partial match: use short model name.
|
|
model_name = get_model_short_name(lookup_path.lower())
|
|
all_model_hf_paths = sorted(_MODEL_HF_PATH_TO_NAME.keys(), key=len, reverse=True)
|
|
for registered_model_hf_id in all_model_hf_paths:
|
|
registered_model_name = get_model_short_name(registered_model_hf_id.lower())
|
|
if registered_model_name == model_name:
|
|
logger.debug("Resolved model name '%s' from partial path match.", registered_model_hf_id)
|
|
model_id = _MODEL_HF_PATH_TO_NAME[registered_model_hf_id]
|
|
return _CONFIG_REGISTRY.get(model_id)
|
|
|
|
# 3. Use detectors (path or model_index pipeline name).
|
|
if os.path.exists(model_path):
|
|
config = verify_model_config_and_directory(model_path, required_component_dirs=[])
|
|
elif allow_remote:
|
|
config = maybe_download_model_index(model_path, revision=revision)
|
|
else:
|
|
return None
|
|
|
|
pipeline_name = (_resolve_class_name(config) or "").lower()
|
|
scheduler = config.get("scheduler")
|
|
if (pipeline_name == "heliospyramidpipeline" and config.get("is_distilled") is True and isinstance(scheduler, list)
|
|
and len(scheduler) >= 2 and scheduler[1] == "HeliosDMDScheduler"):
|
|
helios_model_id = _MODEL_HF_PATH_TO_NAME.get("BestWishYsh/Helios-Distilled")
|
|
if helios_model_id is not None:
|
|
logger.debug("Resolved Helios-Distilled from authoritative model index metadata.")
|
|
return _CONFIG_REGISTRY.get(helios_model_id)
|
|
variant = config.get("fastvideo_ltx2_variant", "").lower()
|
|
|
|
matched_model_names: list[str] = []
|
|
for model_id, detector in _MODEL_NAME_DETECTORS:
|
|
if detector(model_path.lower()) or detector(pipeline_name) or detector(variant):
|
|
logger.debug("Matched model name '%s' using a registered detector.", model_id)
|
|
matched_model_names.append(model_id)
|
|
|
|
if matched_model_names:
|
|
if len(matched_model_names) > 1:
|
|
# The first detector match always wins: registration order is the
|
|
# supported precedence (dedicated entries register before broad
|
|
# family ones, e.g. LTX-2 distilled before LTX-2 base), even when
|
|
# a path detector and a class-name detector disagree.
|
|
# Specificity only decides whether that choice is ambiguous. When
|
|
# the first match shares more of the query path with its
|
|
# registered HF paths than every other match does (e.g. an
|
|
# LTX-2.3 distilled directory that the LTX-2 base detector also
|
|
# claims through the shared pipeline class name), resolve
|
|
# silently. Otherwise warn.
|
|
path_lower = model_path.lower()
|
|
first_score, *other_scores = [_pattern_specificity(name, path_lower) for name in matched_model_names]
|
|
if first_score <= max(other_scores):
|
|
logger.warning(
|
|
"Multiple models matched for path '%s': %s. Using the first matched: '%s'.",
|
|
model_path,
|
|
matched_model_names,
|
|
matched_model_names[0],
|
|
)
|
|
model_id = matched_model_names[0]
|
|
return _CONFIG_REGISTRY.get(model_id)
|
|
|
|
if raise_on_missing:
|
|
raise RuntimeError(f"No model info found for model path: {model_path}")
|
|
return None
|
|
|
|
|
|
def _mmaudio_variant_detector(expected: str) -> Callable[[str], bool]:
|
|
|
|
def detector(path: str) -> bool:
|
|
normalized = path.lower().replace("-", "_")
|
|
return expected in normalized and (expected == "large_44k_v2" or "large_44k_v2" not in normalized)
|
|
|
|
return detector
|
|
|
|
|
|
def _unversioned_mmaudio_detector(*, mode: str) -> Callable[[str], bool]:
|
|
variants = ("small_16k", "small_44k", "medium_44k", "large_44k")
|
|
|
|
def detector(path: str) -> bool:
|
|
normalized = path.lower().replace("-", "_")
|
|
# This fallback is path-only. Matching ``mmaudiopipeline`` would also
|
|
# fire for every variant-specific model_index and create ambiguity.
|
|
if "mmaudio" not in normalized or "mmaudiopipeline" in normalized:
|
|
return False
|
|
if any(variant in normalized for variant in variants):
|
|
return False
|
|
return ("16k" in normalized) if mode == "16k" else ("16k" not in normalized)
|
|
|
|
return detector
|
|
|
|
|
|
def _register_wan_configs(definitions: tuple[WanModelDefinition, ...]) -> None:
|
|
for definition in definitions:
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=getattr(wan_pipeline_config, definition.pipeline_config),
|
|
workload_types=tuple(WorkloadType(value) for value in definition.workload_types),
|
|
hf_model_paths=list(definition.hf_model_paths),
|
|
model_detectors=[definition.matches] if definition.match_any else None,
|
|
model_family="wan",
|
|
default_preset=definition.preset,
|
|
)
|
|
|
|
|
|
def _register_configs() -> None:
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=HeliosPipelineConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=["BestWishYsh/Helios-Distilled"],
|
|
model_detectors=[],
|
|
model_family="helios",
|
|
default_preset="helios_distilled_t2v",
|
|
pipeline_cls_name="HeliosPyramidPipeline",
|
|
)
|
|
|
|
# Official MMAudio video/text-to-audio variants. Converted directories keep
|
|
# the variant in their path, allowing the registry to select the matching
|
|
# 16 kHz or 44.1 kHz component configuration before any modules are loaded.
|
|
mmaudio_variants = (
|
|
("small_16k", MMAudioSmall16kV2AConfig),
|
|
("small_44k", MMAudioSmall44kV2AConfig),
|
|
("medium_44k", MMAudioMedium44kV2AConfig),
|
|
("large_44k_v2", MMAudioLarge44kV2PipelineConfig),
|
|
("large_44k", MMAudioLarge44kV2AConfig),
|
|
)
|
|
for variant, pipeline_config_cls in mmaudio_variants:
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=pipeline_config_cls,
|
|
workload_types=(WorkloadType.V2A, WorkloadType.T2A),
|
|
hf_model_paths=[
|
|
f"FastVideo/MMAudio-{variant.replace('_', '-')}-Diffusers",
|
|
],
|
|
model_detectors=[_mmaudio_variant_detector(variant)],
|
|
model_family="mmaudio",
|
|
default_preset=f"mmaudio_{variant}",
|
|
pipeline_cls_name="MMAudioPipeline",
|
|
)
|
|
|
|
# Preserve converted preprocessing trees and older local checkpoint names
|
|
# that predate explicit variant tags. These detectors intentionally do not
|
|
# inspect ``_class_name=MMAudioPipeline`` so they cannot overlap the five
|
|
# exact variant entries above.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=MMAudioSmall16kV2AConfig,
|
|
workload_types=(WorkloadType.V2A, WorkloadType.T2A),
|
|
model_detectors=[_unversioned_mmaudio_detector(mode="16k")],
|
|
model_family="mmaudio",
|
|
default_preset="mmaudio_small_16k",
|
|
pipeline_cls_name="MMAudioPipeline",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=MMAudioV2AConfig,
|
|
workload_types=(WorkloadType.V2A, WorkloadType.T2A),
|
|
model_detectors=[_unversioned_mmaudio_detector(mode="44k")],
|
|
model_family="mmaudio",
|
|
default_preset="mmaudio_large_44k_v2",
|
|
pipeline_cls_name="MMAudioPipeline",
|
|
)
|
|
|
|
# LTX-2.5 distilled — registered before every older/generic LTX entry so
|
|
# its ancestral-sampling preset and architecture flags cannot be shadowed.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LTX2T2VConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=[
|
|
"FastVideo/LTX-2.5-Distilled-Diffusers",
|
|
"FastVideo/LTX2.5-Distilled-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: ("ltx-2.5" in path.lower() or "ltx2.5" in path.lower()) and "distilled" in path.lower(),
|
|
],
|
|
model_family="ltx2",
|
|
default_preset="ltx2_5_distilled_two_stage",
|
|
)
|
|
# LTX-2.5 dev — raw Lightricks split checkpoints must first be converted
|
|
# into the standard component layout consumed by FastVideo loaders.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LTX2T2VConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=[
|
|
"FastVideo/LTX-2.5-Dev-Diffusers",
|
|
"FastVideo/LTX2.5-Dev-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: ("ltx-2.5" in path.lower() or "ltx2.5" in path.lower()) and "distilled" not in path.lower(),
|
|
],
|
|
model_family="ltx2",
|
|
default_preset="ltx2_5_dev",
|
|
)
|
|
|
|
# LTX-2 (distilled) — registered before the generic base detector so its
|
|
# detector wins over the base detector when both fire. The detector loop in
|
|
# ``get_model_name_for_path`` ORs the path-based check with a
|
|
# pipeline-name check (``ltx2pipeline``) which the base detector's
|
|
# "distilled not in path" predicate matches as True (the
|
|
# pipeline_name string contains no "distilled" marker), so the
|
|
# less-specific BASE detector would otherwise win when the
|
|
# input is the absolute path of the distilled checkpoint.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LTX2T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/LTX2-Distilled-Diffusers",
|
|
# LTX-2.3 distilled aliases share the distilled pipeline/preset.
|
|
"FastVideo/LTX2.3-Distilled-Diffusers",
|
|
"FastVideo/LTX-2.3-Distilled-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: ("ltx2" in path.lower() or "ltx-2" in path.lower()) and "distilled" in path.lower(),
|
|
],
|
|
model_family="ltx2",
|
|
default_preset="ltx2_distilled",
|
|
)
|
|
# LTX-2.3 (base) — registered before the LTX-2.0 base entry so its more
|
|
# specific 2.3 detector wins. Uses the same pipeline config; the new
|
|
# arch flags are read from the checkpoint config.json.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LTX2T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"Lightricks/LTX-2.3",
|
|
"FastVideo/LTX2.3-base",
|
|
"FastVideo/LTX2.3-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: (any(token in path.lower() for token in (
|
|
"lightricks/ltx-2.3",
|
|
"ltx2.3-base",
|
|
"ltx2.3-diffusers",
|
|
"ltx-2.3-diffusers",
|
|
)) and "distilled" not in path.lower()),
|
|
],
|
|
model_family="ltx2",
|
|
default_preset="ltx2_3_base",
|
|
)
|
|
# LTX-2 (base) — excludes 2.3 so the dedicated 2.3 entry above wins.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LTX2T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"Lightricks/LTX-2",
|
|
"FastVideo/LTX2-base",
|
|
"FastVideo/LTX2-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: ("ltx2" in path.lower() or "ltx-2" in path.lower()) and "distilled" not in path.lower() and
|
|
"2.3" not in path.lower(),
|
|
],
|
|
model_family="ltx2",
|
|
default_preset="ltx2_base",
|
|
)
|
|
|
|
# Stable Audio Open (text-to-audio). Both variants must be loaded
|
|
# from the FastVideo-curated converted Diffusers-format repos —
|
|
# the upstream `stabilityai/stable-audio-open-{1.0,small}` repos
|
|
# ship `model.safetensors` as a single monolithic checkpoint with
|
|
# no per-component subfolders our standard loader can consume. See
|
|
# `scripts/checkpoint_conversion/stable_audio_to_diffusers.py`.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=StableAudioT2AConfig,
|
|
# Keep T2V as a backward-compatible alias for existing callers while
|
|
# exposing the semantically correct audio workload to new clients.
|
|
workload_types=(WorkloadType.T2A, WorkloadType.T2V),
|
|
hf_model_paths=[
|
|
"FastVideo/stable-audio-open-1.0-Diffusers",
|
|
],
|
|
# Substring match against HF cache snapshot paths (the lookup
|
|
# runs on the resolved local directory, which uses `--` between
|
|
# org and repo: `models--FastVideo--stable-audio-open-1.0-Diffusers`).
|
|
model_detectors=[
|
|
lambda path: "stable-audio-open-1" in path.lower(),
|
|
],
|
|
model_family="stable_audio",
|
|
default_preset="stable_audio_open_1_0_base",
|
|
)
|
|
# Small variant uses its own `pipeline_config_cls` so it picks up
|
|
# the smaller (524288-sample) training window in `sample_size` /
|
|
# `max_audio_duration_s`.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=StableAudioOpenSmallConfig,
|
|
workload_types=(WorkloadType.T2A, WorkloadType.T2V),
|
|
hf_model_paths=[
|
|
"FastVideo/stable-audio-open-small-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: "stable-audio-open-small" in path.lower(),
|
|
],
|
|
model_family="stable_audio",
|
|
default_preset="stable_audio_open_small",
|
|
)
|
|
|
|
def _is_flux2_klein(path: str) -> bool:
|
|
path_lower = path.lower()
|
|
return "flux.2-klein" in path_lower or "flux2-klein" in path_lower or "flux2klein" in path_lower
|
|
|
|
def _is_flux2_full(path: str) -> bool:
|
|
path_lower = path.lower()
|
|
is_flux2 = "flux.2" in path_lower or "flux2" in path_lower or "flux_2" in path_lower or "flux-2" in path_lower
|
|
return is_flux2 and "klein" not in path_lower
|
|
|
|
# Flux2 Klein (distilled, 4-step, no guidance)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Flux2KleinPipelineConfig,
|
|
workload_types=(WorkloadType.T2I, ),
|
|
hf_model_paths=[
|
|
"black-forest-labs/FLUX.2-klein-4B",
|
|
"black-forest-labs/FLUX.2-klein-9B",
|
|
],
|
|
model_detectors=[
|
|
_is_flux2_klein,
|
|
],
|
|
model_family="flux2",
|
|
default_preset="flux2_klein_4b",
|
|
)
|
|
# Flux2 (full, Mistral3 text encoder, embedded guidance)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Flux2PipelineConfig,
|
|
workload_types=(WorkloadType.T2I, ),
|
|
hf_model_paths=[
|
|
"black-forest-labs/FLUX.2-dev",
|
|
],
|
|
model_detectors=[
|
|
_is_flux2_full,
|
|
],
|
|
model_family="flux2",
|
|
default_preset="flux2_dev",
|
|
)
|
|
|
|
# Hunyuan 1.5 (specific)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Hunyuan15T2V480PConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"hunyuanvideo-community/HunyuanVideo-1.5-Diffusers-480p_t2v",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"hunyuan15",
|
|
"hunyuanvideo15",
|
|
"hunyuanvideo-1.5",
|
|
"hunyuanvideo_1.5",
|
|
)),
|
|
],
|
|
model_family="hunyuan15",
|
|
default_preset="hunyuan15_t2v_480p",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Hunyuan15I2V480PStepDistilledConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"hunyuanvideo-community/HunyuanVideo-1.5-Diffusers-480p_i2v_step_distilled",
|
|
],
|
|
model_family="hunyuan15",
|
|
default_preset="hunyuan15_i2v_480p_distilled",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Hunyuan15T2V720PConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"hunyuanvideo-community/HunyuanVideo-1.5-Diffusers-720p_t2v",
|
|
],
|
|
model_family="hunyuan15",
|
|
default_preset="hunyuan15_t2v_720p",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Hunyuan15I2V720PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"hunyuanvideo-community/HunyuanVideo-1.5-Diffusers-720p_i2v_distilled",
|
|
],
|
|
model_family="hunyuan15",
|
|
default_preset="hunyuan15_i2v_720p_distilled",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Hunyuan15SR1080PConfig,
|
|
workload_types=(),
|
|
hf_model_paths=["weizhou03/HunyuanVideo-1.5-Diffusers-1080p", "weizhou03/HunyuanVideo-1.5-Diffusers-1080p-2SR"],
|
|
model_family="hunyuan15",
|
|
default_preset="hunyuan15_sr_1080p",
|
|
)
|
|
|
|
# Hunyuan (excludes hyworld, versioned models, and removed GameCraft checkpoints)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=HunyuanConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"hunyuanvideo-community/HunyuanVideo",
|
|
],
|
|
model_detectors=[
|
|
lambda path: "hunyuan" in path.lower() and "gamecraft" not in path.lower() and "hyworld" not in path.lower(
|
|
) and "1.5" not in path.lower() and "1-5" not in path.lower()
|
|
],
|
|
model_family="hunyuan",
|
|
default_preset="hunyuan_t2v",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=FastHunyuanConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/FastHunyuan-diffusers",
|
|
],
|
|
model_family="hunyuan",
|
|
default_preset="fast_hunyuan_t2v",
|
|
)
|
|
|
|
# HYWorld
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=HYWorldConfig,
|
|
workload_types=(),
|
|
hf_model_paths=[
|
|
"FastVideo/HY-WorldPlay-Bidirectional-Diffusers",
|
|
],
|
|
model_detectors=[lambda path: "hyworld" in path.lower()],
|
|
model_family="hyworld",
|
|
default_preset="hyworld_t2v",
|
|
)
|
|
|
|
# LingBotWorld2 causal-fast
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LingBotWorld2CausalFastI2V480PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"robbyant/lingbot-world-v2-14b-causal-fast",
|
|
],
|
|
model_detectors=[
|
|
lambda path:
|
|
("lingbot-world-v2-14b-causal-fast" in path.lower() or "lingbotworld2causalfastpipeline" in path.lower())
|
|
],
|
|
model_family="lingbotworld2",
|
|
default_preset="lingbotworld2_causal_fast_i2v",
|
|
)
|
|
|
|
# LingBotWorld-Fast — registered BEFORE the LingBotWorld base entry so its
|
|
# detector wins when both fire. The base detector only excludes the
|
|
# "causal-fast" spelling, so it also matches this checkpoint's path and its
|
|
# `lingbotworldcausaldmdpipeline` model_index name; the detector loop keeps
|
|
# the first match, which must be this more specific entry.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LingBotWorldFastI2V480PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/LingBot-World-Fast-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: ("lingbot-world-fast" in path.lower() or "lingbotworldfast" in path.lower() or
|
|
"lingbotworldcausaldmdpipeline" in path.lower())
|
|
],
|
|
model_family="lingbotworld_fast",
|
|
default_preset="lingbotworld_fast_i2v",
|
|
pipeline_cls_name="LingBotWorldFastPipeline",
|
|
)
|
|
|
|
# LingBotWorld
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LingBotWorldI2V480PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/LingBot-World-Base-Cam-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path:
|
|
(("lingbotworld" in path.lower() or "lingbot-world" in path.lower()) and "causal-fast" not in path.lower()
|
|
and "causalfast" not in path.lower() and "-fast" not in path.lower() and "causaldmd" not in path.lower())
|
|
],
|
|
model_family="lingbotworld",
|
|
default_preset="lingbotworld_i2v",
|
|
)
|
|
# LingBot-Video MoE T2V with the released second-stage refiner.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LingBotVideoT2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=["FastVideo/LingBot-Video-MoE-30B-A3B-Diffusers"],
|
|
model_detectors=[lambda path: "lingbotvideomoepipeline" in path.lower()],
|
|
model_family="lingbot_video",
|
|
default_preset="lingbot_video_moe_refiner_t2v",
|
|
pipeline_cls_name="LingBotVideoPipeline",
|
|
)
|
|
# LingBot-Video Dense T2V
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=LingBotVideoT2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=["FastVideo/LingBot-Video-Dense-1.3B-Diffusers"],
|
|
model_detectors=[lambda path: "lingbotvideodensepipeline" in path.lower()],
|
|
model_family="lingbot_video",
|
|
default_preset="lingbot_video_dense_t2v",
|
|
pipeline_cls_name="LingBotVideoPipeline",
|
|
)
|
|
|
|
def _kandinsky5_detector(require: tuple[str, ...] = (), exclude: tuple[str, ...] = ()) -> Callable[[str], bool]:
|
|
|
|
def detect(path: str) -> bool:
|
|
path_lower = path.lower()
|
|
if "kandinsky5" not in path_lower and "kandinsky-5" not in path_lower:
|
|
return False
|
|
return (all(token in path_lower for token in require) and not any(token in path_lower for token in exclude))
|
|
|
|
return detect
|
|
|
|
# t2v/i2v exclude each other so a checkpoint stored under a directory
|
|
# containing the other token (e.g. ~/i2v_experiments/kandinsky5-t2v-ft)
|
|
# falls through to the model_index _class_name fallback detectors below
|
|
# instead of being misrouted.
|
|
_is_kandinsky5_t2v = _kandinsky5_detector(require=("t2v", ), exclude=("i2v", ))
|
|
_is_kandinsky5_i2v = _kandinsky5_detector(require=("i2v", ), exclude=("t2v", ))
|
|
_is_kandinsky5_t2v_lite = _kandinsky5_detector(require=("t2v", "lite"), exclude=("i2v", "distilled"))
|
|
_is_kandinsky5_t2v_pro = _kandinsky5_detector(require=("t2v", "pro"), exclude=("i2v", "distilled"))
|
|
_is_kandinsky5_t2v_lite_distilled = _kandinsky5_detector(require=("t2v", "lite", "distilled"), exclude=("i2v", ))
|
|
_is_kandinsky5_t2v_pro_distilled = _kandinsky5_detector(require=("t2v", "pro", "distilled"), exclude=("i2v", ))
|
|
_is_kandinsky5_i2v_lite = _kandinsky5_detector(require=("i2v", "lite"), exclude=("t2v", "distilled"))
|
|
_is_kandinsky5_i2v_pro = _kandinsky5_detector(require=("i2v", "pro"), exclude=("t2v", "distilled"))
|
|
_is_kandinsky5_i2v_lite_distilled = _kandinsky5_detector(require=("i2v", "lite", "distilled"), exclude=("t2v", ))
|
|
_is_kandinsky5_i2v_pro_distilled = _kandinsky5_detector(require=("i2v", "pro", "distilled"), exclude=("t2v", ))
|
|
|
|
# Kandinsky5 Lite T2V
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-5.0-T2V-Lite-sft-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky5_t2v_lite,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_t2v_lite_5s",
|
|
pipeline_cls_name="Kandinsky5T2VPipeline",
|
|
)
|
|
|
|
# Kandinsky5 Pro T2V
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-5.0-T2V-Pro-sft-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky5_t2v_pro,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_t2v_pro_5s",
|
|
)
|
|
|
|
# Kandinsky5 Lite T2V Distilled
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-5.0-T2V-Lite-distilled16steps-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky5_t2v_lite_distilled,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_t2v_lite_distilled_5s",
|
|
)
|
|
|
|
# Kandinsky5 Pro T2V Distilled
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5T2VConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-5.0-T2V-Pro-distilled-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky5_t2v_pro_distilled,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_t2v_pro_distilled_5s",
|
|
)
|
|
|
|
# Kandinsky5 Lite I2V
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5I2VConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=["kandinskylab/Kandinsky-5.0-I2V-Lite-5s-Diffusers"],
|
|
model_detectors=[
|
|
_is_kandinsky5_i2v_lite,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_i2v_lite_5s",
|
|
pipeline_cls_name="Kandinsky5I2VPipeline",
|
|
)
|
|
|
|
# Kandinsky5 Pro I2V
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5I2VConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=["kandinskylab/Kandinsky-5.0-I2V-Pro-sft-5s-Diffusers"],
|
|
model_detectors=[
|
|
_is_kandinsky5_i2v_pro,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_i2v_pro_5s",
|
|
)
|
|
|
|
# Kandinsky5 Pro I2V Distilled
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5I2VConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=["kandinskylab/Kandinsky-5.0-I2V-Pro-distilled-5s-Diffusers"],
|
|
model_detectors=[
|
|
_is_kandinsky5_i2v_pro_distilled,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_i2v_pro_distilled_5s",
|
|
)
|
|
|
|
# Kandinsky5 Lite I2V Distilled (no official hub repo yet; local
|
|
# conversions get distilled sampling defaults instead of the sft ones the
|
|
# fallback would apply).
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5I2VConfig,
|
|
workload_types=(),
|
|
model_detectors=[
|
|
_is_kandinsky5_i2v_lite_distilled,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_i2v_lite_distilled_5s",
|
|
pipeline_cls_name="Kandinsky5I2VPipeline",
|
|
)
|
|
|
|
# Kandinsky5 fallbacks — registered AFTER the variant detectors so those
|
|
# win first-match. Catch checkpoints the variant detectors cannot resolve:
|
|
# token-less local paths matched via the model_index _class_name
|
|
# ("kandinsky5t2vpipeline" carries no lite/pro marker), variant combos
|
|
# without a dedicated entry (e.g. I2V Lite distilled), and t2v+i2v
|
|
# ambiguous paths resolved by the checkpoint's _class_name.
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5T2VConfig,
|
|
workload_types=(),
|
|
model_detectors=[
|
|
_is_kandinsky5_t2v,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_t2v_lite_5s",
|
|
pipeline_cls_name="Kandinsky5T2VPipeline",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky5I2VConfig,
|
|
workload_types=(),
|
|
model_detectors=[
|
|
_is_kandinsky5_i2v,
|
|
],
|
|
model_family="kandinsky5",
|
|
default_preset="kandinsky5_i2v_lite_5s",
|
|
pipeline_cls_name="Kandinsky5I2VPipeline",
|
|
)
|
|
|
|
# Kandinsky6 video super-resolution (video -> video). Registered before the Kandinsky6 TI2VA entries: VSR bundle
|
|
# names also contain the Kandinsky6 family markers and the first matching detector wins (the TI2VA detector excludes
|
|
# VSR bundles too). There is no V2V WorkloadType, so, like the Hunyuan15 SR entry, it declares no workload. Both
|
|
# bundles share the pipeline; the distilled one (PiflowScheduler, 2 steps) gets its own preset.
|
|
def _is_kandinsky6_sr(path: str) -> bool:
|
|
path_lower = path.lower()
|
|
if "kandinsky6" not in path_lower and "kandinsky-6" not in path_lower:
|
|
return False
|
|
# Only the last path component counts, so a parent directory called "sr" does not make a TI2VA checkpoint SR.
|
|
name = path_lower.rstrip("/").rsplit("/", 1)[-1].replace("_", "-").replace(".", "-")
|
|
return "6sr" in name or "superres" in name or "super-res" in name or any(token in ("sr", "vsr")
|
|
for token in name.split("-"))
|
|
|
|
def _is_kandinsky6_sr_distilled(path: str) -> bool:
|
|
return _is_kandinsky6_sr(path) and "distill" in path.lower().rstrip("/").rsplit("/", 1)[-1]
|
|
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky6SRPipelineConfig,
|
|
workload_types=(),
|
|
hf_model_paths=["kandinskylab/Kandinsky-6.0-VSR-distilled2steps-5s-Diffusers"],
|
|
model_detectors=[_is_kandinsky6_sr_distilled],
|
|
model_family="kandinsky6_sr",
|
|
default_preset="kandinsky6_sr_distilled",
|
|
pipeline_cls_name="Kandinsky6SRPipeline",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky6SRPipelineConfig,
|
|
workload_types=(),
|
|
hf_model_paths=["kandinskylab/Kandinsky-6.0-VSR-5s-Diffusers"],
|
|
model_detectors=[lambda path: _is_kandinsky6_sr(path) and not _is_kandinsky6_sr_distilled(path)],
|
|
model_family="kandinsky6_sr",
|
|
default_preset="kandinsky6_sr",
|
|
pipeline_cls_name="Kandinsky6SRPipeline",
|
|
)
|
|
|
|
# Kandinsky6 (TI2VA) -- a single pipeline handles text-only and
|
|
# image+text calls (see Kandinsky6TI2VAPipeline's docstring), so unlike
|
|
# Kandinsky5 there is no t2v/i2v detector split: any path/class-name
|
|
# containing "kandinsky6" or "kandinsky-6" resolves here (except VSR
|
|
# bundles, see above). The only split is base vs pi-Flow distilled, laid
|
|
# out like the LTX-2 distilled/base pair: the distilled entry is registered
|
|
# FIRST and the base detector excludes distilled names, so neither can
|
|
# swallow the other. Both bundles declare the same model_index
|
|
# `_class_name`, so a local copy counts as distilled only when its
|
|
# directory name is a Kandinsky-6 name containing "distill"
|
|
# ("Kandinsky-6.0-Pro-distill-5s-Diffusers"); any other directory resolves
|
|
# to the base entry.
|
|
def _is_kandinsky6_ti2va(path: str) -> bool:
|
|
path_lower = path.lower()
|
|
return ("kandinsky6" in path_lower or "kandinsky-6" in path_lower) and not _is_kandinsky6_sr(path_lower)
|
|
|
|
def _is_kandinsky6_distilled(path: str) -> bool:
|
|
# Looked up in the last path component only, like the VSR markers above.
|
|
name = path.lower().rstrip("/").rsplit("/", 1)[-1]
|
|
return _is_kandinsky6_ti2va(path) and "distill" in name
|
|
|
|
def _is_kandinsky6(path: str) -> bool:
|
|
return _is_kandinsky6_ti2va(path) and not _is_kandinsky6_distilled(path)
|
|
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky6TI2VAConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-6.0-Pro-distill-5s-Diffusers",
|
|
"kandinskylab/Kandinsky-6.0-Lite-distill-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky6_distilled,
|
|
],
|
|
model_family="kandinsky6",
|
|
default_preset="kandinsky6_ti2va_distilled",
|
|
pipeline_cls_name="Kandinsky6TI2VAPipeline",
|
|
)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Kandinsky6TI2VAConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=[
|
|
"kandinskylab/Kandinsky-6.0-Pro-5s-Diffusers",
|
|
"kandinskylab/Kandinsky-6.0-Pro-sft-5s-Diffusers",
|
|
"kandinskylab/Kandinsky-6.0-Lite-5s-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
_is_kandinsky6,
|
|
],
|
|
model_family="kandinsky6",
|
|
default_preset="kandinsky6_ti2va",
|
|
pipeline_cls_name="Kandinsky6TI2VAPipeline",
|
|
)
|
|
|
|
# MatrixGame 2.0 (I2V)
|
|
register_configs(
|
|
sampling_param_cls=MatrixGame2SamplingParam,
|
|
pipeline_config_cls=MatrixGame2I2V480PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers",
|
|
"FastVideo/Matrix-Game-2.0-GTA-Distilled-Diffusers",
|
|
"FastVideo/Matrix-Game-2.0-TempleRun-Distilled-Diffusers",
|
|
# Legacy HF paths (kept for backward compat - pre-rename names):
|
|
"FastVideo/Matrix-Game-2.0-Base-Diffusers",
|
|
"FastVideo/Matrix-Game-2.0-GTA-Diffusers",
|
|
"FastVideo/Matrix-Game-2.0-TempleRun-Diffusers",
|
|
# Zelda World Model
|
|
"mignonjia/mg_longtuning_distilled_zelda", # distilled using streaming long tuning which init from mg_sf_distilled_zelda_1k_steps
|
|
"mignonjia/mg_sf_distilled_zelda_1k_steps", # distilled using self forcing for 1k steps
|
|
"mignonjia/mg_sf_distilled_zelda", # distilled using self forcing for 3k steps
|
|
"mignonjia/mg_causal_zelda",
|
|
"mignonjia/mg_bidirectional_zelda",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"matrix-game-2",
|
|
"matrixgame2",
|
|
"matrix-game-2.0",
|
|
)),
|
|
],
|
|
model_family="matrixgame",
|
|
default_preset="matrixgame2_i2v",
|
|
)
|
|
# MatrixGame 3.0 (I2V)
|
|
register_configs(
|
|
sampling_param_cls=MatrixGame3SamplingParam,
|
|
pipeline_config_cls=MatrixGame3I2V720PConfig,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/Matrix-Game-3.0-Base-Distilled-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"matrix-game-3",
|
|
"matrixgame3",
|
|
"matrix-game-3.0",
|
|
)),
|
|
],
|
|
model_family="matrixgame",
|
|
default_preset="matrixgame3_i2v",
|
|
)
|
|
|
|
# GEN3C (must register before generic Cosmos detector)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Gen3CConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"FastVideo/GEN3C-Cosmos-7B-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: "gen3c" in path.lower(),
|
|
],
|
|
model_family="gen3c",
|
|
default_preset="gen3c_cosmos_7b",
|
|
)
|
|
|
|
# Cosmos 2.5 DFD V2W (2B). Register before the generic Cosmos 2.5
|
|
# detector so converted directories whose names contain DFD select the
|
|
# fixed four-step I2V preset.
|
|
def _cosmos25_dfd_detector(path: str) -> bool:
|
|
# "dfd" is matched in the last path component only (like the
|
|
# Kandinsky-6 distilled marker above) so a parent directory that
|
|
# merely contains "dfd" cannot re-label a base Predict2.5 package.
|
|
path_lower = path.lower()
|
|
name = path_lower.rstrip("/").rsplit("/", 1)[-1]
|
|
tokens = ("cosmos25", "cosmos2_5", "cosmos2.5", "cosmos-predict2.5")
|
|
return "dfd" in name and any(token in path_lower for token in tokens)
|
|
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Cosmos25Config,
|
|
workload_types=(WorkloadType.I2V, ),
|
|
model_detectors=[_cosmos25_dfd_detector],
|
|
model_family="cosmos25",
|
|
default_preset="cosmos25_dfd_v2w_2b",
|
|
)
|
|
|
|
# Cosmos 2.5 (2B)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Cosmos25Config,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"KyleShao/Cosmos-Predict2.5-2B-Diffusers",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"cosmos25",
|
|
"cosmos2_5",
|
|
"cosmos2.5",
|
|
"cosmos-predict2.5",
|
|
)) and "14b" not in path.lower(),
|
|
],
|
|
model_family="cosmos25",
|
|
default_preset="cosmos25_predict2_2b",
|
|
)
|
|
|
|
# Cosmos 2.5 (14B)
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=Cosmos25_14BConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"nvidia/Cosmos-Predict2.5-14B",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"cosmos25",
|
|
"cosmos2_5",
|
|
"cosmos2.5",
|
|
)) and "14b" in path.lower(),
|
|
],
|
|
model_family="cosmos25",
|
|
default_preset="cosmos25_predict2_2b",
|
|
)
|
|
|
|
# Cosmos 2
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=CosmosConfig,
|
|
workload_types=(WorkloadType.T2V, ),
|
|
hf_model_paths=[
|
|
"nvidia/Cosmos-Predict2-2B-Video2World",
|
|
],
|
|
model_detectors=[
|
|
lambda path: "cosmos" in path.lower() and ("2.5" not in path.lower() and "2_5" not in path.lower() and "25"
|
|
not in path.lower() and "gen3c" not in path.lower()),
|
|
],
|
|
model_family="cosmos",
|
|
default_preset="cosmos_predict2_2b",
|
|
)
|
|
|
|
_register_wan_configs(WAN_MODEL_DEFINITIONS)
|
|
|
|
# Pika H3 Flex. It reuses MiniMax-H3's components, but its six-forward
|
|
# re-noise sampler and bucket geometry are a separate family contract.
|
|
register_configs(
|
|
sampling_param_cls=PikaH3FlexSamplingParam,
|
|
pipeline_config_cls=PikaH3FlexPipelineConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=["Pika-Labs/Pika-H3-Flex"],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"pika-h3-flex",
|
|
"pika_h3_flex",
|
|
"pikah3flexmodularpipeline",
|
|
"pikah3flexref2vamodularpipeline",
|
|
)),
|
|
],
|
|
model_family="pika_h3_flex",
|
|
default_preset="pika_h3_flex_t2va",
|
|
pipeline_cls_name="PikaH3FlexModularPipeline",
|
|
)
|
|
|
|
# MiniMax H3
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=MiniMaxH3PipelineConfig,
|
|
workload_types=(WorkloadType.T2V, WorkloadType.I2V),
|
|
hf_model_paths=[
|
|
"MiniMaxAI/MiniMax-H3",
|
|
"FastVideo/FastVideo-Minimax-FastH3-Preview-v0.2",
|
|
"FastVideo/FastVideo-FastH3-8-Step-V2",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"minimax-h3",
|
|
"minimax_h3",
|
|
"fasth3",
|
|
"minimaxh3modularpipeline",
|
|
"minimaxh3ref2vamodularpipeline",
|
|
)),
|
|
],
|
|
model_family="minimax_h3",
|
|
default_preset="minimax_h3_t2va",
|
|
# FastH3 full checkpoints need not carry a Diffusers model_index.json;
|
|
# the native full-checkpoint loader still uses the standard H3 graph.
|
|
pipeline_cls_name="MiniMaxH3ModularPipeline",
|
|
)
|
|
|
|
# SD3.5
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=SD35Config,
|
|
workload_types=(WorkloadType.T2I, ),
|
|
hf_model_paths=[
|
|
"stabilityai/stable-diffusion-3.5-medium",
|
|
],
|
|
model_detectors=[
|
|
lambda path: any(token in path.lower() for token in (
|
|
"sd35",
|
|
"stablediffusion3",
|
|
"stabilityai__stable-diffusion-3.5-medium",
|
|
)),
|
|
],
|
|
model_family="sd35",
|
|
default_preset="sd35_medium",
|
|
)
|
|
|
|
# FLUX.1-dev (Diffusers)
|
|
register_configs(
|
|
sampling_param_cls=FluxSamplingParam,
|
|
pipeline_config_cls=FluxPipelineConfig,
|
|
workload_types=(WorkloadType.T2I, ),
|
|
hf_model_paths=[
|
|
"black-forest-labs/FLUX.1-dev",
|
|
],
|
|
model_detectors=[
|
|
lambda path: "fluxpipeline" in path,
|
|
lambda path: "flux.1-dev" in path or "flux_1_dev" in path,
|
|
lambda path: "/flux/" in path or path.endswith("/flux"),
|
|
],
|
|
)
|
|
|
|
register_configs(
|
|
sampling_param_cls=None,
|
|
pipeline_config_cls=QwenImage21PipelineConfig,
|
|
workload_types=(WorkloadType.T2I, WorkloadType.I2I),
|
|
hf_model_paths=["Qwen/Qwen-Image-2.1"],
|
|
model_detectors=[
|
|
lambda path: "qwenimage21pipeline" in path or "qwen-image-2.1" in path or "qwen_image21" in path,
|
|
],
|
|
model_family="qwen_image21",
|
|
default_preset="qwen_image21",
|
|
pipeline_cls_name="QwenImage21Pipeline",
|
|
)
|
|
|
|
|
|
# --- Part 3: Main Resolver ---
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class ModelInfo:
|
|
pipeline_cls: type[ComposedPipelineBase]
|
|
sampling_param_cls: type[SamplingParam]
|
|
pipeline_config_cls: type[PipelineConfig]
|
|
|
|
|
|
@lru_cache(maxsize=32)
|
|
def get_model_info(
|
|
model_path: str,
|
|
pipeline_type: PipelineType | str | None = None,
|
|
workload_type: WorkloadType | None = None,
|
|
override_pipeline_cls_name: str | None = None,
|
|
revision: str | None = None,
|
|
) -> ModelInfo:
|
|
from fastvideo.pipelines.pipeline_registry import (PipelineType, get_pipeline_registry)
|
|
|
|
if pipeline_type is None:
|
|
pipeline_type = PipelineType.BASIC
|
|
elif isinstance(pipeline_type, str):
|
|
pipeline_type = PipelineType.from_string(pipeline_type)
|
|
|
|
if workload_type is None:
|
|
workload_type = WorkloadType.T2V
|
|
|
|
config_info = _get_config_info(model_path, raise_on_missing=True, revision=revision)
|
|
assert config_info is not None, "config_info must be resolved"
|
|
|
|
if override_pipeline_cls_name:
|
|
# Explicit override: skip config resolution entirely so checkpoints
|
|
# without a diffusers model_index.json keep working (and no download
|
|
# is triggered just to log the replaced name).
|
|
pipeline_name: str | None = override_pipeline_cls_name
|
|
logger.info("Using override pipeline class name %s", pipeline_name)
|
|
else:
|
|
if os.path.exists(model_path):
|
|
config = verify_model_config_and_directory(model_path, required_component_dirs=[])
|
|
else:
|
|
config = maybe_download_model_index(model_path, revision=revision)
|
|
|
|
pipeline_name = _resolve_class_name(config)
|
|
if config_info.pipeline_cls_name is not None:
|
|
# The resolved (path/detector-based) config pins the pipeline class,
|
|
# e.g. an I2V checkpoint whose `_class_name` would otherwise resolve
|
|
# to the T2V pipeline.
|
|
logger.info("Pinning pipeline class name from %s to %s", pipeline_name, config_info.pipeline_cls_name)
|
|
pipeline_name = config_info.pipeline_cls_name
|
|
|
|
if pipeline_name is None:
|
|
raise ValueError("Model config does not contain a _class_name attribute. "
|
|
"Only diffusers format is supported.")
|
|
|
|
pipeline_registry = get_pipeline_registry(pipeline_type)
|
|
pipeline_cls = pipeline_registry.resolve_pipeline_cls(pipeline_name, pipeline_type, workload_type)
|
|
|
|
sampling_param_cls = config_info.sampling_param_cls or SamplingParam
|
|
|
|
return ModelInfo(
|
|
pipeline_cls=pipeline_cls,
|
|
sampling_param_cls=sampling_param_cls,
|
|
pipeline_config_cls=config_info.pipeline_config_cls,
|
|
)
|
|
|
|
|
|
def get_pipeline_config_cls_from_name(pipeline_name_or_path: str) -> type[PipelineConfig]:
|
|
config_info = _get_config_info(pipeline_name_or_path, raise_on_missing=False)
|
|
if config_info is None:
|
|
raise ValueError(
|
|
f"No match found for pipeline {pipeline_name_or_path}, please check the pipeline name or path.")
|
|
return config_info.pipeline_config_cls
|
|
|
|
|
|
def get_sampling_param_cls_for_name(pipeline_name_or_path: str, *, allow_remote: bool = True) -> Any | None:
|
|
config_info = _get_config_info(pipeline_name_or_path, raise_on_missing=False, allow_remote=allow_remote)
|
|
if config_info is None:
|
|
logger.warning("No match found for pipeline %s, using default sampling param.", pipeline_name_or_path)
|
|
return None
|
|
return config_info.sampling_param_cls
|
|
|
|
|
|
_register_configs()
|
|
|
|
|
|
def _register_presets() -> None:
|
|
from fastvideo.api.presets import register_preset
|
|
from fastvideo.pipelines.basic.cosmos.presets import (
|
|
ALL_PRESETS as COSMOS_PRESETS, )
|
|
from fastvideo.pipelines.basic.gen3c.presets import (
|
|
ALL_PRESETS as GEN3C_PRESETS, )
|
|
from fastvideo.pipelines.basic.hunyuan.presets import (
|
|
ALL_PRESETS as HUNYUAN_PRESETS, )
|
|
from fastvideo.pipelines.basic.hunyuan15.presets import (
|
|
ALL_PRESETS as HUNYUAN15_PRESETS, )
|
|
from fastvideo.pipelines.basic.helios.presets import (
|
|
ALL_PRESETS as HELIOS_PRESETS, )
|
|
from fastvideo.pipelines.basic.hyworld.presets import (
|
|
ALL_PRESETS as HYWORLD_PRESETS, )
|
|
from fastvideo.pipelines.basic.kandinsky5.presets import (
|
|
ALL_PRESETS as KANDINSKY5_PRESETS, )
|
|
from fastvideo.pipelines.basic.kandinsky6.presets import (
|
|
ALL_PRESETS as KANDINSKY6_PRESETS, )
|
|
from fastvideo.pipelines.basic.kandinsky6_sr.presets import (
|
|
ALL_PRESETS as KANDINSKY6_SR_PRESETS, )
|
|
from fastvideo.pipelines.basic.lingbotworld.presets import (
|
|
ALL_PRESETS as LINGBOTWORLD_PRESETS, )
|
|
from fastvideo.pipelines.basic.lingbotworld2.presets import (
|
|
ALL_PRESETS as LINGBOTWORLD2_PRESETS, )
|
|
from fastvideo.pipelines.basic.lingbotworld_fast.presets import (
|
|
ALL_PRESETS as LINGBOTWORLD_FAST_PRESETS, )
|
|
from fastvideo.pipelines.basic.lingbot_video.presets import (
|
|
ALL_PRESETS as LINGBOT_VIDEO_PRESETS, )
|
|
from fastvideo.pipelines.basic.ltx2.presets import (
|
|
ALL_PRESETS as LTX2_PRESETS, )
|
|
from fastvideo.pipelines.basic.magi_human.presets import (
|
|
ALL_PRESETS as MAGI_HUMAN_PRESETS, )
|
|
from fastvideo.pipelines.basic.matrixgame2.presets import (
|
|
ALL_PRESETS as MATRIXGAME2_PRESETS, )
|
|
from fastvideo.pipelines.basic.matrixgame3.presets import (
|
|
ALL_PRESETS as MATRIXGAME3_PRESETS, )
|
|
from fastvideo.pipelines.basic.minimax_h3.presets import (
|
|
ALL_PRESETS as MINIMAX_H3_PRESETS, )
|
|
from fastvideo.pipelines.basic.pika_h3_flex.presets import (
|
|
ALL_PRESETS as PIKA_H3_FLEX_PRESETS, )
|
|
from fastvideo.pipelines.basic.mmaudio.presets import (
|
|
ALL_PRESETS as MMAUDIO_PRESETS, )
|
|
from fastvideo.pipelines.basic.sd35.presets import (
|
|
ALL_PRESETS as SD35_PRESETS, )
|
|
from fastvideo.pipelines.basic.stable_audio.presets import (
|
|
ALL_PRESETS as STABLE_AUDIO_PRESETS, )
|
|
from fastvideo.pipelines.basic.wan.presets import (
|
|
ALL_PRESETS as WAN_PRESETS, )
|
|
from fastvideo.pipelines.basic.qwen_image21.presets import (
|
|
ALL_PRESETS as QWEN_IMAGE21_PRESETS, )
|
|
from fastvideo.pipelines.basic.flux_2.presets import (
|
|
ALL_PRESETS as FLUX2_PRESETS, )
|
|
|
|
all_preset_groups = (
|
|
COSMOS_PRESETS,
|
|
FLUX2_PRESETS,
|
|
GEN3C_PRESETS,
|
|
HUNYUAN_PRESETS,
|
|
HUNYUAN15_PRESETS,
|
|
HELIOS_PRESETS,
|
|
HYWORLD_PRESETS,
|
|
KANDINSKY5_PRESETS,
|
|
KANDINSKY6_PRESETS,
|
|
KANDINSKY6_SR_PRESETS,
|
|
LINGBOT_VIDEO_PRESETS,
|
|
LINGBOTWORLD_PRESETS,
|
|
LINGBOTWORLD2_PRESETS,
|
|
LINGBOTWORLD_FAST_PRESETS,
|
|
LTX2_PRESETS,
|
|
MAGI_HUMAN_PRESETS,
|
|
MATRIXGAME2_PRESETS,
|
|
MATRIXGAME3_PRESETS,
|
|
MINIMAX_H3_PRESETS,
|
|
PIKA_H3_FLEX_PRESETS,
|
|
MMAUDIO_PRESETS,
|
|
SD35_PRESETS,
|
|
STABLE_AUDIO_PRESETS,
|
|
WAN_PRESETS,
|
|
QWEN_IMAGE21_PRESETS,
|
|
)
|
|
for group in all_preset_groups:
|
|
for preset in group:
|
|
register_preset(preset)
|
|
|
|
|
|
_register_presets()
|
|
|
|
|
|
def get_model_family(model_path: str) -> str | None:
|
|
"""Return the ``model_family`` string for a model path, or ``None``."""
|
|
config_info = _get_config_info(model_path, raise_on_missing=False)
|
|
if config_info is None:
|
|
return None
|
|
return config_info.model_family
|
|
|
|
|
|
def get_default_preset(model_path: str) -> str | None:
|
|
"""Return the ``default_preset`` name for a model path."""
|
|
config_info = _get_config_info(model_path, raise_on_missing=False)
|
|
if config_info is None:
|
|
return None
|
|
return config_info.default_preset
|
|
|
|
|
|
def get_preset_selection(model_path: str) -> tuple[str | None, str | None]:
|
|
"""Return ``(default_preset, model_family)`` for a model path.
|
|
|
|
Single-lookup variant of :func:`get_default_preset` +
|
|
:func:`get_model_family`; callers that need both should prefer this
|
|
to avoid walking the registry twice.
|
|
"""
|
|
config_info = _get_config_info(model_path, raise_on_missing=False)
|
|
if config_info is None:
|
|
return None, None
|
|
return config_info.default_preset, config_info.model_family
|
|
|
|
|
|
def get_registered_model_paths() -> list[str]:
|
|
"""Return all registered HuggingFace model paths.
|
|
|
|
Useful for UIs and tooling that need to enumerate supported models.
|
|
"""
|
|
return sorted(_MODEL_HF_PATH_TO_NAME.keys())
|
|
|
|
|
|
def get_registered_models_with_workloads(workload_type: str | None = None, ) -> list[dict[str, Any]]:
|
|
"""Return models with workload metadata, optionally filtered by workload.
|
|
|
|
Args:
|
|
workload_type: If set (e.g. "t2v", "i2v", "t2i"), only return models
|
|
that support this workload. If None, return all with workload_types.
|
|
|
|
Returns:
|
|
List of dicts with keys: id, label, workload_types.
|
|
"""
|
|
result: list[dict[str, Any]] = []
|
|
for path in sorted(_MODEL_HF_PATH_TO_NAME.keys()):
|
|
model_id = _MODEL_HF_PATH_TO_NAME[path]
|
|
config_info = _CONFIG_REGISTRY.get(model_id)
|
|
if config_info is None:
|
|
continue
|
|
workload_values = [w.value for w in config_info.workload_types]
|
|
if workload_type is not None and workload_type.lower() not in workload_values:
|
|
continue
|
|
label = path.split("/")[-1].replace("-", " ").replace("_", " ")
|
|
result.append({
|
|
"id": path,
|
|
"label": label,
|
|
"workload_types": workload_values,
|
|
})
|
|
return result
|
|
|
|
|
|
__all__ = [
|
|
"ConfigInfo",
|
|
"ModelInfo",
|
|
"get_default_preset",
|
|
"get_model_family",
|
|
"get_model_info",
|
|
"get_pipeline_config_cls_from_name",
|
|
"get_registered_model_paths",
|
|
"get_registered_models_with_workloads",
|
|
"get_sampling_param_cls_for_name",
|
|
"get_pipeline_config_classes",
|
|
]
|