feat(pipelines): wire native_spec for arches missing single_file_model entry

ChronoEdit, HunyuanImage, Kandinsky5, LongCat, Ovis, NucleusMoE, Bria,
BriaFibo. Each inherits from_single_file via FromOriginalModelMixin
but has no SINGLE_FILE_LOADABLE_CLASSES entry; calling it crashed with
"FromOriginalModelMixin is currently only compatible with [...]".

TransformerSpec(cls=...) for each. Bria specs in
pipelines/bria/__init__.py; the rest are module-level in
model_<arch>.py since they have no package directory.
This commit is contained in:
CalamitousFelicitousness
2026-05-25 05:47:56 +01:00
parent d01d637d94
commit e7d2e28d3d
8 changed files with 63 additions and 6 deletions
+29
View File
@@ -0,0 +1,29 @@
"""Bria pipeline package.
Exports :data:`BRIA_SPEC` and :data:`BRIA_FIBO_SPEC` for use by
:mod:`pipelines.model_bria` together with :mod:`pipelines.native_transformer`.
Bria ships two transformer variants:
- The original Bria family uses a custom :class:`BriaTransformer2DModel`
imported from :mod:`pipelines.bria.transformer_bria`. The custom class
has no entry in diffusers' ``SINGLE_FILE_LOADABLE_CLASSES`` table, so a
community single-file selection previously crashed in
``ModelMixin.from_pretrained``.
- Bria FIBO (and FIBO Edit) use the upstream
:class:`diffusers.BriaFiboTransformer2DModel`, which also lacks a
``SINGLE_FILE_LOADABLE_CLASSES`` entry. Same crash.
Both specs use the default 3-prefix detection
(``model.diffusion_model.``, ``diffusion_model.``, ``net.``), no
converter, and no siblings.
"""
import diffusers
from pipelines.bria.transformer_bria import BriaTransformer2DModel
from pipelines.native_transformer import TransformerSpec
BRIA_SPEC = TransformerSpec(cls=BriaTransformer2DModel)
BRIA_FIBO_SPEC = TransformerSpec(cls=diffusers.BriaFiboTransformer2DModel)
+4 -1
View File
@@ -20,11 +20,13 @@ def load_bria(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False)
log.debug(f'Load model: type=BriaFibo repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}')
from pipelines.bria import BRIA_FIBO_SPEC
transformer = generic.load_transformer(
repo_id,
cls_name=diffusers.BriaFiboTransformer2DModel,
load_config=diffusers_load_config,
allow_quant=False,
native_spec=BRIA_FIBO_SPEC,
)
text_encoder = generic.load_text_encoder(
repo_id,
@@ -66,7 +68,8 @@ def load_bria(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False)
log.debug(f'Load model: type=Bria repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}')
transformer = generic.load_transformer(repo_id, cls_name=BriaTransformer2DModel, load_config=diffusers_load_config)
from pipelines.bria import BRIA_SPEC
transformer = generic.load_transformer(repo_id, cls_name=BriaTransformer2DModel, load_config=diffusers_load_config, native_spec=BRIA_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config)
pipe = BriaPipeline.from_pretrained(
+5 -1
View File
@@ -3,6 +3,10 @@ import transformers
from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
CHRONOEDIT_SPEC = TransformerSpec(cls=diffusers.ChronoEditTransformer3DModel)
def postprocess(p, result): # pylint: disable=unused-argument
@@ -21,7 +25,7 @@ def load_chrono(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False)
log.debug(f'Load model: type=ChronoEdit repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}')
transformer = generic.load_transformer(repo_id, cls_name=diffusers.ChronoEditTransformer3DModel, load_config=diffusers_load_config, subfolder="transformer")
transformer = generic.load_transformer(repo_id, cls_name=diffusers.ChronoEditTransformer3DModel, load_config=diffusers_load_config, subfolder="transformer", native_spec=CHRONOEDIT_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.UMT5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder")
try:
+5 -1
View File
@@ -5,6 +5,10 @@ import diffusers
from modules import shared, sd_models, devices, model_quant, sd_hijack_te, sd_hijack_vae
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
HUNYUANIMAGE_SPEC = TransformerSpec(cls=diffusers.HunyuanImageTransformer2DModel)
def load_hyimage(checkpoint_info, diffusers_load_config=None): # pylint: disable=unused-argument
@@ -16,7 +20,7 @@ def load_hyimage(checkpoint_info, diffusers_load_config=None): # pylint: disable
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config)
log.debug(f'Load model: type=HunyuanImage21 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}')
transformer = generic.load_transformer(repo_id, cls_name=diffusers.HunyuanImageTransformer2DModel, load_config=diffusers_load_config, subfolder="transformer")
transformer = generic.load_transformer(repo_id, cls_name=diffusers.HunyuanImageTransformer2DModel, load_config=diffusers_load_config, subfolder="transformer", native_spec=HUNYUANIMAGE_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config, subfolder="text_encoder")
text_encoder_2 = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder_2", allow_shared=False)
+5 -1
View File
@@ -3,6 +3,10 @@ import diffusers
from modules import shared, sd_models, devices, model_quant, sd_hijack_te, sd_hijack_vae
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
KANDINSKY5_SPEC = TransformerSpec(cls=diffusers.Kandinsky5Transformer3DModel)
def load_kandinsky21(checkpoint_info, diffusers_load_config=None):
@@ -83,7 +87,7 @@ def load_kandinsky5(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config)
log.debug(f'Load model: type=Kandinsky50 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}')
transformer = generic.load_transformer(repo_id, cls_name=diffusers.Kandinsky5Transformer3DModel, load_config=diffusers_load_config)
transformer = generic.load_transformer(repo_id, cls_name=diffusers.Kandinsky5Transformer3DModel, load_config=diffusers_load_config, native_spec=KANDINSKY5_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config)
if 'I2I' in repo_id:
+5 -1
View File
@@ -3,6 +3,10 @@ import diffusers
from modules import shared, devices, sd_models, model_quant, sd_hijack_te
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
LONGCAT_SPEC = TransformerSpec(cls=diffusers.LongCatImageTransformer2DModel)
def load_longcat(checkpoint_info, diffusers_load_config=None):
@@ -14,7 +18,7 @@ def load_longcat(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False)
log.debug(f'Load model: type=LongCat repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}')
transformer = generic.load_transformer(repo_id, cls_name=diffusers.LongCatImageTransformer2DModel, load_config=diffusers_load_config)
transformer = generic.load_transformer(repo_id, cls_name=diffusers.LongCatImageTransformer2DModel, load_config=diffusers_load_config, native_spec=LONGCAT_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config)
text_processor = transformers.Qwen2VLProcessor.from_pretrained(repo_id, subfolder='tokenizer', cache_dir=shared.opts.hfcache_dir)
+5
View File
@@ -3,6 +3,10 @@ import transformers
from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
NUCLEUS_SPEC = TransformerSpec(cls=diffusers.NucleusMoEImageTransformer2DModel)
def load_nucleus(checkpoint_info, diffusers_load_config=None):
@@ -18,6 +22,7 @@ def load_nucleus(checkpoint_info, diffusers_load_config=None):
repo_id,
cls_name=diffusers.NucleusMoEImageTransformer2DModel,
load_config=diffusers_load_config,
native_spec=NUCLEUS_SPEC,
)
text_encoder = generic.load_text_encoder(
repo_id,
+5 -1
View File
@@ -3,6 +3,10 @@ import diffusers
from modules import shared, devices, sd_models, model_quant, sd_hijack_te
from modules.logger import log
from pipelines import generic
from pipelines.native_transformer import TransformerSpec
OVIS_SPEC = TransformerSpec(cls=diffusers.OvisImageTransformer2DModel)
def load_ovis(checkpoint_info, diffusers_load_config=None):
@@ -14,7 +18,7 @@ def load_ovis(checkpoint_info, diffusers_load_config=None):
load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False)
log.debug(f'Load model: type=OvisImage repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}')
transformer = generic.load_transformer(repo_id, cls_name=diffusers.OvisImageTransformer2DModel, load_config=diffusers_load_config)
transformer = generic.load_transformer(repo_id, cls_name=diffusers.OvisImageTransformer2DModel, load_config=diffusers_load_config, native_spec=OVIS_SPEC)
text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen3Model, load_config=diffusers_load_config)
pipe = diffusers.OvisImagePipeline.from_pretrained(