mirror of
https://github.com/vladmandic/automatic
synced 2026-09-18 16:54:33 +02:00
feat(model): register minimax h3 as a text2image base model
Reference entries for the bf16 repo and the sdnq uint4 quant load the modular pipeline through the standard dispatch. Image tabs run the model in still mode with audio off; the video tab keeps its own overrides through the shared per-generation hook. Detailer is not supported and is disabled with a warning.
This commit is contained in:
@@ -374,6 +374,14 @@
|
||||
"size": 75.64,
|
||||
"date": "2025 September"
|
||||
},
|
||||
"MiniMaxAI MiniMax-H3": {
|
||||
"path": "MiniMaxAI/MiniMax-H3",
|
||||
"preview": "MiniMaxAI--MiniMax-H3.jpg",
|
||||
"desc": "MiniMax-H3 generates video with synchronized stereo audio in a single denoising pass through a 33B single-stream transformer with a Qwen3-VL conditioner. In image tabs the model runs in experimental still mode, keeping the first frame of a minimal generation.",
|
||||
"extras": "sampler: None",
|
||||
"size": 134,
|
||||
"date": "2026 August"
|
||||
},
|
||||
"Freepik F-Lite": {
|
||||
"path": "Freepik/F-Lite",
|
||||
"preview": "Freepik--F-Lite.jpg",
|
||||
|
||||
@@ -79,6 +79,14 @@
|
||||
"date": "2025 October",
|
||||
"size": 23.53
|
||||
},
|
||||
"MiniMaxAI MiniMax-H3 sdnq-uint4": {
|
||||
"path": "OzzyGT/MiniMax_H3_sdnq_dynamic_4bit",
|
||||
"preview": "MiniMaxAI--MiniMax-H3.jpg",
|
||||
"desc": "Quantization of MiniMaxAI/MiniMax-H3 using SDNQ: dynamic 4-bit uint. Video with synchronized audio; in image tabs the model runs in experimental still mode.",
|
||||
"extras": "sampler: None",
|
||||
"size": 51,
|
||||
"date": "2026 August"
|
||||
},
|
||||
"Z-Image-Turbo sdnq-svd-uint4": {
|
||||
"path": "Disty0/Z-Image-Turbo-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Z-Image-Turbo-SDNQ-uint4-svd-r32.jpg",
|
||||
|
||||
@@ -156,6 +156,8 @@ def get_model_type(pipe):
|
||||
model_type = 'mochivideo'
|
||||
elif "Allegro" in name:
|
||||
model_type = 'allegrovideo'
|
||||
elif 'MiniMaxH3' in name:
|
||||
model_type = 'minimaxh3'
|
||||
# cloud models
|
||||
elif 'GoogleVeo' in name:
|
||||
model_type = 'veo3'
|
||||
|
||||
@@ -540,6 +540,13 @@ def update_pipeline(sd_model, p: processing.StableDiffusionProcessing):
|
||||
log.warning('Processing: op=update model not loaded')
|
||||
return None
|
||||
updated_model = sd_model
|
||||
if 'MiniMaxH3' in sd_model.__class__.__name__ and not isinstance(p, processing.StableDiffusionProcessingVideo):
|
||||
# image tabs run the model in still mode; the video tab applies its own overrides
|
||||
from modules.video_models import video_modular
|
||||
video_modular.apply_minimax_overrides(p, sd_model, still=True, audio=False)
|
||||
if getattr(p, 'detailer_enabled', False):
|
||||
log.warning(f'Processing: cls={sd_model.__class__.__name__} detailer not supported')
|
||||
p.detailer_enabled = False
|
||||
if sd_models.get_diffusers_task(sd_model) == sd_models.DiffusersTaskType.INPAINTING and getattr(p, 'image_mask', None) is None and p.task_args.get('image_mask', None) is None and getattr(p, 'mask', None) is None:
|
||||
log.warning('Processing: mode=inpaint mask=None')
|
||||
updated_model = sd_models.set_diffuser_pipe(sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE)
|
||||
@@ -569,7 +576,7 @@ def validate_pipeline(p: processing.StableDiffusionProcessing):
|
||||
if m.custom is not None:
|
||||
models_cls.append(m.custom)
|
||||
is_video_model = shared.sd_model.__class__.__name__ in models_cls
|
||||
override_video_pipelines = ['WanPipeline', 'WanImageToVideoPipeline', 'WanVACEPipeline']
|
||||
override_video_pipelines = ['WanPipeline', 'WanImageToVideoPipeline', 'WanVACEPipeline', 'MiniMaxH3ModularPipeline']
|
||||
is_video_pipeline = ('video' in p.__class__.__name__.lower()) or (shared.sd_model.__class__.__name__ in override_video_pipelines)
|
||||
if is_video_model and not is_video_pipeline:
|
||||
log.error(f'Mismatch: type={shared.sd_model_type} cls={shared.sd_model.__class__.__name__} request={p.__class__.__name__} video model with non-video pipeline')
|
||||
|
||||
@@ -115,6 +115,8 @@ def guess_by_name(fn, current_guess):
|
||||
new_guess = 'Cosmos'
|
||||
elif 'f-lite' in fn.lower():
|
||||
new_guess = 'FLite'
|
||||
elif 'minimax' in fn.lower():
|
||||
new_guess = 'MiniMaxH3'
|
||||
elif 'wan' in fn.lower():
|
||||
new_guess = 'WanAI'
|
||||
if 'chronoedit' in fn.lower():
|
||||
|
||||
@@ -493,6 +493,10 @@ def load_diffuser_force(detected_model_type: str, checkpoint_info: CheckpointInf
|
||||
from pipelines.model_wanai import load_wan
|
||||
sd_model = load_wan(checkpoint_info, diffusers_load_config)
|
||||
allow_post_quant = False
|
||||
elif model_type in ['MiniMaxH3']:
|
||||
from pipelines.model_minimax import load_minimax
|
||||
sd_model = load_minimax(checkpoint_info, diffusers_load_config)
|
||||
allow_post_quant = False
|
||||
elif model_type in ['ChronoEdit']:
|
||||
from pipelines.model_chrono import load_chrono
|
||||
sd_model = load_chrono(checkpoint_info, diffusers_load_config)
|
||||
|
||||
@@ -55,6 +55,7 @@ pipelines = {
|
||||
'PixArtAlpha': getattr(diffusers, 'PixArtAlphaPipeline', None),
|
||||
'PixArtSigma': getattr(diffusers, 'PixArtSigmaPipeline', None),
|
||||
'PRXPixel': getattr(diffusers, 'PRXPixelPipeline', None),
|
||||
'MiniMaxH3': getattr(diffusers, 'MiniMaxH3ModularPipeline', None),
|
||||
'Qwen': getattr(diffusers, 'QwenImagePipeline', None),
|
||||
'Sana': getattr(diffusers, 'SanaPipeline', None),
|
||||
'WanAI': getattr(diffusers, 'WanPipeline', None),
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import diffusers
|
||||
from modules import shared, devices, sd_models
|
||||
from modules.logger import log
|
||||
|
||||
|
||||
def load_minimax(checkpoint_info, diffusers_load_config=None): # pylint: disable=unused-argument
|
||||
from modules.video_models import video_modular, video_load
|
||||
repo_id = sd_models.path_to_repo(checkpoint_info)
|
||||
sd_models.hf_auth_check(checkpoint_info)
|
||||
if repo_id is None or repo_id.lower() == 'none':
|
||||
return None
|
||||
offline_args = {'local_files_only': True} if shared.opts.offline_mode else {}
|
||||
log.debug(f'Load model: type=MiniMaxH3 repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}')
|
||||
|
||||
pipe = video_modular.load_modular_pipe(
|
||||
getattr(diffusers, 'MiniMaxH3ModularPipeline', None),
|
||||
repo_id,
|
||||
workflow='fl2va',
|
||||
offline_args=offline_args,
|
||||
)
|
||||
if pipe is None:
|
||||
return None
|
||||
|
||||
video_modular.install_state_hook(pipe)
|
||||
video_load.loaded_model = None # image-path load invalidates the video tab's name cache
|
||||
if hasattr(pipe, 'vae') and hasattr(pipe.vae, 'enable_tiling'):
|
||||
pipe.vae.enable_tiling()
|
||||
|
||||
devices.torch_gc()
|
||||
return pipe
|
||||
Reference in New Issue
Block a user