AUTOMATIC1111 Model Loading System: How Safetensors and Checkpoint Merging Work
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.
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 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 (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 (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 (lines 12-25):
- Safetensors path: Uses
safetensors.torch.load_filewith optional memory-mapping controlled by the optiondisable_mmap_load_safetensors(lines 15-22). - Legacy
.ckptpath: Falls back totorch.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 (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.
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 (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) whensave_as_halfis 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).
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 viadisable_mmap_load_safetensorsinshared_options.pylines 128-130), enabling zero-copy reads that drastically reduce RAM usage and improve loading speeds on network drives. - Security: Unlike pickle-based
.ckptfiles, 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:
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:
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:
- Open the "Checkpoint Merger" tab.
- Select Primary Model (A), Secondary Model (B), and Tertiary Model (C) from the dropdowns.
- Choose the "Add difference" interpolation method and set the Multiplier (M) (e.g., 0.2).
- Optionally enable "Save as float16" and select ".safetensors" as the output format.
- 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 (lines 36-53).
Summary
- File discovery occurs via
modelloader.load_modelsinmodules/modelloader.py, which scans for.safetensorsand.ckptextensions. - Loading logic branches in
sd_models.read_state_dictbetweensafetensors.torch.load_file(with optional mmap) andtorch.loadfor 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_modelmergerusing 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →