3v324v23 commited on
Commit
a8ec95a
·
1 Parent(s): 6b21f20

Deploy minimal Fooocus to Hugging Face Space

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .huggingface.yaml +3 -0
  2. entry_with_update.py +46 -0
  3. fooocus_version.py +1 -0
  4. launch.py +152 -0
  5. models/checkpoints/put_checkpoints_here +0 -0
  6. models/clip/put_clip_or_text_encoder_models_here +0 -0
  7. models/clip_vision/put_clip_vision_models_here +0 -0
  8. models/clip_vision/wd-v1-4-moat-tagger-v2.csv +0 -0
  9. models/configs/anything_v3.yaml +73 -0
  10. models/configs/v1-inference.yaml +70 -0
  11. models/configs/v1-inference_clip_skip_2.yaml +73 -0
  12. models/configs/v1-inference_clip_skip_2_fp16.yaml +74 -0
  13. models/configs/v1-inference_fp16.yaml +71 -0
  14. models/configs/v1-inpainting-inference.yaml +71 -0
  15. models/configs/v2-inference-v.yaml +68 -0
  16. models/configs/v2-inference-v_fp32.yaml +68 -0
  17. models/configs/v2-inference.yaml +67 -0
  18. models/configs/v2-inference_fp32.yaml +67 -0
  19. models/configs/v2-inpainting-inference.yaml +158 -0
  20. models/controlnet/put_controlnets_and_t2i_here +0 -0
  21. models/diffusers/put_diffusers_models_here +0 -0
  22. models/embeddings/put_embeddings_or_textual_inversion_concepts_here +0 -0
  23. models/gligen/put_gligen_models_here +0 -0
  24. models/hypernetworks/put_hypernetworks_here +0 -0
  25. models/inpaint/put_inpaint_here +0 -0
  26. models/loras/put_loras_here +0 -0
  27. models/prompt_expansion/fooocus_expansion/config.json +40 -0
  28. models/prompt_expansion/fooocus_expansion/merges.txt +0 -0
  29. models/prompt_expansion/fooocus_expansion/positive.txt +642 -0
  30. models/prompt_expansion/fooocus_expansion/special_tokens_map.json +5 -0
  31. models/prompt_expansion/fooocus_expansion/tokenizer.json +0 -0
  32. models/prompt_expansion/fooocus_expansion/tokenizer_config.json +10 -0
  33. models/prompt_expansion/fooocus_expansion/vocab.json +0 -0
  34. models/prompt_expansion/put_prompt_expansion_here +0 -0
  35. models/safety_checker/put_safety_checker_models_here +0 -0
  36. models/style_models/put_t2i_style_model_here +0 -0
  37. models/unet/put_unet_files_here +0 -0
  38. models/upscale_models/put_esrgan_and_other_upscale_models_here +0 -0
  39. models/vae/put_vae_here +0 -0
  40. models/vae_approx/put_taesd_encoder_pth_and_taesd_decoder_pth_here +0 -0
  41. modules/__init__.py +0 -0
  42. modules/anisotropic.py +200 -0
  43. modules/async_worker.py +1485 -0
  44. modules/auth.py +41 -0
  45. modules/config.py +997 -0
  46. modules/constants.py +5 -0
  47. modules/core.py +341 -0
  48. modules/default_pipeline.py +515 -0
  49. modules/extra_utils.py +41 -0
  50. modules/flags.py +191 -0
.huggingface.yaml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ sdk: gradio
2
+ python_version: 3.10
3
+ app_file: entry_with_update.py
entry_with_update.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+
5
+ root = os.path.dirname(os.path.abspath(__file__))
6
+ sys.path.append(root)
7
+ os.chdir(root)
8
+
9
+
10
+ try:
11
+ import pygit2
12
+ pygit2.option(pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0)
13
+
14
+ repo = pygit2.Repository(os.path.abspath(os.path.dirname(__file__)))
15
+
16
+ branch_name = repo.head.shorthand
17
+
18
+ remote_name = 'origin'
19
+ remote = repo.remotes[remote_name]
20
+
21
+ remote.fetch()
22
+
23
+ local_branch_ref = f'refs/heads/{branch_name}'
24
+ local_branch = repo.lookup_reference(local_branch_ref)
25
+
26
+ remote_reference = f'refs/remotes/{remote_name}/{branch_name}'
27
+ remote_commit = repo.revparse_single(remote_reference)
28
+
29
+ merge_result, _ = repo.merge_analysis(remote_commit.id)
30
+
31
+ if merge_result & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE:
32
+ print("Already up-to-date")
33
+ elif merge_result & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD:
34
+ local_branch.set_target(remote_commit.id)
35
+ repo.head.set_target(remote_commit.id)
36
+ repo.checkout_tree(repo.get(remote_commit.id))
37
+ repo.reset(local_branch.target, pygit2.GIT_RESET_HARD)
38
+ print("Fast-forward merge")
39
+ elif merge_result & pygit2.GIT_MERGE_ANALYSIS_NORMAL:
40
+ print("Update failed - Did you modify any file?")
41
+ except Exception as e:
42
+ print('Update failed.')
43
+ print(str(e))
44
+
45
+ print('Update succeeded.')
46
+ from launch import *
fooocus_version.py ADDED
@@ -0,0 +1 @@
 
 
1
+ version = '2.5.5'
launch.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import ssl
3
+ import sys
4
+
5
+ print('[System ARGV] ' + str(sys.argv))
6
+
7
+ root = os.path.dirname(os.path.abspath(__file__))
8
+ sys.path.append(root)
9
+ os.chdir(root)
10
+
11
+ os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
12
+ os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0"
13
+ if "GRADIO_SERVER_PORT" not in os.environ:
14
+ os.environ["GRADIO_SERVER_PORT"] = "7865"
15
+
16
+ ssl._create_default_https_context = ssl._create_unverified_context
17
+
18
+ import platform
19
+ import fooocus_version
20
+
21
+ from build_launcher import build_launcher
22
+ from modules.launch_util import is_installed, run, python, run_pip, requirements_met, delete_folder_content
23
+ from modules.model_loader import load_file_from_url
24
+
25
+ REINSTALL_ALL = False
26
+ TRY_INSTALL_XFORMERS = False
27
+
28
+
29
+ def prepare_environment():
30
+ torch_index_url = os.environ.get('TORCH_INDEX_URL', "https://download.pytorch.org/whl/cu121")
31
+ torch_command = os.environ.get('TORCH_COMMAND',
32
+ f"pip install torch==2.1.0 torchvision==0.16.0 --extra-index-url {torch_index_url}")
33
+ requirements_file = os.environ.get('REQS_FILE', "requirements_versions.txt")
34
+
35
+ print(f"Python {sys.version}")
36
+ print(f"Fooocus version: {fooocus_version.version}")
37
+
38
+ if REINSTALL_ALL or not is_installed("torch") or not is_installed("torchvision"):
39
+ run(f'"{python}" -m {torch_command}', "Installing torch and torchvision", "Couldn't install torch", live=True)
40
+
41
+ if TRY_INSTALL_XFORMERS:
42
+ if REINSTALL_ALL or not is_installed("xformers"):
43
+ xformers_package = os.environ.get('XFORMERS_PACKAGE', 'xformers==0.0.23')
44
+ if platform.system() == "Windows":
45
+ if platform.python_version().startswith("3.10"):
46
+ run_pip(f"install -U -I --no-deps {xformers_package}", "xformers", live=True)
47
+ else:
48
+ print("Installation of xformers is not supported in this version of Python.")
49
+ print(
50
+ "You can also check this and build manually: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers#building-xformers-on-windows-by-duckness")
51
+ if not is_installed("xformers"):
52
+ exit(0)
53
+ elif platform.system() == "Linux":
54
+ run_pip(f"install -U -I --no-deps {xformers_package}", "xformers")
55
+
56
+ if REINSTALL_ALL or not requirements_met(requirements_file):
57
+ run_pip(f"install -r \"{requirements_file}\"", "requirements")
58
+
59
+ return
60
+
61
+
62
+ vae_approx_filenames = [
63
+ ('xlvaeapp.pth', 'https://huggingface.co/lllyasviel/misc/resolve/main/xlvaeapp.pth'),
64
+ ('vaeapp_sd15.pth', 'https://huggingface.co/lllyasviel/misc/resolve/main/vaeapp_sd15.pt'),
65
+ ('xl-to-v1_interposer-v4.0.safetensors',
66
+ 'https://huggingface.co/mashb1t/misc/resolve/main/xl-to-v1_interposer-v4.0.safetensors')
67
+ ]
68
+
69
+
70
+ def ini_args():
71
+ from args_manager import args
72
+ return args
73
+
74
+
75
+ prepare_environment()
76
+ build_launcher()
77
+ args = ini_args()
78
+
79
+ if args.gpu_device_id is not None:
80
+ os.environ['CUDA_VISIBLE_DEVICES'] = str(args.gpu_device_id)
81
+ print("Set device to:", args.gpu_device_id)
82
+
83
+ if args.hf_mirror is not None:
84
+ os.environ['HF_MIRROR'] = str(args.hf_mirror)
85
+ print("Set hf_mirror to:", args.hf_mirror)
86
+
87
+ from modules import config
88
+ from modules.hash_cache import init_cache
89
+
90
+ os.environ["U2NET_HOME"] = config.path_inpaint
91
+
92
+ os.environ['GRADIO_TEMP_DIR'] = config.temp_path
93
+
94
+ if config.temp_path_cleanup_on_launch:
95
+ print(f'[Cleanup] Attempting to delete content of temp dir {config.temp_path}')
96
+ result = delete_folder_content(config.temp_path, '[Cleanup] ')
97
+ if result:
98
+ print("[Cleanup] Cleanup successful")
99
+ else:
100
+ print(f"[Cleanup] Failed to delete content of temp dir.")
101
+
102
+
103
+ def download_models(default_model, previous_default_models, checkpoint_downloads, embeddings_downloads, lora_downloads, vae_downloads):
104
+ from modules.util import get_file_from_folder_list
105
+
106
+ for file_name, url in vae_approx_filenames:
107
+ load_file_from_url(url=url, model_dir=config.path_vae_approx, file_name=file_name)
108
+
109
+ load_file_from_url(
110
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_expansion.bin',
111
+ model_dir=config.path_fooocus_expansion,
112
+ file_name='pytorch_model.bin'
113
+ )
114
+
115
+ if args.disable_preset_download:
116
+ print('Skipped model download.')
117
+ return default_model, checkpoint_downloads
118
+
119
+ if not args.always_download_new_model:
120
+ if not os.path.isfile(get_file_from_folder_list(default_model, config.paths_checkpoints)):
121
+ for alternative_model_name in previous_default_models:
122
+ if os.path.isfile(get_file_from_folder_list(alternative_model_name, config.paths_checkpoints)):
123
+ print(f'You do not have [{default_model}] but you have [{alternative_model_name}].')
124
+ print(f'Fooocus will use [{alternative_model_name}] to avoid downloading new models, '
125
+ f'but you are not using the latest models.')
126
+ print('Use --always-download-new-model to avoid fallback and always get new models.')
127
+ checkpoint_downloads = {}
128
+ default_model = alternative_model_name
129
+ break
130
+
131
+ for file_name, url in checkpoint_downloads.items():
132
+ model_dir = os.path.dirname(get_file_from_folder_list(file_name, config.paths_checkpoints))
133
+ load_file_from_url(url=url, model_dir=model_dir, file_name=file_name)
134
+ for file_name, url in embeddings_downloads.items():
135
+ load_file_from_url(url=url, model_dir=config.path_embeddings, file_name=file_name)
136
+ for file_name, url in lora_downloads.items():
137
+ model_dir = os.path.dirname(get_file_from_folder_list(file_name, config.paths_loras))
138
+ load_file_from_url(url=url, model_dir=model_dir, file_name=file_name)
139
+ for file_name, url in vae_downloads.items():
140
+ load_file_from_url(url=url, model_dir=config.path_vae, file_name=file_name)
141
+
142
+ return default_model, checkpoint_downloads
143
+
144
+
145
+ config.default_base_model_name, config.checkpoint_downloads = download_models(
146
+ config.default_base_model_name, config.previous_default_models, config.checkpoint_downloads,
147
+ config.embeddings_downloads, config.lora_downloads, config.vae_downloads)
148
+
149
+ config.update_files()
150
+ init_cache(config.model_filenames, config.paths_checkpoints, config.lora_filenames, config.paths_loras)
151
+
152
+ from webui import *
models/checkpoints/put_checkpoints_here ADDED
File without changes
models/clip/put_clip_or_text_encoder_models_here ADDED
File without changes
models/clip_vision/put_clip_vision_models_here ADDED
File without changes
models/clip_vision/wd-v1-4-moat-tagger-v2.csv ADDED
The diff for this file is too large to render. See raw diff
 
