comprehensive ModelConfig refactor to support compatible HuggingFace dev/schnell models
This commit is contained in:
parent
e32be7bf31
commit
344ac90c74
@ -263,7 +263,7 @@ Or, with the correct python environment active, create and run a separate script
|
|||||||
from mflux import Flux1, Config
|
from mflux import Flux1, Config
|
||||||
|
|
||||||
# Load the model
|
# Load the model
|
||||||
flux = Flux1.from_alias(
|
flux = Flux1.from_name(
|
||||||
alias="schnell", # "schnell" or "dev"
|
alias="schnell", # "schnell" or "dev"
|
||||||
quantize=8, # 4 or 8
|
quantize=8, # 4 or 8
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mflux"
|
name = "mflux"
|
||||||
version = "0.5.1"
|
version = "0.6.0"
|
||||||
description = "A MLX port of FLUX based on the Huggingface Diffusers implementation."
|
description = "A MLX port of FLUX based on the Huggingface Diffusers implementation."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["diffusers", "flux", "mlx"]
|
keywords = ["diffusers", "flux", "mlx"]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from mflux.config.config import Config, ConfigControlnet
|
from mflux.config.config import Config, ConfigControlnet
|
||||||
from mflux.config.model_config import ModelConfig
|
from mflux.config.model_config import ModelConfig, ModelLookup
|
||||||
from mflux.controlnet.flux_controlnet import Flux1Controlnet
|
from mflux.controlnet.flux_controlnet import Flux1Controlnet
|
||||||
from mflux.error.exceptions import StopImageGenerationException
|
from mflux.error.exceptions import StopImageGenerationException
|
||||||
from mflux.flux.flux import Flux1
|
from mflux.flux.flux import Flux1
|
||||||
@ -11,6 +11,7 @@ __all__ = [
|
|||||||
"Config",
|
"Config",
|
||||||
"ConfigControlnet",
|
"ConfigControlnet",
|
||||||
"ModelConfig",
|
"ModelConfig",
|
||||||
|
"ModelLookup",
|
||||||
"ImageUtil",
|
"ImageUtil",
|
||||||
"StopImageGenerationException",
|
"StopImageGenerationException",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,27 +1,98 @@
|
|||||||
from enum import Enum
|
from dataclasses import dataclass
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
DEFAULT_TRAIN_STEPS = 1000
|
||||||
|
|
||||||
|
KNOWN_SEQUENCE_LENGTH_BY_BASE_MODEL = {"dev": 512, "schnell": 256}
|
||||||
|
|
||||||
|
|
||||||
class ModelConfig(Enum):
|
class ModelConfigError(ValueError):
|
||||||
FLUX1_DEV = ("black-forest-labs/FLUX.1-dev", "dev", 1000, 512)
|
"""User error in model config."""
|
||||||
FLUX1_SCHNELL = ("black-forest-labs/FLUX.1-schnell", "schnell", 1000, 256)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
model_name: str,
|
|
||||||
alias: str,
|
|
||||||
num_train_steps: int,
|
|
||||||
max_sequence_length: int,
|
|
||||||
):
|
|
||||||
self.alias = alias
|
|
||||||
self.model_name = model_name
|
|
||||||
self.num_train_steps = num_train_steps
|
|
||||||
self.max_sequence_length = max_sequence_length
|
|
||||||
|
|
||||||
|
class InvalidBaseModel(ModelConfigError):
|
||||||
|
"""Invalid base model, cannot infer model properties."""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ModelConfig:
|
||||||
|
model_name: str
|
||||||
|
num_train_steps: int
|
||||||
|
max_sequence_length: int
|
||||||
|
supports_guidance: bool
|
||||||
|
base_model: str | None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alias(self):
|
||||||
|
# maintain compatibility with < 0.4.0 behavior
|
||||||
|
# where alias is the name of an official model
|
||||||
|
if self.model_name.startswith("black-forest-labs/FLUX.1-"):
|
||||||
|
return self.model_name[len("black-forest-labs/FLUX.1-") :].lower()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
DefaultModelConfigs = {
|
||||||
|
"dev": ModelConfig(
|
||||||
|
model_name="black-forest-labs/FLUX.1-dev",
|
||||||
|
num_train_steps=DEFAULT_TRAIN_STEPS,
|
||||||
|
max_sequence_length=KNOWN_SEQUENCE_LENGTH_BY_BASE_MODEL["dev"],
|
||||||
|
supports_guidance=True,
|
||||||
|
base_model=None,
|
||||||
|
),
|
||||||
|
"schnell": ModelConfig(
|
||||||
|
model_name="black-forest-labs/FLUX.1-schnell",
|
||||||
|
num_train_steps=DEFAULT_TRAIN_STEPS,
|
||||||
|
max_sequence_length=KNOWN_SEQUENCE_LENGTH_BY_BASE_MODEL["schnell"],
|
||||||
|
supports_guidance=False,
|
||||||
|
base_model=None,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ModelLookup:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_alias(alias: str) -> "ModelConfig":
|
def from_name(
|
||||||
try:
|
alias: str,
|
||||||
for model in ModelConfig:
|
base_model: Literal["dev", "schnell"] | None = None,
|
||||||
if model.alias == alias:
|
) -> ModelConfig:
|
||||||
return model
|
if alias in DefaultModelConfigs:
|
||||||
except KeyError:
|
return DefaultModelConfigs[alias]
|
||||||
raise ValueError(f"'{alias}' is not a valid model")
|
|
||||||
|
if all(["dev" not in alias, "schnell" not in alias, base_model is None]):
|
||||||
|
raise ModelConfigError(
|
||||||
|
"Cannot infer base model and max_sequence_length "
|
||||||
|
f"from model reference: {alias!r}. "
|
||||||
|
"Please specify --base-model [dev | schnell]"
|
||||||
|
)
|
||||||
|
|
||||||
|
if base_model is not None and base_model not in ["dev", "schnell"]:
|
||||||
|
raise InvalidBaseModel("As of this version, mflux only recognizes base models dev or schnell")
|
||||||
|
|
||||||
|
if base_model is None:
|
||||||
|
# infer base model on apparent model namming
|
||||||
|
if "dev" in alias:
|
||||||
|
base_model = "dev"
|
||||||
|
elif "schnell" in alias:
|
||||||
|
base_model = "schnell"
|
||||||
|
|
||||||
|
if base_model == "dev":
|
||||||
|
supports_guidance = True
|
||||||
|
max_sequence_length = KNOWN_SEQUENCE_LENGTH_BY_BASE_MODEL["dev"]
|
||||||
|
elif base_model == "schnell":
|
||||||
|
supports_guidance = False
|
||||||
|
max_sequence_length = KNOWN_SEQUENCE_LENGTH_BY_BASE_MODEL["schnell"]
|
||||||
|
|
||||||
|
return ModelConfig(
|
||||||
|
alias, # actually this arg is model_name
|
||||||
|
DEFAULT_TRAIN_STEPS,
|
||||||
|
max_sequence_length,
|
||||||
|
supports_guidance,
|
||||||
|
base_model,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# maintain old `ModelConfig.from_alias` function name for backwards compatibility in user code and docs
|
||||||
|
ModelConfig.from_alias = ModelLookup.from_name
|
||||||
|
# keep these class members to be backwards compatible with < 0.5.0 ModelConfig Enum implementation
|
||||||
|
ModelConfig.FLUX1_DEV = DefaultModelConfigs["dev"]
|
||||||
|
ModelConfig.FLUX1_SCHNELL = DefaultModelConfigs["schnell"]
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from mlx import nn
|
|||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
from mflux.config.config import Config
|
from mflux.config.config import Config
|
||||||
from mflux.config.model_config import ModelConfig
|
from mflux.config.model_config import ModelConfig, ModelLookup
|
||||||
from mflux.config.runtime_config import RuntimeConfig
|
from mflux.config.runtime_config import RuntimeConfig
|
||||||
from mflux.error.exceptions import StopImageGenerationException
|
from mflux.error.exceptions import StopImageGenerationException
|
||||||
from mflux.latent_creator.latent_creator import LatentCreator
|
from mflux.latent_creator.latent_creator import LatentCreator
|
||||||
@ -136,12 +136,15 @@ class Flux1(nn.Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_alias(alias: str, quantize: int | None = None) -> "Flux1":
|
def from_name(model_name: str, quantize: int | None = None) -> "Flux1":
|
||||||
return Flux1(
|
return Flux1(
|
||||||
model_config=ModelConfig.from_alias(alias),
|
model_config=ModelLookup.from_name(model_name),
|
||||||
quantize=quantize,
|
quantize=quantize,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# maintain old `from_alias` function name for backwards compatibility in user code and docs
|
||||||
|
from_alias = from_name
|
||||||
|
|
||||||
def save_model(self, base_path: str) -> None:
|
def save_model(self, base_path: str) -> None:
|
||||||
ModelSaver.save_model(self, self.bits, base_path)
|
ModelSaver.save_model(self, self.bits, base_path)
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from mflux import Config, Flux1, ModelConfig, StopImageGenerationException
|
from mflux import Config, Flux1, ModelLookup, StopImageGenerationException
|
||||||
from mflux.ui.cli.parsers import CommandLineParser
|
from mflux.ui.cli.parsers import CommandLineParser
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ def main():
|
|||||||
|
|
||||||
# Load the model
|
# Load the model
|
||||||
flux = Flux1(
|
flux = Flux1(
|
||||||
model_config=ModelConfig.from_alias(args.model),
|
model_config=ModelLookup.from_name(args.model, base_model=args.base_model),
|
||||||
quantize=args.quantize,
|
quantize=args.quantize,
|
||||||
local_path=args.path,
|
local_path=args.path,
|
||||||
lora_paths=args.lora_paths,
|
lora_paths=args.lora_paths,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from mflux import ConfigControlnet, Flux1Controlnet, ModelConfig, StopImageGenerationException
|
from mflux import ConfigControlnet, Flux1Controlnet, ModelLookup, StopImageGenerationException
|
||||||
from mflux.ui.cli.parsers import CommandLineParser
|
from mflux.ui.cli.parsers import CommandLineParser
|
||||||
|
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ def main():
|
|||||||
|
|
||||||
# Load the model
|
# Load the model
|
||||||
flux = Flux1Controlnet(
|
flux = Flux1Controlnet(
|
||||||
model_config=ModelConfig.from_alias(args.model),
|
model_config=ModelLookup.from_name(args.model, base_model=args.base_model),
|
||||||
quantize=args.quantize,
|
quantize=args.quantize,
|
||||||
local_path=args.path,
|
local_path=args.path,
|
||||||
lora_paths=args.lora_paths,
|
lora_paths=args.lora_paths,
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class TimeTextEmbed(nn.Module):
|
|||||||
def __init__(self, model_config: ModelConfig):
|
def __init__(self, model_config: ModelConfig):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.text_embedder = TextEmbedder()
|
self.text_embedder = TextEmbedder()
|
||||||
self.guidance_embedder = GuidanceEmbedder() if model_config == ModelConfig.FLUX1_DEV else None
|
self.guidance_embedder = GuidanceEmbedder() if model_config.supports_guidance else None
|
||||||
self.timestep_embedder = TimestepEmbedder()
|
self.timestep_embedder = TimestepEmbedder()
|
||||||
|
|
||||||
def __call__(
|
def __call__(
|
||||||
|
|||||||
@ -57,10 +57,13 @@ class GeneratedImage:
|
|||||||
# mflux_version is used by future metadata readers
|
# mflux_version is used by future metadata readers
|
||||||
# to determine supportability of metadata-derived workflows
|
# to determine supportability of metadata-derived workflows
|
||||||
"mflux_version": GeneratedImage.get_version(),
|
"mflux_version": GeneratedImage.get_version(),
|
||||||
"model": str(self.model_config.alias),
|
"model": str(self.model_config.alias)
|
||||||
|
if self.model_config.alias is not None
|
||||||
|
else self.model_config.model_name,
|
||||||
|
"base_model": str(self.model_config.base_model),
|
||||||
"seed": self.seed,
|
"seed": self.seed,
|
||||||
"steps": self.steps,
|
"steps": self.steps,
|
||||||
"guidance": self.guidance if ModelConfig.FLUX1_DEV else None, # only the dev model supports guidance
|
"guidance": self.guidance if self.model_config.supports_guidance else None,
|
||||||
"precision": str(self.precision),
|
"precision": str(self.precision),
|
||||||
"quantize": self.quantization,
|
"quantize": self.quantization,
|
||||||
"generation_time_seconds": round(self.generation_time, 2),
|
"generation_time_seconds": round(self.generation_time, 2),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from mflux import Flux1, ModelConfig
|
from mflux import Flux1, ModelLookup
|
||||||
from mflux.ui.cli.parsers import CommandLineParser
|
from mflux.ui.cli.parsers import CommandLineParser
|
||||||
|
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ def main():
|
|||||||
print(f"Saving model {args.model} with quantization level {args.quantize}\n")
|
print(f"Saving model {args.model} with quantization level {args.quantize}\n")
|
||||||
|
|
||||||
flux = Flux1(
|
flux = Flux1(
|
||||||
model_config=ModelConfig.from_alias(args.model),
|
model_config=ModelLookup.from_name(args.model, base_model=args.base_model),
|
||||||
quantize=args.quantize,
|
quantize=args.quantize,
|
||||||
lora_paths=args.lora_paths,
|
lora_paths=args.lora_paths,
|
||||||
lora_scales=args.lora_scales,
|
lora_scales=args.lora_scales,
|
||||||
|
|||||||
@ -6,6 +6,21 @@ from pathlib import Path
|
|||||||
from mflux.ui import defaults as ui_defaults
|
from mflux.ui import defaults as ui_defaults
|
||||||
|
|
||||||
|
|
||||||
|
class ModelSpecAction(argparse.Action):
|
||||||
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
|
if values in ["dev", "schnell"]:
|
||||||
|
setattr(namespace, self.dest, values)
|
||||||
|
return
|
||||||
|
|
||||||
|
if values.count("/") != 1:
|
||||||
|
raise argparse.ArgumentError(
|
||||||
|
self, ('Value must be either "dev", "schnell", or "' f'in format "org/model". Got: {values}')
|
||||||
|
)
|
||||||
|
|
||||||
|
# If we got here, values contains exactly one slash
|
||||||
|
setattr(namespace, self.dest, values)
|
||||||
|
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
class CommandLineParser(argparse.ArgumentParser):
|
class CommandLineParser(argparse.ArgumentParser):
|
||||||
|
|
||||||
@ -19,12 +34,12 @@ class CommandLineParser(argparse.ArgumentParser):
|
|||||||
|
|
||||||
def add_model_arguments(self, path_type: t.Literal["load", "save"] = "load", require_model_arg: bool = True) -> None:
|
def add_model_arguments(self, path_type: t.Literal["load", "save"] = "load", require_model_arg: bool = True) -> None:
|
||||||
|
|
||||||
self.add_argument("--model", "-m", type=str, required=require_model_arg, choices=ui_defaults.MODEL_CHOICES, help=f"The model to use ({' or '.join(ui_defaults.MODEL_CHOICES)}).")
|
self.add_argument("--model", "-m", type=str, required=require_model_arg, action=ModelSpecAction, help=f"The model to use ({' or '.join(ui_defaults.MODEL_CHOICES)} or a compatible huggingface repo_id org/model).")
|
||||||
|
|
||||||
if path_type == "load":
|
if path_type == "load":
|
||||||
self.add_argument("--path", type=str, default=None, help="Local path for loading a model from disk")
|
self.add_argument("--path", type=str, default=None, help="Local path for loading a model from disk")
|
||||||
else:
|
else:
|
||||||
self.add_argument("--path", type=str, required=True, help="Local path for saving a model to disk.")
|
self.add_argument("--path", type=str, required=True, help="Local path for saving a model to disk.")
|
||||||
|
self.add_argument("--base-model", type=str, required=False, choices=ui_defaults.MODEL_CHOICES, help="When using a third-party huggingface model, explicitly specify whether the base model is dev or schnell")
|
||||||
self.add_argument("--quantize", "-q", type=int, choices=ui_defaults.QUANTIZE_CHOICES, default=None, help=f"Quantize the model ({' or '.join(map(str, ui_defaults.QUANTIZE_CHOICES))}, Default is None)")
|
self.add_argument("--quantize", "-q", type=int, choices=ui_defaults.QUANTIZE_CHOICES, default=None, help=f"Quantize the model ({' or '.join(map(str, ui_defaults.QUANTIZE_CHOICES))}, Default is None)")
|
||||||
|
|
||||||
def add_lora_arguments(self) -> None:
|
def add_lora_arguments(self) -> None:
|
||||||
@ -93,6 +108,9 @@ class CommandLineParser(argparse.ArgumentParser):
|
|||||||
# when not provided by CLI flag, find it in the config file
|
# when not provided by CLI flag, find it in the config file
|
||||||
namespace.model = prior_gen_metadata.get("model", None)
|
namespace.model = prior_gen_metadata.get("model", None)
|
||||||
|
|
||||||
|
if namespace.base_model is None:
|
||||||
|
namespace.base_model = prior_gen_metadata.get("base_model", None)
|
||||||
|
|
||||||
if namespace.prompt is None:
|
if namespace.prompt is None:
|
||||||
namespace.prompt = prior_gen_metadata.get("prompt", None)
|
namespace.prompt = prior_gen_metadata.get("prompt", None)
|
||||||
|
|
||||||
|
|||||||
@ -93,10 +93,12 @@ def test_model_arg_not_in_file(mflux_generate_parser, mflux_generate_minimal_arg
|
|||||||
with patch('sys.argv', mflux_generate_minimal_argv + ['--model', 'dev', '--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
with patch('sys.argv', mflux_generate_minimal_argv + ['--model', 'dev', '--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
||||||
args = mflux_generate_parser.parse_args()
|
args = mflux_generate_parser.parse_args()
|
||||||
assert args.model == "dev"
|
assert args.model == "dev"
|
||||||
|
assert args.base_model is None
|
||||||
# test value read from flag
|
# test value read from flag
|
||||||
with patch('sys.argv', mflux_generate_minimal_argv + ['--model', 'schnell', '--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
with patch('sys.argv', mflux_generate_minimal_argv + ['--model', 'schnell', '--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
||||||
args = mflux_generate_parser.parse_args()
|
args = mflux_generate_parser.parse_args()
|
||||||
assert args.model == "schnell"
|
assert args.model == "schnell"
|
||||||
|
assert args.base_model is None
|
||||||
|
|
||||||
|
|
||||||
def test_model_arg_in_file(mflux_generate_parser, mflux_generate_minimal_argv, base_metadata_dict, temp_dir):
|
def test_model_arg_in_file(mflux_generate_parser, mflux_generate_minimal_argv, base_metadata_dict, temp_dir):
|
||||||
@ -114,6 +116,25 @@ def test_model_arg_in_file(mflux_generate_parser, mflux_generate_minimal_argv, b
|
|||||||
assert args.model == "schnell"
|
assert args.model == "schnell"
|
||||||
|
|
||||||
|
|
||||||
|
def test_base_model_arg_in_file(mflux_generate_parser, mflux_generate_minimal_argv, base_metadata_dict, temp_dir):
|
||||||
|
metadata_file = temp_dir / "model.json"
|
||||||
|
with metadata_file.open("wt") as m:
|
||||||
|
base_metadata_dict["model"] = "some-lab/some-model"
|
||||||
|
base_metadata_dict["base_model"] = "dev"
|
||||||
|
json.dump(base_metadata_dict, m, indent=4)
|
||||||
|
# test value read from file
|
||||||
|
with patch('sys.argv', mflux_generate_minimal_argv + ['--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
||||||
|
args = mflux_generate_parser.parse_args()
|
||||||
|
assert args.model == "some-lab/some-model"
|
||||||
|
assert args.base_model == "dev"
|
||||||
|
# test value read from flag, overrides value from file
|
||||||
|
with patch('sys.argv', mflux_generate_minimal_argv + ['--base-model', 'schnell', '--config-from-metadata', metadata_file.as_posix()]): # fmt: off
|
||||||
|
args = mflux_generate_parser.parse_args()
|
||||||
|
assert args.model == "some-lab/some-model"
|
||||||
|
# override metadata base model with CLI --base-model
|
||||||
|
assert args.base_model == "schnell"
|
||||||
|
|
||||||
|
|
||||||
def test_prompt_arg(mflux_generate_parser, mflux_generate_minimal_argv, base_metadata_dict, temp_dir):
|
def test_prompt_arg(mflux_generate_parser, mflux_generate_minimal_argv, base_metadata_dict, temp_dir):
|
||||||
metadata_file = temp_dir / "prompt.json"
|
metadata_file = temp_dir / "prompt.json"
|
||||||
file_prompt = "origin of the universe"
|
file_prompt = "origin of the universe"
|
||||||
|
|||||||
68
tests/test_model_config.py
Normal file
68
tests/test_model_config.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from mflux.config.model_config import InvalidBaseModel, ModelConfig, ModelConfigError, ModelLookup
|
||||||
|
|
||||||
|
|
||||||
|
def test_from_alias_function_redirect():
|
||||||
|
# backwards compatibility for when user follows older docs
|
||||||
|
# but is using a newer mflux version >= 0.5
|
||||||
|
assert ModelConfig.from_alias == ModelLookup.from_name
|
||||||
|
|
||||||
|
|
||||||
|
def test_model_config_class_members_and_alias():
|
||||||
|
# these FLUX1_* class members and the alias attribute
|
||||||
|
# existed as members of ModelConfig when it was an Enum
|
||||||
|
# keep them around for backwards compatibility
|
||||||
|
assert ModelConfig.FLUX1_DEV.alias == "dev"
|
||||||
|
assert ModelConfig.FLUX1_SCHNELL.alias == "schnell"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bfl_dev():
|
||||||
|
model_attrs = ModelLookup.from_name("dev")
|
||||||
|
assert model_attrs.model_name.startswith("black-forest-labs/")
|
||||||
|
assert model_attrs.max_sequence_length == 512
|
||||||
|
assert model_attrs.supports_guidance is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_bfl_schnell():
|
||||||
|
model_attrs = ModelLookup.from_name("schnell")
|
||||||
|
assert model_attrs.model_name.startswith("black-forest-labs/")
|
||||||
|
assert model_attrs.max_sequence_length == 256
|
||||||
|
assert model_attrs.supports_guidance is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_community_dev_implicit_base_model():
|
||||||
|
model_attrs = ModelLookup.from_name("acme-lab/some-awesome-dev-model")
|
||||||
|
assert model_attrs.max_sequence_length == 512
|
||||||
|
assert model_attrs.supports_guidance is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_community_schnell_implicit_base_model():
|
||||||
|
model_attrs = ModelLookup.from_name("acme-lab/some-quick-schnell-model")
|
||||||
|
assert model_attrs.max_sequence_length == 256
|
||||||
|
assert model_attrs.supports_guidance is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_community_dev_explicit_base_model():
|
||||||
|
model_attrs = ModelLookup.from_name("acme-lab/some-awesome-model", base_model="dev")
|
||||||
|
assert model_attrs.max_sequence_length == 512
|
||||||
|
assert model_attrs.supports_guidance is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_community_schnell_explicit_base_model():
|
||||||
|
model_attrs = ModelLookup.from_name("acme-lab/some-awesome-model", base_model="schnell")
|
||||||
|
assert model_attrs.max_sequence_length == 256
|
||||||
|
assert model_attrs.supports_guidance is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_model_config_error():
|
||||||
|
assert pytest.raises(ModelConfigError, ModelLookup.from_name, "acme-lab/some-model-who-knows-what-its-based-on")
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_base_model_error():
|
||||||
|
assert pytest.raises(
|
||||||
|
InvalidBaseModel,
|
||||||
|
ModelLookup.from_name,
|
||||||
|
"acme-lab/some-model-who-knows-what-its-based-on",
|
||||||
|
base_model="something_unknown",
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue
Block a user