From 7e51186e607f5aed227783acb7272dde0d94d8e1 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Sun, 21 Jun 2026 11:19:08 +0200 Subject: [PATCH] better handle onnxruntime Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 7 ++++-- installer.py | 6 +++++ modules/dml/__init__.py | 2 +- modules/loader.py | 23 ++++++++++++------- modules/onnx_impl/__init__.py | 28 ++++++++++++++---------- modules/onnx_impl/execution_providers.py | 15 ++++++------- modules/shared.py | 4 ---- modules/shared_items.py | 2 ++ modules/ui_definitions.py | 27 +++++++++++++++++++---- wiki | 2 +- 10 files changed, 77 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a5c1bd0..64b7e20c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,14 @@ # Change Log for SD.Next -## Update for 2026-06-20 +## Update for 2026-06-21 - **Features** - **SDNQ** support for NPU during quantization and inference - add option: force dtype on load use to force model components to override loading with desired dtype regardless of component config - **UI** - - + - StandardUI: marked as legacy + - ModernUI: old txt2img and img2img tabs are marked as legacy and hidden by default - **Internal** - delay init of video models - **Fixes** @@ -19,6 +20,8 @@ - `mps` install `torchsde` as requirement - `vae` scale factor improved detection - `ui` networks details scrollbars + - `onnxruntime` handle invalid version + - `onnxruntime` mark all import paths as non-critical ## Update for 2026-06-16 diff --git a/installer.py b/installer.py index c726855b0..7108df17e 100644 --- a/installer.py +++ b/installer.py @@ -607,6 +607,12 @@ def check_onnx(): install('onnx', 'onnx', ignore=True) if not installed('onnxruntime', quiet=True) and not (installed('onnxruntime-gpu', quiet=True) or installed('onnxruntime-openvino', quiet=True) or installed('onnxruntime-training', quiet=True)): # allow either install(os.environ.get('ONNXRUNTIME_COMMAND', 'onnxruntime'), ignore=True) + else: + onnx_version = package_version('onnxruntime') or '' + if onnx_version.startswith('1.1'): + log.warning(f'ONNX: onnxruntime={onnx_version} upgrade required') + uninstall('onnxruntime', quiet=True) + install(os.environ.get('ONNXRUNTIME_COMMAND', 'onnxruntime'), ignore=True) ts('onnx', t_start) diff --git a/modules/dml/__init__.py b/modules/dml/__init__.py index 24d80a424..892a02d42 100644 --- a/modules/dml/__init__.py +++ b/modules/dml/__init__.py @@ -1,5 +1,5 @@ import platform -from typing import NamedTuple, Optional +from typing import NamedTuple from collections.abc import Callable import torch from modules.logger import log diff --git a/modules/loader.py b/modules/loader.py index 3f018e964..a84b5ddf9 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -175,12 +175,15 @@ except Exception as e: timer.startup.record("transformers") try: - import onnxruntime # pylint: disable=W0611,C0411 - onnxruntime.set_default_logger_severity(4) - onnxruntime.set_default_logger_verbosity(1) - onnxruntime.disable_telemetry_events() + import onnxruntime as ort# pylint: disable=W0611,C0411 + ort.set_default_logger_severity(4) + ort.set_default_logger_verbosity(1) + ort.disable_telemetry_events() + _onnx = True except Exception as e: - log.warning(f'Torch onnxruntime: {e}') + log.warning(f'Init onnxruntime: {e}') + ort = None + _onnx = False timer.startup.record("onnx") timer.startup.record("fastapi") @@ -200,7 +203,7 @@ try: diffusers.utils.import_utils._k_diffusion_available = True # pylint: disable=protected-access # monkey-patch since we use k-diffusion from git diffusers.utils.import_utils._k_diffusion_version = '0.0.12' # pylint: disable=protected-access diffusers.utils.import_utils._bitsandbytes_available = _bnb # pylint: disable=protected-access - + diffusers.utils.import_utils._onnx_available = _onnx # pylint: disable=protected-access import diffusers # pylint: disable=W0611,C0411 import diffusers.loaders.single_file # pylint: disable=W0611,C0411 diffusers.loaders.single_file.logging.tqdm = partial(tqdm, unit='C') @@ -244,11 +247,15 @@ except Exception: def get_packages(): return { "torch": getattr(torch, "__long_version__", torch.__version__), + "torchvision": torchvision.__version__, "diffusers": diffusers.__version__, - "gradio": gradio.__version__, "transformers": transformers.__version__, "accelerate": accelerate.__version__, "hub": huggingface_hub.__version__, + "gradio": gradio.__version__, + "pydantic": pydantic.__version__, + "numpy": np.__version__, + "onnxruntime": ort.__version__ if ort is not None else None, } try: @@ -282,4 +289,4 @@ class VersionString(str): # support both string and tuple for version check torch.__version__ = VersionString(torch.__version__) log.info(f'Torch: torch=={torch.__version__} torchvision=={torchvision.__version__}') -log.info(f'Packages: diffusers=={diffusers.__version__} transformers=={transformers.__version__} accelerate=={accelerate.__version__} gradio=={gradio.__version__} pydantic=={pydantic.__version__} numpy=={np.__version__} cv2=={cv2.__version__}') +log.info(f'Packages: diffusers=={diffusers.__version__} transformers=={transformers.__version__} accelerate=={accelerate.__version__} gradio=={gradio.__version__} pydantic=={pydantic.__version__} numpy=={np.__version__} cv2=={cv2.__version__} onnxruntime=={ort.__version__ if ort is not None else None}') diff --git a/modules/onnx_impl/__init__.py b/modules/onnx_impl/__init__.py index 6c9b27e98..8b1cb3fdc 100644 --- a/modules/onnx_impl/__init__.py +++ b/modules/onnx_impl/__init__.py @@ -1,22 +1,28 @@ -from modules.logger import log -from typing import Any, Dict, Optional +from typing import Any import numpy as np import torch import diffusers from installer import installed, install +from modules.logger import log +from modules.loader import _onnx initialized = False -try: - import onnxruntime as ort -except Exception as e: - log.error(f'ONNX import error: {e}') +if _onnx: + try: + import onnxruntime as ort + except Exception as e: + log.error(f'ONNX import error: {e}') + ort = None + initialized = True +else: ort = None + initialized = True -class DynamicSessionOptions(ort.SessionOptions): +class DynamicSessionOptions(ort.SessionOptions if ort is not None else object): config: dict | None = None def __init__(self): @@ -24,7 +30,7 @@ class DynamicSessionOptions(ort.SessionOptions): self.enable_mem_pattern = False @classmethod - def from_sess_options(cls, sess_options: ort.SessionOptions): + def from_sess_options(cls, sess_options): if isinstance(sess_options, DynamicSessionOptions): return sess_options.copy() return DynamicSessionOptions() @@ -71,9 +77,9 @@ class TemporalModule(TorchCompatibleModule): """ provider: Any path: str - sess_options: ort.SessionOptions + sess_options: ort.SessionOptions if ort is not None else object - def __init__(self, provider: Any, path: str, sess_options: ort.SessionOptions): + def __init__(self, provider: Any, path: str, sess_options): self.provider = provider self.path = path self.sess_options = sess_options @@ -89,7 +95,7 @@ class TemporalModule(TorchCompatibleModule): return self -class OnnxRuntimeModel(TorchCompatibleModule, diffusers.OnnxRuntimeModel): +class OnnxRuntimeModel(TorchCompatibleModule, diffusers.OnnxRuntimeModel if ort is not None else object): config = {} # dummy def to(self, *args, **kwargs): diff --git a/modules/onnx_impl/execution_providers.py b/modules/onnx_impl/execution_providers.py index 1b0a47be5..10d0bc53f 100644 --- a/modules/onnx_impl/execution_providers.py +++ b/modules/onnx_impl/execution_providers.py @@ -11,6 +11,7 @@ class ExecutionProvider(str, Enum): ROCm = "ROCMExecutionProvider" MIGraphX = "MIGraphXExecutionProvider" OpenVINO = "OpenVINOExecutionProvider" + Azure = "AzureExecutionProvider" EP_TO_NAME = { @@ -20,6 +21,7 @@ EP_TO_NAME = { ExecutionProvider.ROCm: "gpu-rocm", # test required ExecutionProvider.MIGraphX: "gpu-migraphx", # test required ExecutionProvider.OpenVINO: "gpu-openvino", # test required + ExecutionProvider.Azure: "gpu-azure", # test required } TORCH_DEVICE_TO_EP = { "cpu": ExecutionProvider.CPU if devices.backend != "openvino" else ExecutionProvider.OpenVINO, @@ -29,14 +31,11 @@ TORCH_DEVICE_TO_EP = { "meta": None, } - -try: - import onnxruntime as ort - available_execution_providers: list[ExecutionProvider] = ort.get_available_providers() -except Exception as e: - log.error(f'ONNX import error: {e}') +from modules.onnx_impl import ort +if ort is not None: + available_execution_providers: list[ExecutionProvider] = [ExecutionProvider(ep) for ep in ort.get_available_providers()] +else: available_execution_providers = [] - ort = None def get_default_execution_provider() -> ExecutionProvider: @@ -96,7 +95,7 @@ def get_provider() -> tuple: def install_execution_provider(ep: ExecutionProvider): import importlib # pylint: disable=deprecated-module - from installer import installed, install, uninstall + from installer import install, uninstall res = "
"
     res += uninstall(["onnxruntime", "onnxruntime-directml", "onnxruntime-gpu", "onnxruntime-training", "onnxruntime-openvino"], quiet=True)
     packages = ["onnxruntime"] # Failed to load olive: cannot import name '__version__' from 'onnxruntime'