models/configs/anything_v3.yaml ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 4
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
71
+ params:
72
+ layer: "hidden"
73
+ layer_idx: -2
models/configs/v1-inference.yaml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 4
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
models/configs/v1-inference_clip_skip_2.yaml ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 4
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
71
+ params:
72
+ layer: "hidden"
73
+ layer_idx: -2
models/configs/v1-inference_clip_skip_2_fp16.yaml ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ use_fp16: True
33
+ image_size: 32 # unused
34
+ in_channels: 4
35
+ out_channels: 4
36
+ model_channels: 320
37
+ attention_resolutions: [ 4, 2, 1 ]
38
+ num_res_blocks: 2
39
+ channel_mult: [ 1, 2, 4, 4 ]
40
+ num_heads: 8
41
+ use_spatial_transformer: True
42
+ transformer_depth: 1
43
+ context_dim: 768
44
+ use_checkpoint: True
45
+ legacy: False
46
+
47
+ first_stage_config:
48
+ target: ldm.models.autoencoder.AutoencoderKL
49
+ params:
50
+ embed_dim: 4
51
+ monitor: val/rec_loss
52
+ ddconfig:
53
+ double_z: true
54
+ z_channels: 4
55
+ resolution: 256
56
+ in_channels: 3
57
+ out_ch: 3
58
+ ch: 128
59
+ ch_mult:
60
+ - 1
61
+ - 2
62
+ - 4
63
+ - 4
64
+ num_res_blocks: 2
65
+ attn_resolutions: []
66
+ dropout: 0.0
67
+ lossconfig:
68
+ target: torch.nn.Identity
69
+
70
+ cond_stage_config:
71
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
72
+ params:
73
+ layer: "hidden"
74
+ layer_idx: -2
models/configs/v1-inference_fp16.yaml ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ use_fp16: True
33
+ image_size: 32 # unused
34
+ in_channels: 4
35
+ out_channels: 4
36
+ model_channels: 320
37
+ attention_resolutions: [ 4, 2, 1 ]
38
+ num_res_blocks: 2
39
+ channel_mult: [ 1, 2, 4, 4 ]
40
+ num_heads: 8
41
+ use_spatial_transformer: True
42
+ transformer_depth: 1
43
+ context_dim: 768
44
+ use_checkpoint: True
45
+ legacy: False
46
+
47
+ first_stage_config:
48
+ target: ldm.models.autoencoder.AutoencoderKL
49
+ params:
50
+ embed_dim: 4
51
+ monitor: val/rec_loss
52
+ ddconfig:
53
+ double_z: true
54
+ z_channels: 4
55
+ resolution: 256
56
+ in_channels: 3
57
+ out_ch: 3
58
+ ch: 128
59
+ ch_mult:
60
+ - 1
61
+ - 2
62
+ - 4
63
+ - 4
64
+ num_res_blocks: 2
65
+ attn_resolutions: []
66
+ dropout: 0.0
67
+ lossconfig:
68
+ target: torch.nn.Identity
69
+
70
+ cond_stage_config:
71
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
models/configs/v1-inpainting-inference.yaml ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 7.5e-05
3
+ target: ldm.models.diffusion.ddpm.LatentInpaintDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: hybrid # important
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ finetune_keys: null
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 2500 ] # NOTE for resuming. use 10000 if starting from scratch
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 9 # 4 data + 4 downscaled image + 1 mask
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
71
+
models/configs/v2-inference-v.yaml ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-4
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ parameterization: "v"
6
+ linear_start: 0.00085
7
+ linear_end: 0.0120
8
+ num_timesteps_cond: 1
9
+ log_every_t: 200
10
+ timesteps: 1000
11
+ first_stage_key: "jpg"
12
+ cond_stage_key: "txt"
13
+ image_size: 64
14
+ channels: 4
15
+ cond_stage_trainable: false
16
+ conditioning_key: crossattn
17
+ monitor: val/loss_simple_ema
18
+ scale_factor: 0.18215
19
+ use_ema: False # we set this to false because this is an inference only config
20
+
21
+ unet_config:
22
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
23
+ params:
24
+ use_checkpoint: True
25
+ use_fp16: True
26
+ image_size: 32 # unused
27
+ in_channels: 4
28
+ out_channels: 4
29
+ model_channels: 320
30
+ attention_resolutions: [ 4, 2, 1 ]
31
+ num_res_blocks: 2
32
+ channel_mult: [ 1, 2, 4, 4 ]
33
+ num_head_channels: 64 # need to fix for flash-attn
34
+ use_spatial_transformer: True
35
+ use_linear_in_transformer: True
36
+ transformer_depth: 1
37
+ context_dim: 1024
38
+ legacy: False
39
+
40
+ first_stage_config:
41
+ target: ldm.models.autoencoder.AutoencoderKL
42
+ params:
43
+ embed_dim: 4
44
+ monitor: val/rec_loss
45
+ ddconfig:
46
+ #attn_type: "vanilla-xformers"
47
+ double_z: true
48
+ z_channels: 4
49
+ resolution: 256
50
+ in_channels: 3
51
+ out_ch: 3
52
+ ch: 128
53
+ ch_mult:
54
+ - 1
55
+ - 2
56
+ - 4
57
+ - 4
58
+ num_res_blocks: 2
59
+ attn_resolutions: []
60
+ dropout: 0.0
61
+ lossconfig:
62
+ target: torch.nn.Identity
63
+
64
+ cond_stage_config:
65
+ target: ldm.modules.encoders.modules.FrozenOpenCLIPEmbedder
66
+ params:
67
+ freeze: True
68
+ layer: "penultimate"
models/configs/v2-inference-v_fp32.yaml ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-4
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ parameterization: "v"
6
+ linear_start: 0.00085
7
+ linear_end: 0.0120
8
+ num_timesteps_cond: 1
9
+ log_every_t: 200
10
+ timesteps: 1000
11
+ first_stage_key: "jpg"
12
+ cond_stage_key: "txt"
13
+ image_size: 64
14
+ channels: 4
15
+ cond_stage_trainable: false
16
+ conditioning_key: crossattn
17
+ monitor: val/loss_simple_ema
18
+ scale_factor: 0.18215
19
+ use_ema: False # we set this to false because this is an inference only config
20
+
21
+ unet_config:
22
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
23
+ params:
24
+ use_checkpoint: True
25
+ use_fp16: False
26
+ image_size: 32 # unused
27
+ in_channels: 4
28
+ out_channels: 4
29
+ model_channels: 320
30
+ attention_resolutions: [ 4, 2, 1 ]
31
+ num_res_blocks: 2
32
+ channel_mult: [ 1, 2, 4, 4 ]
33
+ num_head_channels: 64 # need to fix for flash-attn
34
+ use_spatial_transformer: True
35
+ use_linear_in_transformer: True
36
+ transformer_depth: 1
37
+ context_dim: 1024
38
+ legacy: False
39
+
40
+ first_stage_config:
41
+ target: ldm.models.autoencoder.AutoencoderKL
42
+ params:
43
+ embed_dim: 4
44
+ monitor: val/rec_loss
45
+ ddconfig:
46
+ #attn_type: "vanilla-xformers"
47
+ double_z: true
48
+ z_channels: 4
49
+ resolution: 256
50
+ in_channels: 3
51
+ out_ch: 3
52
+ ch: 128
53
+ ch_mult:
54
+ - 1
55
+ - 2
56
+ - 4
57
+ - 4
58
+ num_res_blocks: 2
59
+ attn_resolutions: []
60
+ dropout: 0.0
61
+ lossconfig:
62
+ target: torch.nn.Identity
63
+
64
+ cond_stage_config:
65
+ target: ldm.modules.encoders.modules.FrozenOpenCLIPEmbedder
66
+ params:
67
+ freeze: True
68
+ layer: "penultimate"
models/configs/v2-inference.yaml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-4
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False # we set this to false because this is an inference only config
19
+
20
+ unet_config:
21
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
22
+ params:
23
+ use_checkpoint: True
24
+ use_fp16: True
25
+ image_size: 32 # unused
26
+ in_channels: 4
27
+ out_channels: 4
28
+ model_channels: 320
29
+ attention_resolutions: [ 4, 2, 1 ]
30
+ num_res_blocks: 2
31
+ channel_mult: [ 1, 2, 4, 4 ]
32
+ num_head_channels: 64 # need to fix for flash-attn
33
+ use_spatial_transformer: True
34
+ use_linear_in_transformer: True
35
+ transformer_depth: 1
36
+ context_dim: 1024
37
+ legacy: False
38
+
39
+ first_stage_config:
40
+ target: ldm.models.autoencoder.AutoencoderKL
41
+ params:
42
+ embed_dim: 4
43
+ monitor: val/rec_loss
44
+ ddconfig:
45
+ #attn_type: "vanilla-xformers"
46
+ double_z: true
47
+ z_channels: 4
48
+ resolution: 256
49
+ in_channels: 3
50
+ out_ch: 3
51
+ ch: 128
52
+ ch_mult:
53
+ - 1
54
+ - 2
55
+ - 4
56
+ - 4
57
+ num_res_blocks: 2
58
+ attn_resolutions: []
59
+ dropout: 0.0
60
+ lossconfig:
61
+ target: torch.nn.Identity
62
+
63
+ cond_stage_config:
64
+ target: ldm.modules.encoders.modules.FrozenOpenCLIPEmbedder
65
+ params:
66
+ freeze: True
67
+ layer: "penultimate"
models/configs/v2-inference_fp32.yaml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-4
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False # we set this to false because this is an inference only config
19
+
20
+ unet_config:
21
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
22
+ params:
23
+ use_checkpoint: True
24
+ use_fp16: False
25
+ image_size: 32 # unused
26
+ in_channels: 4
27
+ out_channels: 4
28
+ model_channels: 320
29
+ attention_resolutions: [ 4, 2, 1 ]
30
+ num_res_blocks: 2
31
+ channel_mult: [ 1, 2, 4, 4 ]
32
+ num_head_channels: 64 # need to fix for flash-attn
33
+ use_spatial_transformer: True
34
+ use_linear_in_transformer: True
35
+ transformer_depth: 1
36
+ context_dim: 1024
37
+ legacy: False
38
+
39
+ first_stage_config:
40
+ target: ldm.models.autoencoder.AutoencoderKL
41
+ params:
42
+ embed_dim: 4
43
+ monitor: val/rec_loss
44
+ ddconfig:
45
+ #attn_type: "vanilla-xformers"
46
+ double_z: true
47
+ z_channels: 4
48
+ resolution: 256
49
+ in_channels: 3
50
+ out_ch: 3
51
+ ch: 128
52
+ ch_mult:
53
+ - 1
54
+ - 2
55
+ - 4
56
+ - 4
57
+ num_res_blocks: 2
58
+ attn_resolutions: []
59
+ dropout: 0.0
60
+ lossconfig:
61
+ target: torch.nn.Identity
62
+
63
+ cond_stage_config:
64
+ target: ldm.modules.encoders.modules.FrozenOpenCLIPEmbedder
65
+ params:
66
+ freeze: True
67
+ layer: "penultimate"
models/configs/v2-inpainting-inference.yaml ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 5.0e-05
3
+ target: ldm.models.diffusion.ddpm.LatentInpaintDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false
15
+ conditioning_key: hybrid
16
+ scale_factor: 0.18215
17
+ monitor: val/loss_simple_ema
18
+ finetune_keys: null
19
+ use_ema: False
20
+
21
+ unet_config:
22
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
23
+ params:
24
+ use_checkpoint: True
25
+ image_size: 32 # unused
26
+ in_channels: 9
27
+ out_channels: 4
28
+ model_channels: 320
29
+ attention_resolutions: [ 4, 2, 1 ]
30
+ num_res_blocks: 2
31
+ channel_mult: [ 1, 2, 4, 4 ]
32
+ num_head_channels: 64 # need to fix for flash-attn
33
+ use_spatial_transformer: True
34
+ use_linear_in_transformer: True
35
+ transformer_depth: 1
36
+ context_dim: 1024
37
+ legacy: False
38
+
39
+ first_stage_config:
40
+ target: ldm.models.autoencoder.AutoencoderKL
41
+ params:
42
+ embed_dim: 4
43
+ monitor: val/rec_loss
44
+ ddconfig:
45
+ #attn_type: "vanilla-xformers"
46
+ double_z: true
47
+ z_channels: 4
48
+ resolution: 256
49
+ in_channels: 3
50
+ out_ch: 3
51
+ ch: 128
52
+ ch_mult:
53
+ - 1
54
+ - 2
55
+ - 4
56
+ - 4
57
+ num_res_blocks: 2
58
+ attn_resolutions: [ ]
59
+ dropout: 0.0
60
+ lossconfig:
61
+ target: torch.nn.Identity
62
+
63
+ cond_stage_config:
64
+ target: ldm.modules.encoders.modules.FrozenOpenCLIPEmbedder
65
+ params:
66
+ freeze: True
67
+ layer: "penultimate"
68
+
69
+
70
+ data:
71
+ target: ldm.data.laion.WebDataModuleFromConfig
72
+ params:
73
+ tar_base: null # for concat as in LAION-A
74
+ p_unsafe_threshold: 0.1
75
+ filter_word_list: "data/filters.yaml"
76
+ max_pwatermark: 0.45
77
+ batch_size: 8
78
+ num_workers: 6
79
+ multinode: True
80
+ min_size: 512
81
+ train:
82
+ shards:
83
+ - "pipe:aws s3 cp s3://stability-aws/laion-a-native/part-0/{00000..18699}.tar -"
84
+ - "pipe:aws s3 cp s3://stability-aws/laion-a-native/part-1/{00000..18699}.tar -"
85
+ - "pipe:aws s3 cp s3://stability-aws/laion-a-native/part-2/{00000..18699}.tar -"
86
+ - "pipe:aws s3 cp s3://stability-aws/laion-a-native/part-3/{00000..18699}.tar -"
87
+ - "pipe:aws s3 cp s3://stability-aws/laion-a-native/part-4/{00000..18699}.tar -" #{00000-94333}.tar"
88
+ shuffle: 10000
89
+ image_key: jpg
90
+ image_transforms:
91
+ - target: torchvision.transforms.Resize
92
+ params:
93
+ size: 512
94
+ interpolation: 3
95
+ - target: torchvision.transforms.RandomCrop
96
+ params:
97
+ size: 512
98
+ postprocess:
99
+ target: ldm.data.laion.AddMask
100
+ params:
101
+ mode: "512train-large"
102
+ p_drop: 0.25
103
+ # NOTE use enough shards to avoid empty validation loops in workers
104
+ validation:
105
+ shards:
106
+ - "pipe:aws s3 cp s3://deep-floyd-s3/datasets/laion_cleaned-part5/{93001..94333}.tar - "
107
+ shuffle: 0
108
+ image_key: jpg
109
+ image_transforms:
110
+ - target: torchvision.transforms.Resize
111
+ params:
112
+ size: 512
113
+ interpolation: 3
114
+ - target: torchvision.transforms.CenterCrop
115
+ params:
116
+ size: 512
117
+ postprocess:
118
+ target: ldm.data.laion.AddMask
119
+ params:
120
+ mode: "512train-large"
121
+ p_drop: 0.25
122
+
123
+ lightning:
124
+ find_unused_parameters: True
125
+ modelcheckpoint:
126
+ params:
127
+ every_n_train_steps: 5000
128
+
129
+ callbacks:
130
+ metrics_over_trainsteps_checkpoint:
131
+ params:
132
+ every_n_train_steps: 10000
133
+
134
+ image_logger:
135
+ target: main.ImageLogger
136
+ params:
137
+ enable_autocast: False
138
+ disabled: False
139
+ batch_frequency: 1000
140
+ max_images: 4
141
+ increase_log_steps: False
142
+ log_first_step: False
143
+ log_images_kwargs:
144
+ use_ema_scope: False
145
+ inpaint: False
146
+ plot_progressive_rows: False
147
+ plot_diffusion_rows: False
148
+ N: 4
149
+ unconditional_guidance_scale: 5.0
150
+ unconditional_guidance_label: [""]
151
+ ddim_steps: 50 # todo check these out for depth2img,
152
+ ddim_eta: 0.0 # todo check these out for depth2img,
153
+
154
+ trainer:
155
+ benchmark: True
156
+ val_check_interval: 5000000
157
+ num_sanity_val_steps: 0
158
+ accumulate_grad_batches: 1
models/controlnet/put_controlnets_and_t2i_here ADDED
File without changes
models/diffusers/put_diffusers_models_here ADDED
File without changes
models/embeddings/put_embeddings_or_textual_inversion_concepts_here ADDED
File without changes
models/gligen/put_gligen_models_here ADDED
File without changes
models/hypernetworks/put_hypernetworks_here ADDED
File without changes
models/inpaint/put_inpaint_here ADDED
File without changes
models/loras/put_loras_here ADDED
File without changes
models/prompt_expansion/fooocus_expansion/config.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "gpt2",
3
+ "activation_function": "gelu_new",
4
+ "architectures": [
5
+ "GPT2LMHeadModel"
6
+ ],
7
+ "attn_pdrop": 0.1,
8
+ "bos_token_id": 50256,
9
+ "embd_pdrop": 0.1,
10
+ "eos_token_id": 50256,
11
+ "pad_token_id": 50256,
12
+ "initializer_range": 0.02,
13
+ "layer_norm_epsilon": 1e-05,
14
+ "model_type": "gpt2",
15
+ "n_ctx": 1024,
16
+ "n_embd": 768,
17
+ "n_head": 12,
18
+ "n_inner": null,
19
+ "n_layer": 12,
20
+ "n_positions": 1024,
21
+ "reorder_and_upcast_attn": false,
22
+ "resid_pdrop": 0.1,
23
+ "scale_attn_by_inverse_layer_idx": false,
24
+ "scale_attn_weights": true,
25
+ "summary_activation": null,
26
+ "summary_first_dropout": 0.1,
27
+ "summary_proj_to_labels": true,
28
+ "summary_type": "cls_index",
29
+ "summary_use_proj": true,
30
+ "task_specific_params": {
31
+ "text-generation": {
32
+ "do_sample": true,
33
+ "max_length": 50
34
+ }
35
+ },
36
+ "torch_dtype": "float32",
37
+ "transformers_version": "4.23.0.dev0",
38
+ "use_cache": true,
39
+ "vocab_size": 50257
40
+ }
models/prompt_expansion/fooocus_expansion/merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
models/prompt_expansion/fooocus_expansion/positive.txt ADDED
@@ -0,0 +1,642 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ abundant
2
+ accelerated
3
+ accepted
4
+ accepting
5
+ acclaimed
6
+ accomplished
7
+ acknowledged
8
+ activated
9
+ adapted
10
+ adjusted
11
+ admirable
12
+ adorable
13
+ adorned
14
+ advanced
15
+ adventurous
16
+ advocated
17
+ aesthetic
18
+ affirmed
19
+ affluent
20
+ agile
21
+ aimed
22
+ aligned
23
+ alive
24
+ altered
25
+ amazing
26
+ ambient
27
+ amplified
28
+ analytical
29
+ animated
30
+ appealing
31
+ applauded
32
+ appreciated
33
+ ardent
34
+ aromatic
35
+ arranged
36
+ arresting
37
+ articulate
38
+ artistic
39
+ associated
40
+ assured
41
+ astonishing
42
+ astounding
43
+ atmosphere
44
+ attempted
45
+ attentive
46
+ attractive
47
+ authentic
48
+ authoritative
49
+ awarded
50
+ awesome
51
+ backed
52
+ background
53
+ baked
54
+ balance
55
+ balanced
56
+ balancing
57
+ beaten
58
+ beautiful
59
+ beloved
60
+ beneficial
61
+ benevolent
62
+ best
63
+ bestowed
64
+ blazing
65
+ blended
66
+ blessed
67
+ boosted
68
+ borne
69
+ brave
70
+ breathtaking
71
+ brewed
72
+ bright
73
+ brilliant
74
+ brought
75
+ built
76
+ burning
77
+ calm
78
+ calmed
79
+ candid
80
+ caring
81
+ carried
82
+ catchy
83
+ celebrated
84
+ celestial
85
+ certain
86
+ championed
87
+ changed
88
+ charismatic
89
+ charming
90
+ chased
91
+ cheered
92
+ cheerful
93
+ cherished
94
+ chic
95
+ chosen
96
+ cinematic
97
+ clad
98
+ classic
99
+ classy
100
+ clear
101
+ coached
102
+ coherent
103
+ collected
104
+ color
105
+ colorful
106
+ colors
107
+ colossal
108
+ combined
109
+ comforting
110
+ commanding
111
+ committed
112
+ compassionate
113
+ compatible
114
+ complete
115
+ complex
116
+ complimentary
117
+ composed
118
+ composition
119
+ comprehensive
120
+ conceived
121
+ conferred
122
+ confident
123
+ connected
124
+ considerable
125
+ considered
126
+ consistent
127
+ conspicuous
128
+ constructed
129
+ constructive
130
+ contemplated
131
+ contemporary
132
+ content
133
+ contrasted
134
+ conveyed
135
+ cooked
136
+ cool
137
+ coordinated
138
+ coupled
139
+ courageous
140
+ coveted
141
+ cozy
142
+ created
143
+ creative
144
+ credited
145
+ crisp
146
+ critical
147
+ cultivated
148
+ cured
149
+ curious
150
+ current
151
+ customized
152
+ cute
153
+ daring
154
+ darling
155
+ dazzling
156
+ decorated
157
+ decorative
158
+ dedicated
159
+ deep
160
+ defended
161
+ definitive
162
+ delicate
163
+ delightful
164
+ delivered
165
+ depicted
166
+ designed
167
+ desirable
168
+ desired
169
+ destined
170
+ detail
171
+ detailed
172
+ determined
173
+ developed
174
+ devoted
175
+ devout
176
+ diligent
177
+ direct
178
+ directed
179
+ discovered
180
+ dispatched
181
+ displayed
182
+ distilled
183
+ distinct
184
+ distinctive
185
+ distinguished
186
+ diverse
187
+ divine
188
+ dramatic
189
+ draped
190
+ dreamed
191
+ driven
192
+ dynamic
193
+ earnest
194
+ eased
195
+ ecstatic
196
+ educated
197
+ effective
198
+ elaborate
199
+ elegant
200
+ elevated
201
+ elite
202
+ eminent
203
+ emotional
204
+ empowered
205
+ empowering
206
+ enchanted
207
+ encouraged
208
+ endorsed
209
+ endowed
210
+ enduring
211
+ energetic
212
+ engaging
213
+ enhanced
214
+ enigmatic
215
+ enlightened
216
+ enormous
217
+ enticing
218
+ envisioned
219
+ epic
220
+ esteemed
221
+ eternal
222
+ everlasting
223
+ evolved
224
+ exalted
225
+ examining
226
+ excellent
227
+ exceptional
228
+ exciting
229
+ exclusive
230
+ exemplary
231
+ exotic
232
+ expansive
233
+ exposed
234
+ expressive
235
+ exquisite
236
+ extended
237
+ extraordinary
238
+ extremely
239
+ fabulous
240
+ facilitated
241
+ fair
242
+ faithful
243
+ famous
244
+ fancy
245
+ fantastic
246
+ fascinating
247
+ fashionable
248
+ fashioned
249
+ favorable
250
+ favored
251
+ fearless
252
+ fermented
253
+ fertile
254
+ festive
255
+ fiery
256
+ fine
257
+ finest
258
+ firm
259
+ fixed
260
+ flaming
261
+ flashing
262
+ flashy
263
+ flavored
264
+ flawless
265
+ flourishing
266
+ flowing
267
+ focus
268
+ focused
269
+ formal
270
+ formed
271
+ fortunate
272
+ fostering
273
+ frank
274
+ fresh
275
+ fried
276
+ friendly
277
+ fruitful
278
+ fulfilled
279
+ full
280
+ futuristic
281
+ generous
282
+ gentle
283
+ genuine
284
+ gifted
285
+ gigantic
286
+ glamorous
287
+ glorious
288
+ glossy
289
+ glowing
290
+ gorgeous
291
+ graceful
292
+ gracious
293
+ grand
294
+ granted
295
+ grateful
296
+ great
297
+ grilled
298
+ grounded
299
+ grown
300
+ guarded
301
+ guided
302
+ hailed
303
+ handsome
304
+ healing
305
+ healthy
306
+ heartfelt
307
+ heavenly
308
+ heroic
309
+ highly
310
+ historic
311
+ holistic
312
+ holy
313
+ honest
314
+ honored
315
+ hoped
316
+ hopeful
317
+ iconic
318
+ ideal
319
+ illuminated
320
+ illuminating
321
+ illumination
322
+ illustrious
323
+ imaginative
324
+ imagined
325
+ immense
326
+ immortal
327
+ imposing
328
+ impressive
329
+ improved
330
+ incredible
331
+ infinite
332
+ informed
333
+ ingenious
334
+ innocent
335
+ innovative
336
+ insightful
337
+ inspirational
338
+ inspired
339
+ inspiring
340
+ instructed
341
+ integrated
342
+ intense
343
+ intricate
344
+ intriguing
345
+ invaluable
346
+ invented
347
+ investigative
348
+ invincible
349
+ inviting
350
+ irresistible
351
+ joined
352
+ joyful
353
+ keen
354
+ kindly
355
+ kinetic
356
+ knockout
357
+ laced
358
+ lasting
359
+ lauded
360
+ lavish
361
+ legendary
362
+ lifted
363
+ light
364
+ limited
365
+ linked
366
+ lively
367
+ located
368
+ logical
369
+ loved
370
+ lovely
371
+ loving
372
+ loyal
373
+ lucid
374
+ lucky
375
+ lush
376
+ luxurious
377
+ luxury
378
+ magic
379
+ magical
380
+ magnificent
381
+ majestic
382
+ marked
383
+ marvelous
384
+ massive
385
+ matched
386
+ matured
387
+ meaningful
388
+ memorable
389
+ merged
390
+ merry
391
+ meticulous
392
+ mindful
393
+ miraculous
394
+ modern
395
+ modified
396
+ monstrous
397
+ monumental
398
+ motivated
399
+ motivational
400
+ moved
401
+ moving
402
+ mystical
403
+ mythical
404
+ naive
405
+ neat
406
+ new
407
+ nice
408
+ nifty
409
+ noble
410
+ notable
411
+ noteworthy
412
+ novel
413
+ nuanced
414
+ offered
415
+ open
416
+ optimal
417
+ optimistic
418
+ orderly
419
+ organized
420
+ original
421
+ originated
422
+ outstanding
423
+ overwhelming
424
+ paired
425
+ palpable
426
+ passionate
427
+ peaceful
428
+ perfect
429
+ perfected
430
+ perpetual
431
+ persistent
432
+ phenomenal
433
+ pious
434
+ pivotal
435
+ placed
436
+ planned
437
+ pleasant
438
+ pleased
439
+ pleasing
440
+ plentiful
441
+ plotted
442
+ plush
443
+ poetic
444
+ poignant
445
+ polished
446
+ positive
447
+ praised
448
+ precious
449
+ precise
450
+ premier
451
+ premium
452
+ presented
453
+ preserved
454
+ prestigious
455
+ pretty
456
+ priceless
457
+ prime
458
+ pristine
459
+ probing
460
+ productive
461
+ professional
462
+ profound
463
+ progressed
464
+ progressive
465
+ prominent
466
+ promoted
467
+ pronounced
468
+ propelled
469
+ proportional
470
+ prosperous
471
+ protected
472
+ provided
473
+ provocative
474
+ pure
475
+ pursued
476
+ pushed
477
+ quaint
478
+ quality
479
+ questioning
480
+ quiet
481
+ radiant
482
+ rare
483
+ rational
484
+ real
485
+ reborn
486
+ reclaimed
487
+ recognized
488
+ recovered
489
+ refined
490
+ reflected
491
+ refreshed
492
+ refreshing
493
+ related
494
+ relaxed
495
+ relentless
496
+ reliable
497
+ relieved
498
+ remarkable
499
+ renewed
500
+ renowned
501
+ representative
502
+ rescued
503
+ resilient
504
+ respected
505
+ respectful
506
+ restored
507
+ retrieved
508
+ revealed
509
+ revealing
510
+ revered
511
+ revived
512
+ rewarded
513
+ rich
514
+ roasted
515
+ robust
516
+ romantic
517
+ royal
518
+ sacred
519
+ salient
520
+ satisfied
521
+ satisfying
522
+ saturated
523
+ saved
524
+ scenic
525
+ scientific
526
+ select
527
+ sensational
528
+ serious
529
+ set
530
+ shaped
531
+ sharp
532
+ shielded
533
+ shining
534
+ shiny
535
+ shown
536
+ significant
537
+ silent
538
+ sincere
539
+ singular
540
+ situated
541
+ sleek
542
+ slick
543
+ smart
544
+ snug
545
+ solemn
546
+ solid
547
+ soothing
548
+ sophisticated
549
+ sought
550
+ sparkling
551
+ special
552
+ spectacular
553
+ sped
554
+ spirited
555
+ spiritual
556
+ splendid
557
+ spread
558
+ stable
559
+ steady
560
+ still
561
+ stimulated
562
+ stimulating
563
+ stirred
564
+ straightforward
565
+ striking
566
+ strong
567
+ structured
568
+ stunning
569
+ sturdy
570
+ stylish
571
+ sublime
572
+ successful
573
+ sunny
574
+ superb
575
+ superior
576
+ supplied
577
+ supported
578
+ supportive
579
+ supreme
580
+ sure
581
+ surreal
582
+ sweet
583
+ symbolic
584
+ symmetry
585
+ synchronized
586
+ systematic
587
+ tailored
588
+ taking
589
+ targeted
590
+ taught
591
+ tempting
592
+ tender
593
+ terrific
594
+ thankful
595
+ theatrical
596
+ thought
597
+ thoughtful
598
+ thrilled
599
+ thrilling
600
+ thriving
601
+ tidy
602
+ timeless
603
+ touching
604
+ tough
605
+ trained
606
+ tranquil
607
+ transformed
608
+ translucent
609
+ transparent
610
+ transported
611
+ tremendous
612
+ trendy
613
+ tried
614
+ trim
615
+ true
616
+ trustworthy
617
+ unbelievable
618
+ unconditional
619
+ uncovered
620
+ unified
621
+ unique
622
+ united
623
+ universal
624
+ unmatched
625
+ unparalleled
626
+ upheld
627
+ valiant
628
+ valued
629
+ varied
630
+ very
631
+ vibrant
632
+ virtuous
633
+ vivid
634
+ warm
635
+ wealthy
636
+ whole
637
+ winning
638
+ wished
639
+ witty
640
+ wonderful
641
+ worshipped
642
+ worthy
models/prompt_expansion/fooocus_expansion/special_tokens_map.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "bos_token": "<|endoftext|>",
3
+ "eos_token": "<|endoftext|>",
4
+ "unk_token": "<|endoftext|>"
5
+ }
models/prompt_expansion/fooocus_expansion/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
models/prompt_expansion/fooocus_expansion/tokenizer_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "bos_token": "<|endoftext|>",
4
+ "eos_token": "<|endoftext|>",
5
+ "model_max_length": 1024,
6
+ "name_or_path": "gpt2",
7
+ "special_tokens_map_file": null,
8
+ "tokenizer_class": "GPT2Tokenizer",
9
+ "unk_token": "<|endoftext|>"
10
+ }
models/prompt_expansion/fooocus_expansion/vocab.json ADDED
The diff for this file is too large to render. See raw diff
 
