From 567b9e7014c9e1ad0a4fa2706dd513c8292dee68 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Wed, 29 Oct 2025 11:10:47 -0400 Subject: [PATCH] add hunyuanimage3 loader Signed-off-by: Vladimir Mandic --- modules/modeldata.py | 2 ++ modules/sd_detect.py | 2 ++ modules/sd_models.py | 4 ++++ modules/sd_offload.py | 2 +- modules/shared_items.py | 1 + pipelines/model_hyimage.py | 25 +++++++++++++++++++++++++ 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/modules/modeldata.py b/modules/modeldata.py index c7224d06a..77f8f47d0 100644 --- a/modules/modeldata.py +++ b/modules/modeldata.py @@ -80,6 +80,8 @@ def get_model_type(pipe): model_type = 'wanai' elif 'HDM-xut' in name: model_type = 'hdm' + elif 'HunyuanImage3' in name: + model_type = 'hunyuanimage3' elif 'HunyuanImage' in name: model_type = 'hunyuanimage' else: diff --git a/modules/sd_detect.py b/modules/sd_detect.py index 52284c9fb..8dd37fa50 100644 --- a/modules/sd_detect.py +++ b/modules/sd_detect.py @@ -113,6 +113,8 @@ def guess_by_name(fn, current_guess): return 'Kandinsky 2.2' elif 'kandinsky-3' in fn.lower(): return 'Kandinsky 3.0' + elif 'hunyuanimage3' in fn.lower(): + return 'HunyuanImage3' elif 'hunyuanimage' in fn.lower(): return 'HunyuanImage' elif 'x-omni' in fn.lower(): diff --git a/modules/sd_models.py b/modules/sd_models.py index 22159fcfe..4ee2152ac 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -402,6 +402,10 @@ def load_diffuser_force(model_type, checkpoint_info, diffusers_load_config, op=' from pipelines.model_hyimage import load_hyimage sd_model = load_hyimage(checkpoint_info, diffusers_load_config) # pylint: disable=assignment-from-none allow_post_quant = False + elif model_type in ['HunyuanImage3']: + from pipelines.model_hyimage import load_hyimage3 + sd_model = load_hyimage3(checkpoint_info, diffusers_load_config) # pylint: disable=assignment-from-none + allow_post_quant = False elif model_type in ['X-Omni']: from pipelines.model_xomni import load_xomni sd_model = load_xomni(checkpoint_info, diffusers_load_config) # pylint: disable=assignment-from-none diff --git a/modules/sd_offload.py b/modules/sd_offload.py index 85d245c34..e41e65f42 100644 --- a/modules/sd_offload.py +++ b/modules/sd_offload.py @@ -14,7 +14,7 @@ from modules.timer import process as process_timer debug = os.environ.get('SD_MOVE_DEBUG', None) is not None verbose = os.environ.get('SD_MOVE_VERBOSE', None) is not None debug_move = log.trace if debug else lambda *args, **kwargs: None -offload_warn = ['sc', 'sd3', 'f1', 'h1', 'hunyuandit', 'auraflow', 'omnigen', 'omnigen2', 'cogview4', 'cosmos', 'chroma', 'x-omni', 'hunyuanimage'] +offload_warn = ['sc', 'sd3', 'f1', 'h1', 'hunyuandit', 'auraflow', 'omnigen', 'omnigen2', 'cogview4', 'cosmos', 'chroma', 'x-omni', 'hunyuanimage', 'hunyuanimage3'] offload_post = ['h1'] offload_hook_instance = None balanced_offload_exclude = ['CogView4Pipeline', 'MeissonicPipeline'] diff --git a/modules/shared_items.py b/modules/shared_items.py index 29490562a..a7d77d641 100644 --- a/modules/shared_items.py +++ b/modules/shared_items.py @@ -58,6 +58,7 @@ pipelines = { 'Bria': getattr(diffusers, 'DiffusionPipeline', None), 'hdm': getattr(diffusers, 'DiffusionPipeline', None), 'X-Omni': getattr(diffusers, 'DiffusionPipeline', None), + 'HunyuanImage3': getattr(diffusers, 'DiffusionPipeline', None), } diff --git a/pipelines/model_hyimage.py b/pipelines/model_hyimage.py index b91cff00c..86620d326 100644 --- a/pipelines/model_hyimage.py +++ b/pipelines/model_hyimage.py @@ -35,3 +35,28 @@ def load_hyimage(checkpoint_info, diffusers_load_config={}): # pylint: disable=u devices.torch_gc(force=True, reason='load') return pipe + + +def load_hyimage3(checkpoint_info, diffusers_load_config={}): # pylint: disable=unused-argument + repo_id = sd_models.path_to_repo(checkpoint_info) + sd_models.hf_auth_check(checkpoint_info) + shared.log.debug(f'Load model: type=HunyuanImage3 repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}') + + from sdnq import SDNQConfig # import sdnq to register it into transformers + pipe = transformers.AutoModelForCausalLM.from_pretrained( + repo_id, + attn_implementation="sdpa", + trust_remote_code=True, + torch_dtype=devices.dtype, + device_map="auto", + moe_impl="eager", + ) + pipe.load_tokenizer(repo_id) + pipe.__call__ = pipe.generate_image + pipe.task_args = { + 'stream': True, + 'diff_infer_steps': 20, + } + + devices.torch_gc(force=True, reason='load') + return pipe