diff --git a/modules/shared.py b/modules/shared.py
index 1a292c3dc..71b86b5d1 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -17,7 +17,6 @@ import modules.paths as paths
 from modules.json_helpers import readfile # pylint: disable=W0611
 from modules.shared_helpers import listdir, req # pylint: disable=W0611
 from modules import errors, devices, shared_state, cmd_args, theme, history, files_cache # pylint: disable=unused-import
-from modules.shared_defaults import get_default_modes
 from modules.memstats import memory_stats # pylint: disable=unused-import
 
 log.debug('Initializing: pipelines')
@@ -152,9 +151,6 @@ def list_samplers():
     return modules.sd_samplers.all_samplers
 
 
-log.debug('Initializing: default modes')
-startup_offload_mode, startup_offload_min_gpu, startup_offload_max_gpu, startup_cross_attention, startup_sdp_options, startup_sdp_choices, startup_sdp_override_options, startup_sdp_override_choices, startup_offload_always, startup_offload_never = get_default_modes(cmd_opts=cmd_opts, mem_stat=mem_stat)
-
 log.debug('Initializing: settings')
 from modules import ui_definitions
 from modules.ui_definitions import OptionInfo, options_section # pylint: disable=unused-import
diff --git a/modules/shared_items.py b/modules/shared_items.py
index 32e6a8e37..753bdaed3 100644
--- a/modules/shared_items.py
+++ b/modules/shared_items.py
@@ -136,6 +136,7 @@ def list_crossattention():
 
 def get_pipelines():
     from modules.logger import log
