Skip to content

Configuration

config

Configuration system with Pydantic validation.

Replaces the scattered configuration across dependencies.json, repo-config.json, and hardcoded values in PowerShell scripts. Provides a single, typed, validated configuration model.

ToolConfig

Bases: BaseModel

Configuration for an external tool (e.g. VS Build Tools).

ToolsConfig

Bases: BaseModel

All external tools configuration.

TorchConfig

Bases: BaseModel

PyTorch installation configuration.

RocmWindowsConfig

Bases: BaseModel

AMD ROCm on Windows configuration.

Uses AMD's official wheels from repo.radeon.com instead of the standard PyTorch index. Requires specific AMD Adrenalin drivers and currently only supports Python 3.12.

Two-phase install:

  1. ROCm SDK wheels (runtime environment).
  2. PyTorch wheels built for ROCm (torch, torchvision, torchaudio).

get_torch_urls(python_version)

Get the PyTorch wheel URLs for the given Python version.

Parameters:

Name Type Description Default
python_version tuple[int, int]

(major, minor) tuple, e.g. (3, 12).

required

Returns:

Type Description
list[str] | None

List of wheel URLs, or None if no match.

Source code in umeairt_installer/config.py
def get_torch_urls(self, python_version: tuple[int, int]) -> list[str] | None:
    """Get the PyTorch wheel URLs for the given Python version.

    Args:
        python_version: ``(major, minor)`` tuple, e.g. ``(3, 12)``.

    Returns:
        List of wheel URLs, or ``None`` if no match.
    """
    cp_tag = f"cp{python_version[0]}{python_version[1]}"
    return self.torch_wheels.get(cp_tag)

WheelConfig

Bases: BaseModel

A pre-built wheel package to install.

Supports version-aware wheels via the versions mapping: each key is a CPython tag (e.g. "cp311", "cp312") and the value is the download URL for that version.

Optionally, checksums maps CPython tags to expected SHA-256 hex digests for supply-chain verification.

Legacy format (flat name + url) is still supported.

resolve(python_version, cuda_tag='')

Pick the wheel matching the running Python and CUDA version.

Resolution order for versioned wheels: 1. {platform}_{cuda_tag}_{cpython_tag} — OS + CUDA + Python match 2. {cuda_tag}_{cpython_tag} — OS-agnostic CUDA + Python match 3. {platform}_{cpython_tag} — OS + Python match 4. {cpython_tag} — OS-agnostic Python fallback 5. {platform}_{cuda_tag}_abi3 — OS + CUDA, any Python 6. {cuda_tag}_abi3 — CUDA, any Python 7. {platform}_abi3 — OS, any Python 8. abi3 — any OS, any Python

Parameters:

Name Type Description Default
python_version tuple[int, int]

(major, minor) tuple, e.g. (3, 13).

required
cuda_tag str

CUDA tag, e.g. "cu130" or "cu128".

''

Returns:

Type Description
tuple[str, str, str | None] | None

(name, url, sha256_or_None) tuple, or None if no match.

