Source code for openstef_foundation_models.inference.providers

# SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
#
# SPDX-License-Identifier: MPL-2.0

"""Typed ONNX Runtime execution-provider configuration.

Each provider is a small pydantic config that compiles to an ONNX Runtime
``(name, options)`` tuple via :meth:`ExecutionProviderConfig.to_ort`. Keeping
providers as typed configs (rather than raw strings) lets users opt into
hardware acceleration — CUDA, TensorRT FP16, CoreML/ANE — without touching
model code, and keeps the options validated and discoverable.
"""

from pathlib import Path
from typing import Annotated, Literal

from pydantic import Field

from openstef_core.base_model import BaseConfig

#: An ONNX Runtime provider specification: ``(provider_name, provider_options)``.
type OrtProvider = tuple[str, dict[str, object]]


[docs] class CpuProvider(BaseConfig): """The default CPU execution provider.""" kind: Literal["cpu"] = Field(default="cpu", description="Discriminator tag for execution-provider type.")
[docs] def to_ort(self) -> OrtProvider: """Compile to an ONNX Runtime provider tuple. Returns: The ``CPUExecutionProvider`` with no options. """ return ("CPUExecutionProvider", {})
[docs] class CudaProvider(BaseConfig): """The CUDA (NVIDIA GPU) execution provider.""" kind: Literal["cuda"] = Field(default="cuda", description="Discriminator tag for execution-provider type.") device_id: int = Field(default=0, ge=0, description="CUDA device index to run on.")
[docs] def to_ort(self) -> OrtProvider: """Compile to an ONNX Runtime provider tuple. Returns: The ``CUDAExecutionProvider`` with the configured device id. """ return ("CUDAExecutionProvider", {"device_id": self.device_id})
[docs] class TensorRTProvider(BaseConfig): """The TensorRT execution provider (NVIDIA, ahead-of-time engine build). FP16 with a persistent engine cache is the recommended production path on NVIDIA hardware: the first run pays the engine-build cost, subsequent runs load the cached engine. """ kind: Literal["tensorrt"] = Field(default="tensorrt", description="Discriminator tag for execution-provider type.") device_id: int = Field(default=0, ge=0, description="CUDA device index to run on.") fp16: bool = Field(default=True, description="Enable FP16 precision for faster inference.") engine_cache_dir: Path | None = Field( default=None, description="Directory to persist built TensorRT engines. When set, engine caching is enabled.", )
[docs] def to_ort(self) -> OrtProvider: """Compile to an ONNX Runtime provider tuple. Returns: The ``TensorrtExecutionProvider`` with precision and engine-cache options. """ options: dict[str, object] = { "device_id": self.device_id, "trt_fp16_enable": self.fp16, } if self.engine_cache_dir is not None: options["trt_engine_cache_enable"] = True options["trt_engine_cache_path"] = str(self.engine_cache_dir) return ("TensorrtExecutionProvider", options)
[docs] class CoreMLProvider(BaseConfig): """The CoreML execution provider (Apple, GPU/Neural Engine). ``ModelFormat=MLProgram`` is required for modern CoreML: the legacy ``NeuralNetwork`` format fragments the graph and silently falls back to CPU for many ops. """ kind: Literal["coreml"] = Field(default="coreml", description="Discriminator tag for execution-provider type.") model_format: Literal["MLProgram", "NeuralNetwork"] = Field( default="MLProgram", description="CoreML model format. MLProgram is required for modern op coverage.", ) compute_units: Literal["CPUOnly", "CPUAndGPU", "CPUAndNeuralEngine", "ALL"] = Field( default="ALL", description="Which compute units CoreML may dispatch to. Prefer 'CPUAndGPU' for large transformer " "graphs: allowing the Neural Engine ('ALL'/'CPUAndNeuralEngine') can make CoreML's ahead-of-time " "compile run for many minutes for no inference win.", ) cache_dir: Path | None = Field( default=None, description="Directory for CoreML's compiled-model cache (ORT 'ModelCacheDirectory'). CoreML compiles " "the graph ahead of time on session build, which is slow; caching it cuts a warm rebuild from tens of " "seconds to a few. The cache is ORT-version/OS/hardware-specific — a local speedup, not a portable " "artifact. Requires 'MLProgram' format.", )
[docs] def to_ort(self) -> OrtProvider: """Compile to an ONNX Runtime provider tuple. Returns: The ``CoreMLExecutionProvider`` with format, compute-unit and (optional) cache options. """ options: dict[str, object] = {"ModelFormat": self.model_format, "MLComputeUnits": self.compute_units} if self.cache_dir is not None: options["ModelCacheDirectory"] = str(self.cache_dir) return ("CoreMLExecutionProvider", options)
#: An execution-provider config, discriminated by its ``kind`` tag. ExecutionProvider = Annotated[ CpuProvider | CudaProvider | TensorRTProvider | CoreMLProvider, Field(discriminator="kind"), ]
[docs] class SessionOptionsConfig(BaseConfig): """A subset of ONNX Runtime ``SessionOptions`` exposed as typed config.""" graph_optimization_level: Literal["DISABLE_ALL", "ENABLE_BASIC", "ENABLE_EXTENDED", "ENABLE_ALL"] = Field( default="ENABLE_ALL", description="Graph optimization level applied when loading the model.", ) intra_op_num_threads: int | None = Field( default=None, ge=0, description="Threads used within a single operator. None uses the ONNX Runtime default.", ) inter_op_num_threads: int | None = Field( default=None, ge=0, description="Threads used across operators. None uses the ONNX Runtime default.", )
__all__ = [ "CoreMLProvider", "CpuProvider", "CudaProvider", "ExecutionProvider", "SessionOptionsConfig", "TensorRTProvider", ]