models/prompt_expansion/put_prompt_expansion_here ADDED
File without changes
models/safety_checker/put_safety_checker_models_here ADDED
File without changes
models/style_models/put_t2i_style_model_here ADDED
File without changes
models/unet/put_unet_files_here ADDED
File without changes
models/upscale_models/put_esrgan_and_other_upscale_models_here ADDED
File without changes
models/vae/put_vae_here ADDED
File without changes
models/vae_approx/put_taesd_encoder_pth_and_taesd_decoder_pth_here ADDED
File without changes
modules/__init__.py ADDED
File without changes
modules/anisotropic.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+
4
+ Tensor = torch.Tensor
5
+ Device = torch.DeviceObjType
6
+ Dtype = torch.Type
7
+ pad = torch.nn.functional.pad
8
+
9
+
10
+ def _compute_zero_padding(kernel_size: tuple[int, int] | int) -> tuple[int, int]:
11
+ ky, kx = _unpack_2d_ks(kernel_size)
12
+ return (ky - 1) // 2, (kx - 1) // 2
13
+
14
+
15
+ def _unpack_2d_ks(kernel_size: tuple[int, int] | int) -> tuple[int, int]:
16
+ if isinstance(kernel_size, int):
17
+ ky = kx = kernel_size
18
+ else:
19
+ assert len(kernel_size) == 2, '2D Kernel size should have a length of 2.'
20
+ ky, kx = kernel_size
21
+
22
+ ky = int(ky)
23
+ kx = int(kx)
24
+ return ky, kx
25
+
26
+
27
+ def gaussian(
28
+ window_size: int, sigma: Tensor | float, *, device: Device | None = None, dtype: Dtype | None = None
29
+ ) -> Tensor:
30
+
31
+ batch_size = sigma.shape[0]
32
+
33
+ x = (torch.arange(window_size, device=sigma.device, dtype=sigma.dtype) - window_size // 2).expand(batch_size, -1)
34
+
35
+ if window_size % 2 == 0:
36
+ x = x + 0.5
37
+
38
+ gauss = torch.exp(-x.pow(2.0) / (2 * sigma.pow(2.0)))
39
+
40
+ return gauss / gauss.sum(-1, keepdim=True)
41
+
42
+
43
+ def get_gaussian_kernel1d(
44
+ kernel_size: int,
45
+ sigma: float | Tensor,
46
+ force_even: bool = False,
47
+ *,
48
+ device: Device | None = None,
49
+ dtype: Dtype | None = None,
50
+ ) -> Tensor:
51
+
52
+ return gaussian(kernel_size, sigma, device=device, dtype=dtype)
53
+
54
+
55
+ def get_gaussian_kernel2d(
56
+ kernel_size: tuple[int, int] | int,
57
+ sigma: tuple[float, float] | Tensor,
58
+ force_even: bool = False,
59
+ *,
60
+ device: Device | None = None,
61
+ dtype: Dtype | None = None,
62
+ ) -> Tensor:
63
+
64
+ sigma = torch.Tensor([[sigma, sigma]]).to(device=device, dtype=dtype)
65
+
66
+ ksize_y, ksize_x = _unpack_2d_ks(kernel_size)
67
+ sigma_y, sigma_x = sigma[:, 0, None], sigma[:, 1, None]
68
+
69
+ kernel_y = get_gaussian_kernel1d(ksize_y, sigma_y, force_even, device=device, dtype=dtype)[..., None]
70
+ kernel_x = get_gaussian_kernel1d(ksize_x, sigma_x, force_even, device=device, dtype=dtype)[..., None]
71
+
72
+ return kernel_y * kernel_x.view(-1, 1, ksize_x)
73
+
74
+
75
+ def _bilateral_blur(
76
+ input: Tensor,
77
+ guidance: Tensor | None,
78
+ kernel_size: tuple[int, int] | int,
79
+ sigma_color: float | Tensor,
80
+ sigma_space: tuple[float, float] | Tensor,
81
+ border_type: str = 'reflect',
82
+ color_distance_type: str = 'l1',
83
+ ) -> Tensor:
84
+
85
+ if isinstance(sigma_color, Tensor):
86
+ sigma_color = sigma_color.to(device=input.device, dtype=input.dtype).view(-1, 1, 1, 1, 1)
87
+
88
+ ky, kx = _unpack_2d_ks(kernel_size)
89
+ pad_y, pad_x = _compute_zero_padding(kernel_size)
90
+
91
+ padded_input = pad(input, (pad_x, pad_x, pad_y, pad_y), mode=border_type)
92
+ unfolded_input = padded_input.unfold(2, ky, 1).unfold(3, kx, 1).flatten(-2) # (B, C, H, W, Ky x Kx)
93
+
94
+ if guidance is None:
95
+ guidance = input
96
+ unfolded_guidance = unfolded_input
97
+ else:
98
+ padded_guidance = pad(guidance, (pad_x, pad_x, pad_y, pad_y), mode=border_type)
99
+ unfolded_guidance = padded_guidance.unfold(2, ky, 1).unfold(3, kx, 1).flatten(-2) # (B, C, H, W, Ky x Kx)
100
+
101
+ diff = unfolded_guidance - guidance.unsqueeze(-1)
102
+ if color_distance_type == "l1":
103
+ color_distance_sq = diff.abs().sum(1, keepdim=True).square()
104
+ elif color_distance_type == "l2":
105
+ color_distance_sq = diff.square().sum(1, keepdim=True)
106
+ else:
107
+ raise ValueError("color_distance_type only acceps l1 or l2")
108
+ color_kernel = (-0.5 / sigma_color**2 * color_distance_sq).exp() # (B, 1, H, W, Ky x Kx)
109
+
110
+ space_kernel = get_gaussian_kernel2d(kernel_size, sigma_space, device=input.device, dtype=input.dtype)
111
+ space_kernel = space_kernel.view(-1, 1, 1, 1, kx * ky)
112
+
113
+ kernel = space_kernel * color_kernel
114
+ out = (unfolded_input * kernel).sum(-1) / kernel.sum(-1)
115
+ return out
116
+
117
+
118
+ def bilateral_blur(
119
+ input: Tensor,
120
+ kernel_size: tuple[int, int] | int = (13, 13),
121
+ sigma_color: float | Tensor = 3.0,
122
+ sigma_space: tuple[float, float] | Tensor = 3.0,
123
+ border_type: str = 'reflect',
124
+ color_distance_type: str = 'l1',
125
+ ) -> Tensor:
126
+ return _bilateral_blur(input, None, kernel_size, sigma_color, sigma_space, border_type, color_distance_type)
127
+
128
+
129
+ def adaptive_anisotropic_filter(x, g=None):
130
+ if g is None:
131
+ g = x
132
+ s, m = torch.std_mean(g, dim=(1, 2, 3), keepdim=True)
133
+ s = s + 1e-5
134
+ guidance = (g - m) / s
135
+ y = _bilateral_blur(x, guidance,
136
+ kernel_size=(13, 13),
137
+ sigma_color=3.0,
138
+ sigma_space=3.0,
139
+ border_type='reflect',
140
+ color_distance_type='l1')
141
+ return y
142
+
143
+
144
+ def joint_bilateral_blur(
145
+ input: Tensor,
146
+ guidance: Tensor,
147
+ kernel_size: tuple[int, int] | int,
148
+ sigma_color: float | Tensor,
149
+ sigma_space: tuple[float, float] | Tensor,
150
+ border_type: str = 'reflect',
151
+ color_distance_type: str = 'l1',
152
+ ) -> Tensor:
153
+ return _bilateral_blur(input, guidance, kernel_size, sigma_color, sigma_space, border_type, color_distance_type)
154
+
155
+
156
+ class _BilateralBlur(torch.nn.Module):
157
+ def __init__(
158
+ self,
159
+ kernel_size: tuple[int, int] | int,
160
+ sigma_color: float | Tensor,
161
+ sigma_space: tuple[float, float] | Tensor,
162
+ border_type: str = 'reflect',
163
+ color_distance_type: str = "l1",
164
+ ) -> None:
165
+ super().__init__()
166
+ self.kernel_size = kernel_size
167
+ self.sigma_color = sigma_color
168
+ self.sigma_space = sigma_space
169
+ self.border_type = border_type
170
+ self.color_distance_type = color_distance_type
171
+
172
+ def __repr__(self) -> str:
173
+ return (
174
+ f"{self.__class__.__name__}"
175
+ f"(kernel_size={self.kernel_size}, "
176
+ f"sigma_color={self.sigma_color}, "
177
+ f"sigma_space={self.sigma_space}, "
178
+ f"border_type={self.border_type}, "
179
+ f"color_distance_type={self.color_distance_type})"
180
+ )
181
+
182
+
183
+ class BilateralBlur(_BilateralBlur):
184
+ def forward(self, input: Tensor) -> Tensor:
185
+ return bilateral_blur(
186
+ input, self.kernel_size, self.sigma_color, self.sigma_space, self.border_type, self.color_distance_type
187
+ )
188
+
189
+
190
+ class JointBilateralBlur(_BilateralBlur):
191
+ def forward(self, input: Tensor, guidance: Tensor) -> Tensor:
192
+ return joint_bilateral_blur(
193
+ input,
194
+ guidance,
195
+ self.kernel_size,
196
+ self.sigma_color,
197
+ self.sigma_space,
198
+ self.border_type,
199
+ self.color_distance_type,
200
+ )
modules/async_worker.py ADDED
@@ -0,0 +1,1485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+
3
+ from extras.inpaint_mask import generate_mask_from_image, SAMOptions
4
+ from modules.patch import PatchSettings, patch_settings, patch_all
5
+ import modules.config
6
+
7
+ patch_all()
8
+
9
+
10
+ class AsyncTask:
11
+ def __init__(self, args):
12
+ from modules.flags import Performance, MetadataScheme, ip_list, disabled
13
+ from modules.util import get_enabled_loras
14
+ from modules.config import default_max_lora_number
15
+ import args_manager
16
+
17
+ self.args = args.copy()
18
+ self.yields = []
19
+ self.results = []
20
+ self.last_stop = False
21
+ self.processing = False
22
+
23
+ self.performance_loras = []
24
+
25
+ if len(args) == 0:
26
+ return
27
+
28
+ args.reverse()
29
+ self.generate_image_grid = args.pop()
30
+ self.prompt = args.pop()
31
+ self.negative_prompt = args.pop()
32
+ self.style_selections = args.pop()
33
+
34
+ self.performance_selection = Performance(args.pop())
35
+ self.steps = self.performance_selection.steps()
36
+ self.original_steps = self.steps
37
+
38
+ self.aspect_ratios_selection = args.pop()
39
+ self.image_number = args.pop()
40
+ self.output_format = args.pop()
41
+ self.seed = int(args.pop())
42
+ self.read_wildcards_in_order = args.pop()
43
+ self.sharpness = args.pop()
44
+ self.cfg_scale = args.pop()
45
+ self.base_model_name = args.pop()
46
+ self.refiner_model_name = args.pop()
47
+ self.refiner_switch = args.pop()
48
+ self.loras = get_enabled_loras([(bool(args.pop()), str(args.pop()), float(args.pop())) for _ in
49
+ range(default_max_lora_number)])
50
+ self.input_image_checkbox = args.pop()
51
+ self.current_tab = args.pop()
52
+ self.uov_method = args.pop()
53
+ self.uov_input_image = args.pop()
54
+ self.outpaint_selections = args.pop()
55
+ self.inpaint_input_image = args.pop()
56
+ self.inpaint_additional_prompt = args.pop()
57
+ self.inpaint_mask_image_upload = args.pop()
58
+
59
+ self.disable_preview = args.pop()
60
+ self.disable_intermediate_results = args.pop()
61
+ self.disable_seed_increment = args.pop()
62
+ self.black_out_nsfw = args.pop()
63
+ self.adm_scaler_positive = args.pop()
64
+ self.adm_scaler_negative = args.pop()
65
+ self.adm_scaler_end = args.pop()
66
+ self.adaptive_cfg = args.pop()
67
+ self.clip_skip = args.pop()
68
+ self.sampler_name = args.pop()
69
+ self.scheduler_name = args.pop()
70
+ self.vae_name = args.pop()
71
+ self.overwrite_step = args.pop()
72
+ self.overwrite_switch = args.pop()
73
+ self.overwrite_width = args.pop()
74
+ self.overwrite_height = args.pop()
75
+ self.overwrite_vary_strength = args.pop()
76
+ self.overwrite_upscale_strength = args.pop()
77
+ self.mixing_image_prompt_and_vary_upscale = args.pop()
78
+ self.mixing_image_prompt_and_inpaint = args.pop()
79
+ self.debugging_cn_preprocessor = args.pop()
80
+ self.skipping_cn_preprocessor = args.pop()
81
+ self.canny_low_threshold = args.pop()
82
+ self.canny_high_threshold = args.pop()
83
+ self.refiner_swap_method = args.pop()
84
+ self.controlnet_softness = args.pop()
85
+ self.freeu_enabled = args.pop()
86
+ self.freeu_b1 = args.pop()
87
+ self.freeu_b2 = args.pop()
88
+ self.freeu_s1 = args.pop()
89
+ self.freeu_s2 = args.pop()
90
+ self.debugging_inpaint_preprocessor = args.pop()
91
+ self.inpaint_disable_initial_latent = args.pop()
92
+ self.inpaint_engine = args.pop()
93
+ self.inpaint_strength = args.pop()
94
+ self.inpaint_respective_field = args.pop()
95
+ self.inpaint_advanced_masking_checkbox = args.pop()
96
+ self.invert_mask_checkbox = args.pop()
97
+ self.inpaint_erode_or_dilate = args.pop()
98
+ self.save_final_enhanced_image_only = args.pop() if not args_manager.args.disable_image_log else False
99
+ self.save_metadata_to_images = args.pop() if not args_manager.args.disable_metadata else False
100
+ self.metadata_scheme = MetadataScheme(
101
+ args.pop()) if not args_manager.args.disable_metadata else MetadataScheme.FOOOCUS
102
+
103
+ self.cn_tasks = {x: [] for x in ip_list}
104
+ for _ in range(modules.config.default_controlnet_image_count):
105
+ cn_img = args.pop()
106
+ cn_stop = args.pop()
107
+ cn_weight = args.pop()
108
+ cn_type = args.pop()
109
+ if cn_img is not None:
110
+ self.cn_tasks[cn_type].append([cn_img, cn_stop, cn_weight])
111
+
112
+ self.debugging_dino = args.pop()
113
+ self.dino_erode_or_dilate = args.pop()
114
+ self.debugging_enhance_masks_checkbox = args.pop()
115
+
116
+ self.enhance_input_image = args.pop()
117
+ self.enhance_checkbox = args.pop()
118
+ self.enhance_uov_method = args.pop()
119
+ self.enhance_uov_processing_order = args.pop()
120
+ self.enhance_uov_prompt_type = args.pop()
121
+ self.enhance_ctrls = []
122
+ for _ in range(modules.config.default_enhance_tabs):
123
+ enhance_enabled = args.pop()
124
+ enhance_mask_dino_prompt_text = args.pop()
125
+ enhance_prompt = args.pop()
126
+ enhance_negative_prompt = args.pop()
127
+ enhance_mask_model = args.pop()
128
+ enhance_mask_cloth_category = args.pop()
129
+ enhance_mask_sam_model = args.pop()
130
+ enhance_mask_text_threshold = args.pop()
131
+ enhance_mask_box_threshold = args.pop()
132
+ enhance_mask_sam_max_detections = args.pop()
133
+ enhance_inpaint_disable_initial_latent = args.pop()
134
+ enhance_inpaint_engine = args.pop()
135
+ enhance_inpaint_strength = args.pop()
136
+ enhance_inpaint_respective_field = args.pop()
137
+ enhance_inpaint_erode_or_dilate = args.pop()
138
+ enhance_mask_invert = args.pop()
139
+ if enhance_enabled:
140
+ self.enhance_ctrls.append([
141
+ enhance_mask_dino_prompt_text,
142
+ enhance_prompt,
143
+ enhance_negative_prompt,
144
+ enhance_mask_model,
145
+ enhance_mask_cloth_category,
146
+ enhance_mask_sam_model,
147
+ enhance_mask_text_threshold,
148
+ enhance_mask_box_threshold,
149
+ enhance_mask_sam_max_detections,
150
+ enhance_inpaint_disable_initial_latent,
151
+ enhance_inpaint_engine,
152
+ enhance_inpaint_strength,
153
+ enhance_inpaint_respective_field,
154
+ enhance_inpaint_erode_or_dilate,
155
+ enhance_mask_invert
156
+ ])
157
+ self.should_enhance = self.enhance_checkbox and (self.enhance_uov_method != disabled.casefold() or len(self.enhance_ctrls) > 0)
158
+ self.images_to_enhance_count = 0
159
+ self.enhance_stats = {}
160
+
161
+ async_tasks = []
162
+
163
+
164
+ class EarlyReturnException(BaseException):
165
+ pass
166
+
167
+
168
+ def worker():
169
+ global async_tasks
170
+
171
+ import os
172
+ import traceback
173
+ import math
174
+ import numpy as np
175
+ import torch
176
+ import time
177
+ import shared
178
+ import random
179
+ import copy
180
+ import cv2
181
+ import modules.default_pipeline as pipeline
182
+ import modules.core as core
183
+ import modules.flags as flags
184
+ import modules.patch
185
+ import ldm_patched.modules.model_management
186
+ import extras.preprocessors as preprocessors
187
+ import modules.inpaint_worker as inpaint_worker
188
+ import modules.constants as constants
189
+ import extras.ip_adapter as ip_adapter
190
+ import extras.face_crop
191
+ import fooocus_version
192
+
193
+ from extras.censor import default_censor
194
+ from modules.sdxl_styles import apply_style, get_random_style, fooocus_expansion, apply_arrays, random_style_name
195
+ from modules.private_logger import log
196
+ from extras.expansion import safe_str
197
+ from modules.util import (remove_empty_str, HWC3, resize_image, get_image_shape_ceil, set_image_shape_ceil,
198
+ get_shape_ceil, resample_image, erode_or_dilate, parse_lora_references_from_prompt,
199
+ apply_wildcards)
200
+ from modules.upscaler import perform_upscale
201
+ from modules.flags import Performance
202
+ from modules.meta_parser import get_metadata_parser
203
+
204
+ pid = os.getpid()
205
+ print(f'Started worker with PID {pid}')
206
+
207
+ try:
208
+ async_gradio_app = shared.gradio_root
209
+ flag = f'''App started successful. Use the app with {str(async_gradio_app.local_url)} or {str(async_gradio_app.server_name)}:{str(async_gradio_app.server_port)}'''
210
+ if async_gradio_app.share:
211
+ flag += f''' or {async_gradio_app.share_url}'''
212
+ print(flag)
213
+ except Exception as e:
214
+ print(e)
215
+
216
+ def progressbar(async_task, number, text):
217
+ print(f'[Fooocus] {text}')
218
+ async_task.yields.append(['preview', (number, text, None)])
219
+
220
+ def yield_result(async_task, imgs, progressbar_index, black_out_nsfw, censor=True, do_not_show_finished_images=False):
221
+ if not isinstance(imgs, list):
222
+ imgs = [imgs]
223
+
224
+ if censor and (modules.config.default_black_out_nsfw or black_out_nsfw):
225
+ progressbar(async_task, progressbar_index, 'Checking for NSFW content ...')
226
+ imgs = default_censor(imgs)
227
+
228
+ async_task.results = async_task.results + imgs
229
+
230
+ if do_not_show_finished_images:
231
+ return
232
+
233
+ async_task.yields.append(['results', async_task.results])
234
+ return
235
+
236
+ def build_image_wall(async_task):
237
+ results = []
238
+
239
+ if len(async_task.results) < 2:
240
+ return
241
+
242
+ for img in async_task.results:
243
+ if isinstance(img, str) and os.path.exists(img):
244
+ img = cv2.imread(img)
245
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
246
+ if not isinstance(img, np.ndarray):
247
+ return
248
+ if img.ndim != 3:
249
+ return
250
+ results.append(img)
251
+
252
+ H, W, C = results[0].shape
253
+
254
+ for img in results:
255
+ Hn, Wn, Cn = img.shape
256
+ if H != Hn:
257
+ return
258
+ if W != Wn:
259
+ return
260
+ if C != Cn:
261
+ return
262
+
263
+ cols = float(len(results)) ** 0.5
264
+ cols = int(math.ceil(cols))
265
+ rows = float(len(results)) / float(cols)
266
+ rows = int(math.ceil(rows))
267
+
268
+ wall = np.zeros(shape=(H * rows, W * cols, C), dtype=np.uint8)
269
+
270
+ for y in range(rows):
271
+ for x in range(cols):
272
+ if y * cols + x < len(results):
273
+ img = results[y * cols + x]
274
+ wall[y * H:y * H + H, x * W:x * W + W, :] = img
275
+
276
+ # must use deep copy otherwise gradio is super laggy. Do not use list.append() .
277
+ async_task.results = async_task.results + [wall]
278
+ return
279
+
280
+ def process_task(all_steps, async_task, callback, controlnet_canny_path, controlnet_cpds_path, current_task_id,
281
+ denoising_strength, final_scheduler_name, goals, initial_latent, steps, switch, positive_cond,
282
+ negative_cond, task, loras, tiled, use_expansion, width, height, base_progress, preparation_steps,
283
+ total_count, show_intermediate_results, persist_image=True):
284
+ if async_task.last_stop is not False:
285
+ ldm_patched.modules.model_management.interrupt_current_processing()
286
+ if 'cn' in goals:
287
+ for cn_flag, cn_path in [
288
+ (flags.cn_canny, controlnet_canny_path),
289
+ (flags.cn_cpds, controlnet_cpds_path)
290
+ ]:
291
+ for cn_img, cn_stop, cn_weight in async_task.cn_tasks[cn_flag]:
292
+ positive_cond, negative_cond = core.apply_controlnet(
293
+ positive_cond, negative_cond,
294
+ pipeline.loaded_ControlNets[cn_path], cn_img, cn_weight, 0, cn_stop)
295
+ imgs = pipeline.process_diffusion(
296
+ positive_cond=positive_cond,
297
+ negative_cond=negative_cond,
298
+ steps=steps,
299
+ switch=switch,
300
+ width=width,
301
+ height=height,
302
+ image_seed=task['task_seed'],
303
+ callback=callback,
304
+ sampler_name=async_task.sampler_name,
305
+ scheduler_name=final_scheduler_name,
306
+ latent=initial_latent,
307
+ denoise=denoising_strength,
308
+ tiled=tiled,
309
+ cfg_scale=async_task.cfg_scale,
310
+ refiner_swap_method=async_task.refiner_swap_method,
311
+ disable_preview=async_task.disable_preview
312
+ )
313
+ del positive_cond, negative_cond # Save memory
314
+ if inpaint_worker.current_task is not None:
315
+ imgs = [inpaint_worker.current_task.post_process(x) for x in imgs]
316
+ current_progress = int(base_progress + (100 - preparation_steps) / float(all_steps) * steps)
317
+ if modules.config.default_black_out_nsfw or async_task.black_out_nsfw:
318
+ progressbar(async_task, current_progress, 'Checking for NSFW content ...')
319
+ imgs = default_censor(imgs)
320
+ progressbar(async_task, current_progress, f'Saving image {current_task_id + 1}/{total_count} to system ...')
321
+ img_paths = save_and_log(async_task, height, imgs, task, use_expansion, width, loras, persist_image)
322
+ yield_result(async_task, img_paths, current_progress, async_task.black_out_nsfw, False,
323
+ do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results)
324
+
325
+ return imgs, img_paths, current_progress
326
+
327
+ def apply_patch_settings(async_task):
328
+ patch_settings[pid] = PatchSettings(
329
+ async_task.sharpness,
330
+ async_task.adm_scaler_end,
331
+ async_task.adm_scaler_positive,
332
+ async_task.adm_scaler_negative,
333
+ async_task.controlnet_softness,
334
+ async_task.adaptive_cfg
335
+ )
336
+
337
+ def save_and_log(async_task, height, imgs, task, use_expansion, width, loras, persist_image=True) -> list:
338
+ img_paths = []
339
+ for x in imgs:
340
+ d = [('Prompt', 'prompt', task['log_positive_prompt']),
341
+ ('Negative Prompt', 'negative_prompt', task['log_negative_prompt']),
342
+ ('Fooocus V2 Expansion', 'prompt_expansion', task['expansion']),
343
+ ('Styles', 'styles',
344
+ str(task['styles'] if not use_expansion else [fooocus_expansion] + task['styles'])),
345
+ ('Performance', 'performance', async_task.performance_selection.value),
346
+ ('Steps', 'steps', async_task.steps),
347
+ ('Resolution', 'resolution', str((width, height))),
348
+ ('Guidance Scale', 'guidance_scale', async_task.cfg_scale),
349
+ ('Sharpness', 'sharpness', async_task.sharpness),
350
+ ('ADM Guidance', 'adm_guidance', str((
351
+ modules.patch.patch_settings[pid].positive_adm_scale,
352
+ modules.patch.patch_settings[pid].negative_adm_scale,
353
+ modules.patch.patch_settings[pid].adm_scaler_end))),
354
+ ('Base Model', 'base_model', async_task.base_model_name),
355
+ ('Refiner Model', 'refiner_model', async_task.refiner_model_name),
356
+ ('Refiner Switch', 'refiner_switch', async_task.refiner_switch)]
357
+
358
+ if async_task.refiner_model_name != 'None':
359
+ if async_task.overwrite_switch > 0:
360
+ d.append(('Overwrite Switch', 'overwrite_switch', async_task.overwrite_switch))
361
+ if async_task.refiner_swap_method != flags.refiner_swap_method:
362
+ d.append(('Refiner Swap Method', 'refiner_swap_method', async_task.refiner_swap_method))
363
+ if modules.patch.patch_settings[pid].adaptive_cfg != modules.config.default_cfg_tsnr:
364
+ d.append(
365
+ ('CFG Mimicking from TSNR', 'adaptive_cfg', modules.patch.patch_settings[pid].adaptive_cfg))
366
+
367
+ if async_task.clip_skip > 1:
368
+ d.append(('CLIP Skip', 'clip_skip', async_task.clip_skip))
369
+ d.append(('Sampler', 'sampler', async_task.sampler_name))
370
+ d.append(('Scheduler', 'scheduler', async_task.scheduler_name))
371
+ d.append(('VAE', 'vae', async_task.vae_name))
372
+ d.append(('Seed', 'seed', str(task['task_seed'])))
373
+
374
+ if async_task.freeu_enabled:
375
+ d.append(('FreeU', 'freeu',
376
+ str((async_task.freeu_b1, async_task.freeu_b2, async_task.freeu_s1, async_task.freeu_s2))))
377
+
378
+ for li, (n, w) in enumerate(loras):
379
+ if n != 'None':
380
+ d.append((f'LoRA {li + 1}', f'lora_combined_{li + 1}', f'{n} : {w}'))
381
+
382
+ metadata_parser = None
383
+ if async_task.save_metadata_to_images:
384
+ metadata_parser = modules.meta_parser.get_metadata_parser(async_task.metadata_scheme)
385
+ metadata_parser.set_data(task['log_positive_prompt'], task['positive'],
386
+ task['log_negative_prompt'], task['negative'],
387
+ async_task.steps, async_task.base_model_name, async_task.refiner_model_name,
388
+ loras, async_task.vae_name)
389
+ d.append(('Metadata Scheme', 'metadata_scheme',
390
+ async_task.metadata_scheme.value if async_task.save_metadata_to_images else async_task.save_metadata_to_images))
391
+ d.append(('Version', 'version', 'Fooocus v' + fooocus_version.version))
392
+ img_paths.append(log(x, d, metadata_parser, async_task.output_format, task, persist_image))
393
+
394
+ return img_paths
395
+
396
+ def apply_control_nets(async_task, height, ip_adapter_face_path, ip_adapter_path, width, current_progress):
397
+ for task in async_task.cn_tasks[flags.cn_canny]:
398
+ cn_img, cn_stop, cn_weight = task
399
+ cn_img = resize_image(HWC3(cn_img), width=width, height=height)
400
+
401
+ if not async_task.skipping_cn_preprocessor:
402
+ cn_img = preprocessors.canny_pyramid(cn_img, async_task.canny_low_threshold,
403
+ async_task.canny_high_threshold)
404
+
405
+ cn_img = HWC3(cn_img)
406
+ task[0] = core.numpy_to_pytorch(cn_img)
407
+ if async_task.debugging_cn_preprocessor:
408
+ yield_result(async_task, cn_img, current_progress, async_task.black_out_nsfw, do_not_show_finished_images=True)
409
+ for task in async_task.cn_tasks[flags.cn_cpds]:
410
+ cn_img, cn_stop, cn_weight = task
411
+ cn_img = resize_image(HWC3(cn_img), width=width, height=height)
412
+
413
+ if not async_task.skipping_cn_preprocessor:
414
+ cn_img = preprocessors.cpds(cn_img)
415
+
416
+ cn_img = HWC3(cn_img)
417
+ task[0] = core.numpy_to_pytorch(cn_img)
418
+ if async_task.debugging_cn_preprocessor:
419
+ yield_result(async_task, cn_img, current_progress, async_task.black_out_nsfw, do_not_show_finished_images=True)
420
+ for task in async_task.cn_tasks[flags.cn_ip]:
421
+ cn_img, cn_stop, cn_weight = task
422
+ cn_img = HWC3(cn_img)
423
+
424
+ # https://github.com/tencent-ailab/IP-Adapter/blob/d580c50a291566bbf9fc7ac0f760506607297e6d/README.md?plain=1#L75
425
+ cn_img = resize_image(cn_img, width=224, height=224, resize_mode=0)
426
+
427
+ task[0] = ip_adapter.preprocess(cn_img, ip_adapter_path=ip_adapter_path)
428
+ if async_task.debugging_cn_preprocessor:
429
+ yield_result(async_task, cn_img, current_progress, async_task.black_out_nsfw, do_not_show_finished_images=True)
430
+ for task in async_task.cn_tasks[flags.cn_ip_face]:
431
+ cn_img, cn_stop, cn_weight = task
432
+ cn_img = HWC3(cn_img)
433
+
434
+ if not async_task.skipping_cn_preprocessor:
435
+ cn_img = extras.face_crop.crop_image(cn_img)
436
+
437
+ # https://github.com/tencent-ailab/IP-Adapter/blob/d580c50a291566bbf9fc7ac0f760506607297e6d/README.md?plain=1#L75
438
+ cn_img = resize_image(cn_img, width=224, height=224, resize_mode=0)
439
+
440
+ task[0] = ip_adapter.preprocess(cn_img, ip_adapter_path=ip_adapter_face_path)
441
+ if async_task.debugging_cn_preprocessor:
442
+ yield_result(async_task, cn_img, current_progress, async_task.black_out_nsfw, do_not_show_finished_images=True)
443
+ all_ip_tasks = async_task.cn_tasks[flags.cn_ip] + async_task.cn_tasks[flags.cn_ip_face]
444
+ if len(all_ip_tasks) > 0:
445
+ pipeline.final_unet = ip_adapter.patch_model(pipeline.final_unet, all_ip_tasks)
446
+
447
+ def apply_vary(async_task, uov_method, denoising_strength, uov_input_image, switch, current_progress, advance_progress=False):
448
+ if 'subtle' in uov_method:
449
+ denoising_strength = 0.5
450
+ if 'strong' in uov_method:
451
+ denoising_strength = 0.85
452
+ if async_task.overwrite_vary_strength > 0:
453
+ denoising_strength = async_task.overwrite_vary_strength
454
+ shape_ceil = get_image_shape_ceil(uov_input_image)
455
+ if shape_ceil < 1024:
456
+ print(f'[Vary] Image is resized because it is too small.')
457
+ shape_ceil = 1024
458
+ elif shape_ceil > 2048:
459
+ print(f'[Vary] Image is resized because it is too big.')
460
+ shape_ceil = 2048
461
+ uov_input_image = set_image_shape_ceil(uov_input_image, shape_ceil)
462
+ initial_pixels = core.numpy_to_pytorch(uov_input_image)
463
+ if advance_progress:
464
+ current_progress += 1
465
+ progressbar(async_task, current_progress, 'VAE encoding ...')
466
+ candidate_vae, _ = pipeline.get_candidate_vae(
467
+ steps=async_task.steps,
468
+ switch=switch,
469
+ denoise=denoising_strength,
470
+ refiner_swap_method=async_task.refiner_swap_method
471
+ )
472
+ initial_latent = core.encode_vae(vae=candidate_vae, pixels=initial_pixels)
473
+ B, C, H, W = initial_latent['samples'].shape
474
+ width = W * 8
475
+ height = H * 8
476
+ print(f'Final resolution is {str((width, height))}.')
477
+ return uov_input_image, denoising_strength, initial_latent, width, height, current_progress
478
+
479
+ def apply_inpaint(async_task, initial_latent, inpaint_head_model_path, inpaint_image,
480
+ inpaint_mask, inpaint_parameterized, denoising_strength, inpaint_respective_field, switch,
481
+ inpaint_disable_initial_latent, current_progress, skip_apply_outpaint=False,
482
+ advance_progress=False):
483
+ if not skip_apply_outpaint:
484
+ inpaint_image, inpaint_mask = apply_outpaint(async_task, inpaint_image, inpaint_mask)
485
+
486
+ inpaint_worker.current_task = inpaint_worker.InpaintWorker(
487
+ image=inpaint_image,
488
+ mask=inpaint_mask,
489
+ use_fill=denoising_strength > 0.99,
490
+ k=inpaint_respective_field
491
+ )
492
+ if async_task.debugging_inpaint_preprocessor:
493
+ yield_result(async_task, inpaint_worker.current_task.visualize_mask_processing(), 100,
494
+ async_task.black_out_nsfw, do_not_show_finished_images=True)
495
+ raise EarlyReturnException
496
+
497
+ if advance_progress:
498
+ current_progress += 1
499
+ progressbar(async_task, current_progress, 'VAE Inpaint encoding ...')
500
+ inpaint_pixel_fill = core.numpy_to_pytorch(inpaint_worker.current_task.interested_fill)
501
+ inpaint_pixel_image = core.numpy_to_pytorch(inpaint_worker.current_task.interested_image)
502
+ inpaint_pixel_mask = core.numpy_to_pytorch(inpaint_worker.current_task.interested_mask)
503
+ candidate_vae, candidate_vae_swap = pipeline.get_candidate_vae(
504
+ steps=async_task.steps,
505
+ switch=switch,
506
+ denoise=denoising_strength,
507
+ refiner_swap_method=async_task.refiner_swap_method
508
+ )
509
+ latent_inpaint, latent_mask = core.encode_vae_inpaint(
510
+ mask=inpaint_pixel_mask,
511
+ vae=candidate_vae,
512
+ pixels=inpaint_pixel_image)
513
+ latent_swap = None
514
+ if candidate_vae_swap is not None:
515
+ if advance_progress:
516
+ current_progress += 1
517
+ progressbar(async_task, current_progress, 'VAE SD15 encoding ...')
518
+ latent_swap = core.encode_vae(
519
+ vae=candidate_vae_swap,
520
+ pixels=inpaint_pixel_fill)['samples']
521
+ if advance_progress:
522
+ current_progress += 1
523
+ progressbar(async_task, current_progress, 'VAE encoding ...')
524
+ latent_fill = core.encode_vae(
525
+ vae=candidate_vae,
526
+ pixels=inpaint_pixel_fill)['samples']
527
+ inpaint_worker.current_task.load_latent(
528
+ latent_fill=latent_fill, latent_mask=latent_mask, latent_swap=latent_swap)
529
+ if inpaint_parameterized:
530
+ pipeline.final_unet = inpaint_worker.current_task.patch(
531
+ inpaint_head_model_path=inpaint_head_model_path,
532
+ inpaint_latent=latent_inpaint,
533
+ inpaint_latent_mask=latent_mask,
534
+ model=pipeline.final_unet
535
+ )
536
+ if not inpaint_disable_initial_latent:
537
+ initial_latent = {'samples': latent_fill}
538
+ B, C, H, W = latent_fill.shape
539
+ height, width = H * 8, W * 8
540
+ final_height, final_width = inpaint_worker.current_task.image.shape[:2]
541
+ print(f'Final resolution is {str((final_width, final_height))}, latent is {str((width, height))}.')
542
+
543
+ return denoising_strength, initial_latent, width, height, current_progress
544
+
545
+ def apply_outpaint(async_task, inpaint_image, inpaint_mask):
546
+ if len(async_task.outpaint_selections) > 0:
547
+ H, W, C = inpaint_image.shape
548
+ if 'top' in async_task.outpaint_selections:
549
+ inpaint_image = np.pad(inpaint_image, [[int(H * 0.3), 0], [0, 0], [0, 0]], mode='edge')
550
+ inpaint_mask = np.pad(inpaint_mask, [[int(H * 0.3), 0], [0, 0]], mode='constant',
551
+ constant_values=255)
552
+ if 'bottom' in async_task.outpaint_selections:
553
+ inpaint_image = np.pad(inpaint_image, [[0, int(H * 0.3)], [0, 0], [0, 0]], mode='edge')
554
+ inpaint_mask = np.pad(inpaint_mask, [[0, int(H * 0.3)], [0, 0]], mode='constant',
555
+ constant_values=255)
556
+
557
+ H, W, C = inpaint_image.shape
558
+ if 'left' in async_task.outpaint_selections:
559
+ inpaint_image = np.pad(inpaint_image, [[0, 0], [int(W * 0.3), 0], [0, 0]], mode='edge')
560
+ inpaint_mask = np.pad(inpaint_mask, [[0, 0], [int(W * 0.3), 0]], mode='constant',
561
+ constant_values=255)
562
+ if 'right' in async_task.outpaint_selections:
563
+ inpaint_image = np.pad(inpaint_image, [[0, 0], [0, int(W * 0.3)], [0, 0]], mode='edge')
564
+ inpaint_mask = np.pad(inpaint_mask, [[0, 0], [0, int(W * 0.3)]], mode='constant',
565
+ constant_values=255)
566
+
567
+ inpaint_image = np.ascontiguousarray(inpaint_image.copy())
568
+ inpaint_mask = np.ascontiguousarray(inpaint_mask.copy())
569
+ async_task.inpaint_strength = 1.0
570
+ async_task.inpaint_respective_field = 1.0
571
+ return inpaint_image, inpaint_mask
572
+
573
+ def apply_upscale(async_task, uov_input_image, uov_method, switch, current_progress, advance_progress=False):
574
+ H, W, C = uov_input_image.shape
575
+ if advance_progress:
576
+ current_progress += 1
577
+ progressbar(async_task, current_progress, f'Upscaling image from {str((W, H))} ...')
578
+ uov_input_image = perform_upscale(uov_input_image)
579
+ print(f'Image upscaled.')
580
+ if '1.5x' in uov_method:
581
+ f = 1.5
582
+ elif '2x' in uov_method:
583
+ f = 2.0
584
+ else:
585
+ f = 1.0
586
+ shape_ceil = get_shape_ceil(H * f, W * f)
587
+ if shape_ceil < 1024:
588
+ print(f'[Upscale] Image is resized because it is too small.')
589
+ uov_input_image = set_image_shape_ceil(uov_input_image, 1024)
590
+ shape_ceil = 1024
591
+ else:
592
+ uov_input_image = resample_image(uov_input_image, width=W * f, height=H * f)
593
+ image_is_super_large = shape_ceil > 2800
594
+ if 'fast' in uov_method:
595
+ direct_return = True
596
+ elif image_is_super_large:
597
+ print('Image is too large. Directly returned the SR image. '
598
+ 'Usually directly return SR image at 4K resolution '
599
+ 'yields better results than SDXL diffusion.')
600
+ direct_return = True
601
+ else:
602
+ direct_return = False
603
+ if direct_return:
604
+ return direct_return, uov_input_image, None, None, None, None, None, current_progress
605
+
606
+ tiled = True
607
+ denoising_strength = 0.382
608
+ if async_task.overwrite_upscale_strength > 0:
609
+ denoising_strength = async_task.overwrite_upscale_strength
610
+ initial_pixels = core.numpy_to_pytorch(uov_input_image)
611
+ if advance_progress:
612
+ current_progress += 1
613
+ progressbar(async_task, current_progress, 'VAE encoding ...')
614
+ candidate_vae, _ = pipeline.get_candidate_vae(
615
+ steps=async_task.steps,
616
+ switch=switch,
617
+ denoise=denoising_strength,
618
+ refiner_swap_method=async_task.refiner_swap_method
619
+ )
620
+ initial_latent = core.encode_vae(
621
+ vae=candidate_vae,
622
+ pixels=initial_pixels, tiled=True)
623
+ B, C, H, W = initial_latent['samples'].shape
624
+ width = W * 8
625
+ height = H * 8
626
+ print(f'Final resolution is {str((width, height))}.')
627
+ return direct_return, uov_input_image, denoising_strength, initial_latent, tiled, width, height, current_progress
628
+
629
+ def apply_overrides(async_task, steps, height, width):
630
+ if async_task.overwrite_step > 0:
631
+ steps = async_task.overwrite_step
632
+ switch = int(round(async_task.steps * async_task.refiner_switch))
633
+ if async_task.overwrite_switch > 0:
634
+ switch = async_task.overwrite_switch
635
+ if async_task.overwrite_width > 0:
636
+ width = async_task.overwrite_width
637
+ if async_task.overwrite_height > 0:
638
+ height = async_task.overwrite_height
639
+ return steps, switch, width, height
640
+
641
+ def process_prompt(async_task, prompt, negative_prompt, base_model_additional_loras, image_number, disable_seed_increment, use_expansion, use_style,
642
+ use_synthetic_refiner, current_progress, advance_progress=False):
643
+ prompts = remove_empty_str([safe_str(p) for p in prompt.splitlines()], default='')
644
+ negative_prompts = remove_empty_str([safe_str(p) for p in negative_prompt.splitlines()], default='')
645
+ prompt = prompts[0]
646
+ negative_prompt = negative_prompts[0]
647
+ if prompt == '':
648
+ # disable expansion when empty since it is not meaningful and influences image prompt
649
+ use_expansion = False
650
+ extra_positive_prompts = prompts[1:] if len(prompts) > 1 else []
651
+ extra_negative_prompts = negative_prompts[1:] if len(negative_prompts) > 1 else []
652
+ if advance_progress:
653
+ current_progress += 1
654
+ progressbar(async_task, current_progress, 'Loading models ...')
655
+ lora_filenames = modules.util.remove_performance_lora(modules.config.lora_filenames,
656
+ async_task.performance_selection)
657
+ loras, prompt = parse_lora_references_from_prompt(prompt, async_task.loras,
658
+ modules.config.default_max_lora_number,
659
+ lora_filenames=lora_filenames)
660
+ loras += async_task.performance_loras
661
+ pipeline.refresh_everything(refiner_model_name=async_task.refiner_model_name,
662
+ base_model_name=async_task.base_model_name,
663
+ loras=loras, base_model_additional_loras=base_model_additional_loras,
664
+ use_synthetic_refiner=use_synthetic_refiner, vae_name=async_task.vae_name)
665
+ pipeline.set_clip_skip(async_task.clip_skip)
666
+ if advance_progress:
667
+ current_progress += 1
668
+ progressbar(async_task, current_progress, 'Processing prompts ...')
669
+ tasks = []
670
+ for i in range(image_number):
671
+ if disable_seed_increment:
672
+ task_seed = async_task.seed % (constants.MAX_SEED + 1)
673
+ else:
674
+ task_seed = (async_task.seed + i) % (constants.MAX_SEED + 1) # randint is inclusive, % is not
675
+
676
+ task_rng = random.Random(task_seed) # may bind to inpaint noise in the future
677
+ task_prompt = apply_wildcards(prompt, task_rng, i, async_task.read_wildcards_in_order)
678
+ task_prompt = apply_arrays(task_prompt, i)
679
+ task_negative_prompt = apply_wildcards(negative_prompt, task_rng, i, async_task.read_wildcards_in_order)
680
+ task_extra_positive_prompts = [apply_wildcards(pmt, task_rng, i, async_task.read_wildcards_in_order) for pmt
681
+ in
682
+ extra_positive_prompts]
683
+ task_extra_negative_prompts = [apply_wildcards(pmt, task_rng, i, async_task.read_wildcards_in_order) for pmt
684
+ in
685
+ extra_negative_prompts]
686
+
687
+ positive_basic_workloads = []
688
+ negative_basic_workloads = []
689
+
690
+ task_styles = async_task.style_selections.copy()
691
+ if use_style:
692
+ placeholder_replaced = False
693
+
694
+ for j, s in enumerate(task_styles):
695
+ if s == random_style_name:
696
+ s = get_random_style(task_rng)
697
+ task_styles[j] = s
698
+ p, n, style_has_placeholder = apply_style(s, positive=task_prompt)
699
+ if style_has_placeholder:
700
+ placeholder_replaced = True
701
+ positive_basic_workloads = positive_basic_workloads + p
702
+ negative_basic_workloads = negative_basic_workloads + n
703
+
704
+ if not placeholder_replaced:
705
+ positive_basic_workloads = [task_prompt] + positive_basic_workloads
706
+ else:
707
+ positive_basic_workloads.append(task_prompt)
708
+
709
+ negative_basic_workloads.append(task_negative_prompt) # Always use independent workload for negative.
710
+
711
+ positive_basic_workloads = positive_basic_workloads + task_extra_positive_prompts
712
+ negative_basic_workloads = negative_basic_workloads + task_extra_negative_prompts
713
+
714
+ positive_basic_workloads = remove_empty_str(positive_basic_workloads, default=task_prompt)
715
+ negative_basic_workloads = remove_empty_str(negative_basic_workloads, default=task_negative_prompt)
716
+
717
+ tasks.append(dict(
718
+ task_seed=task_seed,
719
+ task_prompt=task_prompt,
720
+ task_negative_prompt=task_negative_prompt,
721
+ positive=positive_basic_workloads,
722
+ negative=negative_basic_workloads,
723
+ expansion='',
724
+ c=None,
725
+ uc=None,
726
+ positive_top_k=len(positive_basic_workloads),
727
+ negative_top_k=len(negative_basic_workloads),
728
+ log_positive_prompt='\n'.join([task_prompt] + task_extra_positive_prompts),
729
+ log_negative_prompt='\n'.join([task_negative_prompt] + task_extra_negative_prompts),
730
+ styles=task_styles
731
+ ))
732
+ if use_expansion:
733
+ if advance_progress:
734
+ current_progress += 1
735
+ for i, t in enumerate(tasks):
736
+
737
+ progressbar(async_task, current_progress, f'Preparing Fooocus text #{i + 1} ...')
738
+ expansion = pipeline.final_expansion(t['task_prompt'], t['task_seed'])
739
+ print(f'[Prompt Expansion] {expansion}')
740
+ t['expansion'] = expansion
741
+ t['positive'] = copy.deepcopy(t['positive']) + [expansion] # Deep copy.
742
+ if advance_progress:
743
+ current_progress += 1
744
+ for i, t in enumerate(tasks):
745
+ progressbar(async_task, current_progress, f'Encoding positive #{i + 1} ...')
746
+ t['c'] = pipeline.clip_encode(texts=t['positive'], pool_top_k=t['positive_top_k'])
747
+ if advance_progress:
748
+ current_progress += 1
749
+ for i, t in enumerate(tasks):
750
+ if abs(float(async_task.cfg_scale) - 1.0) < 1e-4:
751
+ t['uc'] = pipeline.clone_cond(t['c'])
752
+ else:
753
+ progressbar(async_task, current_progress, f'Encoding negative #{i + 1} ...')
754
+ t['uc'] = pipeline.clip_encode(texts=t['negative'], pool_top_k=t['negative_top_k'])
755
+ return tasks, use_expansion, loras, current_progress
756
+
757
+ def apply_freeu(async_task):
758
+ print(f'FreeU is enabled!')
759
+ pipeline.final_unet = core.apply_freeu(
760
+ pipeline.final_unet,
761
+ async_task.freeu_b1,
762
+ async_task.freeu_b2,
763
+ async_task.freeu_s1,
764
+ async_task.freeu_s2
765
+ )
766
+
767
+ def patch_discrete(unet, scheduler_name):
768
+ return core.opModelSamplingDiscrete.patch(unet, scheduler_name, False)[0]
769
+
770
+ def patch_edm(unet, scheduler_name):
771
+ return core.opModelSamplingContinuousEDM.patch(unet, scheduler_name, 120.0, 0.002)[0]
772
+
773
+ def patch_samplers(async_task):
774
+ final_scheduler_name = async_task.scheduler_name
775
+
776
+ if async_task.scheduler_name in ['lcm', 'tcd']:
777
+ final_scheduler_name = 'sgm_uniform'
778
+ if pipeline.final_unet is not None:
779
+ pipeline.final_unet = patch_discrete(pipeline.final_unet, async_task.scheduler_name)
780
+ if pipeline.final_refiner_unet is not None:
781
+ pipeline.final_refiner_unet = patch_discrete(pipeline.final_refiner_unet, async_task.scheduler_name)
782
+
783
+ elif async_task.scheduler_name == 'edm_playground_v2.5':
784
+ final_scheduler_name = 'karras'
785
+ if pipeline.final_unet is not None:
786
+ pipeline.final_unet = patch_edm(pipeline.final_unet, async_task.scheduler_name)
787
+ if pipeline.final_refiner_unet is not None:
788
+ pipeline.final_refiner_unet = patch_edm(pipeline.final_refiner_unet, async_task.scheduler_name)
789
+
790
+ return final_scheduler_name
791
+
792
+ def set_hyper_sd_defaults(async_task, current_progress, advance_progress=False):
793
+ print('Enter Hyper-SD mode.')
794
+ if advance_progress:
795
+ current_progress += 1
796
+ progressbar(async_task, current_progress, 'Downloading Hyper-SD components ...')
797
+ async_task.performance_loras += [(modules.config.downloading_sdxl_hyper_sd_lora(), 0.8)]
798
+ if async_task.refiner_model_name != 'None':
799
+ print(f'Refiner disabled in Hyper-SD mode.')
800
+ async_task.refiner_model_name = 'None'
801
+ async_task.sampler_name = 'dpmpp_sde_gpu'
802
+ async_task.scheduler_name = 'karras'
803
+ async_task.sharpness = 0.0
804
+ async_task.cfg_scale = 1.0
805
+ async_task.adaptive_cfg = 1.0
806
+ async_task.refiner_switch = 1.0
807
+ async_task.adm_scaler_positive = 1.0
808
+ async_task.adm_scaler_negative = 1.0
809
+ async_task.adm_scaler_end = 0.0
810
+ return current_progress
811
+
812
+ def set_lightning_defaults(async_task, current_progress, advance_progress=False):
813
+ print('Enter Lightning mode.')
814
+ if advance_progress:
815
+ current_progress += 1
816
+ progressbar(async_task, 1, 'Downloading Lightning components ...')
817
+ async_task.performance_loras += [(modules.config.downloading_sdxl_lightning_lora(), 1.0)]
818
+ if async_task.refiner_model_name != 'None':
819
+ print(f'Refiner disabled in Lightning mode.')
820
+ async_task.refiner_model_name = 'None'
821
+ async_task.sampler_name = 'euler'
822
+ async_task.scheduler_name = 'sgm_uniform'
823
+ async_task.sharpness = 0.0
824
+ async_task.cfg_scale = 1.0
825
+ async_task.adaptive_cfg = 1.0
826
+ async_task.refiner_switch = 1.0
827
+ async_task.adm_scaler_positive = 1.0
828
+ async_task.adm_scaler_negative = 1.0
829
+ async_task.adm_scaler_end = 0.0
830
+ return current_progress
831
+
832
+ def set_lcm_defaults(async_task, current_progress, advance_progress=False):
833
+ print('Enter LCM mode.')
834
+ if advance_progress:
835
+ current_progress += 1
836
+ progressbar(async_task, 1, 'Downloading LCM components ...')
837
+ async_task.performance_loras += [(modules.config.downloading_sdxl_lcm_lora(), 1.0)]
838
+ if async_task.refiner_model_name != 'None':
839
+ print(f'Refiner disabled in LCM mode.')
840
+ async_task.refiner_model_name = 'None'
841
+ async_task.sampler_name = 'lcm'
842
+ async_task.scheduler_name = 'lcm'
843
+ async_task.sharpness = 0.0
844
+ async_task.cfg_scale = 1.0
845
+ async_task.adaptive_cfg = 1.0
846
+ async_task.refiner_switch = 1.0
847
+ async_task.adm_scaler_positive = 1.0
848
+ async_task.adm_scaler_negative = 1.0
849
+ async_task.adm_scaler_end = 0.0
850
+ return current_progress
851
+
852
+ def apply_image_input(async_task, base_model_additional_loras, clip_vision_path, controlnet_canny_path,
853
+ controlnet_cpds_path, goals, inpaint_head_model_path, inpaint_image, inpaint_mask,
854
+ inpaint_parameterized, ip_adapter_face_path, ip_adapter_path, ip_negative_path,
855
+ skip_prompt_processing, use_synthetic_refiner):
856
+ if (async_task.current_tab == 'uov' or (
857
+ async_task.current_tab == 'ip' and async_task.mixing_image_prompt_and_vary_upscale)) \
858
+ and async_task.uov_method != flags.disabled.casefold() and async_task.uov_input_image is not None:
859
+ async_task.uov_input_image, skip_prompt_processing, async_task.steps = prepare_upscale(
860
+ async_task, goals, async_task.uov_input_image, async_task.uov_method, async_task.performance_selection,
861
+ async_task.steps, 1, skip_prompt_processing=skip_prompt_processing)
862
+ if (async_task.current_tab == 'inpaint' or (
863
+ async_task.current_tab == 'ip' and async_task.mixing_image_prompt_and_inpaint)) \
864
+ and isinstance(async_task.inpaint_input_image, dict):
865
+ inpaint_image = async_task.inpaint_input_image['image']
866
+ inpaint_mask = async_task.inpaint_input_image['mask'][:, :, 0]
867
+
868
+ if async_task.inpaint_advanced_masking_checkbox:
869
+ if isinstance(async_task.inpaint_mask_image_upload, dict):
870
+ if (isinstance(async_task.inpaint_mask_image_upload['image'], np.ndarray)
871
+ and isinstance(async_task.inpaint_mask_image_upload['mask'], np.ndarray)
872
+ and async_task.inpaint_mask_image_upload['image'].ndim == 3):
873
+ async_task.inpaint_mask_image_upload = np.maximum(
874
+ async_task.inpaint_mask_image_upload['image'],
875
+ async_task.inpaint_mask_image_upload['mask'])
876
+ if isinstance(async_task.inpaint_mask_image_upload,
877
+ np.ndarray) and async_task.inpaint_mask_image_upload.ndim == 3:
878
+ H, W, C = inpaint_image.shape
879
+ async_task.inpaint_mask_image_upload = resample_image(async_task.inpaint_mask_image_upload,
880
+ width=W, height=H)
881
+ async_task.inpaint_mask_image_upload = np.mean(async_task.inpaint_mask_image_upload, axis=2)
882
+ async_task.inpaint_mask_image_upload = (async_task.inpaint_mask_image_upload > 127).astype(
883
+ np.uint8) * 255
884
+ inpaint_mask = np.maximum(inpaint_mask, async_task.inpaint_mask_image_upload)
885
+
886
+ if int(async_task.inpaint_erode_or_dilate) != 0:
887
+ inpaint_mask = erode_or_dilate(inpaint_mask, async_task.inpaint_erode_or_dilate)
888
+
889
+ if async_task.invert_mask_checkbox:
890
+ inpaint_mask = 255 - inpaint_mask
891
+
892
+ inpaint_image = HWC3(inpaint_image)
893
+ if isinstance(inpaint_image, np.ndarray) and isinstance(inpaint_mask, np.ndarray) \
894
+ and (np.any(inpaint_mask > 127) or len(async_task.outpaint_selections) > 0):
895
+ progressbar(async_task, 1, 'Downloading upscale models ...')
896
+ modules.config.downloading_upscale_model()
897
+ if inpaint_parameterized:
898
+ progressbar(async_task, 1, 'Downloading inpainter ...')
899
+ inpaint_head_model_path, inpaint_patch_model_path = modules.config.downloading_inpaint_models(
900
+ async_task.inpaint_engine)
901
+ base_model_additional_loras += [(inpaint_patch_model_path, 1.0)]
902
+ print(f'[Inpaint] Current inpaint model is {inpaint_patch_model_path}')
903
+ if async_task.refiner_model_name == 'None':
904
+ use_synthetic_refiner = True
905
+ async_task.refiner_switch = 0.8
906
+ else:
907
+ inpaint_head_model_path, inpaint_patch_model_path = None, None
908
+ print(f'[Inpaint] Parameterized inpaint is disabled.')
909
+ if async_task.inpaint_additional_prompt != '':
910
+ if async_task.prompt == '':
911
+ async_task.prompt = async_task.inpaint_additional_prompt
912
+ else:
913
+ async_task.prompt = async_task.inpaint_additional_prompt + '\n' + async_task.prompt
914
+ goals.append('inpaint')
915
+ if async_task.current_tab == 'ip' or \
916
+ async_task.mixing_image_prompt_and_vary_upscale or \
917
+ async_task.mixing_image_prompt_and_inpaint:
918
+ goals.append('cn')
919
+ progressbar(async_task, 1, 'Downloading control models ...')
920
+ if len(async_task.cn_tasks[flags.cn_canny]) > 0:
921
+ controlnet_canny_path = modules.config.downloading_controlnet_canny()
922
+ if len(async_task.cn_tasks[flags.cn_cpds]) > 0:
923
+ controlnet_cpds_path = modules.config.downloading_controlnet_cpds()
924
+ if len(async_task.cn_tasks[flags.cn_ip]) > 0:
925
+ clip_vision_path, ip_negative_path, ip_adapter_path = modules.config.downloading_ip_adapters('ip')
926
+ if len(async_task.cn_tasks[flags.cn_ip_face]) > 0:
927
+ clip_vision_path, ip_negative_path, ip_adapter_face_path = modules.config.downloading_ip_adapters(
928
+ 'face')
929
+ if async_task.current_tab == 'enhance' and async_task.enhance_input_image is not None:
930
+ goals.append('enhance')
931
+ skip_prompt_processing = True
932
+ async_task.enhance_input_image = HWC3(async_task.enhance_input_image)
933
+ return base_model_additional_loras, clip_vision_path, controlnet_canny_path, controlnet_cpds_path, inpaint_head_model_path, inpaint_image, inpaint_mask, ip_adapter_face_path, ip_adapter_path, ip_negative_path, skip_prompt_processing, use_synthetic_refiner
934
+
935
+ def prepare_upscale(async_task, goals, uov_input_image, uov_method, performance, steps, current_progress,
936
+ advance_progress=False, skip_prompt_processing=False):
937
+ uov_input_image = HWC3(uov_input_image)
938
+ if 'vary' in uov_method:
939
+ goals.append('vary')
940
+ elif 'upscale' in uov_method:
941
+ goals.append('upscale')
942
+ if 'fast' in uov_method:
943
+ skip_prompt_processing = True
944
+ steps = 0
945
+ else:
946
+ steps = performance.steps_uov()
947
+
948
+ if advance_progress:
949
+ current_progress += 1
950
+ progressbar(async_task, current_progress, 'Downloading upscale models ...')
951
+ modules.config.downloading_upscale_model()
952
+ return uov_input_image, skip_prompt_processing, steps
953
+
954
+ def prepare_enhance_prompt(prompt: str, fallback_prompt: str):
955
+ if safe_str(prompt) == '' or len(remove_empty_str([safe_str(p) for p in prompt.splitlines()], default='')) == 0:
956
+ prompt = fallback_prompt
957
+
958
+ return prompt
959
+
960
+ def stop_processing(async_task, processing_start_time):
961
+ async_task.processing = False
962
+ processing_time = time.perf_counter() - processing_start_time
963
+ print(f'Processing time (total): {processing_time:.2f} seconds')
964
+
965
+ def process_enhance(all_steps, async_task, callback, controlnet_canny_path, controlnet_cpds_path,
966
+ current_progress, current_task_id, denoising_strength, inpaint_disable_initial_latent,
967
+ inpaint_engine, inpaint_respective_field, inpaint_strength,
968
+ prompt, negative_prompt, final_scheduler_name, goals, height, img, mask,
969
+ preparation_steps, steps, switch, tiled, total_count, use_expansion, use_style,
970
+ use_synthetic_refiner, width, show_intermediate_results=True, persist_image=True):
971
+ base_model_additional_loras = []
972
+ inpaint_head_model_path = None
973
+ inpaint_parameterized = inpaint_engine != 'None' # inpaint_engine = None, improve detail
974
+ initial_latent = None
975
+
976
+ prompt = prepare_enhance_prompt(prompt, async_task.prompt)
977
+ negative_prompt = prepare_enhance_prompt(negative_prompt, async_task.negative_prompt)
978
+
979
+ if 'vary' in goals:
980
+ img, denoising_strength, initial_latent, width, height, current_progress = apply_vary(
981
+ async_task, async_task.enhance_uov_method, denoising_strength, img, switch, current_progress)
982
+ if 'upscale' in goals:
983
+ direct_return, img, denoising_strength, initial_latent, tiled, width, height, current_progress = apply_upscale(
984
+ async_task, img, async_task.enhance_uov_method, switch, current_progress)
985
+ if direct_return:
986
+ d = [('Upscale (Fast)', 'upscale_fast', '2x')]
987
+ if modules.config.default_black_out_nsfw or async_task.black_out_nsfw:
988
+ progressbar(async_task, current_progress, 'Checking for NSFW content ...')
989
+ img = default_censor(img)
990
+ progressbar(async_task, current_progress, f'Saving image {current_task_id + 1}/{total_count} to system ...')
991
+ uov_image_path = log(img, d, output_format=async_task.output_format, persist_image=persist_image)
992
+ yield_result(async_task, uov_image_path, current_progress, async_task.black_out_nsfw, False,
993
+ do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results)
994
+ return current_progress, img, prompt, negative_prompt
995
+
996
+ if 'inpaint' in goals and inpaint_parameterized:
997
+ progressbar(async_task, current_progress, 'Downloading inpainter ...')
998
+ inpaint_head_model_path, inpaint_patch_model_path = modules.config.downloading_inpaint_models(
999
+ inpaint_engine)
1000
+ if inpaint_patch_model_path not in base_model_additional_loras:
1001
+ base_model_additional_loras += [(inpaint_patch_model_path, 1.0)]
1002
+ progressbar(async_task, current_progress, 'Preparing enhance prompts ...')
1003
+ # positive and negative conditioning aren't available here anymore, process prompt again
1004
+ tasks_enhance, use_expansion, loras, current_progress = process_prompt(
1005
+ async_task, prompt, negative_prompt, base_model_additional_loras, 1, True,
1006
+ use_expansion, use_style, use_synthetic_refiner, current_progress)
1007
+ task_enhance = tasks_enhance[0]
1008
+ # TODO could support vary, upscale and CN in the future
1009
+ # if 'cn' in goals:
1010
+ # apply_control_nets(async_task, height, ip_adapter_face_path, ip_adapter_path, width)
1011
+ if async_task.freeu_enabled:
1012
+ apply_freeu(async_task)
1013
+ patch_samplers(async_task)
1014
+ if 'inpaint' in goals:
1015
+ denoising_strength, initial_latent, width, height, current_progress = apply_inpaint(
1016
+ async_task, None, inpaint_head_model_path, img, mask,
1017
+ inpaint_parameterized, inpaint_strength,
1018
+ inpaint_respective_field, switch, inpaint_disable_initial_latent,
1019
+ current_progress, True)
1020
+ imgs, img_paths, current_progress = process_task(all_steps, async_task, callback, controlnet_canny_path,
1021
+ controlnet_cpds_path, current_task_id, denoising_strength,
1022
+ final_scheduler_name, goals, initial_latent, steps, switch,
1023
+ task_enhance['c'], task_enhance['uc'], task_enhance, loras,
1024
+ tiled, use_expansion, width, height, current_progress,
1025
+ preparation_steps, total_count, show_intermediate_results,
1026
+ persist_image)
1027
+
1028
+ del task_enhance['c'], task_enhance['uc'] # Save memory
1029
+ return current_progress, imgs[0], prompt, negative_prompt
1030
+
1031
+ def enhance_upscale(all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
1032
+ current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
1033
+ prompt, negative_prompt, final_scheduler_name, height, img, preparation_steps, switch, tiled,
1034
+ total_count, use_expansion, use_style, use_synthetic_refiner, width, persist_image=True):
1035
+ # reset inpaint worker to prevent tensor size issues and not mix upscale and inpainting
1036
+ inpaint_worker.current_task = None
1037
+
1038
+ current_progress = int(base_progress + (100 - preparation_steps) / float(all_steps) * (done_steps_upscaling + done_steps_inpainting))
1039
+ goals_enhance = []
1040
+ img, skip_prompt_processing, steps = prepare_upscale(
1041
+ async_task, goals_enhance, img, async_task.enhance_uov_method, async_task.performance_selection,
1042
+ enhance_steps, current_progress)
1043
+ steps, _, _, _ = apply_overrides(async_task, steps, height, width)
1044
+ exception_result = ''
1045
+ if len(goals_enhance) > 0:
1046
+ try:
1047
+ current_progress, img, prompt, negative_prompt = process_enhance(
1048
+ all_steps, async_task, callback, controlnet_canny_path,
1049
+ controlnet_cpds_path, current_progress, current_task_id, denoising_strength, False,
1050
+ 'None', 0.0, 0.0, prompt, negative_prompt, final_scheduler_name,
1051
+ goals_enhance, height, img, None, preparation_steps, steps, switch, tiled, total_count,
1052
+ use_expansion, use_style, use_synthetic_refiner, width, persist_image=persist_image)
1053
+
1054
+ except ldm_patched.modules.model_management.InterruptProcessingException:
1055
+ if async_task.last_stop == 'skip':
1056
+ print('User skipped')
1057
+ async_task.last_stop = False
1058
+ # also skip all enhance steps for this image, but add the steps to the progress bar
1059
+ if async_task.enhance_uov_processing_order == flags.enhancement_uov_before:
1060
+ done_steps_inpainting += len(async_task.enhance_ctrls) * enhance_steps
1061
+ exception_result = 'continue'
1062
+ else:
1063
+ print('User stopped')
1064
+ exception_result = 'break'
1065
+ finally:
1066
+ done_steps_upscaling += steps
1067
+ return current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result
1068
+
1069
+ @torch.no_grad()
1070
+ @torch.inference_mode()
1071
+ def handler(async_task: AsyncTask):
1072
+ preparation_start_time = time.perf_counter()
1073
+ async_task.processing = True
1074
+
1075
+ async_task.outpaint_selections = [o.lower() for o in async_task.outpaint_selections]
1076
+ base_model_additional_loras = []
1077
+ async_task.uov_method = async_task.uov_method.casefold()
1078
+ async_task.enhance_uov_method = async_task.enhance_uov_method.casefold()
1079
+
1080
+ if fooocus_expansion in async_task.style_selections:
1081
+ use_expansion = True
1082
+ async_task.style_selections.remove(fooocus_expansion)
1083
+ else:
1084
+ use_expansion = False
1085
+
1086
+ use_style = len(async_task.style_selections) > 0
1087
+
1088
+ if async_task.base_model_name == async_task.refiner_model_name:
1089
+ print(f'Refiner disabled because base model and refiner are same.')
1090
+ async_task.refiner_model_name = 'None'
1091
+
1092
+ current_progress = 0
1093
+ if async_task.performance_selection == Performance.EXTREME_SPEED:
1094
+ set_lcm_defaults(async_task, current_progress, advance_progress=True)
1095
+ elif async_task.performance_selection == Performance.LIGHTNING:
1096
+ set_lightning_defaults(async_task, current_progress, advance_progress=True)
1097
+ elif async_task.performance_selection == Performance.HYPER_SD:
1098
+ set_hyper_sd_defaults(async_task, current_progress, advance_progress=True)
1099
+
1100
+ print(f'[Parameters] Adaptive CFG = {async_task.adaptive_cfg}')
1101
+ print(f'[Parameters] CLIP Skip = {async_task.clip_skip}')
1102
+ print(f'[Parameters] Sharpness = {async_task.sharpness}')
1103
+ print(f'[Parameters] ControlNet Softness = {async_task.controlnet_softness}')
1104
+ print(f'[Parameters] ADM Scale = '
1105
+ f'{async_task.adm_scaler_positive} : '
1106
+ f'{async_task.adm_scaler_negative} : '
1107
+ f'{async_task.adm_scaler_end}')
1108
+ print(f'[Parameters] Seed = {async_task.seed}')
1109
+
1110
+ apply_patch_settings(async_task)
1111
+
1112
+ print(f'[Parameters] CFG = {async_task.cfg_scale}')
1113
+
1114
+ initial_latent = None
1115
+ denoising_strength = 1.0
1116
+ tiled = False
1117
+
1118
+ width, height = async_task.aspect_ratios_selection.replace('×', ' ').split(' ')[:2]
1119
+ width, height = int(width), int(height)
1120
+
1121
+ skip_prompt_processing = False
1122
+
1123
+ inpaint_worker.current_task = None
1124
+ inpaint_parameterized = async_task.inpaint_engine != 'None'
1125
+ inpaint_image = None
1126
+ inpaint_mask = None
1127
+ inpaint_head_model_path = None
1128
+
1129
+ use_synthetic_refiner = False
1130
+
1131
+ controlnet_canny_path = None
1132
+ controlnet_cpds_path = None
1133
+ clip_vision_path, ip_negative_path, ip_adapter_path, ip_adapter_face_path = None, None, None, None
1134
+
1135
+ goals = []
1136
+ tasks = []
1137
+ current_progress = 1
1138
+
1139
+ if async_task.input_image_checkbox:
1140
+ base_model_additional_loras, clip_vision_path, controlnet_canny_path, controlnet_cpds_path, inpaint_head_model_path, inpaint_image, inpaint_mask, ip_adapter_face_path, ip_adapter_path, ip_negative_path, skip_prompt_processing, use_synthetic_refiner = apply_image_input(
1141
+ async_task, base_model_additional_loras, clip_vision_path, controlnet_canny_path, controlnet_cpds_path,
1142
+ goals, inpaint_head_model_path, inpaint_image, inpaint_mask, inpaint_parameterized, ip_adapter_face_path,
1143
+ ip_adapter_path, ip_negative_path, skip_prompt_processing, use_synthetic_refiner)
1144
+
1145
+ # Load or unload CNs
1146
+ progressbar(async_task, current_progress, 'Loading control models ...')
1147
+ pipeline.refresh_controlnets([controlnet_canny_path, controlnet_cpds_path])
1148
+ ip_adapter.load_ip_adapter(clip_vision_path, ip_negative_path, ip_adapter_path)
1149
+ ip_adapter.load_ip_adapter(clip_vision_path, ip_negative_path, ip_adapter_face_path)
1150
+
1151
+ async_task.steps, switch, width, height = apply_overrides(async_task, async_task.steps, height, width)
1152
+
1153
+ print(f'[Parameters] Sampler = {async_task.sampler_name} - {async_task.scheduler_name}')
1154
+ print(f'[Parameters] Steps = {async_task.steps} - {switch}')
1155
+
1156
+ progressbar(async_task, current_progress, 'Initializing ...')
1157
+
1158
+ loras = async_task.loras
1159
+ if not skip_prompt_processing:
1160
+ tasks, use_expansion, loras, current_progress = process_prompt(async_task, async_task.prompt, async_task.negative_prompt,
1161
+ base_model_additional_loras, async_task.image_number,
1162
+ async_task.disable_seed_increment, use_expansion, use_style,
1163
+ use_synthetic_refiner, current_progress, advance_progress=True)
1164
+
1165
+ if len(goals) > 0:
1166
+ current_progress += 1
1167
+ progressbar(async_task, current_progress, 'Image processing ...')
1168
+
1169
+ should_enhance = async_task.enhance_checkbox and (async_task.enhance_uov_method != flags.disabled.casefold() or len(async_task.enhance_ctrls) > 0)
1170
+
1171
+ if 'vary' in goals:
1172
+ async_task.uov_input_image, denoising_strength, initial_latent, width, height, current_progress = apply_vary(
1173
+ async_task, async_task.uov_method, denoising_strength, async_task.uov_input_image, switch,
1174
+ current_progress)
1175
+
1176
+ if 'upscale' in goals:
1177
+ direct_return, async_task.uov_input_image, denoising_strength, initial_latent, tiled, width, height, current_progress = apply_upscale(
1178
+ async_task, async_task.uov_input_image, async_task.uov_method, switch, current_progress,
1179
+ advance_progress=True)
1180
+ if direct_return:
1181
+ d = [('Upscale (Fast)', 'upscale_fast', '2x')]
1182
+ if modules.config.default_black_out_nsfw or async_task.black_out_nsfw:
1183
+ progressbar(async_task, 100, 'Checking for NSFW content ...')
1184
+ async_task.uov_input_image = default_censor(async_task.uov_input_image)
1185
+ progressbar(async_task, 100, 'Saving image to system ...')
1186
+ uov_input_image_path = log(async_task.uov_input_image, d, output_format=async_task.output_format)
1187
+ yield_result(async_task, uov_input_image_path, 100, async_task.black_out_nsfw, False,
1188
+ do_not_show_finished_images=True)
1189
+ return
1190
+
1191
+ if 'inpaint' in goals:
1192
+ try:
1193
+ denoising_strength, initial_latent, width, height, current_progress = apply_inpaint(async_task,
1194
+ initial_latent,
1195
+ inpaint_head_model_path,
1196
+ inpaint_image,
1197
+ inpaint_mask,
1198
+ inpaint_parameterized,
1199
+ async_task.inpaint_strength,
1200
+ async_task.inpaint_respective_field,
1201
+ switch,
1202
+ async_task.inpaint_disable_initial_latent,
1203
+ current_progress,
1204
+ advance_progress=True)
1205
+ except EarlyReturnException:
1206
+ return
1207
+
1208
+ if 'cn' in goals:
1209
+ apply_control_nets(async_task, height, ip_adapter_face_path, ip_adapter_path, width, current_progress)
1210
+ if async_task.debugging_cn_preprocessor:
1211
+ return
1212
+
1213
+ if async_task.freeu_enabled:
1214
+ apply_freeu(async_task)
1215
+
1216
+ # async_task.steps can have value of uov steps here when upscale has been applied
1217
+ steps, _, _, _ = apply_overrides(async_task, async_task.steps, height, width)
1218
+
1219
+ images_to_enhance = []
1220
+ if 'enhance' in goals:
1221
+ async_task.image_number = 1
1222
+ images_to_enhance += [async_task.enhance_input_image]
1223
+ height, width, _ = async_task.enhance_input_image.shape
1224
+ # input image already provided, processing is skipped
1225
+ steps = 0
1226
+ yield_result(async_task, async_task.enhance_input_image, current_progress, async_task.black_out_nsfw, False,
1227
+ async_task.disable_intermediate_results)
1228
+
1229
+ all_steps = steps * async_task.image_number
1230
+
1231
+ if async_task.enhance_checkbox and async_task.enhance_uov_method != flags.disabled.casefold():
1232
+ enhance_upscale_steps = async_task.performance_selection.steps()
1233
+ if 'upscale' in async_task.enhance_uov_method:
1234
+ if 'fast' in async_task.enhance_uov_method:
1235
+ enhance_upscale_steps = 0
1236
+ else:
1237
+ enhance_upscale_steps = async_task.performance_selection.steps_uov()
1238
+ enhance_upscale_steps, _, _, _ = apply_overrides(async_task, enhance_upscale_steps, height, width)
1239
+ enhance_upscale_steps_total = async_task.image_number * enhance_upscale_steps
1240
+ all_steps += enhance_upscale_steps_total
1241
+
1242
+ if async_task.enhance_checkbox and len(async_task.enhance_ctrls) != 0:
1243
+ enhance_steps, _, _, _ = apply_overrides(async_task, async_task.original_steps, height, width)
1244
+ all_steps += async_task.image_number * len(async_task.enhance_ctrls) * enhance_steps
1245
+
1246
+ all_steps = max(all_steps, 1)
1247
+
1248
+ print(f'[Parameters] Denoising Strength = {denoising_strength}')
1249
+
1250
+ if isinstance(initial_latent, dict) and 'samples' in initial_latent:
1251
+ log_shape = initial_latent['samples'].shape
1252
+ else:
1253
+ log_shape = f'Image Space {(height, width)}'
1254
+
1255
+ print(f'[Parameters] Initial Latent shape: {log_shape}')
1256
+
1257
+ preparation_time = time.perf_counter() - preparation_start_time
1258
+ print(f'Preparation time: {preparation_time:.2f} seconds')
1259
+
1260
+ final_scheduler_name = patch_samplers(async_task)
1261
+ print(f'Using {final_scheduler_name} scheduler.')
1262
+
1263
+ async_task.yields.append(['preview', (current_progress, 'Moving model to GPU ...', None)])
1264
+
1265
+ processing_start_time = time.perf_counter()
1266
+
1267
+ preparation_steps = current_progress
1268
+ total_count = async_task.image_number
1269
+
1270
+ def callback(step, x0, x, total_steps, y):
1271
+ if step == 0:
1272
+ async_task.callback_steps = 0
1273
+ async_task.callback_steps += (100 - preparation_steps) / float(all_steps)
1274
+ async_task.yields.append(['preview', (
1275
+ int(current_progress + async_task.callback_steps),
1276
+ f'Sampling step {step + 1}/{total_steps}, image {current_task_id + 1}/{total_count} ...', y)])
1277
+
1278
+ show_intermediate_results = len(tasks) > 1 or async_task.should_enhance
1279
+ persist_image = not async_task.should_enhance or not async_task.save_final_enhanced_image_only
1280
+
1281
+ for current_task_id, task in enumerate(tasks):
1282
+ progressbar(async_task, current_progress, f'Preparing task {current_task_id + 1}/{async_task.image_number} ...')
1283
+ execution_start_time = time.perf_counter()
1284
+
1285
+ try:
1286
+ imgs, img_paths, current_progress = process_task(all_steps, async_task, callback, controlnet_canny_path,
1287
+ controlnet_cpds_path, current_task_id,
1288
+ denoising_strength, final_scheduler_name, goals,
1289
+ initial_latent, async_task.steps, switch, task['c'],
1290
+ task['uc'], task, loras, tiled, use_expansion, width,
1291
+ height, current_progress, preparation_steps,
1292
+ async_task.image_number, show_intermediate_results,
1293
+ persist_image)
1294
+
1295
+ current_progress = int(preparation_steps + (100 - preparation_steps) / float(all_steps) * async_task.steps * (current_task_id + 1))
1296
+ images_to_enhance += imgs
1297
+
1298
+ except ldm_patched.modules.model_management.InterruptProcessingException:
1299
+ if async_task.last_stop == 'skip':
1300
+ print('User skipped')
1301
+ async_task.last_stop = False
1302
+ continue
1303
+ else:
1304
+ print('User stopped')
1305
+ break
1306
+
1307
+ del task['c'], task['uc'] # Save memory
1308
+ execution_time = time.perf_counter() - execution_start_time
1309
+ print(f'Generating and saving time: {execution_time:.2f} seconds')
1310
+
1311
+ if not async_task.should_enhance:
1312
+ print(f'[Enhance] Skipping, preconditions aren\'t met')
1313
+ stop_processing(async_task, processing_start_time)
1314
+ return
1315
+
1316
+ progressbar(async_task, current_progress, 'Processing enhance ...')
1317
+
1318
+ active_enhance_tabs = len(async_task.enhance_ctrls)
1319
+ should_process_enhance_uov = async_task.enhance_uov_method != flags.disabled.casefold()
1320
+ enhance_uov_before = False
1321
+ enhance_uov_after = False
1322
+ if should_process_enhance_uov:
1323
+ active_enhance_tabs += 1
1324
+ enhance_uov_before = async_task.enhance_uov_processing_order == flags.enhancement_uov_before
1325
+ enhance_uov_after = async_task.enhance_uov_processing_order == flags.enhancement_uov_after
1326
+ total_count = len(images_to_enhance) * active_enhance_tabs
1327
+ async_task.images_to_enhance_count = len(images_to_enhance)
1328
+
1329
+ base_progress = current_progress
1330
+ current_task_id = -1
1331
+ done_steps_upscaling = 0
1332
+ done_steps_inpainting = 0
1333
+ enhance_steps, _, _, _ = apply_overrides(async_task, async_task.original_steps, height, width)
1334
+ exception_result = None
1335
+ for index, img in enumerate(images_to_enhance):
1336
+ async_task.enhance_stats[index] = 0
1337
+ enhancement_image_start_time = time.perf_counter()
1338
+
1339
+ last_enhance_prompt = async_task.prompt
1340
+ last_enhance_negative_prompt = async_task.negative_prompt
1341
+
1342
+ if enhance_uov_before:
1343
+ current_task_id += 1
1344
+ persist_image = not async_task.save_final_enhanced_image_only or active_enhance_tabs == 0
1345
+ current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale(
1346
+ all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
1347
+ current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
1348
+ async_task.prompt, async_task.negative_prompt, final_scheduler_name, height, img, preparation_steps,
1349
+ switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner, width, persist_image)
1350
+ async_task.enhance_stats[index] += 1
1351
+
1352
+ if exception_result == 'continue':
1353
+ continue
1354
+ elif exception_result == 'break':
1355
+ break
1356
+
1357
+ # inpaint for all other tabs
1358
+ for enhance_mask_dino_prompt_text, enhance_prompt, enhance_negative_prompt, enhance_mask_model, enhance_mask_cloth_category, enhance_mask_sam_model, enhance_mask_text_threshold, enhance_mask_box_threshold, enhance_mask_sam_max_detections, enhance_inpaint_disable_initial_latent, enhance_inpaint_engine, enhance_inpaint_strength, enhance_inpaint_respective_field, enhance_inpaint_erode_or_dilate, enhance_mask_invert in async_task.enhance_ctrls:
1359
+ current_task_id += 1
1360
+ current_progress = int(base_progress + (100 - preparation_steps) / float(all_steps) * (done_steps_upscaling + done_steps_inpainting))
1361
+ progressbar(async_task, current_progress, f'Preparing enhancement {current_task_id + 1}/{total_count} ...')
1362
+ enhancement_task_start_time = time.perf_counter()
1363
+ is_last_enhance_for_image = (current_task_id + 1) % active_enhance_tabs == 0 and not enhance_uov_after
1364
+ persist_image = not async_task.save_final_enhanced_image_only or is_last_enhance_for_image
1365
+
1366
+ extras = {}
1367
+ if enhance_mask_model == 'sam':
1368
+ print(f'[Enhance] Searching for "{enhance_mask_dino_prompt_text}"')
1369
+ elif enhance_mask_model == 'u2net_cloth_seg':
1370
+ extras['cloth_category'] = enhance_mask_cloth_category
1371
+
1372
+ mask, dino_detection_count, sam_detection_count, sam_detection_on_mask_count = generate_mask_from_image(
1373
+ img, mask_model=enhance_mask_model, extras=extras, sam_options=SAMOptions(
1374
+ dino_prompt=enhance_mask_dino_prompt_text,
1375
+ dino_box_threshold=enhance_mask_box_threshold,
1376
+ dino_text_threshold=enhance_mask_text_threshold,
1377
+ dino_erode_or_dilate=async_task.dino_erode_or_dilate,
1378
+ dino_debug=async_task.debugging_dino,
1379
+ max_detections=enhance_mask_sam_max_detections,
1380
+ model_type=enhance_mask_sam_model,
1381
+ ))
1382
+ if len(mask.shape) == 3:
1383
+ mask = mask[:, :, 0]
1384
+
1385
+ if int(enhance_inpaint_erode_or_dilate) != 0:
1386
+ mask = erode_or_dilate(mask, enhance_inpaint_erode_or_dilate)
1387
+
1388
+ if enhance_mask_invert:
1389
+ mask = 255 - mask
1390
+
1391
+ if async_task.debugging_enhance_masks_checkbox:
1392
+ async_task.yields.append(['preview', (current_progress, 'Loading ...', mask)])
1393
+ yield_result(async_task, mask, current_progress, async_task.black_out_nsfw, False,
1394
+ async_task.disable_intermediate_results)
1395
+ async_task.enhance_stats[index] += 1
1396
+
1397
+ print(f'[Enhance] {dino_detection_count} boxes detected')
1398
+ print(f'[Enhance] {sam_detection_count} segments detected in boxes')
1399
+ print(f'[Enhance] {sam_detection_on_mask_count} segments applied to mask')
1400
+
1401
+ if enhance_mask_model == 'sam' and (dino_detection_count == 0 or not async_task.debugging_dino and sam_detection_on_mask_count == 0):
1402
+ print(f'[Enhance] No "{enhance_mask_dino_prompt_text}" detected, skipping')
1403
+ continue
1404
+
1405
+ goals_enhance = ['inpaint']
1406
+
1407
+ try:
1408
+ current_progress, img, enhance_prompt_processed, enhance_negative_prompt_processed = process_enhance(
1409
+ all_steps, async_task, callback, controlnet_canny_path, controlnet_cpds_path,
1410
+ current_progress, current_task_id, denoising_strength, enhance_inpaint_disable_initial_latent,
1411
+ enhance_inpaint_engine, enhance_inpaint_respective_field, enhance_inpaint_strength,
1412
+ enhance_prompt, enhance_negative_prompt, final_scheduler_name, goals_enhance, height, img, mask,
1413
+ preparation_steps, enhance_steps, switch, tiled, total_count, use_expansion, use_style,
1414
+ use_synthetic_refiner, width, persist_image=persist_image)
1415
+ async_task.enhance_stats[index] += 1
1416
+
1417
+ if (should_process_enhance_uov and async_task.enhance_uov_processing_order == flags.enhancement_uov_after
1418
+ and async_task.enhance_uov_prompt_type == flags.enhancement_uov_prompt_type_last_filled):
1419
+ if enhance_prompt_processed != '':
1420
+ last_enhance_prompt = enhance_prompt_processed
1421
+ if enhance_negative_prompt_processed != '':
1422
+ last_enhance_negative_prompt = enhance_negative_prompt_processed
1423
+
1424
+ except ldm_patched.modules.model_management.InterruptProcessingException:
1425
+ if async_task.last_stop == 'skip':
1426
+ print('User skipped')
1427
+ async_task.last_stop = False
1428
+ continue
1429
+ else:
1430
+ print('User stopped')
1431
+ exception_result = 'break'
1432
+ break
1433
+ finally:
1434
+ done_steps_inpainting += enhance_steps
1435
+
1436
+ enhancement_task_time = time.perf_counter() - enhancement_task_start_time
1437
+ print(f'Enhancement time: {enhancement_task_time:.2f} seconds')
1438
+
1439
+ if exception_result == 'break':
1440
+ break
1441
+
1442
+ if enhance_uov_after:
1443
+ current_task_id += 1
1444
+ # last step in enhance, always save
1445
+ persist_image = True
1446
+ current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale(
1447
+ all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
1448
+ current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
1449
+ last_enhance_prompt, last_enhance_negative_prompt, final_scheduler_name, height, img,
1450
+ preparation_steps, switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner,
1451
+ width, persist_image)
1452
+ async_task.enhance_stats[index] += 1
1453
+
1454
+ if exception_result == 'continue':
1455
+ continue
1456
+ elif exception_result == 'break':
1457
+ break
1458
+
1459
+ enhancement_image_time = time.perf_counter() - enhancement_image_start_time
1460
+ print(f'Enhancement image time: {enhancement_image_time:.2f} seconds')
1461
+
1462
+ stop_processing(async_task, processing_start_time)
1463
+ return
1464
+
1465
+ while True:
1466
+ time.sleep(0.01)
1467
+ if len(async_tasks) > 0:
1468
+ task = async_tasks.pop(0)
1469
+
1470
+ try:
1471
+ handler(task)
1472
+ if task.generate_image_grid:
1473
+ build_image_wall(task)
1474
+ task.yields.append(['finish', task.results])
1475
+ pipeline.prepare_text_encoder(async_call=True)
1476
+ except:
1477
+ traceback.print_exc()
1478
+ task.yields.append(['finish', task.results])
1479
+ finally:
1480
+ if pid in modules.patch.patch_settings:
1481
+ del modules.patch.patch_settings[pid]
1482
+ pass
1483
+
1484
+
1485
+ threading.Thread(target=worker, daemon=True).start()
modules/auth.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import hashlib
3
+ import modules.constants as constants
4
+
5
+ from os.path import exists
6
+
7
+
8
+ def auth_list_to_dict(auth_list):
9
+ auth_dict = {}
10
+ for auth_data in auth_list:
11
+ if 'user' in auth_data:
12
+ if 'hash' in auth_data:
13
+ auth_dict |= {auth_data['user']: auth_data['hash']}
14
+ elif 'pass' in auth_data:
15
+ auth_dict |= {auth_data['user']: hashlib.sha256(bytes(auth_data['pass'], encoding='utf-8')).hexdigest()}
16
+ return auth_dict
17
+
18
+
19
+ def load_auth_data(filename=None):
20
+ auth_dict = None
21
+ if filename != None and exists(filename):
22
+ with open(filename, encoding='utf-8') as auth_file:
23
+ try:
24
+ auth_obj = json.load(auth_file)
25
+ if isinstance(auth_obj, list) and len(auth_obj) > 0:
26
+ auth_dict = auth_list_to_dict(auth_obj)
27
+ except Exception as e:
28
+ print('load_auth_data, e: ' + str(e))
29
+ return auth_dict
30
+
31
+
32
+ auth_dict = load_auth_data(constants.AUTH_FILENAME)
33
+
34
+ auth_enabled = auth_dict != None
35
+
36
+
37
+ def check_auth(user, password):
38
+ if user not in auth_dict:
39
+ return False
40
+ else:
41
+ return hashlib.sha256(bytes(password, encoding='utf-8')).hexdigest() == auth_dict[user]
modules/config.py ADDED
@@ -0,0 +1,997 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import math
4
+ import numbers
5
+
6
+ import args_manager
7
+ import tempfile
8
+ import modules.flags
9
+ import modules.sdxl_styles
10
+
11
+ from modules.model_loader import load_file_from_url
12
+ from modules.extra_utils import makedirs_with_log, get_files_from_folder, try_eval_env_var
13
+ from modules.flags import OutputFormat, Performance, MetadataScheme
14
+
15
+
16
+ def get_config_path(key, default_value):
17
+ env = os.getenv(key)
18
+ if env is not None and isinstance(env, str):
19
+ print(f"Environment: {key} = {env}")
20
+ return env
21
+ else:
22
+ return os.path.abspath(default_value)
23
+
24
+ wildcards_max_bfs_depth = 64
25
+ config_path = get_config_path('config_path', "./config.txt")
26
+ config_example_path = get_config_path('config_example_path', "config_modification_tutorial.txt")
27
+ config_dict = {}
28
+ always_save_keys = []
29
+ visited_keys = []
30
+
31
+ try:
32
+ with open(os.path.abspath(f'./presets/default.json'), "r", encoding="utf-8") as json_file:
33
+ config_dict.update(json.load(json_file))
34
+ except Exception as e:
35
+ print(f'Load default preset failed.')
36
+ print(e)
37
+
38
+ try:
39
+ if os.path.exists(config_path):
40
+ with open(config_path, "r", encoding="utf-8") as json_file:
41
+ config_dict.update(json.load(json_file))
42
+ always_save_keys = list(config_dict.keys())
43
+ except Exception as e:
44
+ print(f'Failed to load config file "{config_path}" . The reason is: {str(e)}')
45
+ print('Please make sure that:')
46
+ print(f'1. The file "{config_path}" is a valid text file, and you have access to read it.')
47
+ print('2. Use "\\\\" instead of "\\" when describing paths.')
48
+ print('3. There is no "," before the last "}".')
49
+ print('4. All key/value formats are correct.')
50
+
51
+
52
+ def try_load_deprecated_user_path_config():
53
+ global config_dict
54
+
55
+ if not os.path.exists('user_path_config.txt'):
56
+ return
57
+
58
+ try:
59
+ deprecated_config_dict = json.load(open('user_path_config.txt', "r", encoding="utf-8"))
60
+
61
+ def replace_config(old_key, new_key):
62
+ if old_key in deprecated_config_dict:
63
+ config_dict[new_key] = deprecated_config_dict[old_key]
64
+ del deprecated_config_dict[old_key]
65
+
66
+ replace_config('modelfile_path', 'path_checkpoints')
67
+ replace_config('lorafile_path', 'path_loras')
68
+ replace_config('embeddings_path', 'path_embeddings')
69
+ replace_config('vae_approx_path', 'path_vae_approx')
70
+ replace_config('upscale_models_path', 'path_upscale_models')
71
+ replace_config('inpaint_models_path', 'path_inpaint')
72
+ replace_config('controlnet_models_path', 'path_controlnet')
73
+ replace_config('clip_vision_models_path', 'path_clip_vision')
74
+ replace_config('fooocus_expansion_path', 'path_fooocus_expansion')
75
+ replace_config('temp_outputs_path', 'path_outputs')
76
+
77
+ if deprecated_config_dict.get("default_model", None) == 'juggernautXL_version6Rundiffusion.safetensors':
78
+ os.replace('user_path_config.txt', 'user_path_config-deprecated.txt')
79
+ print('Config updated successfully in silence. '
80
+ 'A backup of previous config is written to "user_path_config-deprecated.txt".')
81
+ return
82
+
83
+ if input("Newer models and configs are available. "
84
+ "Download and update files? [Y/n]:") in ['n', 'N', 'No', 'no', 'NO']:
85
+ config_dict.update(deprecated_config_dict)
86
+ print('Loading using deprecated old models and deprecated old configs.')
87
+ return
88
+ else:
89
+ os.replace('user_path_config.txt', 'user_path_config-deprecated.txt')
90
+ print('Config updated successfully by user. '
91
+ 'A backup of previous config is written to "user_path_config-deprecated.txt".')
92
+ return
93
+ except Exception as e:
94
+ print('Processing deprecated config failed')
95
+ print(e)
96
+ return
97
+
98
+
99
+ try_load_deprecated_user_path_config()
100
+
101
+ def get_presets():
102
+ preset_folder = 'presets'
103
+ presets = ['initial']
104
+ if not os.path.exists(preset_folder):
105
+ print('No presets found.')
106
+ return presets
107
+
108
+ return presets + [f[:f.index(".json")] for f in os.listdir(preset_folder) if f.endswith('.json')]
109
+
110
+ def update_presets():
111
+ global available_presets
112
+ available_presets = get_presets()
113
+
114
+ def try_get_preset_content(preset):
115
+ if isinstance(preset, str):
116
+ preset_path = os.path.abspath(f'./presets/{preset}.json')
117
+ try:
118
+ if os.path.exists(preset_path):
119
+ with open(preset_path, "r", encoding="utf-8") as json_file:
120
+ json_content = json.load(json_file)
121
+ print(f'Loaded preset: {preset_path}')
122
+ return json_content
123
+ else:
124
+ raise FileNotFoundError
125
+ except Exception as e:
126
+ print(f'Load preset [{preset_path}] failed')
127
+ print(e)
128
+ return {}
129
+
130
+ available_presets = get_presets()
131
+ preset = args_manager.args.preset
132
+ config_dict.update(try_get_preset_content(preset))
133
+
134
+ def get_path_output() -> str:
135
+ """
136
+ Checking output path argument and overriding default path.
137
+ """
138
+ global config_dict
139
+ path_output = get_dir_or_set_default('path_outputs', '../outputs/', make_directory=True)
140
+ if args_manager.args.output_path:
141
+ print(f'Overriding config value path_outputs with {args_manager.args.output_path}')
142
+ config_dict['path_outputs'] = path_output = args_manager.args.output_path
143
+ return path_output
144
+
145
+
146
+ def get_dir_or_set_default(key, default_value, as_array=False, make_directory=False):
147
+ global config_dict, visited_keys, always_save_keys
148
+
149
+ if key not in visited_keys:
150
+ visited_keys.append(key)
151
+
152
+ if key not in always_save_keys:
153
+ always_save_keys.append(key)
154
+
155
+ v = os.getenv(key)
156
+ if v is not None:
157
+ print(f"Environment: {key} = {v}")
158
+ config_dict[key] = v
159
+ else:
160
+ v = config_dict.get(key, None)
161
+
162
+ if isinstance(v, str):
163
+ if make_directory:
164
+ makedirs_with_log(v)
165
+ if os.path.exists(v) and os.path.isdir(v):
166
+ return v if not as_array else [v]
167
+ elif isinstance(v, list):
168
+ if make_directory:
169
+ for d in v:
170
+ makedirs_with_log(d)
171
+ if all([os.path.exists(d) and os.path.isdir(d) for d in v]):
172
+ return v
173
+
174
+ if v is not None:
175
+ print(f'Failed to load config key: {json.dumps({key:v})} is invalid or does not exist; will use {json.dumps({key:default_value})} instead.')
176
+ if isinstance(default_value, list):
177
+ dp = []
178
+ for path in default_value:
179
+ abs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), path))
180
+ dp.append(abs_path)
181
+ os.makedirs(abs_path, exist_ok=True)
182
+ else:
183
+ dp = os.path.abspath(os.path.join(os.path.dirname(__file__), default_value))
184
+ os.makedirs(dp, exist_ok=True)
185
+ if as_array:
186
+ dp = [dp]
187
+ config_dict[key] = dp
188
+ return dp
189
+
190
+
191
+ paths_checkpoints = get_dir_or_set_default('path_checkpoints', ['../models/checkpoints/'], True)
192
+ paths_loras = get_dir_or_set_default('path_loras', ['../models/loras/'], True)
193
+ path_embeddings = get_dir_or_set_default('path_embeddings', '../models/embeddings/')
194
+ path_vae_approx = get_dir_or_set_default('path_vae_approx', '../models/vae_approx/')
195
+ path_vae = get_dir_or_set_default('path_vae', '../models/vae/')
196
+ path_upscale_models = get_dir_or_set_default('path_upscale_models', '../models/upscale_models/')
197
+ path_inpaint = get_dir_or_set_default('path_inpaint', '../models/inpaint/')
198
+ path_controlnet = get_dir_or_set_default('path_controlnet', '../models/controlnet/')
199
+ path_clip_vision = get_dir_or_set_default('path_clip_vision', '../models/clip_vision/')
200
+ path_fooocus_expansion = get_dir_or_set_default('path_fooocus_expansion', '../models/prompt_expansion/fooocus_expansion')
201
+ path_wildcards = get_dir_or_set_default('path_wildcards', '../wildcards/')
202
+ path_safety_checker = get_dir_or_set_default('path_safety_checker', '../models/safety_checker/')
203
+ path_sam = get_dir_or_set_default('path_sam', '../models/sam/')
204
+ path_outputs = get_path_output()
205
+
206
+
207
+ def get_config_item_or_set_default(key, default_value, validator, disable_empty_as_none=False, expected_type=None):
208
+ global config_dict, visited_keys
209
+
210
+ if key not in visited_keys:
211
+ visited_keys.append(key)
212
+
213
+ v = os.getenv(key)
214
+ if v is not None:
215
+ v = try_eval_env_var(v, expected_type)
216
+ print(f"Environment: {key} = {v}")
217
+ config_dict[key] = v
218
+
219
+ if key not in config_dict:
220
+ config_dict[key] = default_value
221
+ return default_value
222
+
223
+ v = config_dict.get(key, None)
224
+ if not disable_empty_as_none:
225
+ if v is None or v == '':
226
+ v = 'None'
227
+ if validator(v):
228
+ return v
229
+ else:
230
+ if v is not None:
231
+ print(f'Failed to load config key: {json.dumps({key:v})} is invalid; will use {json.dumps({key:default_value})} instead.')
232
+ config_dict[key] = default_value
233
+ return default_value
234
+
235
+
236
+ def init_temp_path(path: str | None, default_path: str) -> str:
237
+ if args_manager.args.temp_path:
238
+ path = args_manager.args.temp_path
239
+
240
+ if path != '' and path != default_path:
241
+ try:
242
+ if not os.path.isabs(path):
243
+ path = os.path.abspath(path)
244
+ os.makedirs(path, exist_ok=True)
245
+ print(f'Using temp path {path}')
246
+ return path
247
+ except Exception as e:
248
+ print(f'Could not create temp path {path}. Reason: {e}')
249
+ print(f'Using default temp path {default_path} instead.')
250
+
251
+ os.makedirs(default_path, exist_ok=True)
252
+ return default_path
253
+
254
+
255
+ default_temp_path = os.path.join(tempfile.gettempdir(), 'fooocus')
256
+ temp_path = init_temp_path(get_config_item_or_set_default(
257
+ key='temp_path',
258
+ default_value=default_temp_path,
259
+ validator=lambda x: isinstance(x, str),
260
+ expected_type=str
261
+ ), default_temp_path)
262
+ temp_path_cleanup_on_launch = get_config_item_or_set_default(
263
+ key='temp_path_cleanup_on_launch',
264
+ default_value=True,
265
+ validator=lambda x: isinstance(x, bool),
266
+ expected_type=bool
267
+ )
268
+ default_base_model_name = default_model = get_config_item_or_set_default(
269
+ key='default_model',
270
+ default_value='model.safetensors',
271
+ validator=lambda x: isinstance(x, str),
272
+ expected_type=str
273
+ )
274
+ previous_default_models = get_config_item_or_set_default(
275
+ key='previous_default_models',
276
+ default_value=[],
277
+ validator=lambda x: isinstance(x, list) and all(isinstance(k, str) for k in x),
278
+ expected_type=list
279
+ )
280
+ default_refiner_model_name = default_refiner = get_config_item_or_set_default(
281
+ key='default_refiner',
282
+ default_value='None',
283
+ validator=lambda x: isinstance(x, str),
284
+ expected_type=str
285
+ )
286
+ default_refiner_switch = get_config_item_or_set_default(
287
+ key='default_refiner_switch',
288
+ default_value=0.8,
289
+ validator=lambda x: isinstance(x, numbers.Number) and 0 <= x <= 1,
290
+ expected_type=numbers.Number
291
+ )
292
+ default_loras_min_weight = get_config_item_or_set_default(
293
+ key='default_loras_min_weight',
294
+ default_value=-2,
295
+ validator=lambda x: isinstance(x, numbers.Number) and -10 <= x <= 10,
296
+ expected_type=numbers.Number
297
+ )
298
+ default_loras_max_weight = get_config_item_or_set_default(
299
+ key='default_loras_max_weight',
300
+ default_value=2,
301
+ validator=lambda x: isinstance(x, numbers.Number) and -10 <= x <= 10,
302
+ expected_type=numbers.Number
303
+ )
304
+ default_loras = get_config_item_or_set_default(
305
+ key='default_loras',
306
+ default_value=[
307
+ [
308
+ True,
309
+ "None",
310
+ 1.0
311
+ ],
312
+ [
313
+ True,
314
+ "None",
315
+ 1.0
316
+ ],
317
+ [
318
+ True,
319
+ "None",
320
+ 1.0
321
+ ],
322
+ [
323
+ True,
324
+ "None",
325
+ 1.0
326
+ ],
327
+ [
328
+ True,
329
+ "None",
330
+ 1.0
331
+ ]
332
+ ],
333
+ validator=lambda x: isinstance(x, list) and all(
334
+ len(y) == 3 and isinstance(y[0], bool) and isinstance(y[1], str) and isinstance(y[2], numbers.Number)
335
+ or len(y) == 2 and isinstance(y[0], str) and isinstance(y[1], numbers.Number)
336
+ for y in x),
337
+ expected_type=list
338
+ )
339
+ default_loras = [(y[0], y[1], y[2]) if len(y) == 3 else (True, y[0], y[1]) for y in default_loras]
340
+ default_max_lora_number = get_config_item_or_set_default(
341
+ key='default_max_lora_number',
342
+ default_value=len(default_loras) if isinstance(default_loras, list) and len(default_loras) > 0 else 5,
343
+ validator=lambda x: isinstance(x, int) and x >= 1,
344
+ expected_type=int
345
+ )
346
+ default_cfg_scale = get_config_item_or_set_default(
347
+ key='default_cfg_scale',
348
+ default_value=7.0,
349
+ validator=lambda x: isinstance(x, numbers.Number),
350
+ expected_type=numbers.Number
351
+ )
352
+ default_sample_sharpness = get_config_item_or_set_default(
353
+ key='default_sample_sharpness',
354
+ default_value=2.0,
355
+ validator=lambda x: isinstance(x, numbers.Number),
356
+ expected_type=numbers.Number
357
+ )
358
+ default_sampler = get_config_item_or_set_default(
359
+ key='default_sampler',
360
+ default_value='dpmpp_2m_sde_gpu',
361
+ validator=lambda x: x in modules.flags.sampler_list,
362
+ expected_type=str
363
+ )
364
+ default_scheduler = get_config_item_or_set_default(
365
+ key='default_scheduler',
366
+ default_value='karras',
367
+ validator=lambda x: x in modules.flags.scheduler_list,
368
+ expected_type=str
369
+ )
370
+ default_vae = get_config_item_or_set_default(
371
+ key='default_vae',
372
+ default_value=modules.flags.default_vae,
373
+ validator=lambda x: isinstance(x, str),
374
+ expected_type=str
375
+ )
376
+ default_styles = get_config_item_or_set_default(
377
+ key='default_styles',
378
+ default_value=[
379
+ "Fooocus V2",
380
+ "Fooocus Enhance",
381
+ "Fooocus Sharp"
382
+ ],
383
+ validator=lambda x: isinstance(x, list) and all(y in modules.sdxl_styles.legal_style_names for y in x),
384
+ expected_type=list
385
+ )
386
+ default_prompt_negative = get_config_item_or_set_default(
387
+ key='default_prompt_negative',
388
+ default_value='',
389
+ validator=lambda x: isinstance(x, str),
390
+ disable_empty_as_none=True,
391
+ expected_type=str
392
+ )
393
+ default_prompt = get_config_item_or_set_default(
394
+ key='default_prompt',
395
+ default_value='',
396
+ validator=lambda x: isinstance(x, str),
397
+ disable_empty_as_none=True,
398
+ expected_type=str
399
+ )
400
+ default_performance = get_config_item_or_set_default(
401
+ key='default_performance',
402
+ default_value=Performance.SPEED.value,
403
+ validator=lambda x: x in Performance.values(),
404
+ expected_type=str
405
+ )
406
+ default_image_prompt_checkbox = get_config_item_or_set_default(
407
+ key='default_image_prompt_checkbox',
408
+ default_value=False,
409
+ validator=lambda x: isinstance(x, bool),
410
+ expected_type=bool
411
+ )
412
+ default_enhance_checkbox = get_config_item_or_set_default(
413
+ key='default_enhance_checkbox',
414
+ default_value=False,
415
+ validator=lambda x: isinstance(x, bool),
416
+ expected_type=bool
417
+ )
418
+ default_advanced_checkbox = get_config_item_or_set_default(
419
+ key='default_advanced_checkbox',
420
+ default_value=False,
421
+ validator=lambda x: isinstance(x, bool),
422
+ expected_type=bool
423
+ )
424
+ default_developer_debug_mode_checkbox = get_config_item_or_set_default(
425
+ key='default_developer_debug_mode_checkbox',
426
+ default_value=False,
427
+ validator=lambda x: isinstance(x, bool),
428
+ expected_type=bool
429
+ )
430
+ default_image_prompt_advanced_checkbox = get_config_item_or_set_default(
431
+ key='default_image_prompt_advanced_checkbox',
432
+ default_value=False,
433
+ validator=lambda x: isinstance(x, bool),
434
+ expected_type=bool
435
+ )
436
+ default_max_image_number = get_config_item_or_set_default(
437
+ key='default_max_image_number',
438
+ default_value=32,
439
+ validator=lambda x: isinstance(x, int) and x >= 1,
440
+ expected_type=int
441
+ )
442
+ default_output_format = get_config_item_or_set_default(
443
+ key='default_output_format',
444
+ default_value='png',
445
+ validator=lambda x: x in OutputFormat.list(),
446
+ expected_type=str
447
+ )
448
+ default_image_number = get_config_item_or_set_default(
449
+ key='default_image_number',
450
+ default_value=2,
451
+ validator=lambda x: isinstance(x, int) and 1 <= x <= default_max_image_number,
452
+ expected_type=int
453
+ )
454
+ checkpoint_downloads = get_config_item_or_set_default(
455
+ key='checkpoint_downloads',
456
+ default_value={},
457
+ validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()),
458
+ expected_type=dict
459
+ )
460
+ lora_downloads = get_config_item_or_set_default(
461
+ key='lora_downloads',
462
+ default_value={},
463
+ validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()),
464
+ expected_type=dict
465
+ )
466
+ embeddings_downloads = get_config_item_or_set_default(
467
+ key='embeddings_downloads',
468
+ default_value={},
469
+ validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()),
470
+ expected_type=dict
471
+ )
472
+ vae_downloads = get_config_item_or_set_default(
473
+ key='vae_downloads',
474
+ default_value={},
475
+ validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()),
476
+ expected_type=dict
477
+ )
478
+ available_aspect_ratios = get_config_item_or_set_default(
479
+ key='available_aspect_ratios',
480
+ default_value=modules.flags.sdxl_aspect_ratios,
481
+ validator=lambda x: isinstance(x, list) and all('*' in v for v in x) and len(x) > 1,
482
+ expected_type=list
483
+ )
484
+ default_aspect_ratio = get_config_item_or_set_default(
485
+ key='default_aspect_ratio',
486
+ default_value='1152*896' if '1152*896' in available_aspect_ratios else available_aspect_ratios[0],
487
+ validator=lambda x: x in available_aspect_ratios,
488
+ expected_type=str
489
+ )
490
+ default_inpaint_engine_version = get_config_item_or_set_default(
491
+ key='default_inpaint_engine_version',
492
+ default_value='v2.6',
493
+ validator=lambda x: x in modules.flags.inpaint_engine_versions,
494
+ expected_type=str
495
+ )
496
+ default_selected_image_input_tab_id = get_config_item_or_set_default(
497
+ key='default_selected_image_input_tab_id',
498
+ default_value=modules.flags.default_input_image_tab,
499
+ validator=lambda x: x in modules.flags.input_image_tab_ids,
500
+ expected_type=str
501
+ )
502
+ default_uov_method = get_config_item_or_set_default(
503
+ key='default_uov_method',
504
+ default_value=modules.flags.disabled,
505
+ validator=lambda x: x in modules.flags.uov_list,
506
+ expected_type=str
507
+ )
508
+ default_controlnet_image_count = get_config_item_or_set_default(
509
+ key='default_controlnet_image_count',
510
+ default_value=4,
511
+ validator=lambda x: isinstance(x, int) and x > 0,
512
+ expected_type=int
513
+ )
514
+ default_ip_images = {}
515
+ default_ip_stop_ats = {}
516
+ default_ip_weights = {}
517
+ default_ip_types = {}
518
+
519
+ for image_count in range(default_controlnet_image_count):
520
+ image_count += 1
521
+ default_ip_images[image_count] = get_config_item_or_set_default(
522
+ key=f'default_ip_image_{image_count}',
523
+ default_value='None',
524
+ validator=lambda x: x == 'None' or isinstance(x, str) and os.path.exists(x),
525
+ expected_type=str
526
+ )
527
+
528
+ if default_ip_images[image_count] == 'None':
529
+ default_ip_images[image_count] = None
530
+
531
+ default_ip_types[image_count] = get_config_item_or_set_default(
532
+ key=f'default_ip_type_{image_count}',
533
+ default_value=modules.flags.default_ip,
534
+ validator=lambda x: x in modules.flags.ip_list,
535
+ expected_type=str
536
+ )
537
+
538
+ default_end, default_weight = modules.flags.default_parameters[default_ip_types[image_count]]
539
+
540
+ default_ip_stop_ats[image_count] = get_config_item_or_set_default(
541
+ key=f'default_ip_stop_at_{image_count}',
542
+ default_value=default_end,
543
+ validator=lambda x: isinstance(x, float) and 0 <= x <= 1,
544
+ expected_type=float
545
+ )
546
+ default_ip_weights[image_count] = get_config_item_or_set_default(
547
+ key=f'default_ip_weight_{image_count}',
548
+ default_value=default_weight,
549
+ validator=lambda x: isinstance(x, float) and 0 <= x <= 2,
550
+ expected_type=float
551
+ )
552
+
553
+ default_inpaint_advanced_masking_checkbox = get_config_item_or_set_default(
554
+ key='default_inpaint_advanced_masking_checkbox',
555
+ default_value=False,
556
+ validator=lambda x: isinstance(x, bool),
557
+ expected_type=bool
558
+ )
559
+ default_inpaint_method = get_config_item_or_set_default(
560
+ key='default_inpaint_method',
561
+ default_value=modules.flags.inpaint_option_default,
562
+ validator=lambda x: x in modules.flags.inpaint_options,
563
+ expected_type=str
564
+ )
565
+ default_cfg_tsnr = get_config_item_or_set_default(
566
+ key='default_cfg_tsnr',
567
+ default_value=7.0,
568
+ validator=lambda x: isinstance(x, numbers.Number),
569
+ expected_type=numbers.Number
570
+ )
571
+ default_clip_skip = get_config_item_or_set_default(
572
+ key='default_clip_skip',
573
+ default_value=2,
574
+ validator=lambda x: isinstance(x, int) and 1 <= x <= modules.flags.clip_skip_max,
575
+ expected_type=int
576
+ )
577
+ default_overwrite_step = get_config_item_or_set_default(
578
+ key='default_overwrite_step',
579
+ default_value=-1,
580
+ validator=lambda x: isinstance(x, int),
581
+ expected_type=int
582
+ )
583
+ default_overwrite_switch = get_config_item_or_set_default(
584
+ key='default_overwrite_switch',
585
+ default_value=-1,
586
+ validator=lambda x: isinstance(x, int),
587
+ expected_type=int
588
+ )
589
+ default_overwrite_upscale = get_config_item_or_set_default(
590
+ key='default_overwrite_upscale',
591
+ default_value=-1,
592
+ validator=lambda x: isinstance(x, numbers.Number)
593
+ )
594
+ example_inpaint_prompts = get_config_item_or_set_default(
595
+ key='example_inpaint_prompts',
596
+ default_value=[
597
+ 'highly detailed face', 'detailed girl face', 'detailed man face', 'detailed hand', 'beautiful eyes'
598
+ ],
599
+ validator=lambda x: isinstance(x, list) and all(isinstance(v, str) for v in x),
600
+ expected_type=list
601
+ )
602
+ example_enhance_detection_prompts = get_config_item_or_set_default(
603
+ key='example_enhance_detection_prompts',
604
+ default_value=[
605
+ 'face', 'eye', 'mouth', 'hair', 'hand', 'body'
606
+ ],
607
+ validator=lambda x: isinstance(x, list) and all(isinstance(v, str) for v in x),
608
+ expected_type=list
609
+ )
610
+ default_enhance_tabs = get_config_item_or_set_default(
611
+ key='default_enhance_tabs',
612
+ default_value=3,
613
+ validator=lambda x: isinstance(x, int) and 1 <= x <= 5,
614
+ expected_type=int
615
+ )
616
+ default_enhance_uov_method = get_config_item_or_set_default(
617
+ key='default_enhance_uov_method',
618
+ default_value=modules.flags.disabled,
619
+ validator=lambda x: x in modules.flags.uov_list,
620
+ expected_type=int
621
+ )
622
+ default_enhance_uov_processing_order = get_config_item_or_set_default(
623
+ key='default_enhance_uov_processing_order',
624
+ default_value=modules.flags.enhancement_uov_before,
625
+ validator=lambda x: x in modules.flags.enhancement_uov_processing_order,
626
+ expected_type=int
627
+ )
628
+ default_enhance_uov_prompt_type = get_config_item_or_set_default(
629
+ key='default_enhance_uov_prompt_type',
630
+ default_value=modules.flags.enhancement_uov_prompt_type_original,
631
+ validator=lambda x: x in modules.flags.enhancement_uov_prompt_types,
632
+ expected_type=int
633
+ )
634
+ default_sam_max_detections = get_config_item_or_set_default(
635
+ key='default_sam_max_detections',
636
+ default_value=0,
637
+ validator=lambda x: isinstance(x, int) and 0 <= x <= 10,
638
+ expected_type=int
639
+ )
640
+ default_black_out_nsfw = get_config_item_or_set_default(
641
+ key='default_black_out_nsfw',
642
+ default_value=False,
643
+ validator=lambda x: isinstance(x, bool),
644
+ expected_type=bool
645
+ )
646
+ default_save_only_final_enhanced_image = get_config_item_or_set_default(
647
+ key='default_save_only_final_enhanced_image',
648
+ default_value=False,
649
+ validator=lambda x: isinstance(x, bool),
650
+ expected_type=bool
651
+ )
652
+ default_save_metadata_to_images = get_config_item_or_set_default(
653
+ key='default_save_metadata_to_images',
654
+ default_value=False,
655
+ validator=lambda x: isinstance(x, bool),
656
+ expected_type=bool
657
+ )
658
+ default_metadata_scheme = get_config_item_or_set_default(
659
+ key='default_metadata_scheme',
660
+ default_value=MetadataScheme.FOOOCUS.value,
661
+ validator=lambda x: x in [y[1] for y in modules.flags.metadata_scheme if y[1] == x],
662
+ expected_type=str
663
+ )
664
+ metadata_created_by = get_config_item_or_set_default(
665
+ key='metadata_created_by',
666
+ default_value='',
667
+ validator=lambda x: isinstance(x, str),
668
+ expected_type=str
669
+ )
670
+
671
+ example_inpaint_prompts = [[x] for x in example_inpaint_prompts]
672
+ example_enhance_detection_prompts = [[x] for x in example_enhance_detection_prompts]
673
+
674
+ default_invert_mask_checkbox = get_config_item_or_set_default(
675
+ key='default_invert_mask_checkbox',
676
+ default_value=False,
677
+ validator=lambda x: isinstance(x, bool),
678
+ expected_type=bool
679
+ )
680
+
681
+ default_inpaint_mask_model = get_config_item_or_set_default(
682
+ key='default_inpaint_mask_model',
683
+ default_value='isnet-general-use',
684
+ validator=lambda x: x in modules.flags.inpaint_mask_models,
685
+ expected_type=str
686
+ )
687
+
688
+ default_enhance_inpaint_mask_model = get_config_item_or_set_default(
689
+ key='default_enhance_inpaint_mask_model',
690
+ default_value='sam',
691
+ validator=lambda x: x in modules.flags.inpaint_mask_models,
692
+ expected_type=str
693
+ )
694
+
695
+ default_inpaint_mask_cloth_category = get_config_item_or_set_default(
696
+ key='default_inpaint_mask_cloth_category',
697
+ default_value='full',
698
+ validator=lambda x: x in modules.flags.inpaint_mask_cloth_category,
699
+ expected_type=str
700
+ )
701
+
702
+ default_inpaint_mask_sam_model = get_config_item_or_set_default(
703
+ key='default_inpaint_mask_sam_model',
704
+ default_value='vit_b',
705
+ validator=lambda x: x in modules.flags.inpaint_mask_sam_model,
706
+ expected_type=str
707
+ )
708
+
709
+ default_describe_apply_prompts_checkbox = get_config_item_or_set_default(
710
+ key='default_describe_apply_prompts_checkbox',
711
+ default_value=True,
712
+ validator=lambda x: isinstance(x, bool),
713
+ expected_type=bool
714
+ )
715
+ default_describe_content_type = get_config_item_or_set_default(
716
+ key='default_describe_content_type',
717
+ default_value=[modules.flags.describe_type_photo],
718
+ validator=lambda x: all(k in modules.flags.describe_types for k in x),
719
+ expected_type=list
720
+ )
721
+
722
+ config_dict["default_loras"] = default_loras = default_loras[:default_max_lora_number] + [[True, 'None', 1.0] for _ in range(default_max_lora_number - len(default_loras))]
723
+
724
+ # mapping config to meta parameter
725
+ possible_preset_keys = {
726
+ "default_model": "base_model",
727
+ "default_refiner": "refiner_model",
728
+ "default_refiner_switch": "refiner_switch",
729
+ "previous_default_models": "previous_default_models",
730
+ "default_loras_min_weight": "default_loras_min_weight",
731
+ "default_loras_max_weight": "default_loras_max_weight",
732
+ "default_loras": "<processed>",
733
+ "default_cfg_scale": "guidance_scale",
734
+ "default_sample_sharpness": "sharpness",
735
+ "default_cfg_tsnr": "adaptive_cfg",
736
+ "default_clip_skip": "clip_skip",
737
+ "default_sampler": "sampler",
738
+ "default_scheduler": "scheduler",
739
+ "default_overwrite_step": "steps",
740
+ "default_overwrite_switch": "overwrite_switch",
741
+ "default_performance": "performance",
742
+ "default_image_number": "image_number",
743
+ "default_prompt": "prompt",
744
+ "default_prompt_negative": "negative_prompt",
745
+ "default_styles": "styles",
746
+ "default_aspect_ratio": "resolution",
747
+ "default_save_metadata_to_images": "default_save_metadata_to_images",
748
+ "checkpoint_downloads": "checkpoint_downloads",
749
+ "embeddings_downloads": "embeddings_downloads",
750
+ "lora_downloads": "lora_downloads",
751
+ "vae_downloads": "vae_downloads",
752
+ "default_vae": "vae",
753
+ # "default_inpaint_method": "inpaint_method", # disabled so inpaint mode doesn't refresh after every preset change
754
+ "default_inpaint_engine_version": "inpaint_engine_version",
755
+ }
756
+
757
+ REWRITE_PRESET = False
758
+
759
+ if REWRITE_PRESET and isinstance(args_manager.args.preset, str):
760
+ save_path = 'presets/' + args_manager.args.preset + '.json'
761
+ with open(save_path, "w", encoding="utf-8") as json_file:
762
+ json.dump({k: config_dict[k] for k in possible_preset_keys}, json_file, indent=4)
763
+ print(f'Preset saved to {save_path}. Exiting ...')
764
+ exit(0)
765
+
766
+
767
+ def add_ratio(x):
768
+ a, b = x.replace('*', ' ').split(' ')[:2]
769
+ a, b = int(a), int(b)
770
+ g = math.gcd(a, b)
771
+ return f'{a}×{b} <span style="color: grey;"> \U00002223 {a // g}:{b // g}</span>'
772
+
773
+
774
+ default_aspect_ratio = add_ratio(default_aspect_ratio)
775
+ available_aspect_ratios_labels = [add_ratio(x) for x in available_aspect_ratios]
776
+
777
+
778
+ # Only write config in the first launch.
779
+ if not os.path.exists(config_path):
780
+ with open(config_path, "w", encoding="utf-8") as json_file:
781
+ json.dump({k: config_dict[k] for k in always_save_keys}, json_file, indent=4)
782
+
783
+
784
+ # Always write tutorials.
785
+ with open(config_example_path, "w", encoding="utf-8") as json_file:
786
+ cpa = config_path.replace("\\", "\\\\")
787
+ json_file.write(f'You can modify your "{cpa}" using the below keys, formats, and examples.\n'
788
+ f'Do not modify this file. Modifications in this file will not take effect.\n'
789
+ f'This file is a tutorial and example. Please edit "{cpa}" to really change any settings.\n'
790
+ + 'Remember to split the paths with "\\\\" rather than "\\", '
791
+ 'and there is no "," before the last "}". \n\n\n')
792
+ json.dump({k: config_dict[k] for k in visited_keys}, json_file, indent=4)
793
+
794
+ model_filenames = []
795
+ lora_filenames = []
796
+ vae_filenames = []
797
+ wildcard_filenames = []
798
+
799
+
800
+ def get_model_filenames(folder_paths, extensions=None, name_filter=None):
801
+ if extensions is None:
802
+ extensions = ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch']
803
+ files = []
804
+
805
+ if not isinstance(folder_paths, list):
806
+ folder_paths = [folder_paths]
807
+ for folder in folder_paths:
808
+ files += get_files_from_folder(folder, extensions, name_filter)
809
+
810
+ return files
811
+
812
+
813
+ def update_files():
814
+ global model_filenames, lora_filenames, vae_filenames, wildcard_filenames, available_presets
815
+ model_filenames = get_model_filenames(paths_checkpoints)
816
+ lora_filenames = get_model_filenames(paths_loras)
817
+ vae_filenames = get_model_filenames(path_vae)
818
+ wildcard_filenames = get_files_from_folder(path_wildcards, ['.txt'])
819
+ available_presets = get_presets()
820
+ return
821
+
822
+
823
+ def downloading_inpaint_models(v):
824
+ assert v in modules.flags.inpaint_engine_versions
825
+
826
+ load_file_from_url(
827
+ url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/fooocus_inpaint_head.pth',
828
+ model_dir=path_inpaint,
829
+ file_name='fooocus_inpaint_head.pth'
830
+ )
831
+ head_file = os.path.join(path_inpaint, 'fooocus_inpaint_head.pth')
832
+ patch_file = None
833
+
834
+ if v == 'v1':
835
+ load_file_from_url(
836
+ url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint.fooocus.patch',
837
+ model_dir=path_inpaint,
838
+ file_name='inpaint.fooocus.patch'
839
+ )
840
+ patch_file = os.path.join(path_inpaint, 'inpaint.fooocus.patch')
841
+
842
+ if v == 'v2.5':
843
+ load_file_from_url(
844
+ url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v25.fooocus.patch',
845
+ model_dir=path_inpaint,
846
+ file_name='inpaint_v25.fooocus.patch'
847
+ )
848
+ patch_file = os.path.join(path_inpaint, 'inpaint_v25.fooocus.patch')
849
+
850
+ if v == 'v2.6':
851
+ load_file_from_url(
852
+ url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v26.fooocus.patch',
853
+ model_dir=path_inpaint,
854
+ file_name='inpaint_v26.fooocus.patch'
855
+ )
856
+ patch_file = os.path.join(path_inpaint, 'inpaint_v26.fooocus.patch')
857
+
858
+ return head_file, patch_file
859
+
860
+
861
+ def downloading_sdxl_lcm_lora():
862
+ load_file_from_url(
863
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/sdxl_lcm_lora.safetensors',
864
+ model_dir=paths_loras[0],
865
+ file_name=modules.flags.PerformanceLoRA.EXTREME_SPEED.value
866
+ )
867
+ return modules.flags.PerformanceLoRA.EXTREME_SPEED.value
868
+
869
+
870
+ def downloading_sdxl_lightning_lora():
871
+ load_file_from_url(
872
+ url='https://huggingface.co/mashb1t/misc/resolve/main/sdxl_lightning_4step_lora.safetensors',
873
+ model_dir=paths_loras[0],
874
+ file_name=modules.flags.PerformanceLoRA.LIGHTNING.value
875
+ )
876
+ return modules.flags.PerformanceLoRA.LIGHTNING.value
877
+
878
+
879
+ def downloading_sdxl_hyper_sd_lora():
880
+ load_file_from_url(
881
+ url='https://huggingface.co/mashb1t/misc/resolve/main/sdxl_hyper_sd_4step_lora.safetensors',
882
+ model_dir=paths_loras[0],
883
+ file_name=modules.flags.PerformanceLoRA.HYPER_SD.value
884
+ )
885
+ return modules.flags.PerformanceLoRA.HYPER_SD.value
886
+
887
+
888
+ def downloading_controlnet_canny():
889
+ load_file_from_url(
890
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/control-lora-canny-rank128.safetensors',
891
+ model_dir=path_controlnet,
892
+ file_name='control-lora-canny-rank128.safetensors'
893
+ )
894
+ return os.path.join(path_controlnet, 'control-lora-canny-rank128.safetensors')
895
+
896
+
897
+ def downloading_controlnet_cpds():
898
+ load_file_from_url(
899
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_xl_cpds_128.safetensors',
900
+ model_dir=path_controlnet,
901
+ file_name='fooocus_xl_cpds_128.safetensors'
902
+ )
903
+ return os.path.join(path_controlnet, 'fooocus_xl_cpds_128.safetensors')
904
+
905
+
906
+ def downloading_ip_adapters(v):
907
+ assert v in ['ip', 'face']
908
+
909
+ results = []
910
+
911
+ load_file_from_url(
912
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/clip_vision_vit_h.safetensors',
913
+ model_dir=path_clip_vision,
914
+ file_name='clip_vision_vit_h.safetensors'
915
+ )
916
+ results += [os.path.join(path_clip_vision, 'clip_vision_vit_h.safetensors')]
917
+
918
+ load_file_from_url(
919
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_ip_negative.safetensors',
920
+ model_dir=path_controlnet,
921
+ file_name='fooocus_ip_negative.safetensors'
922
+ )
923
+ results += [os.path.join(path_controlnet, 'fooocus_ip_negative.safetensors')]
924
+
925
+ if v == 'ip':
926
+ load_file_from_url(
927
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus_sdxl_vit-h.bin',
928
+ model_dir=path_controlnet,
929
+ file_name='ip-adapter-plus_sdxl_vit-h.bin'
930
+ )
931
+ results += [os.path.join(path_controlnet, 'ip-adapter-plus_sdxl_vit-h.bin')]
932
+
933
+ if v == 'face':
934
+ load_file_from_url(
935
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus-face_sdxl_vit-h.bin',
936
+ model_dir=path_controlnet,
937
+ file_name='ip-adapter-plus-face_sdxl_vit-h.bin'
938
+ )
939
+ results += [os.path.join(path_controlnet, 'ip-adapter-plus-face_sdxl_vit-h.bin')]
940
+
941
+ return results
942
+
943
+
944
+ def downloading_upscale_model():
945
+ load_file_from_url(
946
+ url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_upscaler_s409985e5.bin',
947
+ model_dir=path_upscale_models,
948
+ file_name='fooocus_upscaler_s409985e5.bin'
949
+ )
950
+ return os.path.join(path_upscale_models, 'fooocus_upscaler_s409985e5.bin')
951
+
952
+ def downloading_safety_checker_model():
953
+ load_file_from_url(
954
+ url='https://huggingface.co/mashb1t/misc/resolve/main/stable-diffusion-safety-checker.bin',
955
+ model_dir=path_safety_checker,
956
+ file_name='stable-diffusion-safety-checker.bin'
957
+ )
958
+ return os.path.join(path_safety_checker, 'stable-diffusion-safety-checker.bin')
959
+
960
+
961
+ def download_sam_model(sam_model: str) -> str:
962
+ match sam_model:
963
+ case 'vit_b':
964
+ return downloading_sam_vit_b()
965
+ case 'vit_l':
966
+ return downloading_sam_vit_l()
967
+ case 'vit_h':
968
+ return downloading_sam_vit_h()
969
+ case _:
970
+ raise ValueError(f"sam model {sam_model} does not exist.")
971
+
972
+
973
+ def downloading_sam_vit_b():
974
+ load_file_from_url(
975
+ url='https://huggingface.co/mashb1t/misc/resolve/main/sam_vit_b_01ec64.pth',
976
+ model_dir=path_sam,
977
+ file_name='sam_vit_b_01ec64.pth'
978
+ )
979
+ return os.path.join(path_sam, 'sam_vit_b_01ec64.pth')
980
+
981
+
982
+ def downloading_sam_vit_l():
983
+ load_file_from_url(
984
+ url='https://huggingface.co/mashb1t/misc/resolve/main/sam_vit_l_0b3195.pth',
985
+ model_dir=path_sam,
986
+ file_name='sam_vit_l_0b3195.pth'
987
+ )
988
+ return os.path.join(path_sam, 'sam_vit_l_0b3195.pth')
989
+
990
+
991
+ def downloading_sam_vit_h():
992
+ load_file_from_url(
993
+ url='https://huggingface.co/mashb1t/misc/resolve/main/sam_vit_h_4b8939.pth',
994
+ model_dir=path_sam,
995
+ file_name='sam_vit_h_4b8939.pth'
996
+ )
997
+ return os.path.join(path_sam, 'sam_vit_h_4b8939.pth')
modules/constants.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # as in k-diffusion (sampling.py)
2
+ MIN_SEED = 0
3
+ MAX_SEED = 2**63 - 1
4
+
5
+ AUTH_FILENAME = 'auth.json'
modules/core.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import einops
3
+ import torch
4
+ import numpy as np
5
+
6
+ import ldm_patched.modules.model_management
7
+ import ldm_patched.modules.model_detection
8
+ import ldm_patched.modules.model_patcher
9
+ import ldm_patched.modules.utils
10
+ import ldm_patched.modules.controlnet
11
+ import modules.sample_hijack
12
+ import ldm_patched.modules.samplers
13
+ import ldm_patched.modules.latent_formats
14
+
15
+ from ldm_patched.modules.sd import load_checkpoint_guess_config
16
+ from ldm_patched.contrib.external import VAEDecode, EmptyLatentImage, VAEEncode, VAEEncodeTiled, VAEDecodeTiled, \
17
+ ControlNetApplyAdvanced
18
+ from ldm_patched.contrib.external_freelunch import FreeU_V2
19
+ from ldm_patched.modules.sample import prepare_mask
20
+ from modules.lora import match_lora
21
+ from modules.util import get_file_from_folder_list
22
+ from ldm_patched.modules.lora import model_lora_keys_unet, model_lora_keys_clip
23
+ from modules.config import path_embeddings
24
+ from ldm_patched.contrib.external_model_advanced import ModelSamplingDiscrete, ModelSamplingContinuousEDM
25
+
26
+ opEmptyLatentImage = EmptyLatentImage()
27
+ opVAEDecode = VAEDecode()
28
+ opVAEEncode = VAEEncode()
29
+ opVAEDecodeTiled = VAEDecodeTiled()
30
+ opVAEEncodeTiled = VAEEncodeTiled()
31
+ opControlNetApplyAdvanced = ControlNetApplyAdvanced()
32
+ opFreeU = FreeU_V2()
33
+ opModelSamplingDiscrete = ModelSamplingDiscrete()
34
+ opModelSamplingContinuousEDM = ModelSamplingContinuousEDM()
35
+
36
+
37
+ class StableDiffusionModel:
38
+ def __init__(self, unet=None, vae=None, clip=None, clip_vision=None, filename=None, vae_filename=None):
39
+ self.unet = unet
40
+ self.vae = vae
41
+ self.clip = clip
42
+ self.clip_vision = clip_vision
43
+ self.filename = filename
44
+ self.vae_filename = vae_filename
45
+ self.unet_with_lora = unet
46
+ self.clip_with_lora = clip
47
+ self.visited_loras = ''
48
+
49
+ self.lora_key_map_unet = {}
50
+ self.lora_key_map_clip = {}
51
+
52
+ if self.unet is not None:
53
+ self.lora_key_map_unet = model_lora_keys_unet(self.unet.model, self.lora_key_map_unet)
54
+ self.lora_key_map_unet.update({x: x for x in self.unet.model.state_dict().keys()})
55
+
56
+ if self.clip is not None:
57
+ self.lora_key_map_clip = model_lora_keys_clip(self.clip.cond_stage_model, self.lora_key_map_clip)
58
+ self.lora_key_map_clip.update({x: x for x in self.clip.cond_stage_model.state_dict().keys()})
59
+
60
+ @torch.no_grad()
61
+ @torch.inference_mode()
62
+ def refresh_loras(self, loras):
63
+ assert isinstance(loras, list)
64
+
65
+ if self.visited_loras == str(loras):
66
+ return
67
+
68
+ self.visited_loras = str(loras)
69
+
70
+ if self.unet is None:
71
+ return
72
+
73
+ print(f'Request to load LoRAs {str(loras)} for model [{self.filename}].')
74
+
75
+ loras_to_load = []
76
+
77
+ for filename, weight in loras:
78
+ if filename == 'None':
79
+ continue
80
+
81
+ if os.path.exists(filename):
82
+ lora_filename = filename
83
+ else:
84
+ lora_filename = get_file_from_folder_list(filename, modules.config.paths_loras)
85
+
86
+ if not os.path.exists(lora_filename):
87
+ print(f'Lora file not found: {lora_filename}')
88
+ continue
89
+
90
+ loras_to_load.append((lora_filename, weight))
91
+
92
+ self.unet_with_lora = self.unet.clone() if self.unet is not None else None
93
+ self.clip_with_lora = self.clip.clone() if self.clip is not None else None
94
+
95
+ for lora_filename, weight in loras_to_load:
96
+ lora_unmatch = ldm_patched.modules.utils.load_torch_file(lora_filename, safe_load=False)
97
+ lora_unet, lora_unmatch = match_lora(lora_unmatch, self.lora_key_map_unet)
98
+ lora_clip, lora_unmatch = match_lora(lora_unmatch, self.lora_key_map_clip)
99
+
100
+ if len(lora_unmatch) > 12:
101
+ # model mismatch
102
+ continue
103
+
104
+ if len(lora_unmatch) > 0:
105
+ print(f'Loaded LoRA [{lora_filename}] for model [{self.filename}] '
106
+ f'with unmatched keys {list(lora_unmatch.keys())}')
107
+
108
+ if self.unet_with_lora is not None and len(lora_unet) > 0:
109
+ loaded_keys = self.unet_with_lora.add_patches(lora_unet, weight)
110
+ print(f'Loaded LoRA [{lora_filename}] for UNet [{self.filename}] '
111
+ f'with {len(loaded_keys)} keys at weight {weight}.')
112
+ for item in lora_unet:
113
+ if item not in loaded_keys:
114
+ print("UNet LoRA key skipped: ", item)
115
+
116
+ if self.clip_with_lora is not None and len(lora_clip) > 0:
117
+ loaded_keys = self.clip_with_lora.add_patches(lora_clip, weight)
118
+ print(f'Loaded LoRA [{lora_filename}] for CLIP [{self.filename}] '
119
+ f'with {len(loaded_keys)} keys at weight {weight}.')
120
+ for item in lora_clip:
121
+ if item not in loaded_keys:
122
+ print("CLIP LoRA key skipped: ", item)
123
+
124
+
125
+ @torch.no_grad()
126
+ @torch.inference_mode()
127
+ def apply_freeu(model, b1, b2, s1, s2):
128
+ return opFreeU.patch(model=model, b1=b1, b2=b2, s1=s1, s2=s2)[0]
129
+
130
+
131
+ @torch.no_grad()
132
+ @torch.inference_mode()
133
+ def load_controlnet(ckpt_filename):
134
+ return ldm_patched.modules.controlnet.load_controlnet(ckpt_filename)
135
+
136
+
137
+ @torch.no_grad()
138
+ @torch.inference_mode()
139
+ def apply_controlnet(positive, negative, control_net, image, strength, start_percent, end_percent):
140
+ return opControlNetApplyAdvanced.apply_controlnet(positive=positive, negative=negative, control_net=control_net,
141
+ image=image, strength=strength, start_percent=start_percent, end_percent=end_percent)
142
+
143
+
144
+ @torch.no_grad()
145
+ @torch.inference_mode()
146
+ def load_model(ckpt_filename, vae_filename=None):
147
+ unet, clip, vae, vae_filename, clip_vision = load_checkpoint_guess_config(ckpt_filename, embedding_directory=path_embeddings,
148
+ vae_filename_param=vae_filename)
149
+ return StableDiffusionModel(unet=unet, clip=clip, vae=vae, clip_vision=clip_vision, filename=ckpt_filename, vae_filename=vae_filename)
150
+
151
+
152
+ @torch.no_grad()
153
+ @torch.inference_mode()
154
+ def generate_empty_latent(width=1024, height=1024, batch_size=1):
155
+ return opEmptyLatentImage.generate(width=width, height=height, batch_size=batch_size)[0]
156
+
157
+
158
+ @torch.no_grad()
159
+ @torch.inference_mode()
160
+ def decode_vae(vae, latent_image, tiled=False):
161
+ if tiled:
162
+ return opVAEDecodeTiled.decode(samples=latent_image, vae=vae, tile_size=512)[0]
163
+ else:
164
+ return opVAEDecode.decode(samples=latent_image, vae=vae)[0]
165
+
166
+
167
+ @torch.no_grad()
168
+ @torch.inference_mode()
169
+ def encode_vae(vae, pixels, tiled=False):
170
+ if tiled:
171
+ return opVAEEncodeTiled.encode(pixels=pixels, vae=vae, tile_size=512)[0]
172
+ else:
173
+ return opVAEEncode.encode(pixels=pixels, vae=vae)[0]
174
+
175
+
176
+ @torch.no_grad()
177
+ @torch.inference_mode()
178
+ def encode_vae_inpaint(vae, pixels, mask):
179
+ assert mask.ndim == 3 and pixels.ndim == 4
180
+ assert mask.shape[-1] == pixels.shape[-2]
181
+ assert mask.shape[-2] == pixels.shape[-3]
182
+
183
+ w = mask.round()[..., None]
184
+ pixels = pixels * (1 - w) + 0.5 * w
185
+
186
+ latent = vae.encode(pixels)
187
+ B, C, H, W = latent.shape
188
+
189
+ latent_mask = mask[:, None, :, :]
190
+ latent_mask = torch.nn.functional.interpolate(latent_mask, size=(H * 8, W * 8), mode="bilinear").round()
191
+ latent_mask = torch.nn.functional.max_pool2d(latent_mask, (8, 8)).round().to(latent)
192
+
193
+ return latent, latent_mask
194
+
195
+
196
+ class VAEApprox(torch.nn.Module):
197
+ def __init__(self):
198
+ super(VAEApprox, self).__init__()
199
+ self.conv1 = torch.nn.Conv2d(4, 8, (7, 7))
200
+ self.conv2 = torch.nn.Conv2d(8, 16, (5, 5))
201
+ self.conv3 = torch.nn.Conv2d(16, 32, (3, 3))
202
+ self.conv4 = torch.nn.Conv2d(32, 64, (3, 3))
203
+ self.conv5 = torch.nn.Conv2d(64, 32, (3, 3))
204
+ self.conv6 = torch.nn.Conv2d(32, 16, (3, 3))
205
+ self.conv7 = torch.nn.Conv2d(16, 8, (3, 3))
206
+ self.conv8 = torch.nn.Conv2d(8, 3, (3, 3))
207
+ self.current_type = None
208
+
209
+ def forward(self, x):
210
+ extra = 11
211
+ x = torch.nn.functional.interpolate(x, (x.shape[2] * 2, x.shape[3] * 2))
212
+ x = torch.nn.functional.pad(x, (extra, extra, extra, extra))
213
+ for layer in [self.conv1, self.conv2, self.conv3, self.conv4, self.conv5, self.conv6, self.conv7, self.conv8]:
214
+ x = layer(x)
215
+ x = torch.nn.functional.leaky_relu(x, 0.1)
216
+ return x
217
+
218
+
219
+ VAE_approx_models = {}
220
+
221
+
222
+ @torch.no_grad()
223
+ @torch.inference_mode()
224
+ def get_previewer(model):
225
+ global VAE_approx_models
226
+
227
+ from modules.config import path_vae_approx
228
+ is_sdxl = isinstance(model.model.latent_format, ldm_patched.modules.latent_formats.SDXL)
229
+ vae_approx_filename = os.path.join(path_vae_approx, 'xlvaeapp.pth' if is_sdxl else 'vaeapp_sd15.pth')
230
+
231
+ if vae_approx_filename in VAE_approx_models:
232
+ VAE_approx_model = VAE_approx_models[vae_approx_filename]
233
+ else:
234
+ sd = torch.load(vae_approx_filename, map_location='cpu', weights_only=True)
235
+ VAE_approx_model = VAEApprox()
236
+ VAE_approx_model.load_state_dict(sd)
237
+ del sd
238
+ VAE_approx_model.eval()
239
+
240
+ if ldm_patched.modules.model_management.should_use_fp16():
241
+ VAE_approx_model.half()
242
+ VAE_approx_model.current_type = torch.float16
243
+ else:
244
+ VAE_approx_model.float()
245
+ VAE_approx_model.current_type = torch.float32
246
+
247
+ VAE_approx_model.to(ldm_patched.modules.model_management.get_torch_device())
248
+ VAE_approx_models[vae_approx_filename] = VAE_approx_model
249
+
250
+ @torch.no_grad()
251
+ @torch.inference_mode()
252
+ def preview_function(x0, step, total_steps):
253
+ with torch.no_grad():
254
+ x_sample = x0.to(VAE_approx_model.current_type)
255
+ x_sample = VAE_approx_model(x_sample) * 127.5 + 127.5
256
+ x_sample = einops.rearrange(x_sample, 'b c h w -> b h w c')[0]
257
+ x_sample = x_sample.cpu().numpy().clip(0, 255).astype(np.uint8)
258
+ return x_sample
259
+
260
+ return preview_function
261
+
262
+
263
+ @torch.no_grad()
264
+ @torch.inference_mode()
265
+ def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sampler_name='dpmpp_2m_sde_gpu',
266
+ scheduler='karras', denoise=1.0, disable_noise=False, start_step=None, last_step=None,
267
+ force_full_denoise=False, callback_function=None, refiner=None, refiner_switch=-1,
268
+ previewer_start=None, previewer_end=None, sigmas=None, noise_mean=None, disable_preview=False):
269
+
270
+ if sigmas is not None:
271
+ sigmas = sigmas.clone().to(ldm_patched.modules.model_management.get_torch_device())
272
+
273
+ latent_image = latent["samples"]
274
+
275
+ if disable_noise:
276
+ noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device="cpu")
277
+ else:
278
+ batch_inds = latent["batch_index"] if "batch_index" in latent else None
279
+ noise = ldm_patched.modules.sample.prepare_noise(latent_image, seed, batch_inds)
280
+
281
+ if isinstance(noise_mean, torch.Tensor):
282
+ noise = noise + noise_mean - torch.mean(noise, dim=1, keepdim=True)
283
+
284
+ noise_mask = None
285
+ if "noise_mask" in latent:
286
+ noise_mask = latent["noise_mask"]
287
+
288
+ previewer = get_previewer(model)
289
+
290
+ if previewer_start is None:
291
+ previewer_start = 0
292
+
293
+ if previewer_end is None:
294
+ previewer_end = steps
295
+
296
+ def callback(step, x0, x, total_steps):
297
+ ldm_patched.modules.model_management.throw_exception_if_processing_interrupted()
298
+ y = None
299
+ if previewer is not None and not disable_preview:
300
+ y = previewer(x0, previewer_start + step, previewer_end)
301
+ if callback_function is not None:
302
+ callback_function(previewer_start + step, x0, x, previewer_end, y)
303
+
304
+ disable_pbar = False
305
+ modules.sample_hijack.current_refiner = refiner
306
+ modules.sample_hijack.refiner_switch_step = refiner_switch
307
+ ldm_patched.modules.samplers.sample = modules.sample_hijack.sample_hacked
308
+
309
+ try:
310
+ samples = ldm_patched.modules.sample.sample(model,
311
+ noise, steps, cfg, sampler_name, scheduler,
312
+ positive, negative, latent_image,
313
+ denoise=denoise, disable_noise=disable_noise,
314
+ start_step=start_step,
315
+ last_step=last_step,
316
+ force_full_denoise=force_full_denoise, noise_mask=noise_mask,
317
+ callback=callback,
318
+ disable_pbar=disable_pbar, seed=seed, sigmas=sigmas)
319
+
320
+ out = latent.copy()
321
+ out["samples"] = samples
322
+ finally:
323
+ modules.sample_hijack.current_refiner = None
324
+
325
+ return out
326
+
327
+
328
+ @torch.no_grad()
329
+ @torch.inference_mode()
330
+ def pytorch_to_numpy(x):
331
+ return [np.clip(255. * y.cpu().numpy(), 0, 255).astype(np.uint8) for y in x]
332
+
333
+
334
+ @torch.no_grad()
335
+ @torch.inference_mode()
336
+ def numpy_to_pytorch(x):
337
+ y = x.astype(np.float32) / 255.0
338
+ y = y[None]
339
+ y = np.ascontiguousarray(y.copy())
340
+ y = torch.from_numpy(y).float()
341
+ return y
modules/default_pipeline.py ADDED
@@ -0,0 +1,515 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import modules.core as core
2
+ import os
3
+ import torch
4
+ import modules.patch
5
+ import modules.config
6
+ import modules.flags
7
+ import ldm_patched.modules.model_management
8
+ import ldm_patched.modules.latent_formats
9
+ import modules.inpaint_worker
10
+ import extras.vae_interpose as vae_interpose
11
+ from extras.expansion import FooocusExpansion
12
+
13
+ from ldm_patched.modules.model_base import SDXL, SDXLRefiner
14
+ from modules.sample_hijack import clip_separate
15
+ from modules.util import get_file_from_folder_list, get_enabled_loras
16
+
17
+
18
+ model_base = core.StableDiffusionModel()
19
+ model_refiner = core.StableDiffusionModel()
20
+
21
+ final_expansion = None
22
+ final_unet = None
23
+ final_clip = None
24
+ final_vae = None
25
+ final_refiner_unet = None
26
+ final_refiner_vae = None
27
+
28
+ loaded_ControlNets = {}
29
+
30
+
31
+ @torch.no_grad()
32
+ @torch.inference_mode()
33
+ def refresh_controlnets(model_paths):
34
+ global loaded_ControlNets
35
+ cache = {}
36
+ for p in model_paths:
37
+ if p is not None:
38
+ if p in loaded_ControlNets:
39
+ cache[p] = loaded_ControlNets[p]
40
+ else:
41
+ cache[p] = core.load_controlnet(p)
42
+ loaded_ControlNets = cache
43
+ return
44
+
45
+
46
+ @torch.no_grad()
47
+ @torch.inference_mode()
48
+ def assert_model_integrity():
49
+ error_message = None
50
+
51
+ if not isinstance(model_base.unet_with_lora.model, SDXL):
52
+ error_message = 'You have selected base model other than SDXL. This is not supported yet.'
53
+
54
+ if error_message is not None:
55
+ raise NotImplementedError(error_message)
56
+
57
+ return True
58
+
59
+
60
+ @torch.no_grad()
61
+ @torch.inference_mode()
62
+ def refresh_base_model(name, vae_name=None):
63
+ global model_base
64
+
65
+ filename = get_file_from_folder_list(name, modules.config.paths_checkpoints)
66
+
67
+ vae_filename = None
68
+ if vae_name is not None and vae_name != modules.flags.default_vae:
69
+ vae_filename = get_file_from_folder_list(vae_name, modules.config.path_vae)
70
+
71
+ if model_base.filename == filename and model_base.vae_filename == vae_filename:
72
+ return
73
+
74
+ model_base = core.load_model(filename, vae_filename)
75
+ print(f'Base model loaded: {model_base.filename}')
76
+ print(f'VAE loaded: {model_base.vae_filename}')
77
+ return
78
+
79
+
80
+ @torch.no_grad()
81
+ @torch.inference_mode()
82
+ def refresh_refiner_model(name):
83
+ global model_refiner
84
+
85
+ filename = get_file_from_folder_list(name, modules.config.paths_checkpoints)
86
+
87
+ if model_refiner.filename == filename:
88
+ return
89
+
90
+ model_refiner = core.StableDiffusionModel()
91
+
92
+ if name == 'None':
93
+ print(f'Refiner unloaded.')
94
+ return
95
+
96
+ model_refiner = core.load_model(filename)
97
+ print(f'Refiner model loaded: {model_refiner.filename}')
98
+
99
+ if isinstance(model_refiner.unet.model, SDXL):
100
+ model_refiner.clip = None
101
+ model_refiner.vae = None
102
+ elif isinstance(model_refiner.unet.model, SDXLRefiner):
103
+ model_refiner.clip = None
104
+ model_refiner.vae = None
105
+ else:
106
+ model_refiner.clip = None
107
+
108
+ return
109
+
110
+
111
+ @torch.no_grad()
112
+ @torch.inference_mode()
113
+ def synthesize_refiner_model():
114
+ global model_base, model_refiner
115
+
116
+ print('Synthetic Refiner Activated')
117
+ model_refiner = core.StableDiffusionModel(
118
+ unet=model_base.unet,
119
+ vae=model_base.vae,
120
+ clip=model_base.clip,
121
+ clip_vision=model_base.clip_vision,
122
+ filename=model_base.filename
123
+ )
124
+ model_refiner.vae = None
125
+ model_refiner.clip = None
126
+ model_refiner.clip_vision = None
127
+
128
+ return
129
+
130
+
131
+ @torch.no_grad()
132
+ @torch.inference_mode()
133
+ def refresh_loras(loras, base_model_additional_loras=None):
134
+ global model_base, model_refiner
135
+
136
+ if not isinstance(base_model_additional_loras, list):
137
+ base_model_additional_loras = []
138
+
139
+ model_base.refresh_loras(loras + base_model_additional_loras)
140
+ model_refiner.refresh_loras(loras)
141
+
142
+ return
143
+
144
+
145
+ @torch.no_grad()
146
+ @torch.inference_mode()
147
+ def clip_encode_single(clip, text, verbose=False):
148
+ cached = clip.fcs_cond_cache.get(text, None)
149
+ if cached is not None:
150
+ if verbose:
151
+ print(f'[CLIP Cached] {text}')
152
+ return cached
153
+ tokens = clip.tokenize(text)
154
+ result = clip.encode_from_tokens(tokens, return_pooled=True)
155
+ clip.fcs_cond_cache[text] = result
156
+ if verbose:
157
+ print(f'[CLIP Encoded] {text}')
158
+ return result
159
+
160
+
161
+ @torch.no_grad()
162
+ @torch.inference_mode()
163
+ def clone_cond(conds):
164
+ results = []
165
+
166
+ for c, p in conds:
167
+ p = p["pooled_output"]
168
+
169
+ if isinstance(c, torch.Tensor):
170
+ c = c.clone()
171
+
172
+ if isinstance(p, torch.Tensor):
173
+ p = p.clone()
174
+
175
+ results.append([c, {"pooled_output": p}])
176
+
177
+ return results
178
+
179
+
180
+ @torch.no_grad()
181
+ @torch.inference_mode()
182
+ def clip_encode(texts, pool_top_k=1):
183
+ global final_clip
184
+
185
+ if final_clip is None:
186
+ return None
187
+ if not isinstance(texts, list):
188
+ return None
189
+ if len(texts) == 0:
190
+ return None
191
+
192
+ cond_list = []
193
+ pooled_acc = 0
194
+
195
+ for i, text in enumerate(texts):
196
+ cond, pooled = clip_encode_single(final_clip, text)
197
+ cond_list.append(cond)
198
+ if i < pool_top_k:
199
+ pooled_acc += pooled
200
+
201
+ return [[torch.cat(cond_list, dim=1), {"pooled_output": pooled_acc}]]
202
+
203
+
204
+ @torch.no_grad()
205
+ @torch.inference_mode()
206
+ def set_clip_skip(clip_skip: int):
207
+ global final_clip
208
+
209
+ if final_clip is None:
210
+ return
211
+
212
+ final_clip.clip_layer(-abs(clip_skip))
213
+ return
214
+
215
+ @torch.no_grad()
216
+ @torch.inference_mode()
217
+ def clear_all_caches():
218
+ final_clip.fcs_cond_cache = {}
219
+
220
+
221
+ @torch.no_grad()
222
+ @torch.inference_mode()
223
+ def prepare_text_encoder(async_call=True):
224
+ if async_call:
225
+ # TODO: make sure that this is always called in an async way so that users cannot feel it.
226
+ pass
227
+ assert_model_integrity()
228
+ ldm_patched.modules.model_management.load_models_gpu([final_clip.patcher, final_expansion.patcher])
229
+ return
230
+
231
+
232
+ @torch.no_grad()
233
+ @torch.inference_mode()
234
+ def refresh_everything(refiner_model_name, base_model_name, loras,
235
+ base_model_additional_loras=None, use_synthetic_refiner=False, vae_name=None):
236
+ global final_unet, final_clip, final_vae, final_refiner_unet, final_refiner_vae, final_expansion
237
+
238
+ final_unet = None
239
+ final_clip = None
240
+ final_vae = None
241
+ final_refiner_unet = None
242
+ final_refiner_vae = None
243
+
244
+ if use_synthetic_refiner and refiner_model_name == 'None':
245
+ print('Synthetic Refiner Activated')
246
+ refresh_base_model(base_model_name, vae_name)
247
+ synthesize_refiner_model()
248
+ else:
249
+ refresh_refiner_model(refiner_model_name)
250
+ refresh_base_model(base_model_name, vae_name)
251
+
252
+ refresh_loras(loras, base_model_additional_loras=base_model_additional_loras)
253
+ assert_model_integrity()
254
+
255
+ final_unet = model_base.unet_with_lora
256
+ final_clip = model_base.clip_with_lora
257
+ final_vae = model_base.vae
258
+
259
+ final_refiner_unet = model_refiner.unet_with_lora
260
+ final_refiner_vae = model_refiner.vae
261
+
262
+ if final_expansion is None:
263
+ final_expansion = FooocusExpansion()
264
+
265
+ prepare_text_encoder(async_call=True)
266
+ clear_all_caches()
267
+ return
268
+
269
+
270
+ refresh_everything(
271
+ refiner_model_name=modules.config.default_refiner_model_name,
272
+ base_model_name=modules.config.default_base_model_name,
273
+ loras=get_enabled_loras(modules.config.default_loras),
274
+ vae_name=modules.config.default_vae,
275
+ )
276
+
277
+
278
+ @torch.no_grad()
279
+ @torch.inference_mode()
280
+ def vae_parse(latent):
281
+ if final_refiner_vae is None:
282
+ return latent
283
+
284
+ result = vae_interpose.parse(latent["samples"])
285
+ return {'samples': result}
286
+
287
+
288
+ @torch.no_grad()
289
+ @torch.inference_mode()
290
+ def calculate_sigmas_all(sampler, model, scheduler, steps):
291
+ from ldm_patched.modules.samplers import calculate_sigmas_scheduler
292
+
293
+ discard_penultimate_sigma = False
294
+ if sampler in ['dpm_2', 'dpm_2_ancestral']:
295
+ steps += 1
296
+ discard_penultimate_sigma = True
297
+
298
+ sigmas = calculate_sigmas_scheduler(model, scheduler, steps)
299
+
300
+ if discard_penultimate_sigma:
301
+ sigmas = torch.cat([sigmas[:-2], sigmas[-1:]])
302
+ return sigmas
303
+
304
+
305
+ @torch.no_grad()
306
+ @torch.inference_mode()
307
+ def calculate_sigmas(sampler, model, scheduler, steps, denoise):
308
+ if denoise is None or denoise > 0.9999:
309
+ sigmas = calculate_sigmas_all(sampler, model, scheduler, steps)
310
+ else:
311
+ new_steps = int(steps / denoise)
312
+ sigmas = calculate_sigmas_all(sampler, model, scheduler, new_steps)
313
+ sigmas = sigmas[-(steps + 1):]
314
+ return sigmas
315
+
316
+
317
+ @torch.no_grad()
318
+ @torch.inference_mode()
319
+ def get_candidate_vae(steps, switch, denoise=1.0, refiner_swap_method='joint'):
320
+ assert refiner_swap_method in ['joint', 'separate', 'vae']
321
+
322
+ if final_refiner_vae is not None and final_refiner_unet is not None:
323
+ if denoise > 0.9:
324
+ return final_vae, final_refiner_vae
325
+ else:
326
+ if denoise > (float(steps - switch) / float(steps)) ** 0.834: # karras 0.834
327
+ return final_vae, None
328
+ else:
329
+ return final_refiner_vae, None
330
+
331
+ return final_vae, final_refiner_vae
332
+
333
+
334
+ @torch.no_grad()
335
+ @torch.inference_mode()
336
+ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height, image_seed, callback, sampler_name, scheduler_name, latent=None, denoise=1.0, tiled=False, cfg_scale=7.0, refiner_swap_method='joint', disable_preview=False):
337
+ target_unet, target_vae, target_refiner_unet, target_refiner_vae, target_clip \
338
+ = final_unet, final_vae, final_refiner_unet, final_refiner_vae, final_clip
339
+
340
+ assert refiner_swap_method in ['joint', 'separate', 'vae']
341
+
342
+ if final_refiner_vae is not None and final_refiner_unet is not None:
343
+ # Refiner Use Different VAE (then it is SD15)
344
+ if denoise > 0.9:
345
+ refiner_swap_method = 'vae'
346
+ else:
347
+ refiner_swap_method = 'joint'
348
+ if denoise > (float(steps - switch) / float(steps)) ** 0.834: # karras 0.834
349
+ target_unet, target_vae, target_refiner_unet, target_refiner_vae \
350
+ = final_unet, final_vae, None, None
351
+ print(f'[Sampler] only use Base because of partial denoise.')
352
+ else:
353
+ positive_cond = clip_separate(positive_cond, target_model=final_refiner_unet.model, target_clip=final_clip)
354
+ negative_cond = clip_separate(negative_cond, target_model=final_refiner_unet.model, target_clip=final_clip)
355
+ target_unet, target_vae, target_refiner_unet, target_refiner_vae \
356
+ = final_refiner_unet, final_refiner_vae, None, None
357
+ print(f'[Sampler] only use Refiner because of partial denoise.')
358
+
359
+ print(f'[Sampler] refiner_swap_method = {refiner_swap_method}')
360
+
361
+ if latent is None:
362
+ initial_latent = core.generate_empty_latent(width=width, height=height, batch_size=1)
363
+ else:
364
+ initial_latent = latent
365
+
366
+ minmax_sigmas = calculate_sigmas(sampler=sampler_name, scheduler=scheduler_name, model=final_unet.model, steps=steps, denoise=denoise)
367
+ sigma_min, sigma_max = minmax_sigmas[minmax_sigmas > 0].min(), minmax_sigmas.max()
368
+ sigma_min = float(sigma_min.cpu().numpy())
369
+ sigma_max = float(sigma_max.cpu().numpy())
370
+ print(f'[Sampler] sigma_min = {sigma_min}, sigma_max = {sigma_max}')
371
+
372
+ modules.patch.BrownianTreeNoiseSamplerPatched.global_init(
373
+ initial_latent['samples'].to(ldm_patched.modules.model_management.get_torch_device()),
374
+ sigma_min, sigma_max, seed=image_seed, cpu=False)
375
+
376
+ decoded_latent = None
377
+
378
+ if refiner_swap_method == 'joint':
379
+ sampled_latent = core.ksampler(
380
+ model=target_unet,
381
+ refiner=target_refiner_unet,
382
+ positive=positive_cond,
383
+ negative=negative_cond,
384
+ latent=initial_latent,
385
+ steps=steps, start_step=0, last_step=steps, disable_noise=False, force_full_denoise=True,
386
+ seed=image_seed,
387
+ denoise=denoise,
388
+ callback_function=callback,
389
+ cfg=cfg_scale,
390
+ sampler_name=sampler_name,
391
+ scheduler=scheduler_name,
392
+ refiner_switch=switch,
393
+ previewer_start=0,
394
+ previewer_end=steps,
395
+ disable_preview=disable_preview
396
+ )
397
+ decoded_latent = core.decode_vae(vae=target_vae, latent_image=sampled_latent, tiled=tiled)
398
+
399
+ if refiner_swap_method == 'separate':
400
+ sampled_latent = core.ksampler(
401
+ model=target_unet,
402
+ positive=positive_cond,
403
+ negative=negative_cond,
404
+ latent=initial_latent,
405
+ steps=steps, start_step=0, last_step=switch, disable_noise=False, force_full_denoise=False,
406
+ seed=image_seed,
407
+ denoise=denoise,
408
+ callback_function=callback,
409
+ cfg=cfg_scale,
410
+ sampler_name=sampler_name,
411
+ scheduler=scheduler_name,
412
+ previewer_start=0,
413
+ previewer_end=steps,
414
+ disable_preview=disable_preview
415
+ )
416
+ print('Refiner swapped by changing ksampler. Noise preserved.')
417
+
418
+ target_model = target_refiner_unet
419
+ if target_model is None:
420
+ target_model = target_unet
421
+ print('Use base model to refine itself - this may because of developer mode.')
422
+
423
+ sampled_latent = core.ksampler(
424
+ model=target_model,
425
+ positive=clip_separate(positive_cond, target_model=target_model.model, target_clip=target_clip),
426
+ negative=clip_separate(negative_cond, target_model=target_model.model, target_clip=target_clip),
427
+ latent=sampled_latent,
428
+ steps=steps, start_step=switch, last_step=steps, disable_noise=True, force_full_denoise=True,
429
+ seed=image_seed,
430
+ denoise=denoise,
431
+ callback_function=callback,
432
+ cfg=cfg_scale,
433
+ sampler_name=sampler_name,
434
+ scheduler=scheduler_name,
435
+ previewer_start=switch,
436
+ previewer_end=steps,
437
+ disable_preview=disable_preview
438
+ )
439
+
440
+ target_model = target_refiner_vae
441
+ if target_model is None:
442
+ target_model = target_vae
443
+ decoded_latent = core.decode_vae(vae=target_model, latent_image=sampled_latent, tiled=tiled)
444
+
445
+ if refiner_swap_method == 'vae':
446
+ modules.patch.patch_settings[os.getpid()].eps_record = 'vae'
447
+
448
+ if modules.inpaint_worker.current_task is not None:
449
+ modules.inpaint_worker.current_task.unswap()
450
+
451
+ sampled_latent = core.ksampler(
452
+ model=target_unet,
453
+ positive=positive_cond,
454
+ negative=negative_cond,
455
+ latent=initial_latent,
456
+ steps=steps, start_step=0, last_step=switch, disable_noise=False, force_full_denoise=True,
457
+ seed=image_seed,
458
+ denoise=denoise,
459
+ callback_function=callback,
460
+ cfg=cfg_scale,
461
+ sampler_name=sampler_name,
462
+ scheduler=scheduler_name,
463
+ previewer_start=0,
464
+ previewer_end=steps,
465
+ disable_preview=disable_preview
466
+ )
467
+ print('Fooocus VAE-based swap.')
468
+
469
+ target_model = target_refiner_unet
470
+ if target_model is None:
471
+ target_model = target_unet
472
+ print('Use base model to refine itself - this may because of developer mode.')
473
+
474
+ sampled_latent = vae_parse(sampled_latent)
475
+
476
+ k_sigmas = 1.4
477
+ sigmas = calculate_sigmas(sampler=sampler_name,
478
+ scheduler=scheduler_name,
479
+ model=target_model.model,
480
+ steps=steps,
481
+ denoise=denoise)[switch:] * k_sigmas
482
+ len_sigmas = len(sigmas) - 1
483
+
484
+ noise_mean = torch.mean(modules.patch.patch_settings[os.getpid()].eps_record, dim=1, keepdim=True)
485
+
486
+ if modules.inpaint_worker.current_task is not None:
487
+ modules.inpaint_worker.current_task.swap()
488
+
489
+ sampled_latent = core.ksampler(
490
+ model=target_model,
491
+ positive=clip_separate(positive_cond, target_model=target_model.model, target_clip=target_clip),
492
+ negative=clip_separate(negative_cond, target_model=target_model.model, target_clip=target_clip),
493
+ latent=sampled_latent,
494
+ steps=len_sigmas, start_step=0, last_step=len_sigmas, disable_noise=False, force_full_denoise=True,
495
+ seed=image_seed+1,
496
+ denoise=denoise,
497
+ callback_function=callback,
498
+ cfg=cfg_scale,
499
+ sampler_name=sampler_name,
500
+ scheduler=scheduler_name,
501
+ previewer_start=switch,
502
+ previewer_end=steps,
503
+ sigmas=sigmas,
504
+ noise_mean=noise_mean,
505
+ disable_preview=disable_preview
506
+ )
507
+
508
+ target_model = target_refiner_vae
509
+ if target_model is None:
510
+ target_model = target_vae
511
+ decoded_latent = core.decode_vae(vae=target_model, latent_image=sampled_latent, tiled=tiled)
512
+
513
+ images = core.pytorch_to_numpy(decoded_latent)
514
+ modules.patch.patch_settings[os.getpid()].eps_record = None
515
+ return images
modules/extra_utils.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from ast import literal_eval
3
+
4
+
5
+ def makedirs_with_log(path):
6
+ try:
7
+ os.makedirs(path, exist_ok=True)
8
+ except OSError as error:
9
+ print(f'Directory {path} could not be created, reason: {error}')
10
+
11
+
12
+ def get_files_from_folder(folder_path, extensions=None, name_filter=None):
13
+ if not os.path.isdir(folder_path):
14
+ raise ValueError("Folder path is not a valid directory.")
15
+
16
+ filenames = []
17
+
18
+ for root, _, files in os.walk(folder_path, topdown=False):
19
+ relative_path = os.path.relpath(root, folder_path)
20
+ if relative_path == ".":
21
+ relative_path = ""
22
+ for filename in sorted(files, key=lambda s: s.casefold()):
23
+ _, file_extension = os.path.splitext(filename)
24
+ if (extensions is None or file_extension.lower() in extensions) and (name_filter is None or name_filter in _):
25
+ path = os.path.join(relative_path, filename)
26
+ filenames.append(path)
27
+
28
+ return filenames
29
+
30
+
31
+ def try_eval_env_var(value: str, expected_type=None):
32
+ try:
33
+ value_eval = value
34
+ if expected_type is bool:
35
+ value_eval = value.title()
36
+ value_eval = literal_eval(value_eval)
37
+ if expected_type is not None and not isinstance(value_eval, expected_type):
38
+ return value
39
+ return value_eval
40
+ except:
41
+ return value
modules/flags.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import IntEnum, Enum
2
+
3
+ disabled = 'Disabled'
4
+ enabled = 'Enabled'
5
+ subtle_variation = 'Vary (Subtle)'
6
+ strong_variation = 'Vary (Strong)'
7
+ upscale_15 = 'Upscale (1.5x)'
8
+ upscale_2 = 'Upscale (2x)'
9
+ upscale_fast = 'Upscale (Fast 2x)'
10
+
11
+ uov_list = [disabled, subtle_variation, strong_variation, upscale_15, upscale_2, upscale_fast]
12
+
13
+ enhancement_uov_before = "Before First Enhancement"
14
+ enhancement_uov_after = "After Last Enhancement"
15
+ enhancement_uov_processing_order = [enhancement_uov_before, enhancement_uov_after]
16
+
17
+ enhancement_uov_prompt_type_original = 'Original Prompts'
18
+ enhancement_uov_prompt_type_last_filled = 'Last Filled Enhancement Prompts'
19
+ enhancement_uov_prompt_types = [enhancement_uov_prompt_type_original, enhancement_uov_prompt_type_last_filled]
20
+
21
+ CIVITAI_NO_KARRAS = ["euler", "euler_ancestral", "heun", "dpm_fast", "dpm_adaptive", "ddim", "uni_pc"]
22
+
23
+ # fooocus: a1111 (Civitai)
24
+ KSAMPLER = {
25
+ "euler": "Euler",
26
+ "euler_ancestral": "Euler a",
27
+ "heun": "Heun",
28
+ "heunpp2": "",
29
+ "dpm_2": "DPM2",
30
+ "dpm_2_ancestral": "DPM2 a",
31
+ "lms": "LMS",
32
+ "dpm_fast": "DPM fast",
33
+ "dpm_adaptive": "DPM adaptive",
34
+ "dpmpp_2s_ancestral": "DPM++ 2S a",
35
+ "dpmpp_sde": "DPM++ SDE",
36
+ "dpmpp_sde_gpu": "DPM++ SDE",
37
+ "dpmpp_2m": "DPM++ 2M",
38
+ "dpmpp_2m_sde": "DPM++ 2M SDE",
39
+ "dpmpp_2m_sde_gpu": "DPM++ 2M SDE",
40
+ "dpmpp_3m_sde": "",
41
+ "dpmpp_3m_sde_gpu": "",
42
+ "ddpm": "",
43
+ "lcm": "LCM",
44
+ "tcd": "TCD",
45
+ "restart": "Restart"
46
+ }
47
+
48
+ SAMPLER_EXTRA = {
49
+ "ddim": "DDIM",
50
+ "uni_pc": "UniPC",
51
+ "uni_pc_bh2": ""
52
+ }
53
+
54
+ SAMPLERS = KSAMPLER | SAMPLER_EXTRA
55
+
56
+ KSAMPLER_NAMES = list(KSAMPLER.keys())
57
+
58
+ SCHEDULER_NAMES = ["normal", "karras", "exponential", "sgm_uniform", "simple", "ddim_uniform", "lcm", "turbo", "align_your_steps", "tcd", "edm_playground_v2.5"]
59
+ SAMPLER_NAMES = KSAMPLER_NAMES + list(SAMPLER_EXTRA.keys())
60
+
61
+ sampler_list = SAMPLER_NAMES
62
+ scheduler_list = SCHEDULER_NAMES
63
+
64
+ clip_skip_max = 12
65
+
66
+ default_vae = 'Default (model)'
67
+
68
+ refiner_swap_method = 'joint'
69
+
70
+ default_input_image_tab = 'uov_tab'
71
+ input_image_tab_ids = ['uov_tab', 'ip_tab', 'inpaint_tab', 'describe_tab', 'enhance_tab', 'metadata_tab']
72
+
73
+ cn_ip = "ImagePrompt"
74
+ cn_ip_face = "FaceSwap"
75
+ cn_canny = "PyraCanny"
76
+ cn_cpds = "CPDS"
77
+
78
+ ip_list = [cn_ip, cn_canny, cn_cpds, cn_ip_face]
79
+ default_ip = cn_ip
80
+
81
+ default_parameters = {
82
+ cn_ip: (0.5, 0.6), cn_ip_face: (0.9, 0.75), cn_canny: (0.5, 1.0), cn_cpds: (0.5, 1.0)
83
+ } # stop, weight
84
+
85
+ output_formats = ['png', 'jpeg', 'webp']
86
+
87
+ inpaint_mask_models = ['u2net', 'u2netp', 'u2net_human_seg', 'u2net_cloth_seg', 'silueta', 'isnet-general-use', 'isnet-anime', 'sam']
88
+ inpaint_mask_cloth_category = ['full', 'upper', 'lower']
89
+ inpaint_mask_sam_model = ['vit_b', 'vit_l', 'vit_h']
90
+
91
+ inpaint_engine_versions = ['None', 'v1', 'v2.5', 'v2.6']
92
+ inpaint_option_default = 'Inpaint or Outpaint (default)'
93
+ inpaint_option_detail = 'Improve Detail (face, hand, eyes, etc.)'
94
+ inpaint_option_modify = 'Modify Content (add objects, change background, etc.)'
95
+ inpaint_options = [inpaint_option_default, inpaint_option_detail, inpaint_option_modify]
96
+
97
+ describe_type_photo = 'Photograph'
98
+ describe_type_anime = 'Art/Anime'
99
+ describe_types = [describe_type_photo, describe_type_anime]
100
+
101
+ sdxl_aspect_ratios = [
102
+ '704*1408', '704*1344', '768*1344', '768*1280', '832*1216', '832*1152',
103
+ '896*1152', '896*1088', '960*1088', '960*1024', '1024*1024', '1024*960',
104
+ '1088*960', '1088*896', '1152*896', '1152*832', '1216*832', '1280*768',
105
+ '1344*768', '1344*704', '1408*704', '1472*704', '1536*640', '1600*640',
106
+ '1664*576', '1728*576'
107
+ ]
108
+
109
+
110
+ class MetadataScheme(Enum):
111
+ FOOOCUS = 'fooocus'
112
+ A1111 = 'a1111'
113
+
114
+
115
+ metadata_scheme = [
116
+ (f'{MetadataScheme.FOOOCUS.value} (json)', MetadataScheme.FOOOCUS.value),
117
+ (f'{MetadataScheme.A1111.value} (plain text)', MetadataScheme.A1111.value),
118
+ ]
119
+
120
+
121
+ class OutputFormat(Enum):
122
+ PNG = 'png'
123
+ JPEG = 'jpeg'
124
+ WEBP = 'webp'
125
+
126
+ @classmethod
127
+ def list(cls) -> list:
128
+ return list(map(lambda c: c.value, cls))
129
+
130
+
131
+ class PerformanceLoRA(Enum):
132
+ QUALITY = None
133
+ SPEED = None
134
+ EXTREME_SPEED = 'sdxl_lcm_lora.safetensors'
135
+ LIGHTNING = 'sdxl_lightning_4step_lora.safetensors'
136
+ HYPER_SD = 'sdxl_hyper_sd_4step_lora.safetensors'
137
+
138
+
139
+ class Steps(IntEnum):
140
+ QUALITY = 60
141
+ SPEED = 30
142
+ EXTREME_SPEED = 8
143
+ LIGHTNING = 4
144
+ HYPER_SD = 4
145
+
146
+ @classmethod
147
+ def keys(cls) -> list:
148
+ return list(map(lambda c: c, Steps.__members__))
149
+
150
+
151
+ class StepsUOV(IntEnum):
152
+ QUALITY = 36
153
+ SPEED = 18
154
+ EXTREME_SPEED = 8
155
+ LIGHTNING = 4
156
+ HYPER_SD = 4
157
+
158
+
159
+ class Performance(Enum):
160
+ QUALITY = 'Quality'
161
+ SPEED = 'Speed'
162
+ EXTREME_SPEED = 'Extreme Speed'
163
+ LIGHTNING = 'Lightning'
164
+ HYPER_SD = 'Hyper-SD'
165
+
166
+ @classmethod
167
+ def list(cls) -> list:
168
+ return list(map(lambda c: (c.name, c.value), cls))
169
+
170
+ @classmethod
171
+ def values(cls) -> list:
172
+ return list(map(lambda c: c.value, cls))
173
+
174
+ @classmethod
175
+ def by_steps(cls, steps: int | str):
176
+ return cls[Steps(int(steps)).name]
177
+
178
+ @classmethod
179
+ def has_restricted_features(cls, x) -> bool:
180
+ if isinstance(x, Performance):
181
+ x = x.value
182
+ return x in [cls.EXTREME_SPEED.value, cls.LIGHTNING.value, cls.HYPER_SD.value]
183
+
184
+ def steps(self) -> int | None:
185
+ return Steps[self.name].value if self.name in Steps.__members__ else None
186
+
187
+ def steps_uov(self) -> int | None:
188
+ return StepsUOV[self.name].value if self.name in StepsUOV.__members__ else None
189
+
190
+ def lora_filename(self) -> str | None:
191
+ return PerformanceLoRA[self.name].value if self.name in PerformanceLoRA.__members__ else None