Spaces:
Running
on
Zero
Running
on
Zero
File size: 6,687 Bytes
cb5daed 4d6f2bc 48c31e7 4d6f2bc 48c31e7 4d6f2bc 05246f1 1128e78 cb5daed 1128e78 4d6f2bc dffd0bb 4d6f2bc 1128e78 05246f1 4d6f2bc 05246f1 b7fd57e 22a0476 b7fd57e c348e53 22a0476 b7fd57e 48c31e7 b7fd57e 48c31e7 22a0476 b7fd57e 22a0476 b7fd57e 22a0476 b7fd57e 48c31e7 c348e53 4d6f2bc 1128e78 4d6f2bc 1128e78 48c31e7 4d6f2bc cb5daed 4d6f2bc 22a0476 1128e78 48c31e7 4d6f2bc 48c31e7 22a0476 4d6f2bc 1128e78 4d6f2bc 1128e78 48c31e7 1128e78 48c31e7 1128e78 22a0476 c348e53 05246f1 1128e78 48c31e7 22a0476 c348e53 22a0476 05246f1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
import os
import torch
from DeepCache import DeepCacheSDHelper
from diffusers import (
DEISMultistepScheduler,
DPMSolverMultistepScheduler,
EulerAncestralDiscreteScheduler,
HeunDiscreteScheduler,
KDPM2AncestralDiscreteScheduler,
LMSDiscreteScheduler,
PNDMScheduler,
StableDiffusionPipeline,
)
from diffusers.models import AutoencoderKL, AutoencoderTiny
from torch._dynamo import OptimizedModule
from .upscaler import RealESRGAN
ZERO_GPU = (
os.environ.get("SPACES_ZERO_GPU", "").lower() == "true"
or os.environ.get("SPACES_ZERO_GPU", "") == "1"
)
# inspired by ComfyUI
# https://github.com/comfyanonymous/ComfyUI/blob/master/comfy/model_management.py
class Loader:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(Loader, cls).__new__(cls)
cls._instance.pipe = None
cls._instance.upscaler = None
return cls._instance
def _load_upscaler(self, device=None, scale=4):
same_scale = self.upscaler is not None and self.upscaler.scale == scale
if scale == 1:
self.upscaler = None
if scale > 1 and not same_scale:
self.upscaler = RealESRGAN(device=device, scale=scale)
self.upscaler.load_weights()
def _load_deepcache(self, interval=1):
has_deepcache = hasattr(self.pipe, "deepcache")
if has_deepcache and self.pipe.deepcache.params["cache_interval"] == interval:
return
if has_deepcache:
self.pipe.deepcache.disable()
else:
self.pipe.deepcache = DeepCacheSDHelper(pipe=self.pipe)
self.pipe.deepcache.set_params(cache_interval=interval)
self.pipe.deepcache.enable()
def _load_freeu(self, freeu=False):
# https://github.com/huggingface/diffusers/blob/v0.30.0/src/diffusers/models/unets/unet_2d_condition.py
block = self.pipe.unet.up_blocks[0]
attrs = ["b1", "b2", "s1", "s2"]
has_freeu = all(getattr(block, attr, None) is not None for attr in attrs)
if has_freeu and not freeu:
self.pipe.disable_freeu()
elif not has_freeu and freeu:
# https://github.com/ChenyangSi/FreeU
self.pipe.enable_freeu(b1=1.5, b2=1.6, s1=0.9, s2=0.2)
def _load_vae(self, model_name=None, taesd=False, variant=None):
vae_type = type(self.pipe.vae)
is_kl = issubclass(vae_type, (AutoencoderKL, OptimizedModule))
is_tiny = issubclass(vae_type, AutoencoderTiny)
# by default all models use KL
if is_kl and taesd:
# can't compile tiny VAE
print("Switching to Tiny VAE...")
self.pipe.vae = AutoencoderTiny.from_pretrained(
pretrained_model_name_or_path="madebyollin/taesd",
use_safetensors=True,
).to(device=self.pipe.device)
return
if is_tiny and not taesd:
print("Switching to KL VAE...")
model = AutoencoderKL.from_pretrained(
pretrained_model_name_or_path=model_name,
use_safetensors=True,
subfolder="vae",
variant=variant,
).to(device=self.pipe.device)
self.pipe.vae = torch.compile(
mode="reduce-overhead",
fullgraph=True,
model=model,
)
def load(
self,
model,
scheduler,
karras,
taesd,
freeu,
deepcache_interval,
scale,
dtype,
device,
):
model_lower = model.lower()
schedulers = {
"DEIS 2M": DEISMultistepScheduler,
"DPM++ 2M": DPMSolverMultistepScheduler,
"DPM2 a": KDPM2AncestralDiscreteScheduler,
"Euler a": EulerAncestralDiscreteScheduler,
"Heun": HeunDiscreteScheduler,
"LMS": LMSDiscreteScheduler,
"PNDM": PNDMScheduler,
}
scheduler_kwargs = {
"beta_schedule": "scaled_linear",
"timestep_spacing": "leading",
"use_karras_sigmas": karras,
"beta_start": 0.00085,
"beta_end": 0.012,
"steps_offset": 1,
}
if scheduler in ["Euler a", "PNDM"]:
del scheduler_kwargs["use_karras_sigmas"]
# no fp16 variant
if not ZERO_GPU and model_lower not in [
"sg161222/realistic_vision_v5.1_novae",
"prompthero/openjourney-v4",
"linaqruf/anything-v3-1",
]:
variant = "fp16"
else:
variant = None
pipe_kwargs = {
"scheduler": schedulers[scheduler](**scheduler_kwargs),
"pretrained_model_name_or_path": model_lower,
"requires_safety_checker": False,
"use_safetensors": True,
"safety_checker": None,
"variant": variant,
}
# already loaded
if self.pipe is not None:
model_name = self.pipe.config._name_or_path
same_model = model_name.lower() == model_lower
same_scheduler = isinstance(self.pipe.scheduler, schedulers[scheduler])
same_karras = (
not hasattr(self.pipe.scheduler.config, "use_karras_sigmas")
or self.pipe.scheduler.config.use_karras_sigmas == karras
)
if same_model:
if not same_scheduler:
print(f"Switching to {scheduler}...")
if not same_karras:
print(f"{'Enabling' if karras else 'Disabling'} Karras sigmas...")
if not same_scheduler or not same_karras:
self.pipe.scheduler = schedulers[scheduler](**scheduler_kwargs)
self._load_vae(model_lower, taesd, variant)
self._load_freeu(freeu)
self._load_deepcache(deepcache_interval)
self._load_upscaler(device, scale)
torch.cuda.empty_cache()
return self.pipe, self.upscaler
else:
print(f"Unloading {model_name.lower()}...")
self.pipe = None
print(f"Loading {model_lower} with {'Tiny' if taesd else 'KL'} VAE...")
self.pipe = StableDiffusionPipeline.from_pretrained(**pipe_kwargs).to(
device=device,
dtype=dtype,
)
self._load_vae(model_lower, taesd, variant)
self._load_freeu(freeu)
self._load_deepcache(deepcache_interval)
self._load_upscaler(device, scale)
torch.cuda.empty_cache()
return self.pipe, self.upscaler
|