Spaces:
Running
Running
App update
Browse files- app.py +109 -9
- app_settings.py +23 -0
- backend/__pycache__/__init__.cpython-311.pyc +0 -0
- backend/__pycache__/image_saver.cpython-311.pyc +0 -0
- backend/__pycache__/lcm_text_to_image.cpython-311.pyc +0 -0
- backend/lcm_text_to_image.py +256 -44
- backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc +0 -0
- backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc +0 -0
- backend/lcmdiffusion/pipelines/openvino/lcm_ov_pipeline.py +86 -29
- backend/lcmdiffusion/pipelines/openvino/lcm_scheduler.py +67 -20
- backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc +0 -0
- backend/models/lcmdiffusion_setting.py +15 -5
- constants.py +8 -2
- context.py +13 -8
- frontend/__pycache__/utils.cpython-311.pyc +0 -0
- frontend/gui/__pycache__/app_window.cpython-311.pyc +0 -0
- frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc +0 -0
- frontend/gui/__pycache__/ui.cpython-311.pyc +0 -0
- frontend/gui/app_window.py +177 -22
- frontend/utils.py +22 -4
- frontend/webui/text_to_image_ui.py +41 -49
- frontend/webui/ui.py +2 -2
- models/__pycache__/interface_types.cpython-311.pyc +0 -0
- models/__pycache__/settings.cpython-311.pyc +0 -0
- models/settings.py +2 -2
- paths.py +11 -2
- utils.py +11 -0
app.py
CHANGED
@@ -6,7 +6,7 @@ from context import Context
|
|
6 |
from constants import APP_VERSION, LCM_DEFAULT_MODEL_OPENVINO
|
7 |
from models.interface_types import InterfaceType
|
8 |
from constants import DEVICE
|
9 |
-
|
10 |
parser = ArgumentParser(description=f"FAST SD CPU {constants.APP_VERSION}")
|
11 |
parser.add_argument(
|
12 |
"-s",
|
@@ -28,6 +28,12 @@ group.add_argument(
|
|
28 |
action="store_true",
|
29 |
help="Start Web UI",
|
30 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
group.add_argument(
|
32 |
"-v",
|
33 |
"--version",
|
@@ -66,8 +72,8 @@ parser.add_argument(
|
|
66 |
parser.add_argument(
|
67 |
"--guidance_scale",
|
68 |
type=int,
|
69 |
-
help="Guidance scale,default :
|
70 |
-
default=
|
71 |
)
|
72 |
|
73 |
parser.add_argument(
|
@@ -98,28 +104,122 @@ parser.add_argument(
|
|
98 |
action="store_false",
|
99 |
help="Use safety checker",
|
100 |
)
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
parser.add_argument(
|
103 |
"-i",
|
104 |
"--interactive",
|
105 |
action="store_true",
|
106 |
help="Interactive CLI mode",
|
107 |
)
|
108 |
-
|
|
|
|
|
|
|
|
|
109 |
args = parser.parse_args()
|
110 |
|
111 |
if args.version:
|
112 |
print(APP_VERSION)
|
113 |
exit()
|
114 |
|
115 |
-
parser.print_help()
|
116 |
show_system_info()
|
117 |
print(f"Using device : {constants.DEVICE}")
|
118 |
-
|
119 |
app_settings = AppSettings()
|
120 |
app_settings.load()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
123 |
-
|
|
|
124 |
app_settings,
|
125 |
-
args.share,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
from constants import APP_VERSION, LCM_DEFAULT_MODEL_OPENVINO
|
7 |
from models.interface_types import InterfaceType
|
8 |
from constants import DEVICE
|
9 |
+
|
10 |
parser = ArgumentParser(description=f"FAST SD CPU {constants.APP_VERSION}")
|
11 |
parser.add_argument(
|
12 |
"-s",
|
|
|
28 |
action="store_true",
|
29 |
help="Start Web UI",
|
30 |
)
|
31 |
+
group.add_argument(
|
32 |
+
"-r",
|
33 |
+
"--realtime",
|
34 |
+
action="store_true",
|
35 |
+
help="Start realtime inference UI(experimental)",
|
36 |
+
)
|
37 |
group.add_argument(
|
38 |
"-v",
|
39 |
"--version",
|
|
|
72 |
parser.add_argument(
|
73 |
"--guidance_scale",
|
74 |
type=int,
|
75 |
+
help="Guidance scale,default : 1.0",
|
76 |
+
default=1.0,
|
77 |
)
|
78 |
|
79 |
parser.add_argument(
|
|
|
104 |
action="store_false",
|
105 |
help="Use safety checker",
|
106 |
)
|
107 |
+
parser.add_argument(
|
108 |
+
"--use_lcm_lora",
|
109 |
+
action="store_true",
|
110 |
+
help="Use LCM-LoRA",
|
111 |
+
)
|
112 |
+
parser.add_argument(
|
113 |
+
"--base_model_id",
|
114 |
+
type=str,
|
115 |
+
help="LCM LoRA base model ID,Default Lykon/dreamshaper-8",
|
116 |
+
default="Lykon/dreamshaper-8",
|
117 |
+
)
|
118 |
+
parser.add_argument(
|
119 |
+
"--lcm_lora_id",
|
120 |
+
type=str,
|
121 |
+
help="LCM LoRA model ID,Default latent-consistency/lcm-lora-sdv1-5",
|
122 |
+
default="latent-consistency/lcm-lora-sdv1-5",
|
123 |
+
)
|
124 |
parser.add_argument(
|
125 |
"-i",
|
126 |
"--interactive",
|
127 |
action="store_true",
|
128 |
help="Interactive CLI mode",
|
129 |
)
|
130 |
+
parser.add_argument(
|
131 |
+
"--use_tiny_auto_encoder",
|
132 |
+
action="store_true",
|
133 |
+
help="Use tiny auto encoder for SD (TAESD)",
|
134 |
+
)
|
135 |
args = parser.parse_args()
|
136 |
|
137 |
if args.version:
|
138 |
print(APP_VERSION)
|
139 |
exit()
|
140 |
|
141 |
+
# parser.print_help()
|
142 |
show_system_info()
|
143 |
print(f"Using device : {constants.DEVICE}")
|
|
|
144 |
app_settings = AppSettings()
|
145 |
app_settings.load()
|
146 |
+
print(
|
147 |
+
f"Found {len(app_settings.stable_diffsuion_models)} stable diffusion models in config/stable-diffusion-models.txt"
|
148 |
+
)
|
149 |
+
print(
|
150 |
+
f"Found {len(app_settings.lcm_lora_models)} LCM-LoRA models in config/lcm-lora-models.txt"
|
151 |
+
)
|
152 |
+
print(
|
153 |
+
f"Found {len(app_settings.openvino_lcm_models)} OpenVINO LCM models in config/openvino-lcm-models.txt"
|
154 |
+
)
|
155 |
+
if args.gui:
|
156 |
+
from frontend.gui.ui import start_gui
|
157 |
|
158 |
+
print("Starting desktop GUI mode(Qt)")
|
159 |
+
start_gui(
|
160 |
+
[],
|
161 |
+
app_settings,
|
162 |
+
)
|
163 |
+
elif args.webui:
|
164 |
+
from frontend.webui.ui import start_webui
|
165 |
|
166 |
+
print("Starting web UI mode")
|
167 |
+
start_webui(
|
168 |
app_settings,
|
169 |
+
args.share,
|
170 |
+
)
|
171 |
+
elif args.realtime:
|
172 |
+
from frontend.webui.realtime_ui import start_realtime_text_to_image
|
173 |
+
|
174 |
+
print("Starting realtime text to image(EXPERIMENTAL)")
|
175 |
+
start_realtime_text_to_image(args.share)
|
176 |
+
else:
|
177 |
+
context = Context(InterfaceType.CLI)
|
178 |
+
config = app_settings.settings
|
179 |
+
|
180 |
+
if args.use_openvino:
|
181 |
+
config.lcm_diffusion_setting.lcm_model_id = LCM_DEFAULT_MODEL_OPENVINO
|
182 |
+
else:
|
183 |
+
config.lcm_diffusion_setting.lcm_model_id = args.lcm_model_id
|
184 |
+
|
185 |
+
config.lcm_diffusion_setting.prompt = args.prompt
|
186 |
+
config.lcm_diffusion_setting.image_height = args.image_height
|
187 |
+
config.lcm_diffusion_setting.image_width = args.image_width
|
188 |
+
config.lcm_diffusion_setting.guidance_scale = args.guidance_scale
|
189 |
+
config.lcm_diffusion_setting.number_of_images = args.number_of_images
|
190 |
+
config.lcm_diffusion_setting.seed = args.seed
|
191 |
+
config.lcm_diffusion_setting.use_openvino = args.use_openvino
|
192 |
+
config.lcm_diffusion_setting.use_tiny_auto_encoder = args.use_tiny_auto_encoder
|
193 |
+
config.lcm_diffusion_setting.use_lcm_lora = args.use_lcm_lora
|
194 |
+
config.lcm_diffusion_setting.lcm_lora.base_model_id = args.base_model_id
|
195 |
+
config.lcm_diffusion_setting.lcm_lora.lcm_lora_id = args.lcm_lora_id
|
196 |
+
|
197 |
+
if args.seed > -1:
|
198 |
+
config.lcm_diffusion_setting.use_seed = True
|
199 |
+
else:
|
200 |
+
config.lcm_diffusion_setting.use_seed = False
|
201 |
+
config.lcm_diffusion_setting.use_offline_model = args.use_offline_model
|
202 |
+
config.lcm_diffusion_setting.use_safety_checker = args.use_safety_checker
|
203 |
+
|
204 |
+
if args.interactive:
|
205 |
+
while True:
|
206 |
+
user_input = input(">>")
|
207 |
+
if user_input == "exit":
|
208 |
+
break
|
209 |
+
config.lcm_diffusion_setting.prompt = user_input
|
210 |
+
context.generate_text_to_image(
|
211 |
+
settings=config,
|
212 |
+
device=DEVICE,
|
213 |
+
)
|
214 |
+
|
215 |
+
else:
|
216 |
+
context.generate_text_to_image(
|
217 |
+
settings=config,
|
218 |
+
device=DEVICE,
|
219 |
+
)
|
220 |
+
|
221 |
+
|
222 |
+
from frontend.webui.hf_demo import start_demo_text_to_image
|
223 |
+
|
224 |
+
print("Starting demo text to image")
|
225 |
+
start_demo_text_to_image(True)
|
app_settings.py
CHANGED
@@ -2,16 +2,39 @@ import yaml
|
|
2 |
from os import path, makedirs
|
3 |
from models.settings import Settings
|
4 |
from paths import FastStableDiffusionPaths
|
|
|
|
|
5 |
|
6 |
|
7 |
class AppSettings:
|
8 |
def __init__(self):
|
9 |
self.config_path = FastStableDiffusionPaths().get_app_settings_path()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
@property
|
12 |
def settings(self):
|
13 |
return self._config
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
def load(self):
|
16 |
if not path.exists(self.config_path):
|
17 |
base_dir = path.dirname(self.config_path)
|
|
|
2 |
from os import path, makedirs
|
3 |
from models.settings import Settings
|
4 |
from paths import FastStableDiffusionPaths
|
5 |
+
from utils import get_models_from_text_file
|
6 |
+
from constants import OPENVINO_LCM_MODELS_FILE, LCM_LORA_MODELS_FILE, SD_MODELS_FILE
|
7 |
|
8 |
|
9 |
class AppSettings:
|
10 |
def __init__(self):
|
11 |
self.config_path = FastStableDiffusionPaths().get_app_settings_path()
|
12 |
+
self._stable_diffsuion_models = get_models_from_text_file(
|
13 |
+
FastStableDiffusionPaths().get_models_config_path(SD_MODELS_FILE)
|
14 |
+
)
|
15 |
+
self._lcm_lora_models = get_models_from_text_file(
|
16 |
+
FastStableDiffusionPaths().get_models_config_path(LCM_LORA_MODELS_FILE)
|
17 |
+
)
|
18 |
+
self._openvino_lcm_models = get_models_from_text_file(
|
19 |
+
FastStableDiffusionPaths().get_models_config_path(OPENVINO_LCM_MODELS_FILE)
|
20 |
+
)
|
21 |
|
22 |
@property
|
23 |
def settings(self):
|
24 |
return self._config
|
25 |
|
26 |
+
@property
|
27 |
+
def stable_diffsuion_models(self):
|
28 |
+
return self._stable_diffsuion_models
|
29 |
+
|
30 |
+
@property
|
31 |
+
def openvino_lcm_models(self):
|
32 |
+
return self._openvino_lcm_models
|
33 |
+
|
34 |
+
@property
|
35 |
+
def lcm_lora_models(self):
|
36 |
+
return self._lcm_lora_models
|
37 |
+
|
38 |
def load(self):
|
39 |
if not path.exists(self.config_path):
|
40 |
base_dir = path.dirname(self.config_path)
|
backend/__pycache__/__init__.cpython-311.pyc
CHANGED
Binary files a/backend/__pycache__/__init__.cpython-311.pyc and b/backend/__pycache__/__init__.cpython-311.pyc differ
|
|
backend/__pycache__/image_saver.cpython-311.pyc
CHANGED
Binary files a/backend/__pycache__/image_saver.cpython-311.pyc and b/backend/__pycache__/image_saver.cpython-311.pyc differ
|
|
backend/__pycache__/lcm_text_to_image.cpython-311.pyc
CHANGED
Binary files a/backend/__pycache__/lcm_text_to_image.cpython-311.pyc and b/backend/__pycache__/lcm_text_to_image.cpython-311.pyc differ
|
|
backend/lcm_text_to_image.py
CHANGED
@@ -1,20 +1,53 @@
|
|
1 |
from typing import Any
|
2 |
-
from diffusers import
|
|
|
|
|
|
|
|
|
|
|
3 |
from os import path
|
4 |
import torch
|
5 |
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting
|
6 |
import numpy as np
|
7 |
-
from constants import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
9 |
|
10 |
-
|
11 |
from backend.lcmdiffusion.pipelines.openvino.lcm_ov_pipeline import (
|
12 |
-
|
13 |
)
|
14 |
from backend.lcmdiffusion.pipelines.openvino.lcm_scheduler import (
|
15 |
-
LCMScheduler,
|
16 |
)
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
class LCMTextToImage:
|
20 |
def __init__(
|
@@ -23,18 +56,125 @@ class LCMTextToImage:
|
|
23 |
) -> None:
|
24 |
self.pipeline = None
|
25 |
self.use_openvino = False
|
26 |
-
self.device =
|
27 |
self.previous_model_id = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
)
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
def init(
|
40 |
self,
|
@@ -42,44 +182,97 @@ class LCMTextToImage:
|
|
42 |
use_openvino: bool = False,
|
43 |
device: str = "cpu",
|
44 |
use_local_model: bool = False,
|
|
|
|
|
|
|
45 |
) -> None:
|
46 |
self.device = device
|
47 |
self.use_openvino = use_openvino
|
48 |
-
if
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
if self.pipeline:
|
51 |
del self.pipeline
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
)
|
56 |
-
self.pipeline = OVLatentConsistencyModelPipeline.from_pretrained(
|
57 |
model_id,
|
58 |
-
scheduler=scheduler,
|
59 |
-
compile=False,
|
60 |
local_files_only=use_local_model,
|
|
|
|
|
61 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
else:
|
63 |
if self.pipeline:
|
64 |
del self.pipeline
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
-
self.pipeline = DiffusionPipeline.from_pretrained(
|
67 |
-
model_id,
|
68 |
-
custom_pipeline=self._get_lcm_diffusion_pipeline_path(),
|
69 |
-
custom_revision="main",
|
70 |
-
local_files_only=use_local_model,
|
71 |
-
)
|
72 |
-
self.pipeline.to(
|
73 |
-
torch_device=self.device,
|
74 |
-
torch_dtype=torch.float32,
|
75 |
-
)
|
76 |
self.previous_model_id = model_id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
def generate(
|
79 |
self,
|
80 |
lcm_diffusion_setting: LCMDiffusionSetting,
|
81 |
reshape: bool = False,
|
82 |
) -> Any:
|
|
|
83 |
if lcm_diffusion_setting.use_seed:
|
84 |
cur_seed = lcm_diffusion_setting.seed
|
85 |
if self.use_openvino:
|
@@ -87,12 +280,12 @@ class LCMTextToImage:
|
|
87 |
else:
|
88 |
torch.manual_seed(cur_seed)
|
89 |
|
90 |
-
if
|
91 |
print("Using OpenVINO")
|
92 |
if reshape:
|
93 |
print("Reshape and compile")
|
94 |
self.pipeline.reshape(
|
95 |
-
batch_size
|
96 |
height=lcm_diffusion_setting.image_height,
|
97 |
width=lcm_diffusion_setting.image_width,
|
98 |
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
@@ -102,14 +295,33 @@ class LCMTextToImage:
|
|
102 |
if not lcm_diffusion_setting.use_safety_checker:
|
103 |
self.pipeline.safety_checker = None
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
return result_images
|
|
|
1 |
from typing import Any
|
2 |
+
from diffusers import (
|
3 |
+
DiffusionPipeline,
|
4 |
+
AutoencoderTiny,
|
5 |
+
LCMScheduler,
|
6 |
+
UNet2DConditionModel,
|
7 |
+
)
|
8 |
from os import path
|
9 |
import torch
|
10 |
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting
|
11 |
import numpy as np
|
12 |
+
from constants import (
|
13 |
+
DEVICE,
|
14 |
+
LCM_DEFAULT_MODEL,
|
15 |
+
TAESD_MODEL,
|
16 |
+
TAESDXL_MODEL,
|
17 |
+
TAESD_MODEL_OPENVINO,
|
18 |
+
)
|
19 |
+
from huggingface_hub import model_info
|
20 |
+
from backend.models.lcmdiffusion_setting import LCMLora
|
21 |
+
from backend.device import is_openvino_device
|
22 |
|
23 |
+
if is_openvino_device():
|
24 |
+
from huggingface_hub import snapshot_download
|
25 |
+
from optimum.intel.openvino.modeling_diffusion import OVModelVaeDecoder, OVBaseModel
|
26 |
|
27 |
+
# from optimum.intel.openvino.modeling_diffusion import OVStableDiffusionPipeline
|
28 |
from backend.lcmdiffusion.pipelines.openvino.lcm_ov_pipeline import (
|
29 |
+
OVStableDiffusionPipeline,
|
30 |
)
|
31 |
from backend.lcmdiffusion.pipelines.openvino.lcm_scheduler import (
|
32 |
+
LCMScheduler as OpenVinoLCMscheduler,
|
33 |
)
|
34 |
|
35 |
+
class CustomOVModelVaeDecoder(OVModelVaeDecoder):
|
36 |
+
def __init__(
|
37 |
+
self,
|
38 |
+
model,
|
39 |
+
parent_model,
|
40 |
+
ov_config=None,
|
41 |
+
model_dir=None,
|
42 |
+
):
|
43 |
+
super(OVModelVaeDecoder, self).__init__(
|
44 |
+
model,
|
45 |
+
parent_model,
|
46 |
+
ov_config,
|
47 |
+
"vae_decoder",
|
48 |
+
model_dir,
|
49 |
+
)
|
50 |
+
|
51 |
|
52 |
class LCMTextToImage:
|
53 |
def __init__(
|
|
|
56 |
) -> None:
|
57 |
self.pipeline = None
|
58 |
self.use_openvino = False
|
59 |
+
self.device = ""
|
60 |
self.previous_model_id = None
|
61 |
+
self.previous_use_tae_sd = False
|
62 |
+
self.previous_use_lcm_lora = False
|
63 |
+
self.torch_data_type = (
|
64 |
+
torch.float32 if is_openvino_device() or DEVICE == "mps" else torch.float16
|
65 |
+
)
|
66 |
+
print(f"Torch datatype : {self.torch_data_type}")
|
67 |
+
|
68 |
+
def _get_lcm_pipeline(
|
69 |
+
self,
|
70 |
+
lcm_model_id: str,
|
71 |
+
base_model_id: str,
|
72 |
+
use_local_model: bool,
|
73 |
+
):
|
74 |
+
pipeline = None
|
75 |
+
unet = UNet2DConditionModel.from_pretrained(
|
76 |
+
lcm_model_id,
|
77 |
+
torch_dtype=torch.float32,
|
78 |
+
local_files_only=use_local_model
|
79 |
+
# resume_download=True,
|
80 |
+
)
|
81 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
82 |
+
base_model_id,
|
83 |
+
unet=unet,
|
84 |
+
torch_dtype=torch.float32,
|
85 |
+
local_files_only=use_local_model
|
86 |
+
# resume_download=True,
|
87 |
+
)
|
88 |
+
pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config)
|
89 |
+
return pipeline
|
90 |
+
|
91 |
+
def get_tiny_decoder_vae_model(self) -> str:
|
92 |
+
pipeline_class = self.pipeline.__class__.__name__
|
93 |
+
print(f"Pipeline class : {pipeline_class}")
|
94 |
+
if (
|
95 |
+
pipeline_class == "LatentConsistencyModelPipeline"
|
96 |
+
or pipeline_class == "StableDiffusionPipeline"
|
97 |
+
):
|
98 |
+
return TAESD_MODEL
|
99 |
+
elif pipeline_class == "StableDiffusionXLPipeline":
|
100 |
+
return TAESDXL_MODEL
|
101 |
+
elif pipeline_class == "OVStableDiffusionPipeline":
|
102 |
+
return TAESD_MODEL_OPENVINO
|
103 |
+
|
104 |
+
def _get_lcm_model_pipeline(
|
105 |
+
self,
|
106 |
+
model_id: str,
|
107 |
+
use_local_model,
|
108 |
+
):
|
109 |
+
pipeline = None
|
110 |
+
if model_id == LCM_DEFAULT_MODEL:
|
111 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
112 |
+
model_id,
|
113 |
+
local_files_only=use_local_model,
|
114 |
+
)
|
115 |
+
elif model_id == "latent-consistency/lcm-sdxl":
|
116 |
+
pipeline = self._get_lcm_pipeline(
|
117 |
+
model_id,
|
118 |
+
"stabilityai/stable-diffusion-xl-base-1.0",
|
119 |
+
use_local_model,
|
120 |
+
)
|
121 |
|
122 |
+
elif model_id == "latent-consistency/lcm-ssd-1b":
|
123 |
+
pipeline = self._get_lcm_pipeline(
|
124 |
+
model_id,
|
125 |
+
"segmind/SSD-1B",
|
126 |
+
use_local_model,
|
127 |
+
)
|
128 |
+
return pipeline
|
129 |
+
|
130 |
+
def _get_lcm_lora_pipeline(
|
131 |
+
self,
|
132 |
+
base_model_id: str,
|
133 |
+
lcm_lora_id: str,
|
134 |
+
use_local_model: bool,
|
135 |
+
):
|
136 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
137 |
+
base_model_id,
|
138 |
+
torch_dtype=self.torch_data_type,
|
139 |
+
local_files_only=use_local_model,
|
140 |
)
|
141 |
+
pipeline.load_lora_weights(
|
142 |
+
lcm_lora_id,
|
143 |
+
local_files_only=use_local_model,
|
144 |
+
)
|
145 |
+
|
146 |
+
pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config)
|
147 |
+
|
148 |
+
pipeline.fuse_lora()
|
149 |
+
pipeline.unet.to(memory_format=torch.channels_last)
|
150 |
+
return pipeline
|
151 |
+
|
152 |
+
def _pipeline_to_device(self):
|
153 |
+
print(f"Pipeline device : {DEVICE}")
|
154 |
+
print(f"Pipeline dtype : {self.torch_data_type}")
|
155 |
+
self.pipeline.to(
|
156 |
+
torch_device=DEVICE,
|
157 |
+
torch_dtype=self.torch_data_type,
|
158 |
+
)
|
159 |
+
|
160 |
+
def _add_freeu(self):
|
161 |
+
pipeline_class = self.pipeline.__class__.__name__
|
162 |
+
if pipeline_class == "StableDiffusionPipeline":
|
163 |
+
print("Add FreeU - SD")
|
164 |
+
self.pipeline.enable_freeu(
|
165 |
+
s1=0.9,
|
166 |
+
s2=0.2,
|
167 |
+
b1=1.2,
|
168 |
+
b2=1.4,
|
169 |
+
)
|
170 |
+
elif pipeline_class == "StableDiffusionXLPipeline":
|
171 |
+
print("Add FreeU - SDXL")
|
172 |
+
self.pipeline.enable_freeu(
|
173 |
+
s1=0.6,
|
174 |
+
s2=0.4,
|
175 |
+
b1=1.1,
|
176 |
+
b2=1.2,
|
177 |
+
)
|
178 |
|
179 |
def init(
|
180 |
self,
|
|
|
182 |
use_openvino: bool = False,
|
183 |
device: str = "cpu",
|
184 |
use_local_model: bool = False,
|
185 |
+
use_tiny_auto_encoder: bool = False,
|
186 |
+
use_lora: bool = False,
|
187 |
+
lcm_lora: LCMLora = LCMLora(),
|
188 |
) -> None:
|
189 |
self.device = device
|
190 |
self.use_openvino = use_openvino
|
191 |
+
if (
|
192 |
+
self.pipeline is None
|
193 |
+
or self.previous_model_id != model_id
|
194 |
+
or self.previous_use_tae_sd != use_tiny_auto_encoder
|
195 |
+
or self.previous_lcm_lora_base_id != lcm_lora.base_model_id
|
196 |
+
or self.previous_lcm_lora_id != lcm_lora.lcm_lora_id
|
197 |
+
or self.previous_use_lcm_lora != use_lora
|
198 |
+
):
|
199 |
+
if self.use_openvino and is_openvino_device():
|
200 |
if self.pipeline:
|
201 |
del self.pipeline
|
202 |
+
self.pipeline = None
|
203 |
+
|
204 |
+
self.pipeline = OVStableDiffusionPipeline.from_pretrained(
|
|
|
|
|
205 |
model_id,
|
|
|
|
|
206 |
local_files_only=use_local_model,
|
207 |
+
ov_config={"CACHE_DIR": ""},
|
208 |
+
device=DEVICE.upper(),
|
209 |
)
|
210 |
+
|
211 |
+
if use_tiny_auto_encoder:
|
212 |
+
print("Using Tiny Auto Encoder (OpenVINO)")
|
213 |
+
taesd_dir = snapshot_download(
|
214 |
+
repo_id=self.get_tiny_decoder_vae_model(),
|
215 |
+
local_files_only=use_local_model,
|
216 |
+
)
|
217 |
+
self.pipeline.vae_decoder = CustomOVModelVaeDecoder(
|
218 |
+
model=OVBaseModel.load_model(
|
219 |
+
f"{taesd_dir}/vae_decoder/openvino_model.xml"
|
220 |
+
),
|
221 |
+
parent_model=self.pipeline,
|
222 |
+
model_dir=taesd_dir,
|
223 |
+
)
|
224 |
+
|
225 |
else:
|
226 |
if self.pipeline:
|
227 |
del self.pipeline
|
228 |
+
self.pipeline = None
|
229 |
+
|
230 |
+
if use_lora:
|
231 |
+
print("Init LCM-LoRA pipeline")
|
232 |
+
self.pipeline = self._get_lcm_lora_pipeline(
|
233 |
+
lcm_lora.base_model_id,
|
234 |
+
lcm_lora.lcm_lora_id,
|
235 |
+
use_local_model,
|
236 |
+
)
|
237 |
+
else:
|
238 |
+
print("Init LCM Model pipeline")
|
239 |
+
self.pipeline = self._get_lcm_model_pipeline(
|
240 |
+
model_id,
|
241 |
+
use_local_model,
|
242 |
+
)
|
243 |
+
|
244 |
+
if use_tiny_auto_encoder:
|
245 |
+
vae_model = self.get_tiny_decoder_vae_model()
|
246 |
+
print(f"Using Tiny Auto Encoder {vae_model}")
|
247 |
+
self.pipeline.vae = AutoencoderTiny.from_pretrained(
|
248 |
+
vae_model,
|
249 |
+
torch_dtype=torch.float32,
|
250 |
+
local_files_only=use_local_model,
|
251 |
+
)
|
252 |
+
|
253 |
+
self._pipeline_to_device()
|
254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
self.previous_model_id = model_id
|
256 |
+
self.previous_use_tae_sd = use_tiny_auto_encoder
|
257 |
+
self.previous_lcm_lora_base_id = lcm_lora.base_model_id
|
258 |
+
self.previous_lcm_lora_id = lcm_lora.lcm_lora_id
|
259 |
+
self.previous_use_lcm_lora = use_lora
|
260 |
+
print(f"Model :{model_id}")
|
261 |
+
print(f"Pipeline : {self.pipeline}")
|
262 |
+
self.pipeline.scheduler = LCMScheduler.from_config(
|
263 |
+
self.pipeline.scheduler.config,
|
264 |
+
beta_start=0.001,
|
265 |
+
beta_end=0.01,
|
266 |
+
)
|
267 |
+
if use_lora:
|
268 |
+
self._add_freeu()
|
269 |
|
270 |
def generate(
|
271 |
self,
|
272 |
lcm_diffusion_setting: LCMDiffusionSetting,
|
273 |
reshape: bool = False,
|
274 |
) -> Any:
|
275 |
+
guidance_scale = lcm_diffusion_setting.guidance_scale
|
276 |
if lcm_diffusion_setting.use_seed:
|
277 |
cur_seed = lcm_diffusion_setting.seed
|
278 |
if self.use_openvino:
|
|
|
280 |
else:
|
281 |
torch.manual_seed(cur_seed)
|
282 |
|
283 |
+
if lcm_diffusion_setting.use_openvino and is_openvino_device():
|
284 |
print("Using OpenVINO")
|
285 |
if reshape:
|
286 |
print("Reshape and compile")
|
287 |
self.pipeline.reshape(
|
288 |
+
batch_size=-1,
|
289 |
height=lcm_diffusion_setting.image_height,
|
290 |
width=lcm_diffusion_setting.image_width,
|
291 |
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
|
|
295 |
if not lcm_diffusion_setting.use_safety_checker:
|
296 |
self.pipeline.safety_checker = None
|
297 |
|
298 |
+
if (
|
299 |
+
not lcm_diffusion_setting.use_lcm_lora
|
300 |
+
and not lcm_diffusion_setting.use_openvino
|
301 |
+
and lcm_diffusion_setting.guidance_scale != 1.0
|
302 |
+
):
|
303 |
+
print("Not using LCM-LoRA so setting guidance_scale 1.0")
|
304 |
+
guidance_scale = 1.0
|
305 |
+
|
306 |
+
if lcm_diffusion_setting.use_openvino:
|
307 |
+
result_images = self.pipeline(
|
308 |
+
prompt=lcm_diffusion_setting.prompt,
|
309 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
310 |
+
num_inference_steps=lcm_diffusion_setting.inference_steps,
|
311 |
+
guidance_scale=guidance_scale,
|
312 |
+
width=lcm_diffusion_setting.image_width,
|
313 |
+
height=lcm_diffusion_setting.image_height,
|
314 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
315 |
+
).images
|
316 |
+
else:
|
317 |
+
result_images = self.pipeline(
|
318 |
+
prompt=lcm_diffusion_setting.prompt,
|
319 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
320 |
+
num_inference_steps=lcm_diffusion_setting.inference_steps,
|
321 |
+
guidance_scale=guidance_scale,
|
322 |
+
width=lcm_diffusion_setting.image_width,
|
323 |
+
height=lcm_diffusion_setting.image_height,
|
324 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
325 |
+
).images
|
326 |
|
327 |
return result_images
|
backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc
CHANGED
Binary files a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc and b/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc differ
|
|
backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc
CHANGED
Binary files a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc and b/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc differ
|
|
backend/lcmdiffusion/pipelines/openvino/lcm_ov_pipeline.py
CHANGED
@@ -11,7 +11,14 @@ import openvino
|
|
11 |
import torch
|
12 |
|
13 |
from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput
|
14 |
-
from optimum.intel.openvino.modeling_diffusion import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
from optimum.utils import (
|
16 |
DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER,
|
17 |
DIFFUSION_MODEL_TEXT_ENCODER_SUBFOLDER,
|
@@ -22,8 +29,10 @@ from optimum.utils import (
|
|
22 |
|
23 |
|
24 |
from diffusers import logging
|
|
|
25 |
logger = logging.get_logger(__name__) # pylint: disable=invalid-name
|
26 |
|
|
|
27 |
class LCMOVModelUnet(OVModelUnet):
|
28 |
def __call__(
|
29 |
self,
|
@@ -52,8 +61,8 @@ class LCMOVModelUnet(OVModelUnet):
|
|
52 |
outputs = self.request(inputs, shared_memory=True)
|
53 |
return list(outputs.values())
|
54 |
|
55 |
-
class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
56 |
|
|
|
57 |
def __init__(
|
58 |
self,
|
59 |
vae_decoder: openvino.runtime.Model,
|
@@ -78,20 +87,32 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
78 |
self.is_dynamic = dynamic_shapes
|
79 |
self.ov_config = ov_config if ov_config is not None else {}
|
80 |
self._model_save_dir = (
|
81 |
-
Path(model_save_dir.name)
|
|
|
|
|
82 |
)
|
83 |
self.vae_decoder = OVModelVaeDecoder(vae_decoder, self)
|
84 |
self.unet = LCMOVModelUnet(unet, self)
|
85 |
-
self.text_encoder =
|
|
|
|
|
86 |
self.text_encoder_2 = (
|
87 |
-
OVModelTextEncoder(
|
|
|
|
|
|
|
|
|
88 |
if text_encoder_2 is not None
|
89 |
else None
|
90 |
)
|
91 |
-
self.vae_encoder =
|
|
|
|
|
92 |
|
93 |
if "block_out_channels" in self.vae_decoder.config:
|
94 |
-
self.vae_scale_factor = 2 ** (
|
|
|
|
|
95 |
else:
|
96 |
self.vae_scale_factor = 8
|
97 |
|
@@ -119,7 +140,9 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
119 |
}
|
120 |
for name in sub_models.keys():
|
121 |
self._internal_dict[name] = (
|
122 |
-
("optimum", sub_models[name].__class__.__name__)
|
|
|
|
|
123 |
)
|
124 |
|
125 |
self._internal_dict.pop("vae", None)
|
@@ -132,7 +155,7 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
132 |
width: int = -1,
|
133 |
num_images_per_prompt: int = -1,
|
134 |
tokenizer_max_length: int = -1,
|
135 |
-
):
|
136 |
if batch_size == -1 or num_images_per_prompt == -1:
|
137 |
batch_size = -1
|
138 |
else:
|
@@ -152,14 +175,17 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
152 |
if in_channels.is_dynamic:
|
153 |
logger.warning(
|
154 |
"Could not identify `in_channels` from the unet configuration, to statically reshape the unet please provide a configuration."
|
155 |
-
)
|
156 |
self.is_dynamic = True
|
157 |
-
|
158 |
shapes[inputs] = [batch_size, in_channels, height, width]
|
159 |
elif inputs.get_any_name() == "timestep_cond":
|
160 |
shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]]
|
161 |
elif inputs.get_any_name() == "text_embeds":
|
162 |
-
shapes[inputs] = [
|
|
|
|
|
|
|
163 |
elif inputs.get_any_name() == "time_ids":
|
164 |
shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]]
|
165 |
else:
|
@@ -180,10 +206,10 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
180 |
embedding vectors with shape `(len(timesteps), embedding_dim)`
|
181 |
"""
|
182 |
assert len(w.shape) == 1
|
183 |
-
w = w * 1000.
|
184 |
|
185 |
half_dim = embedding_dim // 2
|
186 |
-
emb = np.log(np.array(10000.)) / (half_dim - 1)
|
187 |
emb = np.exp(np.arange(half_dim, dtype=dtype) * -emb)
|
188 |
emb = w.astype(dtype)[:, None] * emb[None, :]
|
189 |
emb = np.concatenate([np.sin(emb), np.cos(emb)], axis=1)
|
@@ -276,7 +302,9 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
276 |
list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"
|
277 |
(nsfw) content, according to the `safety_checker`.
|
278 |
"""
|
279 |
-
height =
|
|
|
|
|
280 |
width = width or self.unet.config.get("sample_size", 64) * self.vae_scale_factor
|
281 |
|
282 |
# check inputs. Raise error if not correct
|
@@ -296,9 +324,11 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
296 |
generator = np.random
|
297 |
|
298 |
# Create torch.Generator instance with same state as np.random.RandomState
|
299 |
-
torch_generator = torch.Generator().manual_seed(
|
|
|
|
|
300 |
|
301 |
-
#do_classifier_free_guidance = guidance_scale > 1.0
|
302 |
|
303 |
# NOTE: when a LCM is distilled from an LDM via latent consistency distillation (Algorithm 1) with guided
|
304 |
# distillation, the forward pass of the LCM learns to approximate sampling from the LDM using CFG with the
|
@@ -313,7 +343,11 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
313 |
)
|
314 |
|
315 |
# set timesteps
|
316 |
-
self.scheduler.set_timesteps(
|
|
|
|
|
|
|
|
|
317 |
timesteps = self.scheduler.timesteps
|
318 |
|
319 |
latents = self.prepare_latents(
|
@@ -328,7 +362,9 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
328 |
|
329 |
# Get Guidance Scale Embedding
|
330 |
w = np.tile(guidance_scale - 1, batch_size * num_images_per_prompt)
|
331 |
-
w_embedding = self.get_guidance_scale_embedding(
|
|
|
|
|
332 |
|
333 |
# Adapted from diffusers to extend it for other runtimes than ORT
|
334 |
timestep_dtype = self.unet.input_dtype.get("timestep", np.float32)
|
@@ -337,32 +373,46 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
337 |
# eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
|
338 |
# eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
|
339 |
# and should be between [0, 1]
|
340 |
-
accepts_eta = "eta" in set(
|
|
|
|
|
341 |
extra_step_kwargs = {}
|
342 |
if accepts_eta:
|
343 |
extra_step_kwargs["eta"] = eta
|
344 |
|
345 |
-
accepts_generator = "generator" in set(
|
|
|
|
|
346 |
if accepts_generator:
|
347 |
extra_step_kwargs["generator"] = torch_generator
|
348 |
|
349 |
num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order
|
350 |
for i, t in enumerate(self.progress_bar(timesteps)):
|
351 |
-
|
352 |
# predict the noise residual
|
353 |
timestep = np.array([t], dtype=timestep_dtype)
|
354 |
-
|
355 |
-
noise_pred = self.unet(
|
|
|
|
|
|
|
|
|
|
|
356 |
|
357 |
# compute the previous noisy sample x_t -> x_t-1
|
358 |
latents, denoised = self.scheduler.step(
|
359 |
-
torch.from_numpy(noise_pred),
|
|
|
|
|
|
|
|
|
360 |
)
|
361 |
|
362 |
latents, denoised = latents.numpy(), denoised.numpy()
|
363 |
|
364 |
# call the callback, if provided
|
365 |
-
if i == len(timesteps) - 1 or (
|
|
|
|
|
366 |
if callback is not None and i % callback_steps == 0:
|
367 |
callback(i, t, latents)
|
368 |
|
@@ -373,7 +423,10 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
373 |
denoised /= self.vae_decoder.config.get("scaling_factor", 0.18215)
|
374 |
# it seems likes there is a strange result for using half-precision vae decoder if batchsize>1
|
375 |
image = np.concatenate(
|
376 |
-
[
|
|
|
|
|
|
|
377 |
)
|
378 |
image, has_nsfw_concept = self.run_safety_checker(image)
|
379 |
|
@@ -382,9 +435,13 @@ class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
|
382 |
else:
|
383 |
do_denormalize = [not has_nsfw for has_nsfw in has_nsfw_concept]
|
384 |
|
385 |
-
image = self.image_processor.postprocess(
|
|
|
|
|
386 |
|
387 |
if not return_dict:
|
388 |
return (image, has_nsfw_concept)
|
389 |
|
390 |
-
return StableDiffusionPipelineOutput(
|
|
|
|
|
|
11 |
import torch
|
12 |
|
13 |
from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput
|
14 |
+
from optimum.intel.openvino.modeling_diffusion import (
|
15 |
+
OVStableDiffusionPipeline,
|
16 |
+
OVModelUnet,
|
17 |
+
OVModelVaeDecoder,
|
18 |
+
OVModelTextEncoder,
|
19 |
+
OVModelVaeEncoder,
|
20 |
+
VaeImageProcessor,
|
21 |
+
)
|
22 |
from optimum.utils import (
|
23 |
DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER,
|
24 |
DIFFUSION_MODEL_TEXT_ENCODER_SUBFOLDER,
|
|
|
29 |
|
30 |
|
31 |
from diffusers import logging
|
32 |
+
|
33 |
logger = logging.get_logger(__name__) # pylint: disable=invalid-name
|
34 |
|
35 |
+
|
36 |
class LCMOVModelUnet(OVModelUnet):
|
37 |
def __call__(
|
38 |
self,
|
|
|
61 |
outputs = self.request(inputs, shared_memory=True)
|
62 |
return list(outputs.values())
|
63 |
|
|
|
64 |
|
65 |
+
class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline):
|
66 |
def __init__(
|
67 |
self,
|
68 |
vae_decoder: openvino.runtime.Model,
|
|
|
87 |
self.is_dynamic = dynamic_shapes
|
88 |
self.ov_config = ov_config if ov_config is not None else {}
|
89 |
self._model_save_dir = (
|
90 |
+
Path(model_save_dir.name)
|
91 |
+
if isinstance(model_save_dir, TemporaryDirectory)
|
92 |
+
else model_save_dir
|
93 |
)
|
94 |
self.vae_decoder = OVModelVaeDecoder(vae_decoder, self)
|
95 |
self.unet = LCMOVModelUnet(unet, self)
|
96 |
+
self.text_encoder = (
|
97 |
+
OVModelTextEncoder(text_encoder, self) if text_encoder is not None else None
|
98 |
+
)
|
99 |
self.text_encoder_2 = (
|
100 |
+
OVModelTextEncoder(
|
101 |
+
text_encoder_2,
|
102 |
+
self,
|
103 |
+
model_name=DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER,
|
104 |
+
)
|
105 |
if text_encoder_2 is not None
|
106 |
else None
|
107 |
)
|
108 |
+
self.vae_encoder = (
|
109 |
+
OVModelVaeEncoder(vae_encoder, self) if vae_encoder is not None else None
|
110 |
+
)
|
111 |
|
112 |
if "block_out_channels" in self.vae_decoder.config:
|
113 |
+
self.vae_scale_factor = 2 ** (
|
114 |
+
len(self.vae_decoder.config["block_out_channels"]) - 1
|
115 |
+
)
|
116 |
else:
|
117 |
self.vae_scale_factor = 8
|
118 |
|
|
|
140 |
}
|
141 |
for name in sub_models.keys():
|
142 |
self._internal_dict[name] = (
|
143 |
+
("optimum", sub_models[name].__class__.__name__)
|
144 |
+
if sub_models[name] is not None
|
145 |
+
else (None, None)
|
146 |
)
|
147 |
|
148 |
self._internal_dict.pop("vae", None)
|
|
|
155 |
width: int = -1,
|
156 |
num_images_per_prompt: int = -1,
|
157 |
tokenizer_max_length: int = -1,
|
158 |
+
):
|
159 |
if batch_size == -1 or num_images_per_prompt == -1:
|
160 |
batch_size = -1
|
161 |
else:
|
|
|
175 |
if in_channels.is_dynamic:
|
176 |
logger.warning(
|
177 |
"Could not identify `in_channels` from the unet configuration, to statically reshape the unet please provide a configuration."
|
178 |
+
)
|
179 |
self.is_dynamic = True
|
180 |
+
|
181 |
shapes[inputs] = [batch_size, in_channels, height, width]
|
182 |
elif inputs.get_any_name() == "timestep_cond":
|
183 |
shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]]
|
184 |
elif inputs.get_any_name() == "text_embeds":
|
185 |
+
shapes[inputs] = [
|
186 |
+
batch_size,
|
187 |
+
self.text_encoder_2.config["projection_dim"],
|
188 |
+
]
|
189 |
elif inputs.get_any_name() == "time_ids":
|
190 |
shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]]
|
191 |
else:
|
|
|
206 |
embedding vectors with shape `(len(timesteps), embedding_dim)`
|
207 |
"""
|
208 |
assert len(w.shape) == 1
|
209 |
+
w = w * 1000.0
|
210 |
|
211 |
half_dim = embedding_dim // 2
|
212 |
+
emb = np.log(np.array(10000.0)) / (half_dim - 1)
|
213 |
emb = np.exp(np.arange(half_dim, dtype=dtype) * -emb)
|
214 |
emb = w.astype(dtype)[:, None] * emb[None, :]
|
215 |
emb = np.concatenate([np.sin(emb), np.cos(emb)], axis=1)
|
|
|
302 |
list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"
|
303 |
(nsfw) content, according to the `safety_checker`.
|
304 |
"""
|
305 |
+
height = (
|
306 |
+
height or self.unet.config.get("sample_size", 64) * self.vae_scale_factor
|
307 |
+
)
|
308 |
width = width or self.unet.config.get("sample_size", 64) * self.vae_scale_factor
|
309 |
|
310 |
# check inputs. Raise error if not correct
|
|
|
324 |
generator = np.random
|
325 |
|
326 |
# Create torch.Generator instance with same state as np.random.RandomState
|
327 |
+
torch_generator = torch.Generator().manual_seed(
|
328 |
+
int(generator.get_state()[1][0])
|
329 |
+
)
|
330 |
|
331 |
+
# do_classifier_free_guidance = guidance_scale > 1.0
|
332 |
|
333 |
# NOTE: when a LCM is distilled from an LDM via latent consistency distillation (Algorithm 1) with guided
|
334 |
# distillation, the forward pass of the LCM learns to approximate sampling from the LDM using CFG with the
|
|
|
343 |
)
|
344 |
|
345 |
# set timesteps
|
346 |
+
self.scheduler.set_timesteps(
|
347 |
+
num_inference_steps,
|
348 |
+
"cpu",
|
349 |
+
original_inference_steps=original_inference_steps,
|
350 |
+
)
|
351 |
timesteps = self.scheduler.timesteps
|
352 |
|
353 |
latents = self.prepare_latents(
|
|
|
362 |
|
363 |
# Get Guidance Scale Embedding
|
364 |
w = np.tile(guidance_scale - 1, batch_size * num_images_per_prompt)
|
365 |
+
w_embedding = self.get_guidance_scale_embedding(
|
366 |
+
w, embedding_dim=self.unet.config.get("time_cond_proj_dim", 256)
|
367 |
+
)
|
368 |
|
369 |
# Adapted from diffusers to extend it for other runtimes than ORT
|
370 |
timestep_dtype = self.unet.input_dtype.get("timestep", np.float32)
|
|
|
373 |
# eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
|
374 |
# eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
|
375 |
# and should be between [0, 1]
|
376 |
+
accepts_eta = "eta" in set(
|
377 |
+
inspect.signature(self.scheduler.step).parameters.keys()
|
378 |
+
)
|
379 |
extra_step_kwargs = {}
|
380 |
if accepts_eta:
|
381 |
extra_step_kwargs["eta"] = eta
|
382 |
|
383 |
+
accepts_generator = "generator" in set(
|
384 |
+
inspect.signature(self.scheduler.step).parameters.keys()
|
385 |
+
)
|
386 |
if accepts_generator:
|
387 |
extra_step_kwargs["generator"] = torch_generator
|
388 |
|
389 |
num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order
|
390 |
for i, t in enumerate(self.progress_bar(timesteps)):
|
|
|
391 |
# predict the noise residual
|
392 |
timestep = np.array([t], dtype=timestep_dtype)
|
393 |
+
|
394 |
+
noise_pred = self.unet(
|
395 |
+
sample=latents,
|
396 |
+
timestep=timestep,
|
397 |
+
timestep_cond=w_embedding,
|
398 |
+
encoder_hidden_states=prompt_embeds,
|
399 |
+
)[0]
|
400 |
|
401 |
# compute the previous noisy sample x_t -> x_t-1
|
402 |
latents, denoised = self.scheduler.step(
|
403 |
+
torch.from_numpy(noise_pred),
|
404 |
+
t,
|
405 |
+
torch.from_numpy(latents),
|
406 |
+
**extra_step_kwargs,
|
407 |
+
return_dict=False,
|
408 |
)
|
409 |
|
410 |
latents, denoised = latents.numpy(), denoised.numpy()
|
411 |
|
412 |
# call the callback, if provided
|
413 |
+
if i == len(timesteps) - 1 or (
|
414 |
+
(i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0
|
415 |
+
):
|
416 |
if callback is not None and i % callback_steps == 0:
|
417 |
callback(i, t, latents)
|
418 |
|
|
|
423 |
denoised /= self.vae_decoder.config.get("scaling_factor", 0.18215)
|
424 |
# it seems likes there is a strange result for using half-precision vae decoder if batchsize>1
|
425 |
image = np.concatenate(
|
426 |
+
[
|
427 |
+
self.vae_decoder(latent_sample=denoised[i : i + 1])[0]
|
428 |
+
for i in range(latents.shape[0])
|
429 |
+
]
|
430 |
)
|
431 |
image, has_nsfw_concept = self.run_safety_checker(image)
|
432 |
|
|
|
435 |
else:
|
436 |
do_denormalize = [not has_nsfw for has_nsfw in has_nsfw_concept]
|
437 |
|
438 |
+
image = self.image_processor.postprocess(
|
439 |
+
image, output_type=output_type, do_denormalize=do_denormalize
|
440 |
+
)
|
441 |
|
442 |
if not return_dict:
|
443 |
return (image, has_nsfw_concept)
|
444 |
|
445 |
+
return StableDiffusionPipelineOutput(
|
446 |
+
images=image, nsfw_content_detected=has_nsfw_concept
|
447 |
+
)
|
backend/lcmdiffusion/pipelines/openvino/lcm_scheduler.py
CHANGED
@@ -213,17 +213,27 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
213 |
if trained_betas is not None:
|
214 |
self.betas = torch.tensor(trained_betas, dtype=torch.float32)
|
215 |
elif beta_schedule == "linear":
|
216 |
-
self.betas = torch.linspace(
|
|
|
|
|
217 |
elif beta_schedule == "scaled_linear":
|
218 |
# this schedule is very specific to the latent diffusion model.
|
219 |
self.betas = (
|
220 |
-
torch.linspace(
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
)
|
222 |
elif beta_schedule == "squaredcos_cap_v2":
|
223 |
# Glide cosine schedule
|
224 |
self.betas = betas_for_alpha_bar(num_train_timesteps)
|
225 |
else:
|
226 |
-
raise NotImplementedError(
|
|
|
|
|
227 |
|
228 |
# Rescale for zero SNR
|
229 |
if rescale_betas_zero_snr:
|
@@ -236,14 +246,18 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
236 |
# For the final step, there is no previous alphas_cumprod because we are already at 0
|
237 |
# `set_alpha_to_one` decides whether we set this parameter simply to one or
|
238 |
# whether we use the final alpha of the "non-previous" one.
|
239 |
-
self.final_alpha_cumprod =
|
|
|
|
|
240 |
|
241 |
# standard deviation of the initial noise distribution
|
242 |
self.init_noise_sigma = 1.0
|
243 |
|
244 |
# setable values
|
245 |
self.num_inference_steps = None
|
246 |
-
self.timesteps = torch.from_numpy(
|
|
|
|
|
247 |
|
248 |
self._step_index = None
|
249 |
|
@@ -269,7 +283,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
269 |
def step_index(self):
|
270 |
return self._step_index
|
271 |
|
272 |
-
def scale_model_input(
|
|
|
|
|
273 |
"""
|
274 |
Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
|
275 |
current timestep.
|
@@ -300,7 +316,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
300 |
batch_size, channels, *remaining_dims = sample.shape
|
301 |
|
302 |
if dtype not in (torch.float32, torch.float64):
|
303 |
-
sample =
|
|
|
|
|
304 |
|
305 |
# Flatten sample for doing quantile calculation along each image
|
306 |
sample = sample.reshape(batch_size, channels * np.prod(remaining_dims))
|
@@ -312,7 +330,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
312 |
s, min=1, max=self.config.sample_max_value
|
313 |
) # When clamped to min=1, equivalent to standard clipping to [-1, 1]
|
314 |
s = s.unsqueeze(1) # (batch_size, 1) because clamp will broadcast along dim=0
|
315 |
-
sample =
|
|
|
|
|
316 |
|
317 |
sample = sample.reshape(batch_size, channels, *remaining_dims)
|
318 |
sample = sample.to(dtype)
|
@@ -349,7 +369,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
349 |
|
350 |
self.num_inference_steps = num_inference_steps
|
351 |
original_steps = (
|
352 |
-
original_inference_steps
|
|
|
|
|
353 |
)
|
354 |
|
355 |
if original_steps > self.config.num_train_timesteps:
|
@@ -375,7 +397,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
375 |
# LCM Inference Steps Schedule
|
376 |
timesteps = lcm_origin_timesteps[::-skipping_step][:num_inference_steps]
|
377 |
|
378 |
-
self.timesteps = torch.from_numpy(timesteps.copy()).to(
|
|
|
|
|
379 |
|
380 |
self._step_index = None
|
381 |
|
@@ -432,7 +456,11 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
432 |
|
433 |
# 2. compute alphas, betas
|
434 |
alpha_prod_t = self.alphas_cumprod[timestep]
|
435 |
-
alpha_prod_t_prev =
|
|
|
|
|
|
|
|
|
436 |
|
437 |
beta_prod_t = 1 - alpha_prod_t
|
438 |
beta_prod_t_prev = 1 - alpha_prod_t_prev
|
@@ -442,11 +470,15 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
442 |
|
443 |
# 4. Compute the predicted original sample x_0 based on the model parameterization
|
444 |
if self.config.prediction_type == "epsilon": # noise-prediction
|
445 |
-
predicted_original_sample = (
|
|
|
|
|
446 |
elif self.config.prediction_type == "sample": # x-prediction
|
447 |
predicted_original_sample = model_output
|
448 |
elif self.config.prediction_type == "v_prediction": # v-prediction
|
449 |
-
predicted_original_sample =
|
|
|
|
|
450 |
else:
|
451 |
raise ValueError(
|
452 |
f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample` or"
|
@@ -455,7 +487,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
455 |
|
456 |
# 5. Clip or threshold "predicted x_0"
|
457 |
if self.config.thresholding:
|
458 |
-
predicted_original_sample = self._threshold_sample(
|
|
|
|
|
459 |
elif self.config.clip_sample:
|
460 |
predicted_original_sample = predicted_original_sample.clamp(
|
461 |
-self.config.clip_sample_range, self.config.clip_sample_range
|
@@ -467,8 +501,12 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
467 |
# 7. Sample and inject noise z ~ N(0, I) for MultiStep Inference
|
468 |
# Noise is not used for one-step sampling.
|
469 |
if len(self.timesteps) > 1:
|
470 |
-
noise = randn_tensor(
|
471 |
-
|
|
|
|
|
|
|
|
|
472 |
else:
|
473 |
prev_sample = denoised
|
474 |
|
@@ -488,7 +526,9 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
488 |
timesteps: torch.IntTensor,
|
489 |
) -> torch.FloatTensor:
|
490 |
# Make sure alphas_cumprod and timestep have same device and dtype as original_samples
|
491 |
-
alphas_cumprod = self.alphas_cumprod.to(
|
|
|
|
|
492 |
timesteps = timesteps.to(original_samples.device)
|
493 |
|
494 |
sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5
|
@@ -501,15 +541,22 @@ class LCMScheduler(SchedulerMixin, ConfigMixin):
|
|
501 |
while len(sqrt_one_minus_alpha_prod.shape) < len(original_samples.shape):
|
502 |
sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1)
|
503 |
|
504 |
-
noisy_samples =
|
|
|
|
|
505 |
return noisy_samples
|
506 |
|
507 |
# Copied from diffusers.schedulers.scheduling_ddpm.DDPMScheduler.get_velocity
|
508 |
def get_velocity(
|
509 |
-
self,
|
|
|
|
|
|
|
510 |
) -> torch.FloatTensor:
|
511 |
# Make sure alphas_cumprod and timestep have same device and dtype as sample
|
512 |
-
alphas_cumprod = self.alphas_cumprod.to(
|
|
|
|
|
513 |
timesteps = timesteps.to(sample.device)
|
514 |
|
515 |
sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5
|
|
|
213 |
if trained_betas is not None:
|
214 |
self.betas = torch.tensor(trained_betas, dtype=torch.float32)
|
215 |
elif beta_schedule == "linear":
|
216 |
+
self.betas = torch.linspace(
|
217 |
+
beta_start, beta_end, num_train_timesteps, dtype=torch.float32
|
218 |
+
)
|
219 |
elif beta_schedule == "scaled_linear":
|
220 |
# this schedule is very specific to the latent diffusion model.
|
221 |
self.betas = (
|
222 |
+
torch.linspace(
|
223 |
+
beta_start**0.5,
|
224 |
+
beta_end**0.5,
|
225 |
+
num_train_timesteps,
|
226 |
+
dtype=torch.float32,
|
227 |
+
)
|
228 |
+
** 2
|
229 |
)
|
230 |
elif beta_schedule == "squaredcos_cap_v2":
|
231 |
# Glide cosine schedule
|
232 |
self.betas = betas_for_alpha_bar(num_train_timesteps)
|
233 |
else:
|
234 |
+
raise NotImplementedError(
|
235 |
+
f"{beta_schedule} does is not implemented for {self.__class__}"
|
236 |
+
)
|
237 |
|
238 |
# Rescale for zero SNR
|
239 |
if rescale_betas_zero_snr:
|
|
|
246 |
# For the final step, there is no previous alphas_cumprod because we are already at 0
|
247 |
# `set_alpha_to_one` decides whether we set this parameter simply to one or
|
248 |
# whether we use the final alpha of the "non-previous" one.
|
249 |
+
self.final_alpha_cumprod = (
|
250 |
+
torch.tensor(1.0) if set_alpha_to_one else self.alphas_cumprod[0]
|
251 |
+
)
|
252 |
|
253 |
# standard deviation of the initial noise distribution
|
254 |
self.init_noise_sigma = 1.0
|
255 |
|
256 |
# setable values
|
257 |
self.num_inference_steps = None
|
258 |
+
self.timesteps = torch.from_numpy(
|
259 |
+
np.arange(0, num_train_timesteps)[::-1].copy().astype(np.int64)
|
260 |
+
)
|
261 |
|
262 |
self._step_index = None
|
263 |
|
|
|
283 |
def step_index(self):
|
284 |
return self._step_index
|
285 |
|
286 |
+
def scale_model_input(
|
287 |
+
self, sample: torch.FloatTensor, timestep: Optional[int] = None
|
288 |
+
) -> torch.FloatTensor:
|
289 |
"""
|
290 |
Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
|
291 |
current timestep.
|
|
|
316 |
batch_size, channels, *remaining_dims = sample.shape
|
317 |
|
318 |
if dtype not in (torch.float32, torch.float64):
|
319 |
+
sample = (
|
320 |
+
sample.float()
|
321 |
+
) # upcast for quantile calculation, and clamp not implemented for cpu half
|
322 |
|
323 |
# Flatten sample for doing quantile calculation along each image
|
324 |
sample = sample.reshape(batch_size, channels * np.prod(remaining_dims))
|
|
|
330 |
s, min=1, max=self.config.sample_max_value
|
331 |
) # When clamped to min=1, equivalent to standard clipping to [-1, 1]
|
332 |
s = s.unsqueeze(1) # (batch_size, 1) because clamp will broadcast along dim=0
|
333 |
+
sample = (
|
334 |
+
torch.clamp(sample, -s, s) / s
|
335 |
+
) # "we threshold xt0 to the range [-s, s] and then divide by s"
|
336 |
|
337 |
sample = sample.reshape(batch_size, channels, *remaining_dims)
|
338 |
sample = sample.to(dtype)
|
|
|
369 |
|
370 |
self.num_inference_steps = num_inference_steps
|
371 |
original_steps = (
|
372 |
+
original_inference_steps
|
373 |
+
if original_inference_steps is not None
|
374 |
+
else self.original_inference_steps
|
375 |
)
|
376 |
|
377 |
if original_steps > self.config.num_train_timesteps:
|
|
|
397 |
# LCM Inference Steps Schedule
|
398 |
timesteps = lcm_origin_timesteps[::-skipping_step][:num_inference_steps]
|
399 |
|
400 |
+
self.timesteps = torch.from_numpy(timesteps.copy()).to(
|
401 |
+
device=device, dtype=torch.long
|
402 |
+
)
|
403 |
|
404 |
self._step_index = None
|
405 |
|
|
|
456 |
|
457 |
# 2. compute alphas, betas
|
458 |
alpha_prod_t = self.alphas_cumprod[timestep]
|
459 |
+
alpha_prod_t_prev = (
|
460 |
+
self.alphas_cumprod[prev_timestep]
|
461 |
+
if prev_timestep >= 0
|
462 |
+
else self.final_alpha_cumprod
|
463 |
+
)
|
464 |
|
465 |
beta_prod_t = 1 - alpha_prod_t
|
466 |
beta_prod_t_prev = 1 - alpha_prod_t_prev
|
|
|
470 |
|
471 |
# 4. Compute the predicted original sample x_0 based on the model parameterization
|
472 |
if self.config.prediction_type == "epsilon": # noise-prediction
|
473 |
+
predicted_original_sample = (
|
474 |
+
sample - beta_prod_t.sqrt() * model_output
|
475 |
+
) / alpha_prod_t.sqrt()
|
476 |
elif self.config.prediction_type == "sample": # x-prediction
|
477 |
predicted_original_sample = model_output
|
478 |
elif self.config.prediction_type == "v_prediction": # v-prediction
|
479 |
+
predicted_original_sample = (
|
480 |
+
alpha_prod_t.sqrt() * sample - beta_prod_t.sqrt() * model_output
|
481 |
+
)
|
482 |
else:
|
483 |
raise ValueError(
|
484 |
f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample` or"
|
|
|
487 |
|
488 |
# 5. Clip or threshold "predicted x_0"
|
489 |
if self.config.thresholding:
|
490 |
+
predicted_original_sample = self._threshold_sample(
|
491 |
+
predicted_original_sample
|
492 |
+
)
|
493 |
elif self.config.clip_sample:
|
494 |
predicted_original_sample = predicted_original_sample.clamp(
|
495 |
-self.config.clip_sample_range, self.config.clip_sample_range
|
|
|
501 |
# 7. Sample and inject noise z ~ N(0, I) for MultiStep Inference
|
502 |
# Noise is not used for one-step sampling.
|
503 |
if len(self.timesteps) > 1:
|
504 |
+
noise = randn_tensor(
|
505 |
+
model_output.shape, generator=generator, device=model_output.device
|
506 |
+
)
|
507 |
+
prev_sample = (
|
508 |
+
alpha_prod_t_prev.sqrt() * denoised + beta_prod_t_prev.sqrt() * noise
|
509 |
+
)
|
510 |
else:
|
511 |
prev_sample = denoised
|
512 |
|
|
|
526 |
timesteps: torch.IntTensor,
|
527 |
) -> torch.FloatTensor:
|
528 |
# Make sure alphas_cumprod and timestep have same device and dtype as original_samples
|
529 |
+
alphas_cumprod = self.alphas_cumprod.to(
|
530 |
+
device=original_samples.device, dtype=original_samples.dtype
|
531 |
+
)
|
532 |
timesteps = timesteps.to(original_samples.device)
|
533 |
|
534 |
sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5
|
|
|
541 |
while len(sqrt_one_minus_alpha_prod.shape) < len(original_samples.shape):
|
542 |
sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1)
|
543 |
|
544 |
+
noisy_samples = (
|
545 |
+
sqrt_alpha_prod * original_samples + sqrt_one_minus_alpha_prod * noise
|
546 |
+
)
|
547 |
return noisy_samples
|
548 |
|
549 |
# Copied from diffusers.schedulers.scheduling_ddpm.DDPMScheduler.get_velocity
|
550 |
def get_velocity(
|
551 |
+
self,
|
552 |
+
sample: torch.FloatTensor,
|
553 |
+
noise: torch.FloatTensor,
|
554 |
+
timesteps: torch.IntTensor,
|
555 |
) -> torch.FloatTensor:
|
556 |
# Make sure alphas_cumprod and timestep have same device and dtype as sample
|
557 |
+
alphas_cumprod = self.alphas_cumprod.to(
|
558 |
+
device=sample.device, dtype=sample.dtype
|
559 |
+
)
|
560 |
timesteps = timesteps.to(sample.device)
|
561 |
|
562 |
sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5
|
backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc
CHANGED
Binary files a/backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc and b/backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc differ
|
|
backend/models/lcmdiffusion_setting.py
CHANGED
@@ -1,19 +1,29 @@
|
|
1 |
from typing import Optional
|
2 |
|
3 |
from pydantic import BaseModel
|
4 |
-
from constants import LCM_DEFAULT_MODEL
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
|
7 |
class LCMDiffusionSetting(BaseModel):
|
8 |
lcm_model_id: str = LCM_DEFAULT_MODEL
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
prompt: str = ""
|
|
|
10 |
image_height: Optional[int] = 512
|
11 |
image_width: Optional[int] = 512
|
12 |
inference_steps: Optional[int] = 4
|
13 |
-
guidance_scale: Optional[float] =
|
14 |
number_of_images: Optional[int] = 1
|
15 |
seed: Optional[int] = -1
|
16 |
-
use_openvino: bool = False
|
17 |
use_seed: bool = False
|
18 |
-
|
19 |
-
use_safety_checker: bool = True
|
|
|
1 |
from typing import Optional
|
2 |
|
3 |
from pydantic import BaseModel
|
4 |
+
from constants import LCM_DEFAULT_MODEL, LCM_DEFAULT_MODEL_OPENVINO
|
5 |
+
|
6 |
+
|
7 |
+
class LCMLora(BaseModel):
|
8 |
+
base_model_id: str = ""
|
9 |
+
lcm_lora_id: str = ""
|
10 |
|
11 |
|
12 |
class LCMDiffusionSetting(BaseModel):
|
13 |
lcm_model_id: str = LCM_DEFAULT_MODEL
|
14 |
+
openvino_lcm_model_id: str = LCM_DEFAULT_MODEL_OPENVINO
|
15 |
+
use_offline_model: bool = False
|
16 |
+
use_lcm_lora: bool = False
|
17 |
+
lcm_lora: Optional[LCMLora] = LCMLora()
|
18 |
+
use_tiny_auto_encoder: bool = False
|
19 |
+
use_openvino: bool = False
|
20 |
prompt: str = ""
|
21 |
+
negative_prompt: str = ""
|
22 |
image_height: Optional[int] = 512
|
23 |
image_width: Optional[int] = 512
|
24 |
inference_steps: Optional[int] = 4
|
25 |
+
guidance_scale: Optional[float] = 1
|
26 |
number_of_images: Optional[int] = 1
|
27 |
seed: Optional[int] = -1
|
|
|
28 |
use_seed: bool = False
|
29 |
+
use_safety_checker: bool = False
|
|
constants.py
CHANGED
@@ -1,10 +1,16 @@
|
|
1 |
from os import environ
|
2 |
|
3 |
-
APP_VERSION = "v1.0.0 beta
|
4 |
LCM_DEFAULT_MODEL = "SimianLuo/LCM_Dreamshaper_v7"
|
5 |
-
LCM_DEFAULT_MODEL_OPENVINO = "rupeshs/LCM-dreamshaper-v7-openvino
|
6 |
APP_NAME = "FastSD CPU"
|
7 |
APP_SETTINGS_FILE = "settings.yaml"
|
8 |
RESULTS_DIRECTORY = "results"
|
9 |
CONFIG_DIRECTORY = "configs"
|
10 |
DEVICE = environ.get("DEVICE", "cpu")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from os import environ
|
2 |
|
3 |
+
APP_VERSION = "v1.0.0 beta 16"
|
4 |
LCM_DEFAULT_MODEL = "SimianLuo/LCM_Dreamshaper_v7"
|
5 |
+
LCM_DEFAULT_MODEL_OPENVINO = "rupeshs/LCM-dreamshaper-v7-openvino"
|
6 |
APP_NAME = "FastSD CPU"
|
7 |
APP_SETTINGS_FILE = "settings.yaml"
|
8 |
RESULTS_DIRECTORY = "results"
|
9 |
CONFIG_DIRECTORY = "configs"
|
10 |
DEVICE = environ.get("DEVICE", "cpu")
|
11 |
+
SD_MODELS_FILE = "stable-diffusion-models.txt"
|
12 |
+
LCM_LORA_MODELS_FILE = "lcm-lora-models.txt"
|
13 |
+
OPENVINO_LCM_MODELS_FILE = "openvino-lcm-models.txt"
|
14 |
+
TAESD_MODEL = "madebyollin/taesd"
|
15 |
+
TAESDXL_MODEL = "madebyollin/taesdxl"
|
16 |
+
TAESD_MODEL_OPENVINO = "deinferno/taesd-openvino"
|
context.py
CHANGED
@@ -2,7 +2,7 @@ from typing import Any
|
|
2 |
from app_settings import Settings
|
3 |
from models.interface_types import InterfaceType
|
4 |
from backend.lcm_text_to_image import LCMTextToImage
|
5 |
-
from time import
|
6 |
from backend.image_saver import ImageSaver
|
7 |
from pprint import pprint
|
8 |
|
@@ -22,23 +22,28 @@ class Context:
|
|
22 |
reshape: bool = False,
|
23 |
device: str = "cpu",
|
24 |
) -> Any:
|
25 |
-
tick =
|
26 |
pprint(settings.lcm_diffusion_setting.model_dump())
|
|
|
|
|
27 |
self.lcm_text_to_image.init(
|
28 |
settings.lcm_diffusion_setting.lcm_model_id,
|
29 |
settings.lcm_diffusion_setting.use_openvino,
|
30 |
device,
|
31 |
settings.lcm_diffusion_setting.use_offline_model,
|
|
|
|
|
|
|
32 |
)
|
33 |
images = self.lcm_text_to_image.generate(
|
34 |
settings.lcm_diffusion_setting,
|
35 |
reshape,
|
36 |
)
|
37 |
-
elapsed =
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
print(f"Elapsed time : {elapsed:.2f} seconds")
|
44 |
return images
|
|
|
2 |
from app_settings import Settings
|
3 |
from models.interface_types import InterfaceType
|
4 |
from backend.lcm_text_to_image import LCMTextToImage
|
5 |
+
from time import perf_counter
|
6 |
from backend.image_saver import ImageSaver
|
7 |
from pprint import pprint
|
8 |
|
|
|
22 |
reshape: bool = False,
|
23 |
device: str = "cpu",
|
24 |
) -> Any:
|
25 |
+
tick = perf_counter()
|
26 |
pprint(settings.lcm_diffusion_setting.model_dump())
|
27 |
+
if not settings.lcm_diffusion_setting.lcm_lora:
|
28 |
+
return None
|
29 |
self.lcm_text_to_image.init(
|
30 |
settings.lcm_diffusion_setting.lcm_model_id,
|
31 |
settings.lcm_diffusion_setting.use_openvino,
|
32 |
device,
|
33 |
settings.lcm_diffusion_setting.use_offline_model,
|
34 |
+
settings.lcm_diffusion_setting.use_tiny_auto_encoder,
|
35 |
+
settings.lcm_diffusion_setting.use_lcm_lora,
|
36 |
+
settings.lcm_diffusion_setting.lcm_lora,
|
37 |
)
|
38 |
images = self.lcm_text_to_image.generate(
|
39 |
settings.lcm_diffusion_setting,
|
40 |
reshape,
|
41 |
)
|
42 |
+
elapsed = perf_counter() - tick
|
43 |
+
ImageSaver.save_images(
|
44 |
+
settings.results_path,
|
45 |
+
images=images,
|
46 |
+
lcm_diffusion_setting=settings.lcm_diffusion_setting,
|
47 |
+
)
|
48 |
print(f"Elapsed time : {elapsed:.2f} seconds")
|
49 |
return images
|
frontend/__pycache__/utils.cpython-311.pyc
CHANGED
Binary files a/frontend/__pycache__/utils.cpython-311.pyc and b/frontend/__pycache__/utils.cpython-311.pyc differ
|
|
frontend/gui/__pycache__/app_window.cpython-311.pyc
CHANGED
Binary files a/frontend/gui/__pycache__/app_window.cpython-311.pyc and b/frontend/gui/__pycache__/app_window.cpython-311.pyc differ
|
|
frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc
CHANGED
Binary files a/frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc and b/frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc differ
|
|
frontend/gui/__pycache__/ui.cpython-311.pyc
CHANGED
Binary files a/frontend/gui/__pycache__/ui.cpython-311.pyc and b/frontend/gui/__pycache__/ui.cpython-311.pyc differ
|
|
frontend/gui/app_window.py
CHANGED
@@ -16,7 +16,7 @@ from PyQt5.QtWidgets import (
|
|
16 |
QToolButton,
|
17 |
QFileDialog,
|
18 |
)
|
19 |
-
|
20 |
from PyQt5.QtGui import QPixmap, QDesktopServices
|
21 |
from PyQt5.QtCore import QSize, QThreadPool, Qt, QUrl
|
22 |
|
@@ -34,18 +34,23 @@ from frontend.utils import is_reshape_required
|
|
34 |
from context import Context
|
35 |
from models.interface_types import InterfaceType
|
36 |
from constants import DEVICE
|
37 |
-
from frontend.utils import enable_openvino_controls
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
|
40 |
class MainWindow(QMainWindow):
|
41 |
def __init__(self, config: AppSettings):
|
42 |
super().__init__()
|
|
|
43 |
self.setWindowTitle(APP_NAME)
|
44 |
-
self.setFixedSize(QSize(600,
|
45 |
self.init_ui()
|
46 |
self.pipeline = None
|
47 |
self.threadpool = QThreadPool()
|
48 |
-
self.config = config
|
49 |
self.device = "cpu"
|
50 |
self.previous_width = 0
|
51 |
self.previous_height = 0
|
@@ -89,6 +94,37 @@ class MainWindow(QMainWindow):
|
|
89 |
self.num_images.setValue(
|
90 |
self.config.settings.lcm_diffusion_setting.number_of_images
|
91 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
|
93 |
def init_ui(self):
|
94 |
self.create_main_tab()
|
@@ -100,20 +136,26 @@ class MainWindow(QMainWindow):
|
|
100 |
self.img = QLabel("<<Image>>")
|
101 |
self.img.setAlignment(Qt.AlignCenter)
|
102 |
self.img.setFixedSize(QSize(512, 512))
|
|
|
103 |
|
104 |
self.prompt = QTextEdit()
|
105 |
self.prompt.setPlaceholderText("A fantasy landscape")
|
106 |
self.prompt.setAcceptRichText(False)
|
|
|
|
|
|
|
|
|
107 |
self.generate = QPushButton("Generate")
|
108 |
self.generate.clicked.connect(self.text_to_image)
|
109 |
-
self.prompt.setFixedHeight(
|
|
|
110 |
self.browse_results = QPushButton("...")
|
111 |
self.browse_results.setFixedWidth(30)
|
112 |
self.browse_results.clicked.connect(self.on_open_results_folder)
|
113 |
self.browse_results.setToolTip("Open output folder")
|
114 |
|
115 |
hlayout = QHBoxLayout()
|
116 |
-
hlayout.addWidget(self.
|
117 |
hlayout.addWidget(self.generate)
|
118 |
hlayout.addWidget(self.browse_results)
|
119 |
|
@@ -130,6 +172,9 @@ class MainWindow(QMainWindow):
|
|
130 |
|
131 |
vlayout = QVBoxLayout()
|
132 |
vlayout.addLayout(hlayout_nav)
|
|
|
|
|
|
|
133 |
vlayout.addLayout(hlayout)
|
134 |
|
135 |
self.tab_widget = QTabWidget(self)
|
@@ -146,11 +191,26 @@ class MainWindow(QMainWindow):
|
|
146 |
self.use_seed = False
|
147 |
|
148 |
def create_settings_tab(self):
|
149 |
-
model_hlayout = QHBoxLayout()
|
150 |
self.lcm_model_label = QLabel("Latent Consistency Model:")
|
151 |
-
self.lcm_model = QLineEdit(LCM_DEFAULT_MODEL)
|
152 |
-
|
153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
self.inference_steps_value = QLabel("Number of inference steps: 4")
|
156 |
self.inference_steps = QSlider(orientation=Qt.Orientation.Horizontal)
|
@@ -166,11 +226,11 @@ class MainWindow(QMainWindow):
|
|
166 |
self.num_images.setValue(1)
|
167 |
self.num_images.valueChanged.connect(self.update_num_images_label)
|
168 |
|
169 |
-
self.guidance_value = QLabel("Guidance scale:
|
170 |
self.guidance = QSlider(orientation=Qt.Orientation.Horizontal)
|
171 |
-
self.guidance.setMaximum(
|
172 |
self.guidance.setMinimum(10)
|
173 |
-
self.guidance.setValue(
|
174 |
self.guidance.valueChanged.connect(self.update_guidance_label)
|
175 |
|
176 |
self.width_value = QLabel("Width :")
|
@@ -178,6 +238,7 @@ class MainWindow(QMainWindow):
|
|
178 |
self.width.addItem("256")
|
179 |
self.width.addItem("512")
|
180 |
self.width.addItem("768")
|
|
|
181 |
self.width.setCurrentText("512")
|
182 |
self.width.currentIndexChanged.connect(self.on_width_changed)
|
183 |
|
@@ -186,6 +247,7 @@ class MainWindow(QMainWindow):
|
|
186 |
self.height.addItem("256")
|
187 |
self.height.addItem("512")
|
188 |
self.height.addItem("768")
|
|
|
189 |
self.height.setCurrentText("512")
|
190 |
self.height.currentIndexChanged.connect(self.on_height_changed)
|
191 |
|
@@ -201,14 +263,27 @@ class MainWindow(QMainWindow):
|
|
201 |
|
202 |
self.use_openvino_check = QCheckBox("Use OpenVINO")
|
203 |
self.use_openvino_check.setChecked(False)
|
|
|
204 |
self.use_local_model_folder = QCheckBox(
|
205 |
"Use locally cached model or downloaded model folder(offline)"
|
206 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
self.use_openvino_check.setEnabled(enable_openvino_controls())
|
208 |
self.use_local_model_folder.setChecked(False)
|
209 |
self.use_local_model_folder.stateChanged.connect(self.use_offline_model_changed)
|
210 |
self.use_openvino_check.stateChanged.connect(self.use_openvino_changed)
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
hlayout = QHBoxLayout()
|
213 |
hlayout.addWidget(self.seed_check)
|
214 |
hlayout.addWidget(self.seed_value)
|
@@ -228,8 +303,18 @@ class MainWindow(QMainWindow):
|
|
228 |
vlayout = QVBoxLayout()
|
229 |
vspacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
230 |
vlayout.addItem(hspacer)
|
231 |
-
vlayout.
|
|
|
232 |
vlayout.addWidget(self.use_local_model_folder)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
vlayout.addItem(slider_hspacer)
|
234 |
vlayout.addWidget(self.inference_steps_value)
|
235 |
vlayout.addWidget(self.inference_steps)
|
@@ -243,7 +328,7 @@ class MainWindow(QMainWindow):
|
|
243 |
vlayout.addWidget(self.guidance)
|
244 |
vlayout.addLayout(hlayout)
|
245 |
vlayout.addWidget(self.safety_checker)
|
246 |
-
|
247 |
vlayout.addWidget(self.results_path_label)
|
248 |
hlayout_path = QHBoxLayout()
|
249 |
hlayout_path.addWidget(self.results_path)
|
@@ -272,11 +357,27 @@ class MainWindow(QMainWindow):
|
|
272 |
vlayout.addWidget(self.label)
|
273 |
self.tab_about.setLayout(vlayout)
|
274 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
def on_show_next_image(self):
|
276 |
if self.image_index != len(self.gen_images) - 1 and len(self.gen_images) > 0:
|
277 |
self.previous_img_btn.setEnabled(True)
|
278 |
self.image_index += 1
|
279 |
-
self.
|
280 |
if self.image_index == len(self.gen_images) - 1:
|
281 |
self.next_img_btn.setEnabled(False)
|
282 |
|
@@ -287,7 +388,7 @@ class MainWindow(QMainWindow):
|
|
287 |
if self.image_index != 0:
|
288 |
self.next_img_btn.setEnabled(True)
|
289 |
self.image_index -= 1
|
290 |
-
self.
|
291 |
if self.image_index == 0:
|
292 |
self.previous_img_btn.setEnabled(False)
|
293 |
|
@@ -314,19 +415,62 @@ class MainWindow(QMainWindow):
|
|
314 |
height_txt = self.height.itemText(index)
|
315 |
self.config.settings.lcm_diffusion_setting.image_height = int(height_txt)
|
316 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
def use_openvino_changed(self, state):
|
318 |
if state == 2:
|
319 |
self.lcm_model.setEnabled(False)
|
|
|
|
|
|
|
|
|
|
|
320 |
self.config.settings.lcm_diffusion_setting.use_openvino = True
|
321 |
else:
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
self.config.settings.lcm_diffusion_setting.use_openvino = False
|
323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
def use_offline_model_changed(self, state):
|
325 |
if state == 2:
|
326 |
self.config.settings.lcm_diffusion_setting.use_offline_model = True
|
327 |
else:
|
328 |
self.config.settings.lcm_diffusion_setting.use_offline_model = False
|
329 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
def use_safety_checker_changed(self, state):
|
331 |
if state == 2:
|
332 |
self.config.settings.lcm_diffusion_setting.use_safety_checker = True
|
@@ -362,11 +506,20 @@ class MainWindow(QMainWindow):
|
|
362 |
def generate_image(self):
|
363 |
self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value()
|
364 |
self.config.settings.lcm_diffusion_setting.prompt = self.prompt.toPlainText()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
|
366 |
if self.config.settings.lcm_diffusion_setting.use_openvino:
|
367 |
-
model_id =
|
368 |
else:
|
369 |
-
model_id = self.lcm_model.
|
370 |
|
371 |
self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id
|
372 |
|
@@ -403,7 +556,7 @@ class MainWindow(QMainWindow):
|
|
403 |
self.next_img_btn.setEnabled(False)
|
404 |
self.previous_img_btn.setEnabled(False)
|
405 |
|
406 |
-
self.
|
407 |
|
408 |
self.previous_width = self.config.settings.lcm_diffusion_setting.image_width
|
409 |
self.previous_height = self.config.settings.lcm_diffusion_setting.image_height
|
@@ -428,8 +581,10 @@ class MainWindow(QMainWindow):
|
|
428 |
self.width.setCurrentText("512")
|
429 |
self.height.setCurrentText("512")
|
430 |
self.inference_steps.setValue(4)
|
431 |
-
self.guidance.setValue(
|
432 |
self.use_openvino_check.setChecked(False)
|
433 |
self.seed_check.setChecked(False)
|
434 |
-
self.safety_checker.setChecked(
|
435 |
self.results_path.setText(FastStableDiffusionPaths().get_results_path())
|
|
|
|
|
|
16 |
QToolButton,
|
17 |
QFileDialog,
|
18 |
)
|
19 |
+
from PyQt5 import QtWidgets, QtCore
|
20 |
from PyQt5.QtGui import QPixmap, QDesktopServices
|
21 |
from PyQt5.QtCore import QSize, QThreadPool, Qt, QUrl
|
22 |
|
|
|
34 |
from context import Context
|
35 |
from models.interface_types import InterfaceType
|
36 |
from constants import DEVICE
|
37 |
+
from frontend.utils import enable_openvino_controls, get_valid_model_id
|
38 |
+
from backend.lcm_models import get_available_models
|
39 |
+
|
40 |
+
# DPI scale fix
|
41 |
+
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
|
42 |
+
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
43 |
|
44 |
|
45 |
class MainWindow(QMainWindow):
|
46 |
def __init__(self, config: AppSettings):
|
47 |
super().__init__()
|
48 |
+
self.config = config
|
49 |
self.setWindowTitle(APP_NAME)
|
50 |
+
self.setFixedSize(QSize(600, 670))
|
51 |
self.init_ui()
|
52 |
self.pipeline = None
|
53 |
self.threadpool = QThreadPool()
|
|
|
54 |
self.device = "cpu"
|
55 |
self.previous_width = 0
|
56 |
self.previous_height = 0
|
|
|
94 |
self.num_images.setValue(
|
95 |
self.config.settings.lcm_diffusion_setting.number_of_images
|
96 |
)
|
97 |
+
self.use_tae_sd.setChecked(
|
98 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder
|
99 |
+
)
|
100 |
+
self.use_lcm_lora.setChecked(
|
101 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora
|
102 |
+
)
|
103 |
+
self.base_model_id.setCurrentText(
|
104 |
+
get_valid_model_id(
|
105 |
+
self.config.stable_diffsuion_models,
|
106 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id,
|
107 |
+
)
|
108 |
+
)
|
109 |
+
self.lcm_lora_id.setCurrentText(
|
110 |
+
get_valid_model_id(
|
111 |
+
self.config.lcm_lora_models,
|
112 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id,
|
113 |
+
)
|
114 |
+
)
|
115 |
+
self.openvino_lcm_model_id.setCurrentText(
|
116 |
+
get_valid_model_id(
|
117 |
+
self.config.openvino_lcm_models,
|
118 |
+
self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id,
|
119 |
+
)
|
120 |
+
)
|
121 |
+
self.neg_prompt.setEnabled(
|
122 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora
|
123 |
+
or self.config.settings.lcm_diffusion_setting.use_openvino
|
124 |
+
)
|
125 |
+
self.openvino_lcm_model_id.setEnabled(
|
126 |
+
self.config.settings.lcm_diffusion_setting.use_openvino
|
127 |
+
)
|
128 |
|
129 |
def init_ui(self):
|
130 |
self.create_main_tab()
|
|
|
136 |
self.img = QLabel("<<Image>>")
|
137 |
self.img.setAlignment(Qt.AlignCenter)
|
138 |
self.img.setFixedSize(QSize(512, 512))
|
139 |
+
self.vspacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
140 |
|
141 |
self.prompt = QTextEdit()
|
142 |
self.prompt.setPlaceholderText("A fantasy landscape")
|
143 |
self.prompt.setAcceptRichText(False)
|
144 |
+
self.neg_prompt = QTextEdit()
|
145 |
+
self.neg_prompt.setPlaceholderText("")
|
146 |
+
self.neg_prompt.setAcceptRichText(False)
|
147 |
+
self.neg_prompt_label = QLabel("Negative prompt (Set guidance scale > 1.0):")
|
148 |
self.generate = QPushButton("Generate")
|
149 |
self.generate.clicked.connect(self.text_to_image)
|
150 |
+
self.prompt.setFixedHeight(40)
|
151 |
+
self.neg_prompt.setFixedHeight(35)
|
152 |
self.browse_results = QPushButton("...")
|
153 |
self.browse_results.setFixedWidth(30)
|
154 |
self.browse_results.clicked.connect(self.on_open_results_folder)
|
155 |
self.browse_results.setToolTip("Open output folder")
|
156 |
|
157 |
hlayout = QHBoxLayout()
|
158 |
+
hlayout.addWidget(self.neg_prompt)
|
159 |
hlayout.addWidget(self.generate)
|
160 |
hlayout.addWidget(self.browse_results)
|
161 |
|
|
|
172 |
|
173 |
vlayout = QVBoxLayout()
|
174 |
vlayout.addLayout(hlayout_nav)
|
175 |
+
vlayout.addItem(self.vspacer)
|
176 |
+
vlayout.addWidget(self.prompt)
|
177 |
+
vlayout.addWidget(self.neg_prompt_label)
|
178 |
vlayout.addLayout(hlayout)
|
179 |
|
180 |
self.tab_widget = QTabWidget(self)
|
|
|
191 |
self.use_seed = False
|
192 |
|
193 |
def create_settings_tab(self):
|
|
|
194 |
self.lcm_model_label = QLabel("Latent Consistency Model:")
|
195 |
+
# self.lcm_model = QLineEdit(LCM_DEFAULT_MODEL)
|
196 |
+
lcm_models = get_available_models()
|
197 |
+
self.lcm_model = QComboBox(self)
|
198 |
+
for model in lcm_models:
|
199 |
+
self.lcm_model.addItem(model)
|
200 |
+
|
201 |
+
self.use_lcm_lora = QCheckBox("Use LCM LoRA")
|
202 |
+
self.use_lcm_lora.setChecked(False)
|
203 |
+
self.use_lcm_lora.stateChanged.connect(self.use_lcm_lora_changed)
|
204 |
+
|
205 |
+
self.lora_base_model_id_label = QLabel("Lora base model ID :")
|
206 |
+
self.base_model_id = QComboBox(self)
|
207 |
+
self.base_model_id.addItems(self.config.stable_diffsuion_models)
|
208 |
+
self.base_model_id.currentIndexChanged.connect(self.on_base_model_id_changed)
|
209 |
+
|
210 |
+
self.lcm_lora_model_id_label = QLabel("LCM LoRA model ID :")
|
211 |
+
self.lcm_lora_id = QComboBox(self)
|
212 |
+
self.lcm_lora_id.addItems(self.config.lcm_lora_models)
|
213 |
+
self.lcm_lora_id.currentIndexChanged.connect(self.on_lcm_lora_id_changed)
|
214 |
|
215 |
self.inference_steps_value = QLabel("Number of inference steps: 4")
|
216 |
self.inference_steps = QSlider(orientation=Qt.Orientation.Horizontal)
|
|
|
226 |
self.num_images.setValue(1)
|
227 |
self.num_images.valueChanged.connect(self.update_num_images_label)
|
228 |
|
229 |
+
self.guidance_value = QLabel("Guidance scale: 1")
|
230 |
self.guidance = QSlider(orientation=Qt.Orientation.Horizontal)
|
231 |
+
self.guidance.setMaximum(20)
|
232 |
self.guidance.setMinimum(10)
|
233 |
+
self.guidance.setValue(10)
|
234 |
self.guidance.valueChanged.connect(self.update_guidance_label)
|
235 |
|
236 |
self.width_value = QLabel("Width :")
|
|
|
238 |
self.width.addItem("256")
|
239 |
self.width.addItem("512")
|
240 |
self.width.addItem("768")
|
241 |
+
self.width.addItem("1024")
|
242 |
self.width.setCurrentText("512")
|
243 |
self.width.currentIndexChanged.connect(self.on_width_changed)
|
244 |
|
|
|
247 |
self.height.addItem("256")
|
248 |
self.height.addItem("512")
|
249 |
self.height.addItem("768")
|
250 |
+
self.height.addItem("1024")
|
251 |
self.height.setCurrentText("512")
|
252 |
self.height.currentIndexChanged.connect(self.on_height_changed)
|
253 |
|
|
|
263 |
|
264 |
self.use_openvino_check = QCheckBox("Use OpenVINO")
|
265 |
self.use_openvino_check.setChecked(False)
|
266 |
+
self.openvino_model_label = QLabel("OpenVINO LCM model:")
|
267 |
self.use_local_model_folder = QCheckBox(
|
268 |
"Use locally cached model or downloaded model folder(offline)"
|
269 |
)
|
270 |
+
self.openvino_lcm_model_id = QComboBox(self)
|
271 |
+
self.openvino_lcm_model_id.addItems(self.config.openvino_lcm_models)
|
272 |
+
self.openvino_lcm_model_id.currentIndexChanged.connect(
|
273 |
+
self.on_openvino_lcm_model_id_changed
|
274 |
+
)
|
275 |
+
|
276 |
self.use_openvino_check.setEnabled(enable_openvino_controls())
|
277 |
self.use_local_model_folder.setChecked(False)
|
278 |
self.use_local_model_folder.stateChanged.connect(self.use_offline_model_changed)
|
279 |
self.use_openvino_check.stateChanged.connect(self.use_openvino_changed)
|
280 |
|
281 |
+
self.use_tae_sd = QCheckBox(
|
282 |
+
"Use Tiny Auto Encoder - TAESD (Fast, moderate quality)"
|
283 |
+
)
|
284 |
+
self.use_tae_sd.setChecked(False)
|
285 |
+
self.use_tae_sd.stateChanged.connect(self.use_tae_sd_changed)
|
286 |
+
|
287 |
hlayout = QHBoxLayout()
|
288 |
hlayout.addWidget(self.seed_check)
|
289 |
hlayout.addWidget(self.seed_value)
|
|
|
303 |
vlayout = QVBoxLayout()
|
304 |
vspacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
305 |
vlayout.addItem(hspacer)
|
306 |
+
vlayout.addWidget(self.lcm_model_label)
|
307 |
+
vlayout.addWidget(self.lcm_model)
|
308 |
vlayout.addWidget(self.use_local_model_folder)
|
309 |
+
vlayout.addWidget(self.use_lcm_lora)
|
310 |
+
vlayout.addWidget(self.lora_base_model_id_label)
|
311 |
+
vlayout.addWidget(self.base_model_id)
|
312 |
+
vlayout.addWidget(self.lcm_lora_model_id_label)
|
313 |
+
vlayout.addWidget(self.lcm_lora_id)
|
314 |
+
vlayout.addWidget(self.use_openvino_check)
|
315 |
+
vlayout.addWidget(self.openvino_model_label)
|
316 |
+
vlayout.addWidget(self.openvino_lcm_model_id)
|
317 |
+
vlayout.addWidget(self.use_tae_sd)
|
318 |
vlayout.addItem(slider_hspacer)
|
319 |
vlayout.addWidget(self.inference_steps_value)
|
320 |
vlayout.addWidget(self.inference_steps)
|
|
|
328 |
vlayout.addWidget(self.guidance)
|
329 |
vlayout.addLayout(hlayout)
|
330 |
vlayout.addWidget(self.safety_checker)
|
331 |
+
|
332 |
vlayout.addWidget(self.results_path_label)
|
333 |
hlayout_path = QHBoxLayout()
|
334 |
hlayout_path.addWidget(self.results_path)
|
|
|
357 |
vlayout.addWidget(self.label)
|
358 |
self.tab_about.setLayout(vlayout)
|
359 |
|
360 |
+
def show_image(self, pixmap):
|
361 |
+
image_width = self.config.settings.lcm_diffusion_setting.image_width
|
362 |
+
image_height = self.config.settings.lcm_diffusion_setting.image_height
|
363 |
+
if image_width > 512 or image_height > 512:
|
364 |
+
new_width = 512 if image_width > 512 else image_width
|
365 |
+
new_height = 512 if image_height > 512 else image_height
|
366 |
+
self.img.setPixmap(
|
367 |
+
pixmap.scaled(
|
368 |
+
new_width,
|
369 |
+
new_height,
|
370 |
+
Qt.KeepAspectRatio,
|
371 |
+
)
|
372 |
+
)
|
373 |
+
else:
|
374 |
+
self.img.setPixmap(pixmap)
|
375 |
+
|
376 |
def on_show_next_image(self):
|
377 |
if self.image_index != len(self.gen_images) - 1 and len(self.gen_images) > 0:
|
378 |
self.previous_img_btn.setEnabled(True)
|
379 |
self.image_index += 1
|
380 |
+
self.show_image(self.gen_images[self.image_index])
|
381 |
if self.image_index == len(self.gen_images) - 1:
|
382 |
self.next_img_btn.setEnabled(False)
|
383 |
|
|
|
388 |
if self.image_index != 0:
|
389 |
self.next_img_btn.setEnabled(True)
|
390 |
self.image_index -= 1
|
391 |
+
self.show_image(self.gen_images[self.image_index])
|
392 |
if self.image_index == 0:
|
393 |
self.previous_img_btn.setEnabled(False)
|
394 |
|
|
|
415 |
height_txt = self.height.itemText(index)
|
416 |
self.config.settings.lcm_diffusion_setting.image_height = int(height_txt)
|
417 |
|
418 |
+
def on_base_model_id_changed(self, index):
|
419 |
+
model_id = self.base_model_id.itemText(index)
|
420 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = model_id
|
421 |
+
|
422 |
+
def on_lcm_lora_id_changed(self, index):
|
423 |
+
model_id = self.lcm_lora_id.itemText(index)
|
424 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = model_id
|
425 |
+
|
426 |
+
def on_openvino_lcm_model_id_changed(self, index):
|
427 |
+
model_id = self.openvino_lcm_model_id.itemText(index)
|
428 |
+
self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id = model_id
|
429 |
+
|
430 |
def use_openvino_changed(self, state):
|
431 |
if state == 2:
|
432 |
self.lcm_model.setEnabled(False)
|
433 |
+
self.use_lcm_lora.setEnabled(False)
|
434 |
+
self.lcm_lora_id.setEnabled(False)
|
435 |
+
self.base_model_id.setEnabled(False)
|
436 |
+
self.neg_prompt.setEnabled(True)
|
437 |
+
self.openvino_lcm_model_id.setEnabled(True)
|
438 |
self.config.settings.lcm_diffusion_setting.use_openvino = True
|
439 |
else:
|
440 |
+
self.lcm_model.setEnabled(True)
|
441 |
+
self.use_lcm_lora.setEnabled(True)
|
442 |
+
self.lcm_lora_id.setEnabled(True)
|
443 |
+
self.base_model_id.setEnabled(True)
|
444 |
+
self.neg_prompt.setEnabled(False)
|
445 |
+
self.openvino_lcm_model_id.setEnabled(False)
|
446 |
self.config.settings.lcm_diffusion_setting.use_openvino = False
|
447 |
|
448 |
+
def use_tae_sd_changed(self, state):
|
449 |
+
if state == 2:
|
450 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = True
|
451 |
+
else:
|
452 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = False
|
453 |
+
|
454 |
def use_offline_model_changed(self, state):
|
455 |
if state == 2:
|
456 |
self.config.settings.lcm_diffusion_setting.use_offline_model = True
|
457 |
else:
|
458 |
self.config.settings.lcm_diffusion_setting.use_offline_model = False
|
459 |
|
460 |
+
def use_lcm_lora_changed(self, state):
|
461 |
+
if state == 2:
|
462 |
+
self.lcm_model.setEnabled(False)
|
463 |
+
self.lcm_lora_id.setEnabled(True)
|
464 |
+
self.base_model_id.setEnabled(True)
|
465 |
+
self.neg_prompt.setEnabled(True)
|
466 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora = True
|
467 |
+
else:
|
468 |
+
self.lcm_model.setEnabled(True)
|
469 |
+
self.lcm_lora_id.setEnabled(False)
|
470 |
+
self.base_model_id.setEnabled(False)
|
471 |
+
self.neg_prompt.setEnabled(False)
|
472 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora = False
|
473 |
+
|
474 |
def use_safety_checker_changed(self, state):
|
475 |
if state == 2:
|
476 |
self.config.settings.lcm_diffusion_setting.use_safety_checker = True
|
|
|
506 |
def generate_image(self):
|
507 |
self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value()
|
508 |
self.config.settings.lcm_diffusion_setting.prompt = self.prompt.toPlainText()
|
509 |
+
self.config.settings.lcm_diffusion_setting.negative_prompt = (
|
510 |
+
self.neg_prompt.toPlainText()
|
511 |
+
)
|
512 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = (
|
513 |
+
self.lcm_lora_id.currentText()
|
514 |
+
)
|
515 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = (
|
516 |
+
self.base_model_id.currentText()
|
517 |
+
)
|
518 |
|
519 |
if self.config.settings.lcm_diffusion_setting.use_openvino:
|
520 |
+
model_id = self.openvino_lcm_model_id.currentText()
|
521 |
else:
|
522 |
+
model_id = self.lcm_model.currentText()
|
523 |
|
524 |
self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id
|
525 |
|
|
|
556 |
self.next_img_btn.setEnabled(False)
|
557 |
self.previous_img_btn.setEnabled(False)
|
558 |
|
559 |
+
self.show_image(self.gen_images[0])
|
560 |
|
561 |
self.previous_width = self.config.settings.lcm_diffusion_setting.image_width
|
562 |
self.previous_height = self.config.settings.lcm_diffusion_setting.image_height
|
|
|
581 |
self.width.setCurrentText("512")
|
582 |
self.height.setCurrentText("512")
|
583 |
self.inference_steps.setValue(4)
|
584 |
+
self.guidance.setValue(10)
|
585 |
self.use_openvino_check.setChecked(False)
|
586 |
self.seed_check.setChecked(False)
|
587 |
+
self.safety_checker.setChecked(False)
|
588 |
self.results_path.setText(FastStableDiffusionPaths().get_results_path())
|
589 |
+
self.use_tae_sd.setChecked(False)
|
590 |
+
self.use_lcm_lora.setChecked(False)
|
frontend/utils.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
from constants import DEVICE
|
|
|
2 |
import platform
|
|
|
3 |
|
4 |
|
5 |
def is_reshape_required(
|
@@ -12,9 +14,6 @@ def is_reshape_required(
|
|
12 |
prev_num_of_images: int,
|
13 |
cur_num_of_images: int,
|
14 |
) -> bool:
|
15 |
-
print(f"width - {prev_width} {cur_width}")
|
16 |
-
print(f"height - {prev_height} {cur_height}")
|
17 |
-
print(f"model - {prev_model} {cur_model}")
|
18 |
reshape_required = False
|
19 |
if (
|
20 |
prev_width != cur_width
|
@@ -29,4 +28,23 @@ def is_reshape_required(
|
|
29 |
|
30 |
|
31 |
def enable_openvino_controls() -> bool:
|
32 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from constants import DEVICE
|
2 |
+
from typing import List
|
3 |
import platform
|
4 |
+
from backend.device import is_openvino_device
|
5 |
|
6 |
|
7 |
def is_reshape_required(
|
|
|
14 |
prev_num_of_images: int,
|
15 |
cur_num_of_images: int,
|
16 |
) -> bool:
|
|
|
|
|
|
|
17 |
reshape_required = False
|
18 |
if (
|
19 |
prev_width != cur_width
|
|
|
28 |
|
29 |
|
30 |
def enable_openvino_controls() -> bool:
|
31 |
+
return is_openvino_device() and platform.system().lower() != "darwin"
|
32 |
+
|
33 |
+
|
34 |
+
def get_valid_model_id(
|
35 |
+
models: List,
|
36 |
+
model_id: str,
|
37 |
+
) -> str:
|
38 |
+
if len(models) == 0:
|
39 |
+
print("Error: model configuration file is empty,please add some models.")
|
40 |
+
return ""
|
41 |
+
if model_id == "":
|
42 |
+
return models[0]
|
43 |
+
|
44 |
+
if model_id in models:
|
45 |
+
return model_id
|
46 |
+
else:
|
47 |
+
print(
|
48 |
+
f"Error:{model_id} Model not found in configuration file,so using first model : {models[0]}"
|
49 |
+
)
|
50 |
+
return models[0]
|
frontend/webui/text_to_image_ui.py
CHANGED
@@ -10,19 +10,6 @@ from frontend.utils import is_reshape_required
|
|
10 |
from app_settings import AppSettings
|
11 |
from constants import DEVICE
|
12 |
from frontend.utils import enable_openvino_controls
|
13 |
-
from scipy.ndimage import zoom
|
14 |
-
import numpy as np
|
15 |
-
from PIL import Image
|
16 |
-
from super_image import CarnModel, ImageLoader
|
17 |
-
from torchvision import transforms
|
18 |
-
|
19 |
-
transform_image = transforms.ToPILImage()
|
20 |
-
|
21 |
-
|
22 |
-
def tensor2img(tensor):
|
23 |
-
tensor = tensor.squeeze(0).cpu().clamp(0, 1)
|
24 |
-
return transform_image(tensor)
|
25 |
-
|
26 |
|
27 |
random_enabled = True
|
28 |
|
@@ -31,16 +18,19 @@ previous_width = 0
|
|
31 |
previous_height = 0
|
32 |
previous_model_id = ""
|
33 |
previous_num_of_images = 0
|
34 |
-
upscaler = CarnModel.from_pretrained("eugenesiow/carn-bam", scale=2)
|
35 |
|
36 |
|
37 |
def generate_text_to_image(
|
38 |
prompt,
|
|
|
|
|
39 |
inference_steps,
|
40 |
guidance_scale,
|
|
|
41 |
seed,
|
42 |
use_openvino,
|
43 |
use_safety_checker,
|
|
|
44 |
) -> Any:
|
45 |
global previous_height, previous_width, previous_model_id, previous_num_of_images
|
46 |
model_id = LCM_DEFAULT_MODEL
|
@@ -52,15 +42,16 @@ def generate_text_to_image(
|
|
52 |
lcm_diffusion_settings = LCMDiffusionSetting(
|
53 |
lcm_model_id=model_id,
|
54 |
prompt=prompt,
|
55 |
-
image_height=
|
56 |
-
image_width=
|
57 |
inference_steps=inference_steps,
|
58 |
guidance_scale=guidance_scale,
|
59 |
-
number_of_images=
|
60 |
seed=seed,
|
61 |
use_openvino=use_openvino,
|
62 |
use_safety_checker=use_safety_checker,
|
63 |
use_seed=use_seed,
|
|
|
64 |
)
|
65 |
settings = Settings(
|
66 |
lcm_diffusion_setting=lcm_diffusion_settings,
|
@@ -69,30 +60,23 @@ def generate_text_to_image(
|
|
69 |
if use_openvino:
|
70 |
reshape = is_reshape_required(
|
71 |
previous_width,
|
72 |
-
|
73 |
previous_height,
|
74 |
-
|
75 |
previous_model_id,
|
76 |
model_id,
|
77 |
previous_num_of_images,
|
78 |
-
|
79 |
)
|
80 |
images = context.generate_text_to_image(
|
81 |
settings,
|
82 |
reshape,
|
83 |
DEVICE,
|
84 |
)
|
85 |
-
previous_width =
|
86 |
-
previous_height =
|
87 |
previous_model_id = model_id
|
88 |
-
previous_num_of_images =
|
89 |
-
out_images = []
|
90 |
-
# for image in images:
|
91 |
-
# out_images.append(image.resize((768, 768), resample=Image.LANCZOS))
|
92 |
-
# # in_image = ImageLoader.load_image(image)
|
93 |
-
# # up_image = upscaler(in_image)
|
94 |
-
# # out_images.append(tensor2img(up_image))
|
95 |
-
# # out_images(image)
|
96 |
|
97 |
return images
|
98 |
|
@@ -124,10 +108,25 @@ def get_text_to_image_ui(app_settings: AppSettings) -> None:
|
|
124 |
elem_id="generate_button",
|
125 |
scale=0,
|
126 |
)
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
with gr.Accordion("Advanced options", open=False):
|
129 |
guidance_scale = gr.Slider(
|
130 |
-
1.0,
|
131 |
)
|
132 |
|
133 |
seed = gr.Number(
|
@@ -144,8 +143,8 @@ def get_text_to_image_ui(app_settings: AppSettings) -> None:
|
|
144 |
|
145 |
openvino_checkbox = gr.Checkbox(
|
146 |
label="Use OpenVINO",
|
147 |
-
value=
|
148 |
-
interactive=
|
149 |
)
|
150 |
|
151 |
safety_checker_checkbox = gr.Checkbox(
|
@@ -153,30 +152,23 @@ def get_text_to_image_ui(app_settings: AppSettings) -> None:
|
|
153 |
value=True,
|
154 |
interactive=True,
|
155 |
)
|
156 |
-
|
157 |
-
|
|
|
|
|
158 |
)
|
159 |
-
# image_height = gr.Slider(
|
160 |
-
# 256, 768, value=384, step=64, label="Image Height",interactive=Fa
|
161 |
-
# )
|
162 |
-
# image_width = gr.Slider(
|
163 |
-
# 256, 768, value=384, step=64, label="Image Width"
|
164 |
-
# )
|
165 |
-
# num_images = gr.Slider(
|
166 |
-
# 1,
|
167 |
-
# 50,
|
168 |
-
# value=1,
|
169 |
-
# step=1,
|
170 |
-
# label="Number of images to generate",
|
171 |
-
# )
|
172 |
|
173 |
input_params = [
|
174 |
prompt,
|
|
|
|
|
175 |
num_inference_steps,
|
176 |
guidance_scale,
|
|
|
177 |
seed,
|
178 |
openvino_checkbox,
|
179 |
safety_checker_checkbox,
|
|
|
180 |
]
|
181 |
|
182 |
with gr.Column():
|
|
|
10 |
from app_settings import AppSettings
|
11 |
from constants import DEVICE
|
12 |
from frontend.utils import enable_openvino_controls
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
random_enabled = True
|
15 |
|
|
|
18 |
previous_height = 0
|
19 |
previous_model_id = ""
|
20 |
previous_num_of_images = 0
|
|
|
21 |
|
22 |
|
23 |
def generate_text_to_image(
|
24 |
prompt,
|
25 |
+
image_height,
|
26 |
+
image_width,
|
27 |
inference_steps,
|
28 |
guidance_scale,
|
29 |
+
num_images,
|
30 |
seed,
|
31 |
use_openvino,
|
32 |
use_safety_checker,
|
33 |
+
tiny_auto_encoder_checkbox,
|
34 |
) -> Any:
|
35 |
global previous_height, previous_width, previous_model_id, previous_num_of_images
|
36 |
model_id = LCM_DEFAULT_MODEL
|
|
|
42 |
lcm_diffusion_settings = LCMDiffusionSetting(
|
43 |
lcm_model_id=model_id,
|
44 |
prompt=prompt,
|
45 |
+
image_height=image_height,
|
46 |
+
image_width=image_width,
|
47 |
inference_steps=inference_steps,
|
48 |
guidance_scale=guidance_scale,
|
49 |
+
number_of_images=num_images,
|
50 |
seed=seed,
|
51 |
use_openvino=use_openvino,
|
52 |
use_safety_checker=use_safety_checker,
|
53 |
use_seed=use_seed,
|
54 |
+
use_tiny_auto_encoder=tiny_auto_encoder_checkbox,
|
55 |
)
|
56 |
settings = Settings(
|
57 |
lcm_diffusion_setting=lcm_diffusion_settings,
|
|
|
60 |
if use_openvino:
|
61 |
reshape = is_reshape_required(
|
62 |
previous_width,
|
63 |
+
image_width,
|
64 |
previous_height,
|
65 |
+
image_height,
|
66 |
previous_model_id,
|
67 |
model_id,
|
68 |
previous_num_of_images,
|
69 |
+
num_images,
|
70 |
)
|
71 |
images = context.generate_text_to_image(
|
72 |
settings,
|
73 |
reshape,
|
74 |
DEVICE,
|
75 |
)
|
76 |
+
previous_width = image_width
|
77 |
+
previous_height = image_height
|
78 |
previous_model_id = model_id
|
79 |
+
previous_num_of_images = num_images
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
return images
|
82 |
|
|
|
108 |
elem_id="generate_button",
|
109 |
scale=0,
|
110 |
)
|
111 |
+
num_inference_steps = gr.Slider(
|
112 |
+
1, 25, value=4, step=1, label="Inference Steps"
|
113 |
+
)
|
114 |
+
image_height = gr.Slider(
|
115 |
+
256, 768, value=512, step=256, label="Image Height"
|
116 |
+
)
|
117 |
+
image_width = gr.Slider(
|
118 |
+
256, 768, value=512, step=256, label="Image Width"
|
119 |
+
)
|
120 |
+
num_images = gr.Slider(
|
121 |
+
1,
|
122 |
+
50,
|
123 |
+
value=1,
|
124 |
+
step=1,
|
125 |
+
label="Number of images to generate",
|
126 |
+
)
|
127 |
with gr.Accordion("Advanced options", open=False):
|
128 |
guidance_scale = gr.Slider(
|
129 |
+
1.0, 2.0, value=1.0, step=0.5, label="Guidance Scale"
|
130 |
)
|
131 |
|
132 |
seed = gr.Number(
|
|
|
143 |
|
144 |
openvino_checkbox = gr.Checkbox(
|
145 |
label="Use OpenVINO",
|
146 |
+
value=False,
|
147 |
+
interactive=enable_openvino_controls(),
|
148 |
)
|
149 |
|
150 |
safety_checker_checkbox = gr.Checkbox(
|
|
|
152 |
value=True,
|
153 |
interactive=True,
|
154 |
)
|
155 |
+
tiny_auto_encoder_checkbox = gr.Checkbox(
|
156 |
+
label="Use tiny auto encoder for SD",
|
157 |
+
value=False,
|
158 |
+
interactive=True,
|
159 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
|
161 |
input_params = [
|
162 |
prompt,
|
163 |
+
image_height,
|
164 |
+
image_width,
|
165 |
num_inference_steps,
|
166 |
guidance_scale,
|
167 |
+
num_images,
|
168 |
seed,
|
169 |
openvino_checkbox,
|
170 |
safety_checker_checkbox,
|
171 |
+
tiny_auto_encoder_checkbox,
|
172 |
]
|
173 |
|
174 |
with gr.Column():
|
frontend/webui/ui.py
CHANGED
@@ -6,7 +6,7 @@ from app_settings import AppSettings
|
|
6 |
|
7 |
|
8 |
def _get_footer_message() -> str:
|
9 |
-
version = f"<center><p>
|
10 |
footer_msg = version + (
|
11 |
' © 2023 <a href="https://github.com/rupeshs">'
|
12 |
" Rupesh Sreeraman</a></p></center>"
|
@@ -19,7 +19,7 @@ def get_web_ui(app_settings: AppSettings) -> gr.Blocks:
|
|
19 |
css=FastStableDiffusionPaths.get_css_path(),
|
20 |
title="FastSD CPU",
|
21 |
) as fastsd_web_ui:
|
22 |
-
gr.HTML("<center><H1>FastSD CPU
|
23 |
with gr.Tabs():
|
24 |
with gr.TabItem("Text to Image"):
|
25 |
get_text_to_image_ui(app_settings)
|
|
|
6 |
|
7 |
|
8 |
def _get_footer_message() -> str:
|
9 |
+
version = f"<center><p> {APP_VERSION} "
|
10 |
footer_msg = version + (
|
11 |
' © 2023 <a href="https://github.com/rupeshs">'
|
12 |
" Rupesh Sreeraman</a></p></center>"
|
|
|
19 |
css=FastStableDiffusionPaths.get_css_path(),
|
20 |
title="FastSD CPU",
|
21 |
) as fastsd_web_ui:
|
22 |
+
gr.HTML("<center><H1>FastSD CPU</H1></center>")
|
23 |
with gr.Tabs():
|
24 |
with gr.TabItem("Text to Image"):
|
25 |
get_text_to_image_ui(app_settings)
|
models/__pycache__/interface_types.cpython-311.pyc
CHANGED
Binary files a/models/__pycache__/interface_types.cpython-311.pyc and b/models/__pycache__/interface_types.cpython-311.pyc differ
|
|
models/__pycache__/settings.cpython-311.pyc
CHANGED
Binary files a/models/__pycache__/settings.cpython-311.pyc and b/models/__pycache__/settings.cpython-311.pyc differ
|
|
models/settings.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
from pydantic import BaseModel
|
2 |
-
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting
|
3 |
from paths import FastStableDiffusionPaths
|
4 |
|
5 |
|
6 |
class Settings(BaseModel):
|
7 |
results_path: str = FastStableDiffusionPaths().get_results_path()
|
8 |
-
lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting()
|
|
|
1 |
from pydantic import BaseModel
|
2 |
+
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting, LCMLora
|
3 |
from paths import FastStableDiffusionPaths
|
4 |
|
5 |
|
6 |
class Settings(BaseModel):
|
7 |
results_path: str = FastStableDiffusionPaths().get_results_path()
|
8 |
+
lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting(lcm_lora=LCMLora())
|
paths.py
CHANGED
@@ -9,7 +9,7 @@ def join_paths(
|
|
9 |
return os.path.join(first_path, second_path)
|
10 |
|
11 |
|
12 |
-
def get_app_path():
|
13 |
app_dir = os.path.dirname(__file__)
|
14 |
work_dir = os.path.dirname(app_dir)
|
15 |
return work_dir
|
@@ -36,7 +36,7 @@ class FastStableDiffusionPaths:
|
|
36 |
return results_path
|
37 |
|
38 |
@staticmethod
|
39 |
-
def get_css_path():
|
40 |
app_dir = os.path.dirname(__file__)
|
41 |
css_path = os.path.join(
|
42 |
app_dir,
|
@@ -46,3 +46,12 @@ class FastStableDiffusionPaths:
|
|
46 |
"style.css",
|
47 |
)
|
48 |
return css_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
return os.path.join(first_path, second_path)
|
10 |
|
11 |
|
12 |
+
def get_app_path() -> str:
|
13 |
app_dir = os.path.dirname(__file__)
|
14 |
work_dir = os.path.dirname(app_dir)
|
15 |
return work_dir
|
|
|
36 |
return results_path
|
37 |
|
38 |
@staticmethod
|
39 |
+
def get_css_path() -> str:
|
40 |
app_dir = os.path.dirname(__file__)
|
41 |
css_path = os.path.join(
|
42 |
app_dir,
|
|
|
46 |
"style.css",
|
47 |
)
|
48 |
return css_path
|
49 |
+
|
50 |
+
@staticmethod
|
51 |
+
def get_models_config_path(model_config_file: str) -> str:
|
52 |
+
configs_path = get_configs_path()
|
53 |
+
models_path = join_paths(
|
54 |
+
configs_path,
|
55 |
+
model_config_file,
|
56 |
+
)
|
57 |
+
return models_path
|
utils.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import platform
|
|
|
2 |
|
3 |
|
4 |
def show_system_info():
|
@@ -8,3 +9,13 @@ def show_system_info():
|
|
8 |
print(f"Processor: {platform.processor()}")
|
9 |
except Exception as ex:
|
10 |
print(f"Error ocurred while getting system information {ex}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import platform
|
2 |
+
from typing import List
|
3 |
|
4 |
|
5 |
def show_system_info():
|
|
|
9 |
print(f"Processor: {platform.processor()}")
|
10 |
except Exception as ex:
|
11 |
print(f"Error ocurred while getting system information {ex}")
|
12 |
+
|
13 |
+
|
14 |
+
def get_models_from_text_file(file_path: str) -> List:
|
15 |
+
models = []
|
16 |
+
with open(file_path, "r") as file:
|
17 |
+
lines = file.readlines()
|
18 |
+
for repo_id in lines:
|
19 |
+
if repo_id.strip() != "":
|
20 |
+
models.append(repo_id.strip())
|
21 |
+
return models
|