Source code in umeairt_installer/config.py
def resolve(
    self,
    python_version: tuple[int, int],
    cuda_tag: str = "",
) -> tuple[str, str, str | None] | None:
    """Pick the wheel matching the running Python and CUDA version.

    Resolution order for versioned wheels:
    1. ``{platform}_{cuda_tag}_{cpython_tag}`` — OS + CUDA + Python match
    2. ``{cuda_tag}_{cpython_tag}`` — OS-agnostic CUDA + Python match
    3. ``{platform}_{cpython_tag}`` — OS + Python match
    4. ``{cpython_tag}`` — OS-agnostic Python fallback
    5. ``{platform}_{cuda_tag}_abi3`` — OS + CUDA, any Python
    6. ``{cuda_tag}_abi3`` — CUDA, any Python
    7. ``{platform}_abi3`` — OS, any Python
    8. ``abi3`` — any OS, any Python

    Args:
        python_version: (major, minor) tuple, e.g. (3, 13).
        cuda_tag: CUDA tag, e.g. ``"cu130"`` or ``"cu128"``.

    Returns:
        (name, url, sha256_or_None) tuple, or None if no match.
    """
    import sys
    platform = "windows" if sys.platform == "win32" else "macos" if sys.platform == "darwin" else "linux"
    cp_tag = f"cp{python_version[0]}{python_version[1]}"

    if self.versions:
        keys_to_try = []
        if cuda_tag:
            keys_to_try.append(f"{platform}_{cuda_tag}_{cp_tag}")
            keys_to_try.append(f"{cuda_tag}_{cp_tag}")
        keys_to_try.append(f"{platform}_{cp_tag}")
        keys_to_try.append(cp_tag)
        # ABI3 fallback — one wheel covers every Python version.
        # The platform-prefixed forms must be tried too: dependencies.json
        # ships `windows_cu130_abi3` / `windows_cu128_abi3` for the
        # SageAttention 2.2.0 Windows builds, and omitting them here sent
        # every Windows install to the PyPI fallback, silently installing
        # sageattention 1.0.6 instead of the pre-built 2.2.0 wheel.
        if cuda_tag:
            keys_to_try.append(f"{platform}_{cuda_tag}_abi3")
            keys_to_try.append(f"{cuda_tag}_abi3")
        keys_to_try.append(f"{platform}_abi3")
        keys_to_try.append("abi3")

        for key in keys_to_try:
            url = self.versions.get(key)
            if url:
                whl_name = url.rsplit("/", 1)[-1].removesuffix(".whl")
                checksum = self.checksums.get(key)
                return whl_name, url, checksum
        return None

    # Legacy: flat name + url (assumed to match current Python)
    if self.name and self.url:
        return self.name, self.url, None
    return None

SageAttentionWheelConfig

Bases: WheelConfig

A SageAttention wheel with GPU compute capability range.

Extends WheelConfig with min_compute_capability and max_compute_capability to select between SageAttention 2 (sm_80–sm_90) and SageAttention 3 Blackwell (sm_100+).

matches_gpu(cc)

Check if this wheel is compatible with the GPU compute capability.

Parameters:

Name Type Description Default
cc tuple[int, int]

Compute capability as (major, minor).

required

Returns:

Type Description
bool

True if the GPU matches the range.

Source code in umeairt_installer/config.py
def matches_gpu(self, cc: tuple[int, int]) -> bool:
    """Check if this wheel is compatible with the GPU compute capability.

    Args:
        cc: Compute capability as ``(major, minor)``.

    Returns:
        ``True`` if the GPU matches the range.
    """
    min_cc = tuple(self.min_compute_capability)
    max_cc = tuple(self.max_compute_capability)
    return min_cc <= cc <= max_cc

PipPackages

Bases: BaseModel

All pip package configurations.

supported_cuda_tags property

List supported CUDA tags from the torch configuration.

get_torch(cuda_tag, *, profile='classic')

Get the TorchConfig for a specific CUDA tag and profile.

When profile is "modern" and :attr:torch_modern is populated, selects from the modern config. For cu128 on the modern profile, falls back to cu126 since PyTorch 2.13 does not ship cu128 wheels.

Parameters:

Name Type Description Default
cuda_tag str

CUDA tag, e.g. "cu130" or "cu128".

required
profile str

"classic" (default) or "modern".

'classic'

Returns:

Type Description
TorchConfig | None

Matching TorchConfig, or None if not available.

Source code in umeairt_installer/config.py
def get_torch(self, cuda_tag: str, *, profile: str = "classic") -> TorchConfig | None:
    """Get the TorchConfig for a specific CUDA tag and profile.

    When *profile* is ``"modern"`` and :attr:`torch_modern` is populated,
    selects from the modern config.  For ``cu128`` on the modern profile,
    falls back to ``cu126`` since PyTorch 2.13 does not ship cu128 wheels.

    Args:
        cuda_tag: CUDA tag, e.g. ``"cu130"`` or ``"cu128"``.
        profile: ``"classic"`` (default) or ``"modern"``.

    Returns:
        Matching TorchConfig, or ``None`` if not available.
    """
    if profile == "modern" and self.torch_modern:
        # cu128 not available for torch 2.13 — fall back to cu126
        tag = "cu126" if cuda_tag == "cu128" else cuda_tag
        cfg = self.torch_modern.get(tag)
        if cfg is not None:
            return cfg
        # Fall through to classic if modern doesn't have this tag

    if isinstance(self.torch, dict):
        return self.torch.get(cuda_tag)
    # Legacy single TorchConfig — return it for any tag
    return self.torch

