# AUTOMATIC1111 Model Loading System: How Safetensors and Checkpoint Merging Work

> Explore AUTOMATIC1111's model loading system discover how safetensors and checkpoint merging work. Learn about weight loading and tensor interpolation for efficient AI art generation. Optimize your workflow today.

- Repository: [AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
- Tags: internals
- Published: 2026-02-24

---

**AUTOMATIC1111's Stable Diffusion WebUI loads model checkpoints by scanning for `.safetensors` and `.ckpt` files, parsing them through `sd_models.read_state_dict`, and applying weights via `load_model_weights`, while the checkpoint merger performs tensor-wise interpolation using weighted sums or add-difference algorithms defined in [`extras.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/extras.py).**

The AUTOMATIC1111 Stable Diffusion WebUI manages hundreds of model checkpoints through a sophisticated loading pipeline that prioritizes the **Safetensors** format for security and speed. Understanding how [`modules/sd_models.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/sd_models.py) handles file discovery, metadata extraction, and weight application—alongside the tensor arithmetic powering the built-in checkpoint merger—enables advanced users to optimize their workflows and create custom model blends according to the source code.

## How AUTOMATIC1111 Discovers and Loads Model Checkpoints

The loading pipeline begins at startup and progresses through distinct phases from file discovery to model hijacking.

### Scanning for Safetensors and CKPT Files

At startup, `sd_models.list_models()` builds the inventory of available models by calling **`modelloader.load_models`** in [`modules/modelloader.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/modelloader.py) (lines 44-66). This function recursively scans user-specified directories for files ending in `.ckpt` or `.safetensors`, automatically downloading a default safetensors checkpoint if the directory is empty.

### Checkpoint Selection and Metadata Resolution

When a user selects a checkpoint via the UI or CLI, the system stores the choice in `shared.opts.sd_model_checkpoint`. The function **`sd_models.select_checkpoint()`** resolves this string to a **`CheckpointInfo`** instance, a data class defined in [`modules/sd_models.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/sd_models.py) (lines 18-28) that holds the filename, SHA-256 hash, and any embedded safetensors metadata.

### Reading State Dicts: Safetensors vs Legacy CKPT

The function **`sd_models.read_state_dict`** serves as the single entry point for deserializing checkpoint files, routing to different loaders based on file extension. In [`modules/sd_models.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/sd_models.py) (lines 12-25):

- **Safetensors path**: Uses `safetensors.torch.load_file` with optional memory-mapping controlled by the option `disable_mmap_load_safetensors` (lines 15-22).
- **Legacy `.ckpt` path**: Falls back to `torch.load` (lines 23-25).

For safetensors files, **`sd_models.read_metadata_from_safetensors`** parses the embedded JSON metadata block—containing thumbnails and model specifications—without loading the full tensor data (lines 84-99).

### Model Instantiation and Weight Application

After reading the state dict, the system locates the associated config file via **`sd_models_config.find_checkpoint_config`**, loads it with **OmegaConf**, and instantiates the model class using `instantiate_from_config` (lines 87-94, 108-119).

The **`sd_models.load_model_weights`** function then applies the state dict to the instantiated model (lines 10-44, 66-91). This stage handles:

- **Half-precision conversion** (`float16`) and optional **FP8** quantization.
- **VAE baking** to embed a specific VAE into the checkpoint.
- Device placement and memory optimization.

Finally, `sd_hijack.model_hijack.hijack` patches the model so the UI can inject extra networks like LoRA, the empty prompt is cached, and the model is marked as loaded (lines 68-73).

## How Checkpoint Merging Works in AUTOMATIC1111

The checkpoint merger, accessible through the "Model Merger" tab, enables tensor-wise blending of up to three models using mathematical interpolation.

### The Model Merger UI Architecture

The user interface is defined in **[`modules/ui_checkpoint_merger.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/ui_checkpoint_merger.py)** (lines 36-53), which presents three dropdowns for selecting the *Primary (A)*, *Secondary (B)*, and *Tertiary (C)* checkpoints, along with radio buttons for the output format (`ckpt` or `safetensors`). When the user clicks **Merge**, the UI invokes **`extras.run_modelmerger`** in [`modules/extras.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/extras.py).

### Loading and Interpolation Algorithms

The merger first loads source state dicts using `sd_models.read_state_dict` for each selected checkpoint (lines 50-65). Depending on the selected radio option, it applies one of three interpolation functions (lines 96-104):

- **Weighted sum**: `theta_0 = (1 - M) * theta_A + M * theta_B`
- **Add difference**: `theta_0 = theta_A + M * (theta_B - theta_C)`
- **No interpolation**: Direct copy of model A

Where `M` represents the user-specified multiplier.

### Tensor-Wise Merging and Special Cases

The implementation walks through every key of the primary checkpoint (`theta_0`). If the key exists in the secondary (and optionally tertiary) dicts, the chosen arithmetic is applied. Special handling exists in [`modules/extras.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/extras.py) (lines 57-88, 92-114) for **inpainting** and **instruct-pix2pix** models where channel dimensions differ between checkpoints.

### Post-Processing and Metadata Preservation

After merging, optional post-processing includes:

- **Half-precision conversion** (`to_half`) when `save_as_half` is enabled.
- **VAE baking** by loading a separate VAE checkpoint and injecting its tensors (lines 21-33).

The merger preserves original checkpoint metadata, embeds new user-supplied JSON blocks, and can append a **merge recipe** describing the operation for reproducibility (lines 58-76, 85-100).

### Saving the Merged Checkpoint

The final state dict (`theta_0`) is written to disk based on the selected extension:

- **Safetensors**: `safetensors.torch.save_file(..., metadata=metadata)` (lines 13-17).
- **Legacy CKPT**: `torch.save(...)`.

After saving, `sd_models.list_models()` refreshes the UI so the new checkpoint appears in dropdown menus immediately (lines 24-26 in [`ui_checkpoint_merger.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/ui_checkpoint_merger.py)).

