JacobPerera commited on
Commit
32643b6
·
1 Parent(s): 6a6b894

Upload 5 files

Browse files
Files changed (5) hide show
  1. launch.py +381 -0
  2. script.js +102 -0
  3. webui-macos-env.sh +19 -0
  4. webui-user.sh +46 -0
  5. webui.py +337 -0
launch.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this scripts installs necessary requirements and launches main program in webui.py
2
+ import subprocess
3
+ import os
4
+ import sys
5
+ import importlib.util
6
+ import shlex
7
+ import platform
8
+ import argparse
9
+ import json
10
+
11
+ parser = argparse.ArgumentParser(add_help=False)
12
+ parser.add_argument("--ui-settings-file", type=str, default='config.json')
13
+ parser.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.realpath(__file__)))
14
+ args, _ = parser.parse_known_args(sys.argv)
15
+
16
+ script_path = os.path.dirname(__file__)
17
+ data_path = os.getcwd()
18
+
19
+ dir_repos = "repositories"
20
+ dir_extensions = "extensions"
21
+ python = sys.executable
22
+ git = os.environ.get('GIT', "git")
23
+ index_url = os.environ.get('INDEX_URL', "")
24
+ stored_commit_hash = None
25
+ skip_install = False
26
+
27
+
28
+ def check_python_version():
29
+ is_windows = platform.system() == "Windows"
30
+ major = sys.version_info.major
31
+ minor = sys.version_info.minor
32
+ micro = sys.version_info.micro
33
+
34
+ if is_windows:
35
+ supported_minors = [10]
36
+ else:
37
+ supported_minors = [7, 8, 9, 10, 11]
38
+
39
+ if not (major == 3 and minor in supported_minors):
40
+ import modules.errors
41
+
42
+ modules.errors.print_error_explanation(f"""
43
+ INCOMPATIBLE PYTHON VERSION
44
+
45
+ This program is tested with 3.10.6 Python, but you have {major}.{minor}.{micro}.
46
+ If you encounter an error with "RuntimeError: Couldn't install torch." message,
47
+ or any other error regarding unsuccessful package (library) installation,
48
+ please downgrade (or upgrade) to the latest version of 3.10 Python
49
+ and delete current Python and "venv" folder in WebUI's directory.
50
+
51
+ You can download 3.10 Python from here: https://www.python.org/downloads/release/python-3109/
52
+
53
+ {"Alternatively, use a binary release of WebUI: https://github.com/AUTOMATIC1111/stable-diffusion-webui/releases" if is_windows else ""}
54
+
55
+ Use --skip-python-version-check to suppress this warning.
56
+ """)
57
+
58
+
59
+ def commit_hash():
60
+ global stored_commit_hash
61
+
62
+ if stored_commit_hash is not None:
63
+ return stored_commit_hash
64
+
65
+ try:
66
+ stored_commit_hash = run(f"{git} rev-parse HEAD").strip()
67
+ except Exception:
68
+ stored_commit_hash = "<none>"
69
+
70
+ return stored_commit_hash
71
+
72
+
73
+ def extract_arg(args, name):
74
+ return [x for x in args if x != name], name in args
75
+
76
+
77
+ def extract_opt(args, name):
78
+ opt = None
79
+ is_present = False
80
+ if name in args:
81
+ is_present = True
82
+ idx = args.index(name)
83
+ del args[idx]
84
+ if idx < len(args) and args[idx][0] != "-":
85
+ opt = args[idx]
86
+ del args[idx]
87
+ return args, is_present, opt
88
+
89
+
90
+ def run(command, desc=None, errdesc=None, custom_env=None, live=False):
91
+ if desc is not None:
92
+ print(desc)
93
+
94
+ if live:
95
+ result = subprocess.run(command, shell=True, env=os.environ if custom_env is None else custom_env)
96
+ if result.returncode != 0:
97
+ raise RuntimeError(f"""{errdesc or 'Error running command'}.
98
+ Command: {command}
99
+ Error code: {result.returncode}""")
100
+
101
+ return ""
102
+
103
+ result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env=os.environ if custom_env is None else custom_env)
104
+
105
+ if result.returncode != 0:
106
+
107
+ message = f"""{errdesc or 'Error running command'}.
108
+ Command: {command}
109
+ Error code: {result.returncode}
110
+ stdout: {result.stdout.decode(encoding="utf8", errors="ignore") if len(result.stdout)>0 else '<empty>'}
111
+ stderr: {result.stderr.decode(encoding="utf8", errors="ignore") if len(result.stderr)>0 else '<empty>'}
112
+ """
113
+ raise RuntimeError(message)
114
+
115
+ return result.stdout.decode(encoding="utf8", errors="ignore")
116
+
117
+
118
+ def check_run(command):
119
+ result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
120
+ return result.returncode == 0
121
+
122
+
123
+ def is_installed(package):
124
+ try:
125
+ spec = importlib.util.find_spec(package)
126
+ except ModuleNotFoundError:
127
+ return False
128
+
129
+ return spec is not None
130
+
131
+
132
+ def repo_dir(name):
133
+ return os.path.join(script_path, dir_repos, name)
134
+
135
+
136
+ def run_python(code, desc=None, errdesc=None):
137
+ return run(f'"{python}" -c "{code}"', desc, errdesc)
138
+
139
+
140
+ def run_pip(args, desc=None):
141
+ if skip_install:
142
+ return
143
+
144
+ index_url_line = f' --index-url {index_url}' if index_url != '' else ''
145
+ return run(f'"{python}" -m pip {args} --prefer-binary{index_url_line}', desc=f"Installing {desc}", errdesc=f"Couldn't install {desc}")
146
+
147
+
148
+ def check_run_python(code):
149
+ return check_run(f'"{python}" -c "{code}"')
150
+
151
+
152
+ def git_clone(url, dir, name, commithash=None):
153
+ # TODO clone into temporary dir and move if successful
154
+
155
+ if os.path.exists(dir):
156
+ if commithash is None:
157
+ return
158
+
159
+ current_hash = run(f'"{git}" -C "{dir}" rev-parse HEAD', None, f"Couldn't determine {name}'s hash: {commithash}").strip()
160
+ if current_hash == commithash:
161
+ return
162
+
163
+ run(f'"{git}" -C "{dir}" fetch', f"Fetching updates for {name}...", f"Couldn't fetch {name}")
164
+ run(f'"{git}" -C "{dir}" checkout {commithash}', f"Checking out commit for {name} with hash: {commithash}...", f"Couldn't checkout commit {commithash} for {name}")
165
+ return
166
+
167
+ run(f'"{git}" clone "{url}" "{dir}"', f"Cloning {name} into {dir}...", f"Couldn't clone {name}")
168
+
169
+ if commithash is not None:
170
+ run(f'"{git}" -C "{dir}" checkout {commithash}', None, "Couldn't checkout {name}'s hash: {commithash}")
171
+
172
+
173
+ def git_pull_recursive(dir):
174
+ for subdir, _, _ in os.walk(dir):
175
+ if os.path.exists(os.path.join(subdir, '.git')):
176
+ try:
177
+ output = subprocess.check_output([git, '-C', subdir, 'pull', '--autostash'])
178
+ print(f"Pulled changes for repository in '{subdir}':\n{output.decode('utf-8').strip()}\n")
179
+ except subprocess.CalledProcessError as e:
180
+ print(f"Couldn't perform 'git pull' on repository in '{subdir}':\n{e.output.decode('utf-8').strip()}\n")
181
+
182
+
183
+ def version_check(commit):
184
+ try:
185
+ import requests
186
+ commits = requests.get('https://api.github.com/repos/AUTOMATIC1111/stable-diffusion-webui/branches/master').json()
187
+ if commit != "<none>" and commits['commit']['sha'] != commit:
188
+ print("--------------------------------------------------------")
189
+ print("| You are not up to date with the most recent release. |")
190
+ print("| Consider running `git pull` to update. |")
191
+ print("--------------------------------------------------------")
192
+ elif commits['commit']['sha'] == commit:
193
+ print("You are up to date with the most recent release.")
194
+ else:
195
+ print("Not a git clone, can't perform version check.")
196
+ except Exception as e:
197
+ print("version check failed", e)
198
+
199
+
200
+ def run_extension_installer(extension_dir):
201
+ path_installer = os.path.join(extension_dir, "install.py")
202
+ if not os.path.isfile(path_installer):
203
+ return
204
+
205
+ try:
206
+ env = os.environ.copy()
207
+ env['PYTHONPATH'] = os.path.abspath(".")
208
+
209
+ print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env))
210
+ except Exception as e:
211
+ print(e, file=sys.stderr)
212
+
213
+
214
+ def list_extensions(settings_file):
215
+ settings = {}
216
+
217
+ try:
218
+ if os.path.isfile(settings_file):
219
+ with open(settings_file, "r", encoding="utf8") as file:
220
+ settings = json.load(file)
221
+ except Exception as e:
222
+ print(e, file=sys.stderr)
223
+
224
+ disabled_extensions = set(settings.get('disabled_extensions', []))
225
+
226
+ return [x for x in os.listdir(os.path.join(data_path, dir_extensions)) if x not in disabled_extensions]
227
+
228
+
229
+ def run_extensions_installers(settings_file):
230
+ if not os.path.isdir(dir_extensions):
231
+ return
232
+
233
+ for dirname_extension in list_extensions(settings_file):
234
+ run_extension_installer(os.path.join(dir_extensions, dirname_extension))
235
+
236
+
237
+ def prepare_environment():
238
+ global skip_install
239
+
240
+ torch_command = os.environ.get('TORCH_COMMAND', "pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 --extra-index-url https://download.pytorch.org/whl/cu117")
241
+ requirements_file = os.environ.get('REQS_FILE', "requirements_versions.txt")
242
+ commandline_args = os.environ.get('COMMANDLINE_ARGS', "")
243
+
244
+ xformers_package = os.environ.get('XFORMERS_PACKAGE', 'xformers==0.0.16rc425')
245
+ gfpgan_package = os.environ.get('GFPGAN_PACKAGE', "git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379")
246
+ clip_package = os.environ.get('CLIP_PACKAGE', "git+https://github.com/openai/CLIP.git@d50d76daa670286dd6cacf3bcd80b5e4823fc8e1")
247
+ openclip_package = os.environ.get('OPENCLIP_PACKAGE', "git+https://github.com/mlfoundations/open_clip.git@bb6e834e9c70d9c27d0dc3ecedeebeaeb1ffad6b")
248
+
249
+ stable_diffusion_repo = os.environ.get('STABLE_DIFFUSION_REPO', "https://github.com/Stability-AI/stablediffusion.git")
250
+ taming_transformers_repo = os.environ.get('TAMING_TRANSFORMERS_REPO', "https://github.com/CompVis/taming-transformers.git")
251
+ k_diffusion_repo = os.environ.get('K_DIFFUSION_REPO', 'https://github.com/crowsonkb/k-diffusion.git')
252
+ codeformer_repo = os.environ.get('CODEFORMER_REPO', 'https://github.com/sczhou/CodeFormer.git')
253
+ blip_repo = os.environ.get('BLIP_REPO', 'https://github.com/salesforce/BLIP.git')
254
+
255
+ stable_diffusion_commit_hash = os.environ.get('STABLE_DIFFUSION_COMMIT_HASH', "47b6b607fdd31875c9279cd2f4f16b92e4ea958e")
256
+ taming_transformers_commit_hash = os.environ.get('TAMING_TRANSFORMERS_COMMIT_HASH', "24268930bf1dce879235a7fddd0b2355b84d7ea6")
257
+ k_diffusion_commit_hash = os.environ.get('K_DIFFUSION_COMMIT_HASH', "5b3af030dd83e0297272d861c19477735d0317ec")
258
+ codeformer_commit_hash = os.environ.get('CODEFORMER_COMMIT_HASH', "c5b4593074ba6214284d6acd5f1719b6c5d739af")
259
+ blip_commit_hash = os.environ.get('BLIP_COMMIT_HASH', "48211a1594f1321b00f14c9f7a5b4813144b2fb9")
260
+
261
+ sys.argv += shlex.split(commandline_args)
262
+
263
+ sys.argv, _ = extract_arg(sys.argv, '-f')
264
+ sys.argv, update_all_extensions = extract_arg(sys.argv, '--update-all-extensions')
265
+ sys.argv, skip_torch_cuda_test = extract_arg(sys.argv, '--skip-torch-cuda-test')
266
+ sys.argv, skip_python_version_check = extract_arg(sys.argv, '--skip-python-version-check')
267
+ sys.argv, reinstall_xformers = extract_arg(sys.argv, '--reinstall-xformers')
268
+ sys.argv, reinstall_torch = extract_arg(sys.argv, '--reinstall-torch')
269
+ sys.argv, update_check = extract_arg(sys.argv, '--update-check')
270
+ sys.argv, run_tests, test_dir = extract_opt(sys.argv, '--tests')
271
+ sys.argv, skip_install = extract_arg(sys.argv, '--skip-install')
272
+ xformers = '--xformers' in sys.argv
273
+ ngrok = '--ngrok' in sys.argv
274
+
275
+ if not skip_python_version_check:
276
+ check_python_version()
277
+
278
+ commit = commit_hash()
279
+
280
+ print(f"Python {sys.version}")
281
+ print(f"Commit hash: {commit}")
282
+
283
+ if reinstall_torch or not is_installed("torch") or not is_installed("torchvision"):
284
+ run(f'"{python}" -m {torch_command}', "Installing torch and torchvision", "Couldn't install torch", live=True)
285
+
286
+ if not skip_torch_cuda_test:
287
+ run_python("import torch; assert torch.cuda.is_available(), 'Torch is not able to use GPU; add --skip-torch-cuda-test to COMMANDLINE_ARGS variable to disable this check'")
288
+
289
+ if not is_installed("gfpgan"):
290
+ run_pip(f"install {gfpgan_package}", "gfpgan")
291
+
292
+ if not is_installed("clip"):
293
+ run_pip(f"install {clip_package}", "clip")
294
+
295
+ if not is_installed("open_clip"):
296
+ run_pip(f"install {openclip_package}", "open_clip")
297
+
298
+ if (not is_installed("xformers") or reinstall_xformers) and xformers:
299
+ if platform.system() == "Windows":
300
+ if platform.python_version().startswith("3.10"):
301
+ run_pip(f"install -U -I --no-deps {xformers_package}", "xformers")
302
+ else:
303
+ print("Installation of xformers is not supported in this version of Python.")
304
+ print("You can also check this and build manually: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers#building-xformers-on-windows-by-duckness")
305
+ if not is_installed("xformers"):
306
+ exit(0)
307
+ elif platform.system() == "Linux":
308
+ run_pip(f"install {xformers_package}", "xformers")
309
+
310
+ if not is_installed("pyngrok") and ngrok:
311
+ run_pip("install pyngrok", "ngrok")
312
+
313
+ os.makedirs(os.path.join(script_path, dir_repos), exist_ok=True)
314
+
315
+ git_clone(stable_diffusion_repo, repo_dir('stable-diffusion-stability-ai'), "Stable Diffusion", stable_diffusion_commit_hash)
316
+ git_clone(taming_transformers_repo, repo_dir('taming-transformers'), "Taming Transformers", taming_transformers_commit_hash)
317
+ git_clone(k_diffusion_repo, repo_dir('k-diffusion'), "K-diffusion", k_diffusion_commit_hash)
318
+ git_clone(codeformer_repo, repo_dir('CodeFormer'), "CodeFormer", codeformer_commit_hash)
319
+ git_clone(blip_repo, repo_dir('BLIP'), "BLIP", blip_commit_hash)
320
+
321
+ if not is_installed("lpips"):
322
+ run_pip(f"install -r \"{os.path.join(repo_dir('CodeFormer'), 'requirements.txt')}\"", "requirements for CodeFormer")
323
+
324
+ if not os.path.isfile(requirements_file):
325
+ requirements_file = os.path.join(script_path, requirements_file)
326
+ run_pip(f"install -r \"{requirements_file}\"", "requirements for Web UI")
327
+
328
+ run_extensions_installers(settings_file=args.ui_settings_file)
329
+
330
+ if update_check:
331
+ version_check(commit)
332
+
333
+ if update_all_extensions:
334
+ git_pull_recursive(os.path.join(data_path, dir_extensions))
335
+
336
+ if "--exit" in sys.argv:
337
+ print("Exiting because of --exit argument")
338
+ exit(0)
339
+
340
+ if run_tests:
341
+ exitcode = tests(test_dir)
342
+ exit(exitcode)
343
+
344
+
345
+ def tests(test_dir):
346
+ if "--api" not in sys.argv:
347
+ sys.argv.append("--api")
348
+ if "--ckpt" not in sys.argv:
349
+ sys.argv.append("--ckpt")
350
+ sys.argv.append(os.path.join(script_path, "test/test_files/empty.pt"))
351
+ if "--skip-torch-cuda-test" not in sys.argv:
352
+ sys.argv.append("--skip-torch-cuda-test")
353
+ if "--disable-nan-check" not in sys.argv:
354
+ sys.argv.append("--disable-nan-check")
355
+
356
+ print(f"Launching Web UI in another process for testing with arguments: {' '.join(sys.argv[1:])}")
357
+
358
+ os.environ['COMMANDLINE_ARGS'] = ""
359
+ with open(os.path.join(script_path, 'test/stdout.txt'), "w", encoding="utf8") as stdout, open(os.path.join(script_path, 'test/stderr.txt'), "w", encoding="utf8") as stderr:
360
+ proc = subprocess.Popen([sys.executable, *sys.argv], stdout=stdout, stderr=stderr)
361
+
362
+ import test.server_poll
363
+ exitcode = test.server_poll.run_tests(proc, test_dir)
364
+
365
+ print(f"Stopping Web UI process with id {proc.pid}")
366
+ proc.kill()
367
+ return exitcode
368
+
369
+
370
+ def start():
371
+ print(f"Launching {'API server' if '--nowebui' in sys.argv else 'Web UI'} with arguments: {' '.join(sys.argv[1:])}")
372
+ import webui
373
+ if '--nowebui' in sys.argv:
374
+ webui.api_only()
375
+ else:
376
+ webui.webui()
377
+
378
+
379
+ if __name__ == "__main__":
380
+ prepare_environment()
381
+ start()
script.js ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function gradioApp() {
2
+ const elems = document.getElementsByTagName('gradio-app')
3
+ const gradioShadowRoot = elems.length == 0 ? null : elems[0].shadowRoot
4
+ return !!gradioShadowRoot ? gradioShadowRoot : document;
5
+ }
6
+
7
+ function get_uiCurrentTab() {
8
+ return gradioApp().querySelector('#tabs button:not(.border-transparent)')
9
+ }
10
+
11
+ function get_uiCurrentTabContent() {
12
+ return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])')
13
+ }
14
+
15
+ uiUpdateCallbacks = []
16
+ uiLoadedCallbacks = []
17
+ uiTabChangeCallbacks = []
18
+ optionsChangedCallbacks = []
19
+ let uiCurrentTab = null
20
+
21
+ function onUiUpdate(callback){
22
+ uiUpdateCallbacks.push(callback)
23
+ }
24
+ function onUiLoaded(callback){
25
+ uiLoadedCallbacks.push(callback)
26
+ }
27
+ function onUiTabChange(callback){
28
+ uiTabChangeCallbacks.push(callback)
29
+ }
30
+ function onOptionsChanged(callback){
31
+ optionsChangedCallbacks.push(callback)
32
+ }
33
+
34
+ function runCallback(x, m){
35
+ try {
36
+ x(m)
37
+ } catch (e) {
38
+ (console.error || console.log).call(console, e.message, e);
39
+ }
40
+ }
41
+ function executeCallbacks(queue, m) {
42
+ queue.forEach(function(x){runCallback(x, m)})
43
+ }
44
+
45
+ var executedOnLoaded = false;
46
+
47
+ document.addEventListener("DOMContentLoaded", function() {
48
+ var mutationObserver = new MutationObserver(function(m){
49
+ if(!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')){
50
+ executedOnLoaded = true;
51
+ executeCallbacks(uiLoadedCallbacks);
52
+ }
53
+
54
+ executeCallbacks(uiUpdateCallbacks, m);
55
+ const newTab = get_uiCurrentTab();
56
+ if ( newTab && ( newTab !== uiCurrentTab ) ) {
57
+ uiCurrentTab = newTab;
58
+ executeCallbacks(uiTabChangeCallbacks);
59
+ }
60
+ });
61
+ mutationObserver.observe( gradioApp(), { childList:true, subtree:true })
62
+ });
63
+
64
+ /**
65
+ * Add a ctrl+enter as a shortcut to start a generation
66
+ */
67
+ document.addEventListener('keydown', function(e) {
68
+ var handled = false;
69
+ if (e.key !== undefined) {
70
+ if((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
71
+ } else if (e.keyCode !== undefined) {
72
+ if((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
73
+ }
74
+ if (handled) {
75
+ button = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
76
+ if (button) {
77
+ button.click();
78
+ }
79
+ e.preventDefault();
80
+ }
81
+ })
82
+
83
+ /**
84
+ * checks that a UI element is not in another hidden element or tab content
85
+ */
86
+ function uiElementIsVisible(el) {
87
+ let isVisible = !el.closest('.\\!hidden');
88
+ if ( ! isVisible ) {
89
+ return false;
90
+ }
91
+
92
+ while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) {
93
+ if ( ! isVisible ) {
94
+ return false;
95
+ } else if ( el.parentElement ) {
96
+ el = el.parentElement
97
+ } else {
98
+ break;
99
+ }
100
+ }
101
+ return isVisible;
102
+ }
webui-macos-env.sh ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ ####################################################################
3
+ # macOS defaults #
4
+ # Please modify webui-user.sh to change these instead of this file #
5
+ ####################################################################
6
+
7
+ if [[ -x "$(command -v python3.10)" ]]
8
+ then
9
+ python_cmd="python3.10"
10
+ fi
11
+
12
+ export install_dir="$HOME"
13
+ export COMMANDLINE_ARGS="--skip-torch-cuda-test --upcast-sampling --no-half-vae --use-cpu interrogate"
14
+ export TORCH_COMMAND="pip install torch==1.12.1 torchvision==0.13.1"
15
+ export K_DIFFUSION_REPO="https://github.com/brkirch/k-diffusion.git"
16
+ export K_DIFFUSION_COMMIT_HASH="51c9778f269cedb55a4d88c79c0246d35bdadb71"
17
+ export PYTORCH_ENABLE_MPS_FALLBACK=1
18
+
19
+ ####################################################################
webui-user.sh ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ #########################################################
3
+ # Uncomment and change the variables below to your need:#
4
+ #########################################################
5
+
6
+ # Install directory without trailing slash
7
+ #install_dir="/home/$(whoami)"
8
+
9
+ # Name of the subdirectory
10
+ #clone_dir="stable-diffusion-webui"
11
+
12
+ # Commandline arguments for webui.py, for example: export COMMANDLINE_ARGS="--medvram --opt-split-attention"
13
+ #export COMMANDLINE_ARGS=""
14
+
15
+ # python3 executable
16
+ #python_cmd="python3"
17
+
18
+ # git executable
19
+ #export GIT="git"
20
+
21
+ # python3 venv without trailing slash (defaults to ${install_dir}/${clone_dir}/venv)
22
+ #venv_dir="venv"
23
+
24
+ # script to launch to start the app
25
+ #export LAUNCH_SCRIPT="launch.py"
26
+
27
+ # install command for torch
28
+ #export TORCH_COMMAND="pip install torch==1.12.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113"
29
+
30
+ # Requirements file to use for stable-diffusion-webui
31
+ #export REQS_FILE="requirements_versions.txt"
32
+
33
+ # Fixed git repos
34
+ #export K_DIFFUSION_PACKAGE=""
35
+ #export GFPGAN_PACKAGE=""
36
+
37
+ # Fixed git commits
38
+ #export STABLE_DIFFUSION_COMMIT_HASH=""
39
+ #export TAMING_TRANSFORMERS_COMMIT_HASH=""
40
+ #export CODEFORMER_COMMIT_HASH=""
41
+ #export BLIP_COMMIT_HASH=""
42
+
43
+ # Uncomment to enable accelerated launch
44
+ #export ACCELERATE="True"
45
+
46
+ ###########################################
webui.py ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import time
4
+ import importlib
5
+ import signal
6
+ import re
7
+ from fastapi import FastAPI
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+ from fastapi.middleware.gzip import GZipMiddleware
10
+ from packaging import version
11
+
12
+ import logging
13
+ logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
14
+
15
+ from modules import paths, timer, import_hook, errors
16
+
17
+ startup_timer = timer.Timer()
18
+
19
+ import torch
20
+ startup_timer.record("import torch")
21
+
22
+ import gradio
23
+ startup_timer.record("import gradio")
24
+
25
+ import ldm.modules.encoders.modules
26
+ startup_timer.record("import ldm")
27
+
28
+ from modules import extra_networks, ui_extra_networks_checkpoints
29
+ from modules import extra_networks_hypernet, ui_extra_networks_hypernets, ui_extra_networks_textual_inversion
30
+ from modules.call_queue import wrap_queued_call, queue_lock, wrap_gradio_gpu_call
31
+
32
+ # Truncate version number of nightly/local build of PyTorch to not cause exceptions with CodeFormer or Safetensors
33
+ if ".dev" in torch.__version__ or "+git" in torch.__version__:
34
+ torch.__long_version__ = torch.__version__
35
+ torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
36
+
37
+ from modules import shared, devices, sd_samplers, upscaler, extensions, localization, ui_tempdir, ui_extra_networks
38
+ import modules.codeformer_model as codeformer
39
+ import modules.face_restoration
40
+ import modules.gfpgan_model as gfpgan
41
+ import modules.img2img
42
+
43
+ import modules.lowvram
44
+ import modules.scripts
45
+ import modules.sd_hijack
46
+ import modules.sd_models
47
+ import modules.sd_vae
48
+ import modules.txt2img
49
+ import modules.script_callbacks
50
+ import modules.textual_inversion.textual_inversion
51
+ import modules.progress
52
+
53
+ import modules.ui
54
+ from modules import modelloader
55
+ from modules.shared import cmd_opts
56
+ import modules.hypernetworks.hypernetwork
57
+
58
+ startup_timer.record("other imports")
59
+
60
+
61
+ if cmd_opts.server_name:
62
+ server_name = cmd_opts.server_name
63
+ else:
64
+ server_name = "0.0.0.0" if cmd_opts.listen else None
65
+
66
+
67
+ def check_versions():
68
+ if shared.cmd_opts.skip_version_check:
69
+ return
70
+
71
+ expected_torch_version = "1.13.1"
72
+
73
+ if version.parse(torch.__version__) < version.parse(expected_torch_version):
74
+ errors.print_error_explanation(f"""
75
+ You are running torch {torch.__version__}.
76
+ The program is tested to work with torch {expected_torch_version}.
77
+ To reinstall the desired version, run with commandline flag --reinstall-torch.
78
+ Beware that this will cause a lot of large files to be downloaded, as well as
79
+ there are reports of issues with training tab on the latest version.
80
+
81
+ Use --skip-version-check commandline argument to disable this check.
82
+ """.strip())
83
+
84
+ expected_xformers_version = "0.0.16rc425"
85
+ if shared.xformers_available:
86
+ import xformers
87
+
88
+ if version.parse(xformers.__version__) < version.parse(expected_xformers_version):
89
+ errors.print_error_explanation(f"""
90
+ You are running xformers {xformers.__version__}.
91
+ The program is tested to work with xformers {expected_xformers_version}.
92
+ To reinstall the desired version, run with commandline flag --reinstall-xformers.
93
+
94
+ Use --skip-version-check commandline argument to disable this check.
95
+ """.strip())
96
+
97
+
98
+ def initialize():
99
+ check_versions()
100
+
101
+ extensions.list_extensions()
102
+ localization.list_localizations(cmd_opts.localizations_dir)
103
+ startup_timer.record("list extensions")
104
+
105
+ if cmd_opts.ui_debug_mode:
106
+ shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
107
+ modules.scripts.load_scripts()
108
+ return
109
+
110
+ modelloader.cleanup_models()
111
+ modules.sd_models.setup_model()
112
+ startup_timer.record("list SD models")
113
+
114
+ codeformer.setup_model(cmd_opts.codeformer_models_path)
115
+ startup_timer.record("setup codeformer")
116
+
117
+ gfpgan.setup_model(cmd_opts.gfpgan_models_path)
118
+ startup_timer.record("setup gfpgan")
119
+
120
+ modelloader.list_builtin_upscalers()
121
+ startup_timer.record("list builtin upscalers")
122
+
123
+ modules.scripts.load_scripts()
124
+ startup_timer.record("load scripts")
125
+
126
+ modelloader.load_upscalers()
127
+ startup_timer.record("load upscalers")
128
+
129
+ modules.sd_vae.refresh_vae_list()
130
+ startup_timer.record("refresh VAE")
131
+
132
+ modules.textual_inversion.textual_inversion.list_textual_inversion_templates()
133
+ startup_timer.record("refresh textual inversion templates")
134
+
135
+ try:
136
+ modules.sd_models.load_model()
137
+ except Exception as e:
138
+ errors.display(e, "loading stable diffusion model")
139
+ print("", file=sys.stderr)
140
+ print("Stable diffusion model failed to load, exiting", file=sys.stderr)
141
+ exit(1)
142
+ startup_timer.record("load SD checkpoint")
143
+
144
+ shared.opts.data["sd_model_checkpoint"] = shared.sd_model.sd_checkpoint_info.title
145
+
146
+ shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights()))
147
+ shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
148
+ shared.opts.onchange("sd_vae_as_default", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
149
+ shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed)
150
+ startup_timer.record("opts onchange")
151
+
152
+ shared.reload_hypernetworks()
153
+ startup_timer.record("reload hypernets")
154
+
155
+ ui_extra_networks.intialize()
156
+ ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion())
157
+ ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks())
158
+ ui_extra_networks.register_page(ui_extra_networks_checkpoints.ExtraNetworksPageCheckpoints())
159
+
160
+ extra_networks.initialize()
161
+ extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet())
162
+ startup_timer.record("extra networks")
163
+
164
+ if cmd_opts.tls_keyfile is not None and cmd_opts.tls_keyfile is not None:
165
+
166
+ try:
167
+ if not os.path.exists(cmd_opts.tls_keyfile):
168
+ print("Invalid path to TLS keyfile given")
169
+ if not os.path.exists(cmd_opts.tls_certfile):
170
+ print(f"Invalid path to TLS certfile: '{cmd_opts.tls_certfile}'")
171
+ except TypeError:
172
+ cmd_opts.tls_keyfile = cmd_opts.tls_certfile = None
173
+ print("TLS setup invalid, running webui without TLS")
174
+ else:
175
+ print("Running with TLS")
176
+ startup_timer.record("TLS")
177
+
178
+ # make the program just exit at ctrl+c without waiting for anything
179
+ def sigint_handler(sig, frame):
180
+ print(f'Interrupted with signal {sig} in {frame}')
181
+ os._exit(0)
182
+
183
+ signal.signal(signal.SIGINT, sigint_handler)
184
+
185
+
186
+ def setup_middleware(app):
187
+ app.middleware_stack = None # reset current middleware to allow modifying user provided list
188
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
189
+ if cmd_opts.cors_allow_origins and cmd_opts.cors_allow_origins_regex:
190
+ app.add_middleware(CORSMiddleware, allow_origins=cmd_opts.cors_allow_origins.split(','), allow_origin_regex=cmd_opts.cors_allow_origins_regex, allow_methods=['*'], allow_credentials=True, allow_headers=['*'])
191
+ elif cmd_opts.cors_allow_origins:
192
+ app.add_middleware(CORSMiddleware, allow_origins=cmd_opts.cors_allow_origins.split(','), allow_methods=['*'], allow_credentials=True, allow_headers=['*'])
193
+ elif cmd_opts.cors_allow_origins_regex:
194
+ app.add_middleware(CORSMiddleware, allow_origin_regex=cmd_opts.cors_allow_origins_regex, allow_methods=['*'], allow_credentials=True, allow_headers=['*'])
195
+ app.build_middleware_stack() # rebuild middleware stack on-the-fly
196
+
197
+
198
+ def create_api(app):
199
+ from modules.api.api import Api
200
+ api = Api(app, queue_lock)
201
+ return api
202
+
203
+
204
+ def wait_on_server(demo=None):
205
+ while 1:
206
+ time.sleep(0.5)
207
+ if shared.state.need_restart:
208
+ shared.state.need_restart = False
209
+ time.sleep(0.5)
210
+ demo.close()
211
+ time.sleep(0.5)
212
+ break
213
+
214
+
215
+ def api_only():
216
+ initialize()
217
+
218
+ app = FastAPI()
219
+ setup_middleware(app)
220
+ api = create_api(app)
221
+
222
+ modules.script_callbacks.app_started_callback(None, app)
223
+
224
+ print(f"Startup time: {startup_timer.summary()}.")
225
+ api.launch(server_name="0.0.0.0" if cmd_opts.listen else "127.0.0.1", port=cmd_opts.port if cmd_opts.port else 7861)
226
+
227
+
228
+ def webui():
229
+ launch_api = cmd_opts.api
230
+ initialize()
231
+
232
+ while 1:
233
+ if shared.opts.clean_temp_dir_at_start:
234
+ ui_tempdir.cleanup_tmpdr()
235
+ startup_timer.record("cleanup temp dir")
236
+
237
+ modules.script_callbacks.before_ui_callback()
238
+ startup_timer.record("scripts before_ui_callback")
239
+
240
+ shared.demo = modules.ui.create_ui()
241
+ startup_timer.record("create ui")
242
+
243
+ if cmd_opts.gradio_queue:
244
+ shared.demo.queue(64)
245
+
246
+ gradio_auth_creds = []
247
+ if cmd_opts.gradio_auth:
248
+ gradio_auth_creds += [x.strip() for x in cmd_opts.gradio_auth.strip('"').replace('\n', '').split(',') if x.strip()]
249
+ if cmd_opts.gradio_auth_path:
250
+ with open(cmd_opts.gradio_auth_path, 'r', encoding="utf8") as file:
251
+ for line in file.readlines():
252
+ gradio_auth_creds += [x.strip() for x in line.split(',') if x.strip()]
253
+
254
+ app, local_url, share_url = shared.demo.launch(
255
+ share=cmd_opts.share,
256
+ server_name=server_name,
257
+ server_port=cmd_opts.port,
258
+ ssl_keyfile=cmd_opts.tls_keyfile,
259
+ ssl_certfile=cmd_opts.tls_certfile,
260
+ debug=cmd_opts.gradio_debug,
261
+ auth=[tuple(cred.split(':')) for cred in gradio_auth_creds] if gradio_auth_creds else None,
262
+ inbrowser=cmd_opts.autolaunch,
263
+ prevent_thread_lock=True
264
+ )
265
+ # after initial launch, disable --autolaunch for subsequent restarts
266
+ cmd_opts.autolaunch = False
267
+
268
+ startup_timer.record("gradio launch")
269
+
270
+ # gradio uses a very open CORS policy via app.user_middleware, which makes it possible for
271
+ # an attacker to trick the user into opening a malicious HTML page, which makes a request to the
272
+ # running web ui and do whatever the attacker wants, including installing an extension and
273
+ # running its code. We disable this here. Suggested by RyotaK.
274
+ app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware']
275
+
276
+ setup_middleware(app)
277
+
278
+ modules.progress.setup_progress_api(app)
279
+
280
+ if launch_api:
281
+ create_api(app)
282
+
283
+ ui_extra_networks.add_pages_to_demo(app)
284
+
285
+ modules.script_callbacks.app_started_callback(shared.demo, app)
286
+ startup_timer.record("scripts app_started_callback")
287
+
288
+ print(f"Startup time: {startup_timer.summary()}.")
289
+
290
+ wait_on_server(shared.demo)
291
+ print('Restarting UI...')
292
+
293
+ startup_timer.reset()
294
+
295
+ sd_samplers.set_samplers()
296
+
297
+ modules.script_callbacks.script_unloaded_callback()
298
+ extensions.list_extensions()
299
+ startup_timer.record("list extensions")
300
+
301
+ localization.list_localizations(cmd_opts.localizations_dir)
302
+
303
+ modelloader.forbid_loaded_nonbuiltin_upscalers()
304
+ modules.scripts.reload_scripts()
305
+ startup_timer.record("load scripts")
306
+
307
+ modules.script_callbacks.model_loaded_callback(shared.sd_model)
308
+ startup_timer.record("model loaded callback")
309
+
310
+ modelloader.load_upscalers()
311
+ startup_timer.record("load upscalers")
312
+
313
+ for module in [module for name, module in sys.modules.items() if name.startswith("modules.ui")]:
314
+ importlib.reload(module)
315
+ startup_timer.record("reload script modules")
316
+
317
+ modules.sd_models.list_models()
318
+ startup_timer.record("list SD models")
319
+
320
+ shared.reload_hypernetworks()
321
+ startup_timer.record("reload hypernetworks")
322
+
323
+ ui_extra_networks.intialize()
324
+ ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion())
325
+ ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks())
326
+ ui_extra_networks.register_page(ui_extra_networks_checkpoints.ExtraNetworksPageCheckpoints())
327
+
328
+ extra_networks.initialize()
329
+ extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet())
330
+ startup_timer.record("initialize extra networks")
331
+
332
+
333
+ if __name__ == "__main__":
334
+ if cmd_opts.nowebui:
335
+ api_only()
336
+ else:
337
+ webui()