metastable 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
metastable/__init__.py ADDED
@@ -0,0 +1,115 @@
1
+ """
2
+ metastable - Stable Diffusion middleware.
3
+
4
+ Pipeline generators (SD1.5, SDXL, Illustrious XL, Flux), compute device
5
+ selection and checkpoint merging, usable from API backends and standalone
6
+ applications alike.
7
+
8
+ Public names are resolved lazily, so `import metastable` stays cheap and
9
+ heavy dependencies (diffusers, transformers) load on first use.
10
+ """
11
+
12
+ from importlib import import_module
13
+ from typing import TYPE_CHECKING
14
+
15
+ from metastable.exceptions import (
16
+ CheckpointLoadError,
17
+ ConfigurationError,
18
+ MergeError,
19
+ MetastableError,
20
+ PipelineError,
21
+ )
22
+
23
+ __version__ = "0.1.0"
24
+
25
+ # public name -> defining module
26
+ _LAZY_EXPORTS = {
27
+ # device
28
+ "DeviceSettings": "metastable.device",
29
+ "configure_device": "metastable.device",
30
+ "get_device_settings": "metastable.device",
31
+ "get_torch_device": "metastable.device",
32
+ "reset_device_settings": "metastable.device",
33
+ "resolve_device_settings": "metastable.device",
34
+ # schedulers
35
+ "SCHEDULERS": "metastable.schedulers",
36
+ "FLUX_SCHEDULERS": "metastable.schedulers",
37
+ # seed
38
+ "get_random_seed": "metastable.seed",
39
+ "resolve_seed": "metastable.seed",
40
+ # model files
41
+ "enumerate_models": "metastable.models",
42
+ "read_safetensors_header": "metastable.models",
43
+ "read_safetensors_metadata": "metastable.models",
44
+ # pipelines
45
+ "BasePipelineGenerator": "metastable.pipelines",
46
+ "FluxPipelineGenerator": "metastable.pipelines",
47
+ "GenerationMetadata": "metastable.pipelines",
48
+ "IllustriousPipelineGenerator": "metastable.pipelines",
49
+ "LoraSpec": "metastable.pipelines",
50
+ "PIPELINES": "metastable.pipelines",
51
+ "SD15PipelineGenerator": "metastable.pipelines",
52
+ "SDXLPipelineGenerator": "metastable.pipelines",
53
+ "available_model_types": "metastable.pipelines",
54
+ "create_generator": "metastable.pipelines",
55
+ "get_generator_class": "metastable.pipelines",
56
+ # merge
57
+ "MergeConfig": "metastable.merge",
58
+ "MergeMethod": "metastable.merge",
59
+ "MergePipeline": "metastable.merge",
60
+ }
61
+
62
+ __all__ = [
63
+ "CheckpointLoadError",
64
+ "ConfigurationError",
65
+ "MergeError",
66
+ "MetastableError",
67
+ "PipelineError",
68
+ "__version__",
69
+ *_LAZY_EXPORTS,
70
+ ]
71
+
72
+
73
+ def __getattr__(name: str):
74
+ module_name = _LAZY_EXPORTS.get(name)
75
+ if module_name is None:
76
+ raise AttributeError(f"module 'metastable' has no attribute '{name}'")
77
+ value = getattr(import_module(module_name), name)
78
+ globals()[name] = value # cache for subsequent lookups
79
+ return value
80
+
81
+
82
+ def __dir__():
83
+ return sorted(set(globals()) | set(__all__))
84
+
85
+
86
+ if TYPE_CHECKING: # pragma: no cover - static analyzers only
87
+ from metastable.device import ( # noqa: F401
88
+ DeviceSettings,
89
+ configure_device,
90
+ get_device_settings,
91
+ get_torch_device,
92
+ reset_device_settings,
93
+ resolve_device_settings,
94
+ )
95
+ from metastable.merge import MergeConfig, MergeMethod, MergePipeline # noqa: F401
96
+ from metastable.models import ( # noqa: F401
97
+ enumerate_models,
98
+ read_safetensors_header,
99
+ read_safetensors_metadata,
100
+ )
101
+ from metastable.pipelines import ( # noqa: F401
102
+ PIPELINES,
103
+ BasePipelineGenerator,
104
+ FluxPipelineGenerator,
105
+ GenerationMetadata,
106
+ IllustriousPipelineGenerator,
107
+ LoraSpec,
108
+ SD15PipelineGenerator,
109
+ SDXLPipelineGenerator,
110
+ available_model_types,
111
+ create_generator,
112
+ get_generator_class,
113
+ )
114
+ from metastable.schedulers import FLUX_SCHEDULERS, SCHEDULERS # noqa: F401
115
+ from metastable.seed import get_random_seed, resolve_seed # noqa: F401
metastable/device.py ADDED
@@ -0,0 +1,398 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Compute Device Selection
4
+
5
+ Centralizes compute-device detection and override handling for every
6
+ supported backend:
7
+
8
+ - "cuda" - NVIDIA GPUs (PyTorch CUDA builds)
9
+ - "rocm" - AMD GPUs (PyTorch ROCm builds; PyTorch exposes HIP through the
10
+ CUDA API, so torch-level device strings stay "cuda[:N]")
11
+ - "mps" - Apple Silicon (Metal Performance Shaders)
12
+ - "cpu" - CPU fallback
13
+
14
+ Configuration is a plain mapping (every key optional):
15
+
16
+ {
17
+ "backend": "auto", # auto | cuda | rocm | mps | cpu
18
+ "index": 0, # GPU ordinal for multi-GPU hosts
19
+ "dtype": "auto", # auto | float16 | bfloat16 | float32
20
+ "gfx_override": "10.3.0", # sets HSA_OVERRIDE_GFX_VERSION (see below)
21
+ "env": {}, # extra env vars, applied before HIP/CUDA init
22
+ }
23
+
24
+ Applications register it once at startup with configure_device(); every
25
+ pipeline generator and merge pipeline then picks it up through
26
+ get_device_settings(). Without configure_device() the library falls back to
27
+ pure auto-detection. Generators also accept an explicit DeviceSettings
28
+ instance for per-object overrides.
29
+
30
+ `gfx_override` exists for AMD cards that are absent from the official ROCm
31
+ support matrix (e.g. RX 5500 XT / Navi 14 is gfx1034): setting it to "10.3.0"
32
+ makes the HSA runtime present the card as gfx1030. The variable must be set
33
+ before the first HIP initialization, so configure_device() must run before
34
+ any other torch.cuda call in the process.
35
+
36
+ Environment overrides are applied exactly once per process and are idempotent;
37
+ resolved settings are cached until configure_device() or
38
+ reset_device_settings() is called.
39
+ """
40
+
41
+ import logging
42
+ import os
43
+ from dataclasses import dataclass
44
+ from typing import Any, Dict, Mapping, Optional
45
+
46
+ import torch
47
+ import torch.cuda as cuda
48
+ import torch.backends.mps as apple_mps
49
+
50
+ from metastable.exceptions import ConfigurationError
51
+
52
+ logger = logging.getLogger(__name__)
53
+
54
+ # Supported dtype aliases for the "dtype" config key
55
+ _DTYPE_ALIASES = {
56
+ "auto": None, # sentinel: resolve from backend
57
+ "float16": torch.float16,
58
+ "fp16": torch.float16,
59
+ "half": torch.float16,
60
+ "bfloat16": torch.bfloat16,
61
+ "bf16": torch.bfloat16,
62
+ "float32": torch.float32,
63
+ "fp32": torch.float32,
64
+ "float": torch.float32,
65
+ }
66
+
67
+ # Backends addressable through the CUDA API (NVIDIA CUDA builds and AMD ROCm
68
+ # builds alike). torch.device("cuda:N") is the correct torch-level string for
69
+ # both; "rocm" is only a backend/vendor label, never a torch device string.
70
+ _CUDA_API_BACKENDS = ("cuda", "rocm")
71
+
72
+ # Module-level guard: environment overrides must be applied before the first
73
+ # HIP/HSA initialization, and only once per process.
74
+ _ENV_APPLIED = False
75
+
76
+ # Process-wide configuration registered via configure_device(), and the
77
+ # settings resolved from it (lazily, on first get_device_settings()).
78
+ _DEVICE_CONFIG: Dict[str, Any] = {}
79
+ _DEVICE_SETTINGS: Optional["DeviceSettings"] = None
80
+
81
+
82
+ @dataclass(frozen=True)
83
+ class DeviceSettings:
84
+ """
85
+ Resolved compute device settings.
86
+
87
+ Attributes:
88
+ backend: Backend label: "cuda", "rocm", "mps", or "cpu".
89
+ torch_device: Torch-level device string ("cuda:N", "mps", "cpu") safe
90
+ to pass to torch APIs, Generator(), and safetensors.
91
+ index: GPU ordinal (multi-GPU hosts); 0 for mps/cpu.
92
+ dtype: Recommended torch dtype for weights/inference.
93
+ dtype_source: "auto" (backend default) or "config" (explicitly set).
94
+ vendor: "nvidia", "amd", "apple", or "none".
95
+ gpu_name: Human-readable GPU name, or None on CPU hosts.
96
+ hip_version: torch.version.hip on ROCm builds, else None.
97
+ """
98
+
99
+ backend: str
100
+ torch_device: str
101
+ index: int
102
+ dtype: torch.dtype
103
+ dtype_source: str
104
+ vendor: str
105
+ gpu_name: Optional[str] = None
106
+ hip_version: Optional[str] = None
107
+
108
+ @classmethod
109
+ def cpu(cls, dtype: torch.dtype = torch.float32) -> "DeviceSettings":
110
+ """Convenience constructor for an explicit CPU device."""
111
+ return cls(
112
+ backend="cpu",
113
+ torch_device="cpu",
114
+ index=0,
115
+ dtype=dtype,
116
+ dtype_source="config",
117
+ vendor="none",
118
+ )
119
+
120
+
121
+ def _normalize_config(device_config: Any) -> Dict[str, Any]:
122
+ """
123
+ Normalize a device config to a plain dict.
124
+
125
+ Accepts None, any Mapping, or an object exposing to_dict() (e.g. the
126
+ attribute-style config containers used by applications).
127
+ """
128
+ if device_config is None:
129
+ return {}
130
+ if isinstance(device_config, Mapping):
131
+ return dict(device_config)
132
+ to_dict = getattr(device_config, "to_dict", None)
133
+ if callable(to_dict):
134
+ result = to_dict()
135
+ if isinstance(result, Mapping):
136
+ return dict(result)
137
+ raise ConfigurationError(
138
+ f"device config: expected a mapping or None, got {type(device_config).__name__}"
139
+ )
140
+
141
+
142
+ def apply_device_env(device_config: Any = None) -> None:
143
+ """
144
+ Apply device-related environment variables (idempotent, once per process).
145
+
146
+ Must run before the first HIP/CUDA initialization - the HSA runtime reads
147
+ HSA_OVERRIDE_GFX_VERSION when it enumerates GPUs, so setting it later has
148
+ no effect. resolve_device_settings() calls this automatically.
149
+
150
+ Args:
151
+ device_config: device configuration mapping (see module docstring)
152
+ """
153
+ global _ENV_APPLIED
154
+ if _ENV_APPLIED:
155
+ return
156
+ _ENV_APPLIED = True
157
+
158
+ params = _normalize_config(device_config)
159
+
160
+ gfx_override = params.get("gfx_override")
161
+ if gfx_override:
162
+ os.environ["HSA_OVERRIDE_GFX_VERSION"] = str(gfx_override)
163
+ logger.info(
164
+ "gfx_override set: HSA_OVERRIDE_GFX_VERSION=%s",
165
+ gfx_override,
166
+ )
167
+
168
+ env_map = params.get("env")
169
+ if env_map:
170
+ for key, value in _normalize_config(env_map).items():
171
+ os.environ[str(key)] = str(value)
172
+ logger.info("device env applied: %s=%s", key, value)
173
+
174
+
175
+ def torch_device_string(backend: str, index: int = 0) -> str:
176
+ """
177
+ Map a backend label to the torch-level device string.
178
+
179
+ Args:
180
+ backend: one of "cuda", "rocm", "mps", "cpu"
181
+ index: GPU ordinal (ignored for mps/cpu)
182
+
183
+ Returns:
184
+ Device string accepted by torch, Generator(), and safetensors
185
+ (e.g. "cuda:0" for both NVIDIA CUDA and AMD ROCm backends).
186
+
187
+ Raises:
188
+ ConfigurationError: if backend is not a recognized label.
189
+ """
190
+ backend = str(backend).strip().lower()
191
+ if backend in _CUDA_API_BACKENDS:
192
+ return f"cuda:{index}"
193
+ if backend == "mps":
194
+ return "mps"
195
+ if backend == "cpu":
196
+ return "cpu"
197
+ raise ConfigurationError(
198
+ f"Unknown device backend '{backend}'. Expected one of: cuda, rocm, mps, cpu"
199
+ )
200
+
201
+
202
+ def resolve_device_settings(device_config: Any = None) -> DeviceSettings:
203
+ """
204
+ Resolve the compute device from configuration and hardware detection.
205
+
206
+ Uncached: use get_device_settings() for the process-wide cached value.
207
+
208
+ Args:
209
+ device_config: device configuration mapping (None or missing keys
210
+ fall back to defaults: backend=auto, index=0,
211
+ dtype=auto, no env overrides)
212
+
213
+ Returns:
214
+ DeviceSettings with the resolved backend, torch device string, dtype,
215
+ vendor, and GPU identification.
216
+
217
+ Raises:
218
+ ConfigurationError: if an explicitly requested backend/dtype is not
219
+ available in the running PyTorch build.
220
+ """
221
+ apply_device_env(device_config)
222
+
223
+ params = _normalize_config(device_config)
224
+ backend_cfg = str(params.get("backend") or "auto").strip().lower()
225
+ index = int(params.get("index") or 0)
226
+ dtype_cfg = str(params.get("dtype") or "auto").strip().lower()
227
+
228
+ hip_version = torch.version.hip
229
+ vendor = "none"
230
+ gpu_name: Optional[str] = None
231
+
232
+ if backend_cfg == "auto":
233
+ if apple_mps.is_available():
234
+ logger.info("Apple Metal Performance Shaders Available!")
235
+ backend, vendor, torch_device = "mps", "apple", "mps"
236
+ elif cuda.is_available():
237
+ gpu_name = cuda.get_device_name(index)
238
+ device_capabilities = cuda.get_device_capability(index)
239
+ device_available_mem, device_total_mem = [
240
+ x / 1024**3 for x in cuda.mem_get_info(index)
241
+ ]
242
+ if hip_version:
243
+ backend, vendor = "rocm", "amd"
244
+ logger.info(
245
+ "AMD ROCm GPU available: %s - HIP %s - %s - %.1f/%.1f GB VRAM",
246
+ gpu_name,
247
+ hip_version,
248
+ device_capabilities,
249
+ device_available_mem,
250
+ device_total_mem,
251
+ )
252
+ else:
253
+ backend, vendor = "cuda", "nvidia"
254
+ logger.info(
255
+ "GPU available: %s - %s - %.1f/%.1f GB VRAM",
256
+ gpu_name,
257
+ device_capabilities,
258
+ device_available_mem,
259
+ device_total_mem,
260
+ )
261
+ torch_device = f"cuda:{index}"
262
+ else:
263
+ backend, torch_device = "cpu", "cpu"
264
+ logger.warning("No GPU found. Using CPU (this will be slow).")
265
+ elif backend_cfg in _CUDA_API_BACKENDS:
266
+ if backend_cfg == "rocm" and not hip_version:
267
+ raise ConfigurationError(
268
+ "device backend is 'rocm' but the installed PyTorch build has no "
269
+ "HIP/ROCm support (torch.version.hip is None). Install a ROCm "
270
+ "build of torch from the PyTorch ROCm wheel index."
271
+ )
272
+ if not cuda.is_available():
273
+ raise ConfigurationError(
274
+ f"device backend is '{backend_cfg}' but torch reports no accessible "
275
+ "GPU. If this is an AMD card: check that the amdgpu driver is "
276
+ "loaded, that your user is in the 'video' and 'render' groups, "
277
+ "and - for cards missing from the ROCm support matrix such as "
278
+ "the RX 5500 XT (gfx1034) - that gfx_override is set "
279
+ "(e.g. gfx_override: '10.3.0')."
280
+ )
281
+ backend = backend_cfg
282
+ vendor = "amd" if hip_version else "nvidia"
283
+ gpu_name = cuda.get_device_name(index)
284
+ torch_device = f"cuda:{index}"
285
+ logger.info(
286
+ "Device backend forced via config: %s (%s%s)",
287
+ backend,
288
+ gpu_name,
289
+ f" - HIP {hip_version}" if hip_version else "",
290
+ )
291
+ elif backend_cfg == "mps":
292
+ if not apple_mps.is_available():
293
+ raise ConfigurationError(
294
+ "device backend is 'mps' but Metal Performance Shaders are not "
295
+ "available on this host."
296
+ )
297
+ backend, vendor, torch_device = "mps", "apple", "mps"
298
+ logger.info("Apple Metal Performance Shaders selected via config.")
299
+ elif backend_cfg == "cpu":
300
+ backend, vendor, torch_device = "cpu", "none", "cpu"
301
+ logger.info("Device backend forced via config: cpu")
302
+ else:
303
+ raise ConfigurationError(
304
+ f"device backend '{backend_cfg}' is not one of: auto, cuda, rocm, mps, cpu"
305
+ )
306
+
307
+ dtype, dtype_source = _resolve_dtype(dtype_cfg, backend)
308
+ return DeviceSettings(
309
+ backend=backend,
310
+ torch_device=torch_device,
311
+ index=index,
312
+ dtype=dtype,
313
+ dtype_source=dtype_source,
314
+ vendor=vendor,
315
+ gpu_name=gpu_name,
316
+ hip_version=hip_version,
317
+ )
318
+
319
+
320
+ def _resolve_dtype(dtype_cfg: str, backend: str) -> tuple:
321
+ """
322
+ Resolve the inference dtype from the config value and backend.
323
+
324
+ Returns:
325
+ Tuple of (torch.dtype, source) where source is "config" for an
326
+ explicit dtype or "auto" for the backend default.
327
+ """
328
+ if dtype_cfg not in _DTYPE_ALIASES:
329
+ raise ConfigurationError(
330
+ f"device dtype '{dtype_cfg}' is not one of: auto, float16, bfloat16, float32"
331
+ )
332
+
333
+ if dtype_cfg != "auto":
334
+ return _DTYPE_ALIASES[dtype_cfg], "config"
335
+
336
+ # Backend defaults: fp32 on CPU, fp16 on every accelerator. ROCm keeps
337
+ # fp16 by default because bf16 support is unreliable on older RDNA GPUs
338
+ # (e.g. RX 5500 XT / gfx1034); opt in explicitly via dtype on RDNA2+
339
+ # cards where bf16 kernels are usable.
340
+ if backend == "cpu":
341
+ return torch.float32, "auto"
342
+ if backend == "rocm":
343
+ logger.info(
344
+ "ROCm: defaulting to float16 (bfloat16 is not reliably supported on "
345
+ "older RDNA GPUs); set dtype: bfloat16 to override."
346
+ )
347
+ return torch.float16, "auto"
348
+
349
+
350
+ def configure_device(device_config: Any = None) -> DeviceSettings:
351
+ """
352
+ Register the process-wide device configuration and resolve it.
353
+
354
+ Call once at application startup, before any other torch.cuda usage,
355
+ so environment overrides (gfx_override, env) take effect.
356
+
357
+ Args:
358
+ device_config: device configuration mapping (see module docstring)
359
+
360
+ Returns:
361
+ The resolved DeviceSettings (also cached for get_device_settings()).
362
+ """
363
+ global _DEVICE_CONFIG, _DEVICE_SETTINGS
364
+ _DEVICE_CONFIG = _normalize_config(device_config)
365
+ _DEVICE_SETTINGS = resolve_device_settings(_DEVICE_CONFIG)
366
+ return _DEVICE_SETTINGS
367
+
368
+
369
+ def get_device_settings() -> DeviceSettings:
370
+ """
371
+ Return the process-wide device settings (resolved lazily and cached).
372
+
373
+ Uses the configuration registered via configure_device(), or pure
374
+ auto-detection when none was registered.
375
+ """
376
+ global _DEVICE_SETTINGS
377
+ if _DEVICE_SETTINGS is None:
378
+ _DEVICE_SETTINGS = resolve_device_settings(_DEVICE_CONFIG)
379
+ return _DEVICE_SETTINGS
380
+
381
+
382
+ def reset_device_settings() -> None:
383
+ """
384
+ Forget the registered configuration and cached settings.
385
+
386
+ Environment overrides already applied to the process are not undone.
387
+ """
388
+ global _DEVICE_CONFIG, _DEVICE_SETTINGS
389
+ _DEVICE_CONFIG = {}
390
+ _DEVICE_SETTINGS = None
391
+
392
+
393
+ def get_torch_device() -> str:
394
+ """
395
+ Convenience accessor for the torch-level device string of the resolved
396
+ device (e.g. "cuda:0" on NVIDIA and AMD ROCm alike, "mps", "cpu").
397
+ """
398
+ return get_device_settings().torch_device
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Custom Exception Classes
4
+
5
+ Domain-specific exceptions raised by metastable. Every exception derives
6
+ from MetastableError so callers can catch library failures with one clause.
7
+ """
8
+
9
+
10
+ class MetastableError(Exception):
11
+ """Base class for every exception raised by metastable."""
12
+ pass
13
+
14
+
15
+ class CheckpointLoadError(MetastableError):
16
+ """
17
+ Exception raised when a checkpoint file cannot be loaded.
18
+
19
+ This can occur due to:
20
+ - File not found
21
+ - Invalid file format
22
+ - Corrupted checkpoint data
23
+ - Insufficient memory
24
+ """
25
+ pass
26
+
27
+
28
+ class MergeError(MetastableError):
29
+ """
30
+ Exception raised when a merge operation fails.
31
+
32
+ This can occur due to:
33
+ - Incompatible model architectures
34
+ - Shape mismatches between tensors
35
+ - Unsupported merge method
36
+ - Memory allocation failures
37
+ """
38
+ pass
39
+
40
+
41
+ class ConfigurationError(MetastableError):
42
+ """
43
+ Exception raised when configuration loading or validation fails.
44
+
45
+ This can occur due to:
46
+ - Unknown device backend or dtype
47
+ - Requested backend not available in the running PyTorch build
48
+ - Malformed configuration mappings
49
+ """
50
+ pass
51
+
52
+
53
+ class PipelineError(MetastableError):
54
+ """
55
+ Exception raised when a pipeline operation fails.
56
+
57
+ This can occur due to:
58
+ - Model not loaded
59
+ - Invalid inference parameters (e.g. unknown scheduler)
60
+ - Device/memory issues
61
+ """
62
+ pass
metastable/images.py ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Image Conversion Helpers
4
+ """
5
+
6
+ from typing import Union
7
+
8
+ import numpy as np
9
+ from PIL import Image
10
+
11
+
12
+ def convert_to_pil(image: Union[np.ndarray, Image.Image]) -> Image.Image:
13
+ """
14
+ Convert a numpy array to a PIL Image if needed.
15
+
16
+ Float arrays with values in [0, 1] are scaled to [0, 255]; anything else
17
+ is cast to uint8 as-is.
18
+ """
19
+ if isinstance(image, np.ndarray):
20
+ if image.max() <= 1.0:
21
+ image = (image * 255).astype(np.uint8)
22
+ else:
23
+ image = image.astype(np.uint8)
24
+ return Image.fromarray(image)
25
+ return image
26
+
27
+
28
+ def convert_mask_to_grayscale(mask: Image.Image) -> Image.Image:
29
+ """Ensure mask is in grayscale ("L") mode."""
30
+ if mask.mode != "L":
31
+ return mask.convert("L")
32
+ return mask
@@ -0,0 +1,44 @@
1
+ """Checkpoint merging: tensor methods, checkpoint ops and merge pipelines."""
2
+
3
+ from metastable.merge.methods import MergeMethod, linear, merge_tensors, slerp
4
+ from metastable.merge.ops import (
5
+ MergeConfig,
6
+ batch_merge_checkpoints,
7
+ load_checkpoint_dict,
8
+ merge_checkpoints,
9
+ save_checkpoint,
10
+ validate_checkpoints,
11
+ )
12
+ from metastable.merge.pipeline import (
13
+ ARCHITECTURES,
14
+ ILLUSTRIOUS_ARCHITECTURE,
15
+ SD15_ARCHITECTURE,
16
+ SDXL_ARCHITECTURE,
17
+ IllustriousMergePipeline,
18
+ MergePipeline,
19
+ ModelArchitectureInfo,
20
+ SD15MergePipeline,
21
+ SDXLMergePipeline,
22
+ )
23
+
24
+ __all__ = [
25
+ "ARCHITECTURES",
26
+ "ILLUSTRIOUS_ARCHITECTURE",
27
+ "IllustriousMergePipeline",
28
+ "MergeConfig",
29
+ "MergeMethod",
30
+ "MergePipeline",
31
+ "ModelArchitectureInfo",
32
+ "SD15MergePipeline",
33
+ "SD15_ARCHITECTURE",
34
+ "SDXLMergePipeline",
35
+ "SDXL_ARCHITECTURE",
36
+ "batch_merge_checkpoints",
37
+ "linear",
38
+ "load_checkpoint_dict",
39
+ "merge_checkpoints",
40
+ "merge_tensors",
41
+ "save_checkpoint",
42
+ "slerp",
43
+ "validate_checkpoints",
44
+ ]