+    """
     if hasattr(diffusers, 'OnnxStableDiffusionPipeline') and 'ONNX Stable Diffusion' not in list(pipelines):
         try:
             from modules.onnx_impl import initialize_onnx
@@ -150,6 +151,7 @@ def get_pipelines():
             log.error(f'ONNX initialization error: {e}')
             onnx_pipelines = {}
         pipelines.update(onnx_pipelines)
+    """
     stats_builtin = 0
     stats_custom = 0
     for k, v in pipelines.copy().items():
diff --git a/modules/ui_definitions.py b/modules/ui_definitions.py
index 27f29970a..8c37468b3 100644
--- a/modules/ui_definitions.py
+++ b/modules/ui_definitions.py
@@ -5,8 +5,6 @@ import gradio as gr
 from modules import paths, shared_items, devices, theme
 from modules.options import OptionInfo, options_section
 from modules.ui_components import DropdownEditable
-from modules.dml import memory_providers, default_memory_provider
-from modules.onnx_impl import execution_providers
 from modules.memstats import memory_stats
 from modules.shared_defaults import get_default_modes
 from modules.shared_items import sdnq_quant_modes, sdnq_matmul_modes
@@ -17,6 +15,24 @@ import modules.caption.vqa
 options_templates = {}
 
 
+def list_onnx_providers():
+    try:
+        from modules.onnx_impl import execution_providers
+        execution_providers = execution_providers.available_execution_providers
+        default_provider = execution_providers.get_default_execution_provider().value
+        return default_provider, execution_providers
+    except Exception:
+        return "CPU", []
+
+
+def list_dml_providers():
+    try:
+        from modules.dml import memory_providers, default_memory_provider
+        return default_memory_provider, memory_providers
+    except Exception:
+        return "Performance Counter", []
+
+
 def list_checkpoint_titles():
     import modules.sd_models # pylint: disable=redefined-outer-name
     return modules.sd_models.checkpoint_titles()
