Spaces:
Sleeping
Sleeping
adamelliotfields
commited on
Commit
•
0177258
1
Parent(s):
9f665e5
Fix refiner progress
Browse files- README.md +34 -0
- lib/config.py +7 -5
- lib/inference.py +19 -10
- lib/loader.py +12 -6
README.md
CHANGED
@@ -48,3 +48,37 @@ preload_from_hub:
|
|
48 |
# diffusion-xl
|
49 |
|
50 |
Gradio app for Stable Diffusion XL.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
# diffusion-xl
|
49 |
|
50 |
Gradio app for Stable Diffusion XL.
|
51 |
+
|
52 |
+
## Usage
|
53 |
+
|
54 |
+
See [DOCS.md](https://huggingface.co/spaces/adamelliotfields/diffusion-xl/blob/main/DOCS.md).
|
55 |
+
|
56 |
+
## Installation
|
57 |
+
|
58 |
+
```sh
|
59 |
+
# clone
|
60 |
+
git clone https://huggingface.co/spaces/adamelliotfields/diffusion-xl.git
|
61 |
+
cd diffusion-xl
|
62 |
+
git remote set-url origin https://adamelliotfields:$HF_TOKEN@huggingface.co/spaces/adamelliotfields/diffusion-xl
|
63 |
+
|
64 |
+
# install
|
65 |
+
python -m venv .venv
|
66 |
+
source .venv/bin/activate
|
67 |
+
pip install -r requirements.txt
|
68 |
+
|
69 |
+
# gradio
|
70 |
+
python app.py --port 7860
|
71 |
+
```
|
72 |
+
|
73 |
+
## Development
|
74 |
+
|
75 |
+
See [pull requests and discussions](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions).
|
76 |
+
|
77 |
+
```sh
|
78 |
+
git fetch origin refs/pr/42:pr/42
|
79 |
+
git checkout pr/42
|
80 |
+
# ...
|
81 |
+
git add .
|
82 |
+
git commit -m "Commit message"
|
83 |
+
git push origin pr/42:refs/pr/42
|
84 |
+
```
|
lib/config.py
CHANGED
@@ -6,7 +6,8 @@ from diffusers import (
|
|
6 |
DPMSolverMultistepScheduler,
|
7 |
EulerAncestralDiscreteScheduler,
|
8 |
EulerDiscreteScheduler,
|
9 |
-
|
|
|
10 |
StableDiffusionXLImg2ImgPipeline,
|
11 |
StableDiffusionXLPipeline,
|
12 |
)
|
@@ -34,22 +35,23 @@ Config = SimpleNamespace(
|
|
34 |
],
|
35 |
VAE_MODEL="madebyollin/sdxl-vae-fp16-fix",
|
36 |
REFINER_MODEL="stabilityai/stable-diffusion-xl-refiner-1.0",
|
37 |
-
SCHEDULER="
|
38 |
SCHEDULERS={
|
39 |
"DDIM": DDIMScheduler,
|
40 |
"DEIS 2M": DEISMultistepScheduler,
|
41 |
"DPM++ 2M": DPMSolverMultistepScheduler,
|
|
|
|
|
42 |
"Euler": EulerDiscreteScheduler,
|
43 |
"Euler a": EulerAncestralDiscreteScheduler,
|
44 |
-
"PNDM": PNDMScheduler,
|
45 |
},
|
46 |
STYLE="sai-enhance",
|
47 |
WIDTH=896,
|
48 |
HEIGHT=1152,
|
49 |
NUM_IMAGES=1,
|
50 |
SEED=-1,
|
51 |
-
GUIDANCE_SCALE=
|
52 |
-
INFERENCE_STEPS=
|
53 |
DEEPCACHE_INTERVAL=1,
|
54 |
SCALE=1,
|
55 |
SCALES=[1, 2, 4],
|
|
|
6 |
DPMSolverMultistepScheduler,
|
7 |
EulerAncestralDiscreteScheduler,
|
8 |
EulerDiscreteScheduler,
|
9 |
+
KDPM2AncestralDiscreteScheduler,
|
10 |
+
KDPM2DiscreteScheduler,
|
11 |
StableDiffusionXLImg2ImgPipeline,
|
12 |
StableDiffusionXLPipeline,
|
13 |
)
|
|
|
35 |
],
|
36 |
VAE_MODEL="madebyollin/sdxl-vae-fp16-fix",
|
37 |
REFINER_MODEL="stabilityai/stable-diffusion-xl-refiner-1.0",
|
38 |
+
SCHEDULER="Euler",
|
39 |
SCHEDULERS={
|
40 |
"DDIM": DDIMScheduler,
|
41 |
"DEIS 2M": DEISMultistepScheduler,
|
42 |
"DPM++ 2M": DPMSolverMultistepScheduler,
|
43 |
+
"DPM2": KDPM2DiscreteScheduler,
|
44 |
+
"DPM2 a": KDPM2AncestralDiscreteScheduler,
|
45 |
"Euler": EulerDiscreteScheduler,
|
46 |
"Euler a": EulerAncestralDiscreteScheduler,
|
|
|
47 |
},
|
48 |
STYLE="sai-enhance",
|
49 |
WIDTH=896,
|
50 |
HEIGHT=1152,
|
51 |
NUM_IMAGES=1,
|
52 |
SEED=-1,
|
53 |
+
GUIDANCE_SCALE=6,
|
54 |
+
INFERENCE_STEPS=35,
|
55 |
DEEPCACHE_INTERVAL=1,
|
56 |
SCALE=1,
|
57 |
SCALES=[1, 2, 4],
|
lib/inference.py
CHANGED
@@ -91,7 +91,7 @@ def generate(
|
|
91 |
style=None,
|
92 |
seed=None,
|
93 |
model="stabilityai/stable-diffusion-xl-base-1.0",
|
94 |
-
scheduler="
|
95 |
width=1024,
|
96 |
height=1024,
|
97 |
guidance_scale=7.5,
|
@@ -100,7 +100,7 @@ def generate(
|
|
100 |
scale=1,
|
101 |
num_images=1,
|
102 |
use_karras=False,
|
103 |
-
use_refiner=
|
104 |
Info: Callable[[str], None] = None,
|
105 |
Error=Exception,
|
106 |
progress=None,
|
@@ -112,30 +112,39 @@ def generate(
|
|
112 |
if seed is None or seed < 0:
|
113 |
seed = int(datetime.now().timestamp() * 1_000_000) % (2**64)
|
114 |
|
115 |
-
EMBEDDINGS_TYPE = ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED
|
116 |
-
|
117 |
KIND = "txt2img"
|
118 |
-
|
119 |
-
CURRENT_IMAGE = 1
|
120 |
CURRENT_STEP = 0
|
|
|
|
|
121 |
|
122 |
if progress is not None:
|
123 |
TQDM = False
|
124 |
-
progress((0, inference_steps), desc=f"Generating image
|
125 |
else:
|
126 |
TQDM = True
|
127 |
|
128 |
def callback_on_step_end(pipeline, step, timestep, latents):
|
129 |
nonlocal CURRENT_IMAGE, CURRENT_STEP
|
|
|
130 |
if progress is None:
|
131 |
return latents
|
|
|
132 |
strength = 1
|
133 |
total_steps = min(int(inference_steps * strength), inference_steps)
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
progress(
|
136 |
(CURRENT_STEP, total_steps),
|
137 |
-
desc=f"Generating image {CURRENT_IMAGE}/{num_images}",
|
138 |
)
|
|
|
139 |
return latents
|
140 |
|
141 |
start = time.perf_counter()
|
@@ -150,6 +159,7 @@ def generate(
|
|
150 |
use_refiner,
|
151 |
TQDM,
|
152 |
)
|
|
|
153 |
# prompt embeds for base and refiner
|
154 |
compel_1 = Compel(
|
155 |
text_encoder=[pipe.text_encoder, pipe.text_encoder_2],
|
@@ -232,7 +242,6 @@ def generate(
|
|
232 |
|
233 |
if progress is not None:
|
234 |
refiner_kwargs["callback_on_step_end"] = callback_on_step_end
|
235 |
-
|
236 |
if use_refiner:
|
237 |
image = refiner(**refiner_kwargs).images[0]
|
238 |
if scale > 1:
|
|
|
91 |
style=None,
|
92 |
seed=None,
|
93 |
model="stabilityai/stable-diffusion-xl-base-1.0",
|
94 |
+
scheduler="DDIM",
|
95 |
width=1024,
|
96 |
height=1024,
|
97 |
guidance_scale=7.5,
|
|
|
100 |
scale=1,
|
101 |
num_images=1,
|
102 |
use_karras=False,
|
103 |
+
use_refiner=False,
|
104 |
Info: Callable[[str], None] = None,
|
105 |
Error=Exception,
|
106 |
progress=None,
|
|
|
112 |
if seed is None or seed < 0:
|
113 |
seed = int(datetime.now().timestamp() * 1_000_000) % (2**64)
|
114 |
|
|
|
|
|
115 |
KIND = "txt2img"
|
|
|
|
|
116 |
CURRENT_STEP = 0
|
117 |
+
CURRENT_IMAGE = 1
|
118 |
+
EMBEDDINGS_TYPE = ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED
|
119 |
|
120 |
if progress is not None:
|
121 |
TQDM = False
|
122 |
+
progress((0, inference_steps), desc=f"Generating image 1/{num_images}")
|
123 |
else:
|
124 |
TQDM = True
|
125 |
|
126 |
def callback_on_step_end(pipeline, step, timestep, latents):
|
127 |
nonlocal CURRENT_IMAGE, CURRENT_STEP
|
128 |
+
|
129 |
if progress is None:
|
130 |
return latents
|
131 |
+
|
132 |
strength = 1
|
133 |
total_steps = min(int(inference_steps * strength), inference_steps)
|
134 |
+
|
135 |
+
# if steps are different we're in the refiner
|
136 |
+
refining = False
|
137 |
+
if CURRENT_STEP == step:
|
138 |
+
CURRENT_STEP = step + 1
|
139 |
+
else:
|
140 |
+
refining = True
|
141 |
+
CURRENT_STEP += 1
|
142 |
+
|
143 |
progress(
|
144 |
(CURRENT_STEP, total_steps),
|
145 |
+
desc=f"{'Refining' if refining else 'Generating'} image {CURRENT_IMAGE}/{num_images}",
|
146 |
)
|
147 |
+
|
148 |
return latents
|
149 |
|
150 |
start = time.perf_counter()
|
|
|
159 |
use_refiner,
|
160 |
TQDM,
|
161 |
)
|
162 |
+
|
163 |
# prompt embeds for base and refiner
|
164 |
compel_1 = Compel(
|
165 |
text_encoder=[pipe.text_encoder, pipe.text_encoder_2],
|
|
|
242 |
|
243 |
if progress is not None:
|
244 |
refiner_kwargs["callback_on_step_end"] = callback_on_step_end
|
|
|
245 |
if use_refiner:
|
246 |
image = refiner(**refiner_kwargs).images[0]
|
247 |
if scale > 1:
|
lib/loader.py
CHANGED
@@ -53,13 +53,13 @@ class Loader:
|
|
53 |
|
54 |
def _unload(self, model, refiner, scale):
|
55 |
to_unload = []
|
56 |
-
if self._should_unload_upscaler(scale):
|
57 |
-
to_unload.append("upscaler")
|
58 |
-
if self._should_unload_refiner(refiner):
|
59 |
-
to_unload.append("refiner")
|
60 |
if self._should_unload_pipeline(model):
|
61 |
to_unload.append("model")
|
62 |
to_unload.append("pipe")
|
|
|
|
|
|
|
|
|
63 |
for component in to_unload:
|
64 |
delattr(self, component)
|
65 |
self._flush()
|
@@ -71,8 +71,13 @@ class Loader:
|
|
71 |
if self.pipe is None:
|
72 |
try:
|
73 |
print(f"Loading {model}...")
|
74 |
-
self.pipe = pipeline.from_pretrained(model, **kwargs).to("cuda")
|
75 |
self.model = model
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
except Exception as e:
|
77 |
print(f"Error loading {model}: {e}")
|
78 |
self.model = None
|
@@ -125,7 +130,7 @@ class Loader:
|
|
125 |
"steps_offset": 1,
|
126 |
}
|
127 |
|
128 |
-
if scheduler not in ["DDIM", "Euler a"
|
129 |
scheduler_kwargs["use_karras_sigmas"] = karras
|
130 |
|
131 |
# https://github.com/huggingface/diffusers/blob/8a3f0c1/scripts/convert_original_stable_diffusion_to_diffusers.py#L939
|
@@ -169,6 +174,7 @@ class Loader:
|
|
169 |
print(f"{'Enabling' if karras else 'Disabling'} Karras sigmas...")
|
170 |
if not same_scheduler or not same_karras:
|
171 |
self.pipe.scheduler = Config.SCHEDULERS[scheduler](**scheduler_kwargs)
|
|
|
172 |
|
173 |
# https://huggingface.co/stabilityai/stable-diffusion-xl-refiner-1.0/blob/main/model_index.json
|
174 |
refiner_kwargs = {
|
|
|
53 |
|
54 |
def _unload(self, model, refiner, scale):
|
55 |
to_unload = []
|
|
|
|
|
|
|
|
|
56 |
if self._should_unload_pipeline(model):
|
57 |
to_unload.append("model")
|
58 |
to_unload.append("pipe")
|
59 |
+
if self._should_unload_refiner(refiner):
|
60 |
+
to_unload.append("refiner")
|
61 |
+
if self._should_unload_upscaler(scale):
|
62 |
+
to_unload.append("upscaler")
|
63 |
for component in to_unload:
|
64 |
delattr(self, component)
|
65 |
self._flush()
|
|
|
71 |
if self.pipe is None:
|
72 |
try:
|
73 |
print(f"Loading {model}...")
|
|
|
74 |
self.model = model
|
75 |
+
self.pipe = pipeline.from_pretrained(model, **kwargs).to("cuda")
|
76 |
+
if self.refiner is not None:
|
77 |
+
self.refiner.vae = self.pipe.vae
|
78 |
+
self.refiner.scheduler = self.pipe.scheduler
|
79 |
+
self.refiner.tokenizer_2 = self.pipe.tokenizer_2
|
80 |
+
self.refiner.text_encoder_2 = self.pipe.text_encoder_2
|
81 |
except Exception as e:
|
82 |
print(f"Error loading {model}: {e}")
|
83 |
self.model = None
|
|
|
130 |
"steps_offset": 1,
|
131 |
}
|
132 |
|
133 |
+
if scheduler not in ["DDIM", "Euler a"]:
|
134 |
scheduler_kwargs["use_karras_sigmas"] = karras
|
135 |
|
136 |
# https://github.com/huggingface/diffusers/blob/8a3f0c1/scripts/convert_original_stable_diffusion_to_diffusers.py#L939
|
|
|
174 |
print(f"{'Enabling' if karras else 'Disabling'} Karras sigmas...")
|
175 |
if not same_scheduler or not same_karras:
|
176 |
self.pipe.scheduler = Config.SCHEDULERS[scheduler](**scheduler_kwargs)
|
177 |
+
self.refiner.scheduler = self.pipe.scheduler
|
178 |
|
179 |
# https://huggingface.co/stabilityai/stable-diffusion-xl-refiner-1.0/blob/main/model_index.json
|
180 |
refiner_kwargs = {
|