RepositoryConfig

Bases: BaseModel

A git repository source.

RepositoriesConfig

Bases: BaseModel

All git repositories.

FileEntry

Bases: BaseModel

A file to download with its destination.

FilesConfig

Bases: BaseModel

All downloadable files.

InstallOptions

Bases: BaseModel

Options for uv pip install.

OptimizationPackage

Bases: BaseModel

A single GPU optimization package with platform/GPU filters.

pypi_package can be a plain string (same on all platforms) or a dict mapping platform names (windows, linux, macos) to platform-specific package names.

requires is a list of tags the environment must satisfy for this package to be installed. Supported tags: nvidia, amd, linux, windows, macos.

get_package_name(platform)

Resolve the pip package name for the given platform.

Parameters:

Name Type Description Default
platform str

"windows", "linux", or "macos".

required

Returns:

Type Description
str | None

Package name string, or None if not available on this platform.

Source code in umeairt_installer/config.py
def get_package_name(self, platform: str) -> str | None:
    """Resolve the pip package name for the given platform.

    Args:
        platform: ``"windows"``, ``"linux"``, or ``"macos"``.

    Returns:
        Package name string, or ``None`` if not available on this platform.
    """
    if isinstance(self.pypi_package, str):
        return self.pypi_package
    return self.pypi_package.get(platform)

OptimizationsConfig

Bases: BaseModel

GPU optimization packages configuration.

DependenciesConfig

Bases: BaseModel

Complete dependencies configuration.

Typed replacement for dependencies.json.

InstallerSettings

Bases: BaseModel

User-local installer settings.

Replaces repo-config.json and hardcoded values. This file should NEVER be overwritten by bootstrap/update.

load_dependencies(path)

Load and validate dependencies.json.

Parameters:

Name Type Description Default
path Path

Path to dependencies.json file.

required

Returns:

Type Description
DependenciesConfig

Validated DependenciesConfig object.

Raises:

Type Description
FileNotFoundError

If the file doesn't exist.

ValueError

If the JSON is invalid.

Source code in umeairt_installer/config.py
def load_dependencies(path: Path) -> DependenciesConfig:
    """
    Load and validate dependencies.json.

    Args:
        path: Path to dependencies.json file.

    Returns:
        Validated DependenciesConfig object.

    Raises:
        FileNotFoundError: If the file doesn't exist.
        ValueError: If the JSON is invalid.
    """
    if not path.exists():
        raise FileNotFoundError(f"Dependencies file not found: {path}")

    with open(path, encoding="utf-8") as f:
        data = json.load(f)

    return DependenciesConfig.model_validate(data)

load_settings(path)

Load user-local settings from local-config.json.

If the file doesn't exist, returns defaults.

Parameters:

Name Type Description Default
path Path

Path to local-config.json.

required

Returns:

Type Description
InstallerSettings

InstallerSettings with loaded or default values.

Source code in umeairt_installer/config.py
def load_settings(path: Path) -> InstallerSettings:
    """
    Load user-local settings from local-config.json.

    If the file doesn't exist, returns defaults.

    Args:
        path: Path to local-config.json.

    Returns:
        InstallerSettings with loaded or default values.
    """
    if not path.exists():
        return InstallerSettings()

    with open(path, encoding="utf-8") as f:
        data = json.load(f)

    return InstallerSettings.model_validate(data)

save_settings(settings, path)

Save settings to local-config.json.

Parameters:

Name Type Description Default
settings InstallerSettings

The settings to save.

required
path Path

Destination file path.

required
Source code in umeairt_installer/config.py
def save_settings(settings: InstallerSettings, path: Path) -> None:
    """
    Save settings to local-config.json.

    Args:
        settings: The settings to save.
        path: Destination file path.
    """
    path.parent.mkdir(parents=True, exist_ok=True)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(
            settings.model_dump(mode="json"),
            f,
            indent=2,
            default=str,
        )