@@ -66,6 +82,9 @@ def create_settings(cmd_opts):
     default_checkpoint = list_checkpoint_titles()[0] if len(list_checkpoint_titles()) > 0 else "model.safetensors"
     default_xetcache_dir = os.environ.get("HF_XET_CACHE ", None) or os.path.join(paths.models_path, 'xet')
 
+    default_onnx_execution_provider, default_onnx_execution_providers = list_onnx_providers()
+    default_dml_memory_provider, default_dml_memory_providers = list_dml_providers()
+
     hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config}
 
     # --- SD Model Loading ---
@@ -266,7 +285,7 @@ def create_settings(cmd_opts):
         "torch_malloc": OptionInfo("native", "Memory allocator", gr.Radio, {"choices": ['native', 'cudaMallocAsync'] }),
 
         "onnx_sep": OptionInfo("

ONNX

", "", gr.HTML), - "onnx_execution_provider": OptionInfo(execution_providers.get_default_execution_provider().value, 'ONNX Execution Provider', gr.Dropdown, lambda: {"choices": execution_providers.available_execution_providers }), + "onnx_execution_provider": OptionInfo(default_onnx_execution_provider, 'ONNX Execution Provider', gr.Dropdown, lambda: {"choices": default_onnx_execution_providers}), "onnx_cpu_fallback": OptionInfo(True, 'ONNX allow fallback to CPU'), "onnx_cache_converted": OptionInfo(True, 'ONNX cache converted models'), "onnx_unload_base": OptionInfo(False, 'ONNX unload base model when processing refiner'), @@ -288,7 +307,7 @@ def create_settings(cmd_opts): "openvino_disable_memory_cleanup": OptionInfo(True, "OpenVINO disable memory cleanup", gr.Checkbox, {"visible": cmd_opts.use_openvino}), "directml_sep": OptionInfo("

DirectML

", "", gr.HTML, {"visible": devices.backend == "directml"}), - "directml_memory_provider": OptionInfo(default_memory_provider, "DirectML memory stats provider", gr.Radio, {"choices": memory_providers, "visible": devices.backend == "directml"}), + "directml_memory_provider": OptionInfo(default_dml_memory_provider, "DirectML memory stats provider", gr.Radio, {"choices": default_dml_memory_providers, "visible": devices.backend == "directml"}), "directml_catch_nan": OptionInfo(False, "DirectML retry ops for NaN", gr.Checkbox, {"visible": devices.backend == "directml"}), })) diff --git a/wiki b/wiki index aecd3199f..49c4883b3 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit aecd3199fb173fd5564c177656d53ae32d1de6ca +Subproject commit 49c4883b3173633af2d5fe207b5f536fa262132f