## Why Safetensors Is the Preferred Format

The **Safetensors** format offers distinct advantages over legacy `.ckpt` files in the AUTOMATIC1111 ecosystem:

- **Memory mapping**: Safetensors supports `mmap` (unless disabled via `disable_mmap_load_safetensors` in [`shared_options.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/shared_options.py) lines 128-130), enabling zero-copy reads that drastically reduce RAM usage and improve loading speeds on network drives.
- **Security**: Unlike pickle-based `.ckpt` files, safetensors does not execute arbitrary Python code during loading, eliminating a major attack vector.
- **Metadata support**: The format natively embeds JSON metadata (thumbnails, model-spec) that the UI surfaces without requiring auxiliary files.

## Practical Code Examples

### Loading a Safetensors Checkpoint Manually

You can programmatically load a checkpoint using the same functions the UI calls:

```python
from modules import sd_models

# Initialize checkpoint info (creates metadata cache)

checkpoint_path = "v1-5-pruned-emaonly.safetensors"
info = sd_models.CheckpointInfo(checkpoint_path)

# Load state dict (safetensors.torch handles the heavy lifting)

state = sd_models.read_state_dict(info.filename)
print(f"Loaded {len(state)} tensors from {info.title}")

```

This uses the extension-based routing logic in `sd_models.read_state_dict` (lines 12-25).

### Merging Two Checkpoints with Weighted Sum

The following Python snippet replicates the core arithmetic of the model merger:

```python
from modules import sd_models
import safetensors.torch

# Load primary and secondary state dicts

primary = sd_models.CheckpointInfo("modelA.safetensors")
secondary = sd_models.CheckpointInfo("modelB.safetensors")

theta_a = sd_models.read_state_dict(primary.filename, map_location="cpu")
theta_b = sd_models.read_state_dict(secondary.filename, map_location="cpu")

# Perform weighted sum (30% of model B)

alpha = 0.30
merged = {
    k: (1 - alpha) * theta_a[k] + alpha * theta_b[k]
    for k in theta_a.keys() if k in theta_b
}

# Save with metadata

out_path = "merged.safetensors"
safetensors.torch.save_file(merged, out_path, metadata=primary.metadata)
print(f"Merged checkpoint saved to {out_path}")

```

This implements the same weighted sum formula found in `extras.run_modelmerger` (lines 96-98).

### Using the UI to Merge Three Checkpoints (Add-Difference)

To perform an add-difference merge through the interface:

1. Open the **"Checkpoint Merger"** tab.
2. Select **Primary Model (A)**, **Secondary Model (B)**, and **Tertiary Model (C)** from the dropdowns.
3. Choose the **"Add difference"** interpolation method and set the **Multiplier (M)** (e.g., 0.2).
4. Optionally enable **"Save as float16"** and select **".safetensors"** as the output format.
5. Click **Merge**—the Web UI executes `extras.run_modelmerger`, displays progress, and adds the new file to the model list.

This workflow is defined in [`modules/ui_checkpoint_merger.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/ui_checkpoint_merger.py) (lines 36-53).

## Summary

- **File discovery** occurs via `modelloader.load_models` in [`modules/modelloader.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/modelloader.py), which scans for `.safetensors` and `.ckpt` extensions.
- **Loading logic** branches in `sd_models.read_state_dict` between `safetensors.torch.load_file` (with optional mmap) and `torch.load` for legacy files.
- **CheckpointInfo** objects encapsulate metadata and file paths, enabling the selection system to resolve model names to physical files.
- **Weight application** happens in `load_model_weights`, handling dtype conversion, VAE baking, and device placement before hijacking.
- **Merging** executes in `extras.run_modelmerger` using tensor-wise interpolation (weighted sum or add-difference), with special handling for architectural differences in inpainting models.
- **Output formats** support both safetensors (preferred for metadata and safety) and legacy CKPT, with automatic UI refresh after saving.

## Frequently Asked Questions

### What is the difference between .ckpt and .safetensors in AUTOMATIC1111?

**Safetensors** stores tensors in a flat binary layout that supports memory-mapping and contains embedded JSON metadata, while **.ckpt** files use Python's pickle format which requires full deserialization into RAM and can execute arbitrary code during loading. The WebUI prioritizes safetensors for faster cold starts and improved security.

### How does the checkpoint merger handle models with different architectures?

The merger in [`modules/extras.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/extras.py) includes special case handling for models like inpainting or instruct-pix2pix variants where tensor channel dimensions may differ. It validates key presence and shape compatibility before applying interpolation arithmetic, skipping incompatible keys rather than failing.

### Can I merge more than two checkpoints at once?

The UI supports three inputs: Primary (A), Secondary (B), and Tertiary (C). The **Add difference** algorithm uses all three models (`A + M*(B-C)`), while **Weighted sum** only requires A and B. You cannot merge four or more models in a single operation through the standard UI, though you can chain merges sequentially.

### Why is my merged model file size different from the originals?

File size changes typically result from **half-precision conversion** (`float16`) which halves storage requirements, or **VAE baking** which adds VAE weights to the checkpoint. Conversely, merging multiple full-precision models without conversion preserves or increases size. The output format (safetensors vs CKPT) also affects compression efficiency.