Skip to content

Commit ac7ecd2

Browse files
committed
Label and load SD .safetensors model files
1 parent 47a44c7 commit ac7ecd2

File tree

4 files changed

+19
-8
lines changed

4 files changed

+19
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Check the [custom scripts](https://github.com/AUTOMATIC1111/stable-diffusion-web
8484
- API
8585
- Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML.
8686
- via extension: [Aesthetic Gradients](https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients), a way to generate images with a specific aesthetic by using clip images embds (implementation of [https://github.com/vicgalle/stable-diffusion-aesthetic-gradients](https://github.com/vicgalle/stable-diffusion-aesthetic-gradients))
87+
- Can use safetensors to safely load model files without python pickle
8788

8889
## Where are Aesthetic Gradients?!?!
8990
Aesthetic Gradients are now an extension. You can install it using git:

modules/modelloader.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def cleanup_models():
8282
src_path = models_path
8383
dest_path = os.path.join(models_path, "Stable-diffusion")
8484
move_files(src_path, dest_path, ".ckpt")
85+
move_files(src_path, dest_path, ".safetensors")
8586
src_path = os.path.join(root_path, "ESRGAN")
8687
dest_path = os.path.join(models_path, "ESRGAN")
8788
move_files(src_path, dest_path)

modules/sd_models.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import gc
55
from collections import namedtuple
66
import torch
7+
from safetensors.torch import load_file
78
import re
89
from omegaconf import OmegaConf
910

@@ -16,9 +17,10 @@
1617
model_dir = "Stable-diffusion"
1718
model_path = os.path.abspath(os.path.join(models_path, model_dir))
1819

19-
CheckpointInfo = namedtuple("CheckpointInfo", ['filename', 'title', 'hash', 'model_name', 'config'])
20+
CheckpointInfo = namedtuple("CheckpointInfo", ['filename', 'title', 'hash', 'model_name', 'config', 'exttype'])
2021
checkpoints_list = {}
2122
checkpoints_loaded = collections.OrderedDict()
23+
checkpoint_types = {'.ckpt':'pickle','.safetensors':'safetensors'}
2224

2325
try:
2426
# this silences the annoying "Some weights of the model checkpoint were not used when initializing..." message at start.
@@ -45,7 +47,7 @@ def checkpoint_tiles():
4547

4648
def list_models():
4749
checkpoints_list.clear()
48-
model_list = modelloader.load_models(model_path=model_path, command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt"])
50+
model_list = modelloader.load_models(model_path=model_path, command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt",".safetensors"])
4951

5052
def modeltitle(path, shorthash):
5153
abspath = os.path.abspath(path)
@@ -60,28 +62,28 @@ def modeltitle(path, shorthash):
6062
if name.startswith("\\") or name.startswith("/"):
6163
name = name[1:]
6264

63-
shortname = os.path.splitext(name.replace("/", "_").replace("\\", "_"))[0]
65+
shortname, ext = os.path.splitext(name.replace("/", "_").replace("\\", "_"))
6466

65-
return f'{name} [{shorthash}]', shortname
67+
return f'{name} [{checkpoint_types[ext]}] [{shorthash}]', shortname
6668

6769
cmd_ckpt = shared.cmd_opts.ckpt
6870
if os.path.exists(cmd_ckpt):
6971
h = model_hash(cmd_ckpt)
7072
title, short_model_name = modeltitle(cmd_ckpt, h)
71-
checkpoints_list[title] = CheckpointInfo(cmd_ckpt, title, h, short_model_name, shared.cmd_opts.config)
73+
checkpoints_list[title] = CheckpointInfo(cmd_ckpt, title, h, short_model_name, shared.cmd_opts.config, '')
7274
shared.opts.data['sd_model_checkpoint'] = title
7375
elif cmd_ckpt is not None and cmd_ckpt != shared.default_sd_model_file:
7476
print(f"Checkpoint in --ckpt argument not found (Possible it was moved to {model_path}: {cmd_ckpt}", file=sys.stderr)
7577
for filename in model_list:
7678
h = model_hash(filename)
7779
title, short_model_name = modeltitle(filename, h)
7880

79-
basename, _ = os.path.splitext(filename)
81+
basename, ext = os.path.splitext(filename)
8082
config = basename + ".yaml"
8183
if not os.path.exists(config):
8284
config = shared.cmd_opts.config
8385

84-
checkpoints_list[title] = CheckpointInfo(filename, title, h, short_model_name, config)
86+
checkpoints_list[title] = CheckpointInfo(filename, title, h, short_model_name, config, ext)
8587

8688

8789
def get_closet_checkpoint_match(searchString):
@@ -173,7 +175,13 @@ def load_model_weights(model, checkpoint_info, vae_file="auto"):
173175
# load from file
174176
print(f"Loading weights [{sd_model_hash}] from {checkpoint_file}")
175177

176-
pl_sd = torch.load(checkpoint_file, map_location=shared.weight_load_location)
178+
if(checkpoint_types[checkpoint_info.exttype] == 'safetensors'):
179+
# safely load weights
180+
# TODO: safetensors supports zero copy fast load to gpu, see issue #684
181+
pl_sd = load_file(checkpoint_file, device=shared.weight_load_location)
182+
else:
183+
pl_sd = torch.load(checkpoint_file, map_location=shared.weight_load_location)
184+
177185
if "global_step" in pl_sd:
178186
print(f"Global Step: {pl_sd['global_step']}")
179187

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ kornia
2828
lark
2929
inflection
3030
GitPython
31+
safetensors

0 commit comments

Comments
 (0)