mirror of
https://github.com/lllyasviel/Fooocus.git
synced 2026-08-16 13:13:16 +02:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab76a26806 | ||
|
|
af33e930d3 | ||
|
|
4a3aac09a3 | ||
|
|
15696da9b8 | ||
|
|
8e6299b898 | ||
|
|
c36e951781 | ||
|
|
d16a54edd6 | ||
|
|
e2f9bcb11d | ||
|
|
523ef5c70e | ||
|
|
9aaa400553 | ||
|
|
7564dd5131 | ||
|
|
978267f461 | ||
|
|
e9bc5e50c6 | ||
|
|
856eb750ab | ||
|
|
6b41af7140 | ||
|
|
532a6e2e67 | ||
|
|
a1bda88aa3 | ||
|
|
3efce581ca | ||
|
|
ee361715af | ||
|
|
c08518abae | ||
|
|
6b44c101db | ||
|
|
5bf96018fe | ||
|
|
d057f2fae9 | ||
|
|
86cba3f223 |
+1
-1
@@ -1 +1 @@
|
|||||||
version = '2.2.1'
|
version = '2.3.1'
|
||||||
|
|||||||
+4
-1
@@ -339,6 +339,8 @@
|
|||||||
"sgm_uniform": "sgm_uniform",
|
"sgm_uniform": "sgm_uniform",
|
||||||
"simple": "simple",
|
"simple": "simple",
|
||||||
"ddim_uniform": "ddim_uniform",
|
"ddim_uniform": "ddim_uniform",
|
||||||
|
"VAE": "VAE",
|
||||||
|
"Default (model)": "Default (model)",
|
||||||
"Forced Overwrite of Sampling Step": "Forced Overwrite of Sampling Step",
|
"Forced Overwrite of Sampling Step": "Forced Overwrite of Sampling Step",
|
||||||
"Set as -1 to disable. For developer debugging.": "Set as -1 to disable. For developer debugging.",
|
"Set as -1 to disable. For developer debugging.": "Set as -1 to disable. For developer debugging.",
|
||||||
"Forced Overwrite of Refiner Switch Step": "Forced Overwrite of Refiner Switch Step",
|
"Forced Overwrite of Refiner Switch Step": "Forced Overwrite of Refiner Switch Step",
|
||||||
@@ -384,5 +386,6 @@
|
|||||||
"Metadata Scheme": "Metadata Scheme",
|
"Metadata Scheme": "Metadata Scheme",
|
||||||
"Image Prompt parameters are not included. Use png and a1111 for compatibility with Civitai.": "Image Prompt parameters are not included. Use png and a1111 for compatibility with Civitai.",
|
"Image Prompt parameters are not included. Use png and a1111 for compatibility with Civitai.": "Image Prompt parameters are not included. Use png and a1111 for compatibility with Civitai.",
|
||||||
"fooocus (json)": "fooocus (json)",
|
"fooocus (json)": "fooocus (json)",
|
||||||
"a1111 (plain text)": "a1111 (plain text)"
|
"a1111 (plain text)": "a1111 (plain text)",
|
||||||
|
"Unsupported image type in input": "Unsupported image type in input"
|
||||||
}
|
}
|
||||||
@@ -427,12 +427,13 @@ def load_checkpoint(config_path=None, ckpt_path=None, output_vae=True, output_cl
|
|||||||
|
|
||||||
return (ldm_patched.modules.model_patcher.ModelPatcher(model, load_device=model_management.get_torch_device(), offload_device=offload_device), clip, vae)
|
return (ldm_patched.modules.model_patcher.ModelPatcher(model, load_device=model_management.get_torch_device(), offload_device=offload_device), clip, vae)
|
||||||
|
|
||||||
def load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, output_clipvision=False, embedding_directory=None, output_model=True):
|
def load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, output_clipvision=False, embedding_directory=None, output_model=True, vae_filename_param=None):
|
||||||
sd = ldm_patched.modules.utils.load_torch_file(ckpt_path)
|
sd = ldm_patched.modules.utils.load_torch_file(ckpt_path)
|
||||||
sd_keys = sd.keys()
|
sd_keys = sd.keys()
|
||||||
clip = None
|
clip = None
|
||||||
clipvision = None
|
clipvision = None
|
||||||
vae = None
|
vae = None
|
||||||
|
vae_filename = None
|
||||||
model = None
|
model = None
|
||||||
model_patcher = None
|
model_patcher = None
|
||||||
clip_target = None
|
clip_target = None
|
||||||
@@ -462,8 +463,12 @@ def load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, o
|
|||||||
model.load_model_weights(sd, "model.diffusion_model.")
|
model.load_model_weights(sd, "model.diffusion_model.")
|
||||||
|
|
||||||
if output_vae:
|
if output_vae:
|
||||||
vae_sd = ldm_patched.modules.utils.state_dict_prefix_replace(sd, {"first_stage_model.": ""}, filter_keys=True)
|
if vae_filename_param is None:
|
||||||
vae_sd = model_config.process_vae_state_dict(vae_sd)
|
vae_sd = ldm_patched.modules.utils.state_dict_prefix_replace(sd, {"first_stage_model.": ""}, filter_keys=True)
|
||||||
|
vae_sd = model_config.process_vae_state_dict(vae_sd)
|
||||||
|
else:
|
||||||
|
vae_sd = ldm_patched.modules.utils.load_torch_file(vae_filename_param)
|
||||||
|
vae_filename = vae_filename_param
|
||||||
vae = VAE(sd=vae_sd)
|
vae = VAE(sd=vae_sd)
|
||||||
|
|
||||||
if output_clip:
|
if output_clip:
|
||||||
@@ -485,7 +490,7 @@ def load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, o
|
|||||||
print("loaded straight to GPU")
|
print("loaded straight to GPU")
|
||||||
model_management.load_model_gpu(model_patcher)
|
model_management.load_model_gpu(model_patcher)
|
||||||
|
|
||||||
return (model_patcher, clip, vae, clipvision)
|
return model_patcher, clip, vae, vae_filename, clipvision
|
||||||
|
|
||||||
|
|
||||||
def load_unet_state_dict(sd): #load unet in diffusers format
|
def load_unet_state_dict(sd): #load unet in diffusers format
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ def worker():
|
|||||||
adaptive_cfg = args.pop()
|
adaptive_cfg = args.pop()
|
||||||
sampler_name = args.pop()
|
sampler_name = args.pop()
|
||||||
scheduler_name = args.pop()
|
scheduler_name = args.pop()
|
||||||
|
vae_name = args.pop()
|
||||||
overwrite_step = args.pop()
|
overwrite_step = args.pop()
|
||||||
overwrite_switch = args.pop()
|
overwrite_switch = args.pop()
|
||||||
overwrite_width = args.pop()
|
overwrite_width = args.pop()
|
||||||
@@ -428,7 +429,7 @@ def worker():
|
|||||||
progressbar(async_task, 3, 'Loading models ...')
|
progressbar(async_task, 3, 'Loading models ...')
|
||||||
pipeline.refresh_everything(refiner_model_name=refiner_model_name, base_model_name=base_model_name,
|
pipeline.refresh_everything(refiner_model_name=refiner_model_name, base_model_name=base_model_name,
|
||||||
loras=loras, base_model_additional_loras=base_model_additional_loras,
|
loras=loras, base_model_additional_loras=base_model_additional_loras,
|
||||||
use_synthetic_refiner=use_synthetic_refiner)
|
use_synthetic_refiner=use_synthetic_refiner, vae_name=vae_name)
|
||||||
|
|
||||||
progressbar(async_task, 3, 'Processing prompts ...')
|
progressbar(async_task, 3, 'Processing prompts ...')
|
||||||
tasks = []
|
tasks = []
|
||||||
@@ -614,12 +615,12 @@ def worker():
|
|||||||
|
|
||||||
H, W, C = inpaint_image.shape
|
H, W, C = inpaint_image.shape
|
||||||
if 'left' in outpaint_selections:
|
if 'left' in outpaint_selections:
|
||||||
inpaint_image = np.pad(inpaint_image, [[0, 0], [int(H * 0.3), 0], [0, 0]], mode='edge')
|
inpaint_image = np.pad(inpaint_image, [[0, 0], [int(W * 0.3), 0], [0, 0]], mode='edge')
|
||||||
inpaint_mask = np.pad(inpaint_mask, [[0, 0], [int(H * 0.3), 0]], mode='constant',
|
inpaint_mask = np.pad(inpaint_mask, [[0, 0], [int(W * 0.3), 0]], mode='constant',
|
||||||
constant_values=255)
|
constant_values=255)
|
||||||
if 'right' in outpaint_selections:
|
if 'right' in outpaint_selections:
|
||||||
inpaint_image = np.pad(inpaint_image, [[0, 0], [0, int(H * 0.3)], [0, 0]], mode='edge')
|
inpaint_image = np.pad(inpaint_image, [[0, 0], [0, int(W * 0.3)], [0, 0]], mode='edge')
|
||||||
inpaint_mask = np.pad(inpaint_mask, [[0, 0], [0, int(H * 0.3)]], mode='constant',
|
inpaint_mask = np.pad(inpaint_mask, [[0, 0], [0, int(W * 0.3)]], mode='constant',
|
||||||
constant_values=255)
|
constant_values=255)
|
||||||
|
|
||||||
inpaint_image = np.ascontiguousarray(inpaint_image.copy())
|
inpaint_image = np.ascontiguousarray(inpaint_image.copy())
|
||||||
@@ -869,6 +870,7 @@ def worker():
|
|||||||
|
|
||||||
d.append(('Sampler', 'sampler', sampler_name))
|
d.append(('Sampler', 'sampler', sampler_name))
|
||||||
d.append(('Scheduler', 'scheduler', scheduler_name))
|
d.append(('Scheduler', 'scheduler', scheduler_name))
|
||||||
|
d.append(('VAE', 'vae', vae_name))
|
||||||
d.append(('Seed', 'seed', str(task['task_seed'])))
|
d.append(('Seed', 'seed', str(task['task_seed'])))
|
||||||
|
|
||||||
if freeu_enabled:
|
if freeu_enabled:
|
||||||
@@ -883,7 +885,7 @@ def worker():
|
|||||||
metadata_parser = modules.meta_parser.get_metadata_parser(metadata_scheme)
|
metadata_parser = modules.meta_parser.get_metadata_parser(metadata_scheme)
|
||||||
metadata_parser.set_data(task['log_positive_prompt'], task['positive'],
|
metadata_parser.set_data(task['log_positive_prompt'], task['positive'],
|
||||||
task['log_negative_prompt'], task['negative'],
|
task['log_negative_prompt'], task['negative'],
|
||||||
steps, base_model_name, refiner_model_name, loras)
|
steps, base_model_name, refiner_model_name, loras, vae_name)
|
||||||
d.append(('Metadata Scheme', 'metadata_scheme', metadata_scheme.value if save_metadata_to_images else save_metadata_to_images))
|
d.append(('Metadata Scheme', 'metadata_scheme', metadata_scheme.value if save_metadata_to_images else save_metadata_to_images))
|
||||||
d.append(('Version', 'version', 'Fooocus v' + fooocus_version.version))
|
d.append(('Version', 'version', 'Fooocus v' + fooocus_version.version))
|
||||||
img_paths.append(log(x, d, metadata_parser, output_format))
|
img_paths.append(log(x, d, metadata_parser, output_format))
|
||||||
|
|||||||
+21
-11
@@ -124,14 +124,6 @@ def try_get_preset_content(preset):
|
|||||||
print(e)
|
print(e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(os.path.abspath(f'./presets/default.json'), "r", encoding="utf-8") as json_file:
|
|
||||||
config_dict.update(json.load(json_file))
|
|
||||||
except Exception as e:
|
|
||||||
print(f'Load default preset failed.')
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
available_presets = get_presets()
|
available_presets = get_presets()
|
||||||
preset = args_manager.args.preset
|
preset = args_manager.args.preset
|
||||||
config_dict.update(try_get_preset_content(preset))
|
config_dict.update(try_get_preset_content(preset))
|
||||||
@@ -197,6 +189,7 @@ paths_checkpoints = get_dir_or_set_default('path_checkpoints', ['../models/check
|
|||||||
paths_loras = get_dir_or_set_default('path_loras', ['../models/loras/'], True)
|
paths_loras = get_dir_or_set_default('path_loras', ['../models/loras/'], True)
|
||||||
path_embeddings = get_dir_or_set_default('path_embeddings', '../models/embeddings/')
|
path_embeddings = get_dir_or_set_default('path_embeddings', '../models/embeddings/')
|
||||||
path_vae_approx = get_dir_or_set_default('path_vae_approx', '../models/vae_approx/')
|
path_vae_approx = get_dir_or_set_default('path_vae_approx', '../models/vae_approx/')
|
||||||
|
path_vae = get_dir_or_set_default('path_vae', '../models/vae/')
|
||||||
path_upscale_models = get_dir_or_set_default('path_upscale_models', '../models/upscale_models/')
|
path_upscale_models = get_dir_or_set_default('path_upscale_models', '../models/upscale_models/')
|
||||||
path_inpaint = get_dir_or_set_default('path_inpaint', '../models/inpaint/')
|
path_inpaint = get_dir_or_set_default('path_inpaint', '../models/inpaint/')
|
||||||
path_controlnet = get_dir_or_set_default('path_controlnet', '../models/controlnet/')
|
path_controlnet = get_dir_or_set_default('path_controlnet', '../models/controlnet/')
|
||||||
@@ -323,8 +316,12 @@ default_loras = get_config_item_or_set_default(
|
|||||||
1.0
|
1.0
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
validator=lambda x: isinstance(x, list) and all(len(y) == 3 and isinstance(y[0], bool) and isinstance(y[1], str) and isinstance(y[2], numbers.Number) for y in x)
|
validator=lambda x: isinstance(x, list) and all(
|
||||||
|
len(y) == 3 and isinstance(y[0], bool) and isinstance(y[1], str) and isinstance(y[2], numbers.Number)
|
||||||
|
or len(y) == 2 and isinstance(y[0], str) and isinstance(y[1], numbers.Number)
|
||||||
|
for y in x)
|
||||||
)
|
)
|
||||||
|
default_loras = [(y[0], y[1], y[2]) if len(y) == 3 else (True, y[0], y[1]) for y in default_loras]
|
||||||
default_max_lora_number = get_config_item_or_set_default(
|
default_max_lora_number = get_config_item_or_set_default(
|
||||||
key='default_max_lora_number',
|
key='default_max_lora_number',
|
||||||
default_value=len(default_loras) if isinstance(default_loras, list) and len(default_loras) > 0 else 5,
|
default_value=len(default_loras) if isinstance(default_loras, list) and len(default_loras) > 0 else 5,
|
||||||
@@ -350,6 +347,11 @@ default_scheduler = get_config_item_or_set_default(
|
|||||||
default_value='karras',
|
default_value='karras',
|
||||||
validator=lambda x: x in modules.flags.scheduler_list
|
validator=lambda x: x in modules.flags.scheduler_list
|
||||||
)
|
)
|
||||||
|
default_vae = get_config_item_or_set_default(
|
||||||
|
key='default_vae',
|
||||||
|
default_value=modules.flags.default_vae,
|
||||||
|
validator=lambda x: isinstance(x, str)
|
||||||
|
)
|
||||||
default_styles = get_config_item_or_set_default(
|
default_styles = get_config_item_or_set_default(
|
||||||
key='default_styles',
|
key='default_styles',
|
||||||
default_value=[
|
default_value=[
|
||||||
@@ -472,7 +474,7 @@ metadata_created_by = get_config_item_or_set_default(
|
|||||||
|
|
||||||
example_inpaint_prompts = [[x] for x in example_inpaint_prompts]
|
example_inpaint_prompts = [[x] for x in example_inpaint_prompts]
|
||||||
|
|
||||||
config_dict["default_loras"] = default_loras = default_loras[:default_max_lora_number] + [['None', 1.0] for _ in range(default_max_lora_number - len(default_loras))]
|
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))]
|
||||||
|
|
||||||
# mapping config to meta parameter
|
# mapping config to meta parameter
|
||||||
possible_preset_keys = {
|
possible_preset_keys = {
|
||||||
@@ -489,6 +491,7 @@ possible_preset_keys = {
|
|||||||
"default_scheduler": "scheduler",
|
"default_scheduler": "scheduler",
|
||||||
"default_overwrite_step": "steps",
|
"default_overwrite_step": "steps",
|
||||||
"default_performance": "performance",
|
"default_performance": "performance",
|
||||||
|
"default_image_number": "image_number",
|
||||||
"default_prompt": "prompt",
|
"default_prompt": "prompt",
|
||||||
"default_prompt_negative": "negative_prompt",
|
"default_prompt_negative": "negative_prompt",
|
||||||
"default_styles": "styles",
|
"default_styles": "styles",
|
||||||
@@ -538,25 +541,32 @@ with open(config_example_path, "w", encoding="utf-8") as json_file:
|
|||||||
|
|
||||||
model_filenames = []
|
model_filenames = []
|
||||||
lora_filenames = []
|
lora_filenames = []
|
||||||
|
vae_filenames = []
|
||||||
wildcard_filenames = []
|
wildcard_filenames = []
|
||||||
|
|
||||||
sdxl_lcm_lora = 'sdxl_lcm_lora.safetensors'
|
sdxl_lcm_lora = 'sdxl_lcm_lora.safetensors'
|
||||||
sdxl_lightning_lora = 'sdxl_lightning_4step_lora.safetensors'
|
sdxl_lightning_lora = 'sdxl_lightning_4step_lora.safetensors'
|
||||||
|
loras_metadata_remove = [sdxl_lcm_lora, sdxl_lightning_lora]
|
||||||
|
|
||||||
|
|
||||||
def get_model_filenames(folder_paths, extensions=None, name_filter=None):
|
def get_model_filenames(folder_paths, extensions=None, name_filter=None):
|
||||||
if extensions is None:
|
if extensions is None:
|
||||||
extensions = ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch']
|
extensions = ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch']
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
|
if not isinstance(folder_paths, list):
|
||||||
|
folder_paths = [folder_paths]
|
||||||
for folder in folder_paths:
|
for folder in folder_paths:
|
||||||
files += get_files_from_folder(folder, extensions, name_filter)
|
files += get_files_from_folder(folder, extensions, name_filter)
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
|
||||||
def update_files():
|
def update_files():
|
||||||
global model_filenames, lora_filenames, wildcard_filenames, available_presets
|
global model_filenames, lora_filenames, vae_filenames, wildcard_filenames, available_presets
|
||||||
model_filenames = get_model_filenames(paths_checkpoints)
|
model_filenames = get_model_filenames(paths_checkpoints)
|
||||||
lora_filenames = get_model_filenames(paths_loras)
|
lora_filenames = get_model_filenames(paths_loras)
|
||||||
|
vae_filenames = get_model_filenames(path_vae)
|
||||||
wildcard_filenames = get_files_from_folder(path_wildcards, ['.txt'])
|
wildcard_filenames = get_files_from_folder(path_wildcards, ['.txt'])
|
||||||
available_presets = get_presets()
|
available_presets = get_presets()
|
||||||
return
|
return
|
||||||
|
|||||||
+6
-4
@@ -35,12 +35,13 @@ opModelSamplingDiscrete = ModelSamplingDiscrete()
|
|||||||
|
|
||||||
|
|
||||||
class StableDiffusionModel:
|
class StableDiffusionModel:
|
||||||
def __init__(self, unet=None, vae=None, clip=None, clip_vision=None, filename=None):
|
def __init__(self, unet=None, vae=None, clip=None, clip_vision=None, filename=None, vae_filename=None):
|
||||||
self.unet = unet
|
self.unet = unet
|
||||||
self.vae = vae
|
self.vae = vae
|
||||||
self.clip = clip
|
self.clip = clip
|
||||||
self.clip_vision = clip_vision
|
self.clip_vision = clip_vision
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.vae_filename = vae_filename
|
||||||
self.unet_with_lora = unet
|
self.unet_with_lora = unet
|
||||||
self.clip_with_lora = clip
|
self.clip_with_lora = clip
|
||||||
self.visited_loras = ''
|
self.visited_loras = ''
|
||||||
@@ -142,9 +143,10 @@ def apply_controlnet(positive, negative, control_net, image, strength, start_per
|
|||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
def load_model(ckpt_filename):
|
def load_model(ckpt_filename, vae_filename=None):
|
||||||
unet, clip, vae, clip_vision = load_checkpoint_guess_config(ckpt_filename, embedding_directory=path_embeddings)
|
unet, clip, vae, vae_filename, clip_vision = load_checkpoint_guess_config(ckpt_filename, embedding_directory=path_embeddings,
|
||||||
return StableDiffusionModel(unet=unet, clip=clip, vae=vae, clip_vision=clip_vision, filename=ckpt_filename)
|
vae_filename_param=vae_filename)
|
||||||
|
return StableDiffusionModel(unet=unet, clip=clip, vae=vae, clip_vision=clip_vision, filename=ckpt_filename, vae_filename=vae_filename)
|
||||||
|
|
||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import os
|
|||||||
import torch
|
import torch
|
||||||
import modules.patch
|
import modules.patch
|
||||||
import modules.config
|
import modules.config
|
||||||
|
import modules.flags
|
||||||
import ldm_patched.modules.model_management
|
import ldm_patched.modules.model_management
|
||||||
import ldm_patched.modules.latent_formats
|
import ldm_patched.modules.latent_formats
|
||||||
import modules.inpaint_worker
|
import modules.inpaint_worker
|
||||||
@@ -58,17 +59,21 @@ def assert_model_integrity():
|
|||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
def refresh_base_model(name):
|
def refresh_base_model(name, vae_name=None):
|
||||||
global model_base
|
global model_base
|
||||||
|
|
||||||
filename = get_file_from_folder_list(name, modules.config.paths_checkpoints)
|
filename = get_file_from_folder_list(name, modules.config.paths_checkpoints)
|
||||||
|
|
||||||
if model_base.filename == filename:
|
vae_filename = None
|
||||||
|
if vae_name is not None and vae_name != modules.flags.default_vae:
|
||||||
|
vae_filename = get_file_from_folder_list(vae_name, modules.config.path_vae)
|
||||||
|
|
||||||
|
if model_base.filename == filename and model_base.vae_filename == vae_filename:
|
||||||
return
|
return
|
||||||
|
|
||||||
model_base = core.StableDiffusionModel()
|
model_base = core.load_model(filename, vae_filename)
|
||||||
model_base = core.load_model(filename)
|
|
||||||
print(f'Base model loaded: {model_base.filename}')
|
print(f'Base model loaded: {model_base.filename}')
|
||||||
|
print(f'VAE loaded: {model_base.vae_filename}')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -216,7 +221,7 @@ def prepare_text_encoder(async_call=True):
|
|||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
def refresh_everything(refiner_model_name, base_model_name, loras,
|
def refresh_everything(refiner_model_name, base_model_name, loras,
|
||||||
base_model_additional_loras=None, use_synthetic_refiner=False):
|
base_model_additional_loras=None, use_synthetic_refiner=False, vae_name=None):
|
||||||
global final_unet, final_clip, final_vae, final_refiner_unet, final_refiner_vae, final_expansion
|
global final_unet, final_clip, final_vae, final_refiner_unet, final_refiner_vae, final_expansion
|
||||||
|
|
||||||
final_unet = None
|
final_unet = None
|
||||||
@@ -227,11 +232,11 @@ def refresh_everything(refiner_model_name, base_model_name, loras,
|
|||||||
|
|
||||||
if use_synthetic_refiner and refiner_model_name == 'None':
|
if use_synthetic_refiner and refiner_model_name == 'None':
|
||||||
print('Synthetic Refiner Activated')
|
print('Synthetic Refiner Activated')
|
||||||
refresh_base_model(base_model_name)
|
refresh_base_model(base_model_name, vae_name)
|
||||||
synthesize_refiner_model()
|
synthesize_refiner_model()
|
||||||
else:
|
else:
|
||||||
refresh_refiner_model(refiner_model_name)
|
refresh_refiner_model(refiner_model_name)
|
||||||
refresh_base_model(base_model_name)
|
refresh_base_model(base_model_name, vae_name)
|
||||||
|
|
||||||
refresh_loras(loras, base_model_additional_loras=base_model_additional_loras)
|
refresh_loras(loras, base_model_additional_loras=base_model_additional_loras)
|
||||||
assert_model_integrity()
|
assert_model_integrity()
|
||||||
@@ -254,7 +259,8 @@ def refresh_everything(refiner_model_name, base_model_name, loras,
|
|||||||
refresh_everything(
|
refresh_everything(
|
||||||
refiner_model_name=modules.config.default_refiner_model_name,
|
refiner_model_name=modules.config.default_refiner_model_name,
|
||||||
base_model_name=modules.config.default_base_model_name,
|
base_model_name=modules.config.default_base_model_name,
|
||||||
loras=get_enabled_loras(modules.config.default_loras)
|
loras=get_enabled_loras(modules.config.default_loras),
|
||||||
|
vae_name=modules.config.default_vae,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ SAMPLER_NAMES = KSAMPLER_NAMES + list(SAMPLER_EXTRA.keys())
|
|||||||
sampler_list = SAMPLER_NAMES
|
sampler_list = SAMPLER_NAMES
|
||||||
scheduler_list = SCHEDULER_NAMES
|
scheduler_list = SCHEDULER_NAMES
|
||||||
|
|
||||||
|
default_vae = 'Default (model)'
|
||||||
|
|
||||||
refiner_swap_method = 'joint'
|
refiner_swap_method = 'joint'
|
||||||
|
|
||||||
cn_ip = "ImagePrompt"
|
cn_ip = "ImagePrompt"
|
||||||
|
|||||||
+89
-35
@@ -1,5 +1,4 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -12,7 +11,7 @@ import modules.config
|
|||||||
import modules.sdxl_styles
|
import modules.sdxl_styles
|
||||||
from modules.flags import MetadataScheme, Performance, Steps
|
from modules.flags import MetadataScheme, Performance, Steps
|
||||||
from modules.flags import SAMPLERS, CIVITAI_NO_KARRAS
|
from modules.flags import SAMPLERS, CIVITAI_NO_KARRAS
|
||||||
from modules.util import quote, unquote, extract_styles_from_prompt, is_json, get_file_from_folder_list, calculate_sha256
|
from modules.util import quote, unquote, extract_styles_from_prompt, is_json, get_file_from_folder_list, sha256
|
||||||
|
|
||||||
re_param_code = r'\s*(\w[\w \-/]+):\s*("(?:\\.|[^\\"])+"|[^,]*)(?:,|$)'
|
re_param_code = r'\s*(\w[\w \-/]+):\s*("(?:\\.|[^\\"])+"|[^,]*)(?:,|$)'
|
||||||
re_param = re.compile(re_param_code)
|
re_param = re.compile(re_param_code)
|
||||||
@@ -27,8 +26,9 @@ def load_parameter_button_click(raw_metadata: dict | str, is_generating: bool):
|
|||||||
loaded_parameter_dict = json.loads(raw_metadata)
|
loaded_parameter_dict = json.loads(raw_metadata)
|
||||||
assert isinstance(loaded_parameter_dict, dict)
|
assert isinstance(loaded_parameter_dict, dict)
|
||||||
|
|
||||||
results = [len(loaded_parameter_dict) > 0, 1]
|
results = [len(loaded_parameter_dict) > 0]
|
||||||
|
|
||||||
|
get_image_number('image_number', 'Image Number', loaded_parameter_dict, results)
|
||||||
get_str('prompt', 'Prompt', loaded_parameter_dict, results)
|
get_str('prompt', 'Prompt', loaded_parameter_dict, results)
|
||||||
get_str('negative_prompt', 'Negative Prompt', loaded_parameter_dict, results)
|
get_str('negative_prompt', 'Negative Prompt', loaded_parameter_dict, results)
|
||||||
get_list('styles', 'Styles', loaded_parameter_dict, results)
|
get_list('styles', 'Styles', loaded_parameter_dict, results)
|
||||||
@@ -46,6 +46,7 @@ def load_parameter_button_click(raw_metadata: dict | str, is_generating: bool):
|
|||||||
get_float('refiner_switch', 'Refiner Switch', loaded_parameter_dict, results)
|
get_float('refiner_switch', 'Refiner Switch', loaded_parameter_dict, results)
|
||||||
get_str('sampler', 'Sampler', loaded_parameter_dict, results)
|
get_str('sampler', 'Sampler', loaded_parameter_dict, results)
|
||||||
get_str('scheduler', 'Scheduler', loaded_parameter_dict, results)
|
get_str('scheduler', 'Scheduler', loaded_parameter_dict, results)
|
||||||
|
get_str('vae', 'VAE', loaded_parameter_dict, results)
|
||||||
get_seed('seed', 'Seed', loaded_parameter_dict, results)
|
get_seed('seed', 'Seed', loaded_parameter_dict, results)
|
||||||
|
|
||||||
if is_generating:
|
if is_generating:
|
||||||
@@ -92,13 +93,25 @@ def get_float(key: str, fallback: str | None, source_dict: dict, results: list,
|
|||||||
results.append(gr.update())
|
results.append(gr.update())
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_number(key: str, fallback: str | None, source_dict: dict, results: list, default=None):
|
||||||
|
try:
|
||||||
|
h = source_dict.get(key, source_dict.get(fallback, default))
|
||||||
|
assert h is not None
|
||||||
|
h = int(h)
|
||||||
|
h = min(h, modules.config.default_max_image_number)
|
||||||
|
results.append(h)
|
||||||
|
except:
|
||||||
|
results.append(1)
|
||||||
|
|
||||||
|
|
||||||
def get_steps(key: str, fallback: str | None, source_dict: dict, results: list, default=None):
|
def get_steps(key: str, fallback: str | None, source_dict: dict, results: list, default=None):
|
||||||
try:
|
try:
|
||||||
h = source_dict.get(key, source_dict.get(fallback, default))
|
h = source_dict.get(key, source_dict.get(fallback, default))
|
||||||
assert h is not None
|
assert h is not None
|
||||||
h = int(h)
|
h = int(h)
|
||||||
# if not in steps or in steps and performance is not the same
|
# if not in steps or in steps and performance is not the same
|
||||||
if h not in iter(Steps) or Steps(h).name.casefold() != source_dict.get('performance', '').replace(' ', '_').casefold():
|
if h not in iter(Steps) or Steps(h).name.casefold() != source_dict.get('performance', '').replace(' ',
|
||||||
|
'_').casefold():
|
||||||
results.append(h)
|
results.append(h)
|
||||||
return
|
return
|
||||||
results.append(-1)
|
results.append(-1)
|
||||||
@@ -169,11 +182,20 @@ def get_freeu(key: str, fallback: str | None, source_dict: dict, results: list,
|
|||||||
|
|
||||||
def get_lora(key: str, fallback: str | None, source_dict: dict, results: list):
|
def get_lora(key: str, fallback: str | None, source_dict: dict, results: list):
|
||||||
try:
|
try:
|
||||||
n, w = source_dict.get(key, source_dict.get(fallback)).split(' : ')
|
split_data = source_dict.get(key, source_dict.get(fallback)).split(' : ')
|
||||||
w = float(w)
|
enabled = True
|
||||||
results.append(True)
|
name = split_data[0]
|
||||||
results.append(n)
|
weight = split_data[1]
|
||||||
results.append(w)
|
|
||||||
|
if len(split_data) == 3:
|
||||||
|
enabled = split_data[0] == 'True'
|
||||||
|
name = split_data[1]
|
||||||
|
weight = split_data[2]
|
||||||
|
|
||||||
|
weight = float(weight)
|
||||||
|
results.append(enabled)
|
||||||
|
results.append(name)
|
||||||
|
results.append(weight)
|
||||||
except:
|
except:
|
||||||
results.append(True)
|
results.append(True)
|
||||||
results.append('None')
|
results.append('None')
|
||||||
@@ -183,7 +205,8 @@ def get_lora(key: str, fallback: str | None, source_dict: dict, results: list):
|
|||||||
def get_sha256(filepath):
|
def get_sha256(filepath):
|
||||||
global hash_cache
|
global hash_cache
|
||||||
if filepath not in hash_cache:
|
if filepath not in hash_cache:
|
||||||
hash_cache[filepath] = calculate_sha256(filepath)
|
# is_safetensors = os.path.splitext(filepath)[1].lower() == '.safetensors'
|
||||||
|
hash_cache[filepath] = sha256(filepath)
|
||||||
|
|
||||||
return hash_cache[filepath]
|
return hash_cache[filepath]
|
||||||
|
|
||||||
@@ -210,7 +233,8 @@ def parse_meta_from_preset(preset_content):
|
|||||||
height = height[:height.index(" ")]
|
height = height[:height.index(" ")]
|
||||||
preset_prepared[meta_key] = (width, height)
|
preset_prepared[meta_key] = (width, height)
|
||||||
else:
|
else:
|
||||||
preset_prepared[meta_key] = items[settings_key] if settings_key in items and items[settings_key] is not None else getattr(modules.config, settings_key)
|
preset_prepared[meta_key] = items[settings_key] if settings_key in items and items[
|
||||||
|
settings_key] is not None else getattr(modules.config, settings_key)
|
||||||
|
|
||||||
if settings_key == "default_styles" or settings_key == "default_aspect_ratio":
|
if settings_key == "default_styles" or settings_key == "default_aspect_ratio":
|
||||||
preset_prepared[meta_key] = str(preset_prepared[meta_key])
|
preset_prepared[meta_key] = str(preset_prepared[meta_key])
|
||||||
@@ -230,6 +254,7 @@ class MetadataParser(ABC):
|
|||||||
self.refiner_model_name: str = ''
|
self.refiner_model_name: str = ''
|
||||||
self.refiner_model_hash: str = ''
|
self.refiner_model_hash: str = ''
|
||||||
self.loras: list = []
|
self.loras: list = []
|
||||||
|
self.vae_name: str = ''
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_scheme(self) -> MetadataScheme:
|
def get_scheme(self) -> MetadataScheme:
|
||||||
@@ -244,7 +269,7 @@ class MetadataParser(ABC):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def set_data(self, raw_prompt, full_prompt, raw_negative_prompt, full_negative_prompt, steps, base_model_name,
|
def set_data(self, raw_prompt, full_prompt, raw_negative_prompt, full_negative_prompt, steps, base_model_name,
|
||||||
refiner_model_name, loras):
|
refiner_model_name, loras, vae_name):
|
||||||
self.raw_prompt = raw_prompt
|
self.raw_prompt = raw_prompt
|
||||||
self.full_prompt = full_prompt
|
self.full_prompt = full_prompt
|
||||||
self.raw_negative_prompt = raw_negative_prompt
|
self.raw_negative_prompt = raw_negative_prompt
|
||||||
@@ -266,6 +291,13 @@ class MetadataParser(ABC):
|
|||||||
lora_path = get_file_from_folder_list(lora_name, modules.config.paths_loras)
|
lora_path = get_file_from_folder_list(lora_name, modules.config.paths_loras)
|
||||||
lora_hash = get_sha256(lora_path)
|
lora_hash = get_sha256(lora_path)
|
||||||
self.loras.append((Path(lora_name).stem, lora_weight, lora_hash))
|
self.loras.append((Path(lora_name).stem, lora_weight, lora_hash))
|
||||||
|
self.vae_name = Path(vae_name).stem
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def remove_special_loras(lora_filenames):
|
||||||
|
for lora_to_remove in modules.config.loras_metadata_remove:
|
||||||
|
if lora_to_remove in lora_filenames:
|
||||||
|
lora_filenames.remove(lora_to_remove)
|
||||||
|
|
||||||
|
|
||||||
class A1111MetadataParser(MetadataParser):
|
class A1111MetadataParser(MetadataParser):
|
||||||
@@ -281,6 +313,7 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
'steps': 'Steps',
|
'steps': 'Steps',
|
||||||
'sampler': 'Sampler',
|
'sampler': 'Sampler',
|
||||||
'scheduler': 'Scheduler',
|
'scheduler': 'Scheduler',
|
||||||
|
'vae': 'VAE',
|
||||||
'guidance_scale': 'CFG scale',
|
'guidance_scale': 'CFG scale',
|
||||||
'seed': 'Seed',
|
'seed': 'Seed',
|
||||||
'resolution': 'Size',
|
'resolution': 'Size',
|
||||||
@@ -368,20 +401,26 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
data['sampler'] = k
|
data['sampler'] = k
|
||||||
break
|
break
|
||||||
|
|
||||||
for key in ['base_model', 'refiner_model']:
|
for key in ['base_model', 'refiner_model', 'vae']:
|
||||||
if key in data:
|
if key in data:
|
||||||
for filename in modules.config.model_filenames:
|
if key == 'vae':
|
||||||
path = Path(filename)
|
self.add_extension_to_filename(data, modules.config.vae_filenames, 'vae')
|
||||||
if data[key] == path.stem:
|
else:
|
||||||
data[key] = filename
|
self.add_extension_to_filename(data, modules.config.model_filenames, key)
|
||||||
break
|
|
||||||
|
|
||||||
if 'lora_hashes' in data:
|
lora_data = ''
|
||||||
|
if 'lora_weights' in data and data['lora_weights'] != '':
|
||||||
|
lora_data = data['lora_weights']
|
||||||
|
elif 'lora_hashes' in data and data['lora_hashes'] != '' and data['lora_hashes'].split(', ')[0].count(':') == 2:
|
||||||
|
lora_data = data['lora_hashes']
|
||||||
|
|
||||||
|
if lora_data != '':
|
||||||
lora_filenames = modules.config.lora_filenames.copy()
|
lora_filenames = modules.config.lora_filenames.copy()
|
||||||
if modules.config.sdxl_lcm_lora in lora_filenames:
|
self.remove_special_loras(lora_filenames)
|
||||||
lora_filenames.remove(modules.config.sdxl_lcm_lora)
|
for li, lora in enumerate(lora_data.split(', ')):
|
||||||
for li, lora in enumerate(data['lora_hashes'].split(', ')):
|
lora_split = lora.split(': ')
|
||||||
lora_name, lora_hash, lora_weight = lora.split(': ')
|
lora_name = lora_split[0]
|
||||||
|
lora_weight = lora_split[2] if len(lora_split) == 3 else lora_split[1]
|
||||||
for filename in lora_filenames:
|
for filename in lora_filenames:
|
||||||
path = Path(filename)
|
path = Path(filename)
|
||||||
if lora_name == path.stem:
|
if lora_name == path.stem:
|
||||||
@@ -397,6 +436,7 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
|
|
||||||
sampler = data['sampler']
|
sampler = data['sampler']
|
||||||
scheduler = data['scheduler']
|
scheduler = data['scheduler']
|
||||||
|
|
||||||
if sampler in SAMPLERS and SAMPLERS[sampler] != '':
|
if sampler in SAMPLERS and SAMPLERS[sampler] != '':
|
||||||
sampler = SAMPLERS[sampler]
|
sampler = SAMPLERS[sampler]
|
||||||
if sampler not in CIVITAI_NO_KARRAS and scheduler == 'karras':
|
if sampler not in CIVITAI_NO_KARRAS and scheduler == 'karras':
|
||||||
@@ -415,6 +455,7 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
|
|
||||||
self.fooocus_to_a1111['performance']: data['performance'],
|
self.fooocus_to_a1111['performance']: data['performance'],
|
||||||
self.fooocus_to_a1111['scheduler']: scheduler,
|
self.fooocus_to_a1111['scheduler']: scheduler,
|
||||||
|
self.fooocus_to_a1111['vae']: Path(data['vae']).stem,
|
||||||
# workaround for multiline prompts
|
# workaround for multiline prompts
|
||||||
self.fooocus_to_a1111['raw_prompt']: self.raw_prompt,
|
self.fooocus_to_a1111['raw_prompt']: self.raw_prompt,
|
||||||
self.fooocus_to_a1111['raw_negative_prompt']: self.raw_negative_prompt,
|
self.fooocus_to_a1111['raw_negative_prompt']: self.raw_negative_prompt,
|
||||||
@@ -430,16 +471,19 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
if key in data:
|
if key in data:
|
||||||
generation_params[self.fooocus_to_a1111[key]] = data[key]
|
generation_params[self.fooocus_to_a1111[key]] = data[key]
|
||||||
|
|
||||||
lora_hashes = []
|
if len(self.loras) > 0:
|
||||||
for index, (lora_name, lora_weight, lora_hash) in enumerate(self.loras):
|
lora_hashes = []
|
||||||
# workaround for Fooocus not knowing LoRA name in LoRA metadata
|
lora_weights = []
|
||||||
lora_hashes.append(f'{lora_name}: {lora_hash}: {lora_weight}')
|
for index, (lora_name, lora_weight, lora_hash) in enumerate(self.loras):
|
||||||
lora_hashes_string = ', '.join(lora_hashes)
|
# workaround for Fooocus not knowing LoRA name in LoRA metadata
|
||||||
|
lora_hashes.append(f'{lora_name}: {lora_hash}')
|
||||||
|
lora_weights.append(f'{lora_name}: {lora_weight}')
|
||||||
|
lora_hashes_string = ', '.join(lora_hashes)
|
||||||
|
lora_weights_string = ', '.join(lora_weights)
|
||||||
|
generation_params[self.fooocus_to_a1111['lora_hashes']] = lora_hashes_string
|
||||||
|
generation_params[self.fooocus_to_a1111['lora_weights']] = lora_weights_string
|
||||||
|
|
||||||
generation_params |= {
|
generation_params[self.fooocus_to_a1111['version']] = data['version']
|
||||||
self.fooocus_to_a1111['lora_hashes']: lora_hashes_string,
|
|
||||||
self.fooocus_to_a1111['version']: data['version']
|
|
||||||
}
|
|
||||||
|
|
||||||
if modules.config.metadata_created_by != '':
|
if modules.config.metadata_created_by != '':
|
||||||
generation_params[self.fooocus_to_a1111['created_by']] = modules.config.metadata_created_by
|
generation_params[self.fooocus_to_a1111['created_by']] = modules.config.metadata_created_by
|
||||||
@@ -452,6 +496,14 @@ class A1111MetadataParser(MetadataParser):
|
|||||||
negative_prompt_text = f"\nNegative prompt: {negative_prompt_resolved}" if negative_prompt_resolved else ""
|
negative_prompt_text = f"\nNegative prompt: {negative_prompt_resolved}" if negative_prompt_resolved else ""
|
||||||
return f"{positive_prompt_resolved}{negative_prompt_text}\n{generation_params_text}".strip()
|
return f"{positive_prompt_resolved}{negative_prompt_text}\n{generation_params_text}".strip()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_extension_to_filename(data, filenames, key):
|
||||||
|
for filename in filenames:
|
||||||
|
path = Path(filename)
|
||||||
|
if data[key] == path.stem:
|
||||||
|
data[key] = filename
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class FooocusMetadataParser(MetadataParser):
|
class FooocusMetadataParser(MetadataParser):
|
||||||
def get_scheme(self) -> MetadataScheme:
|
def get_scheme(self) -> MetadataScheme:
|
||||||
@@ -460,9 +512,8 @@ class FooocusMetadataParser(MetadataParser):
|
|||||||
def parse_json(self, metadata: dict) -> dict:
|
def parse_json(self, metadata: dict) -> dict:
|
||||||
model_filenames = modules.config.model_filenames.copy()
|
model_filenames = modules.config.model_filenames.copy()
|
||||||
lora_filenames = modules.config.lora_filenames.copy()
|
lora_filenames = modules.config.lora_filenames.copy()
|
||||||
if modules.config.sdxl_lcm_lora in lora_filenames:
|
vae_filenames = modules.config.vae_filenames.copy()
|
||||||
lora_filenames.remove(modules.config.sdxl_lcm_lora)
|
self.remove_special_loras(lora_filenames)
|
||||||
|
|
||||||
for key, value in metadata.items():
|
for key, value in metadata.items():
|
||||||
if value in ['', 'None']:
|
if value in ['', 'None']:
|
||||||
continue
|
continue
|
||||||
@@ -470,6 +521,8 @@ class FooocusMetadataParser(MetadataParser):
|
|||||||
metadata[key] = self.replace_value_with_filename(key, value, model_filenames)
|
metadata[key] = self.replace_value_with_filename(key, value, model_filenames)
|
||||||
elif key.startswith('lora_combined_'):
|
elif key.startswith('lora_combined_'):
|
||||||
metadata[key] = self.replace_value_with_filename(key, value, lora_filenames)
|
metadata[key] = self.replace_value_with_filename(key, value, lora_filenames)
|
||||||
|
elif key == 'vae':
|
||||||
|
metadata[key] = self.replace_value_with_filename(key, value, vae_filenames)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -496,6 +549,7 @@ class FooocusMetadataParser(MetadataParser):
|
|||||||
res['refiner_model'] = self.refiner_model_name
|
res['refiner_model'] = self.refiner_model_name
|
||||||
res['refiner_model_hash'] = self.refiner_model_hash
|
res['refiner_model_hash'] = self.refiner_model_hash
|
||||||
|
|
||||||
|
res['vae'] = self.vae_name
|
||||||
res['loras'] = self.loras
|
res['loras'] = self.loras
|
||||||
|
|
||||||
if modules.config.metadata_created_by != '':
|
if modules.config.metadata_created_by != '':
|
||||||
|
|||||||
+36
-5
@@ -7,9 +7,9 @@ import math
|
|||||||
import os
|
import os
|
||||||
import cv2
|
import cv2
|
||||||
import json
|
import json
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from hashlib import sha256
|
|
||||||
|
|
||||||
import modules.sdxl_styles
|
import modules.sdxl_styles
|
||||||
|
|
||||||
@@ -182,16 +182,44 @@ def get_files_from_folder(folder_path, extensions=None, name_filter=None):
|
|||||||
return filenames
|
return filenames
|
||||||
|
|
||||||
|
|
||||||
def calculate_sha256(filename, length=HASH_SHA256_LENGTH) -> str:
|
def sha256(filename, use_addnet_hash=False, length=HASH_SHA256_LENGTH):
|
||||||
hash_sha256 = sha256()
|
print(f"Calculating sha256 for {filename}: ", end='')
|
||||||
|
if use_addnet_hash:
|
||||||
|
with open(filename, "rb") as file:
|
||||||
|
sha256_value = addnet_hash_safetensors(file)
|
||||||
|
else:
|
||||||
|
sha256_value = calculate_sha256(filename)
|
||||||
|
print(f"{sha256_value}")
|
||||||
|
|
||||||
|
return sha256_value[:length] if length is not None else sha256_value
|
||||||
|
|
||||||
|
|
||||||
|
def addnet_hash_safetensors(b):
|
||||||
|
"""kohya-ss hash for safetensors from https://github.com/kohya-ss/sd-scripts/blob/main/library/train_util.py"""
|
||||||
|
hash_sha256 = hashlib.sha256()
|
||||||
|
blksize = 1024 * 1024
|
||||||
|
|
||||||
|
b.seek(0)
|
||||||
|
header = b.read(8)
|
||||||
|
n = int.from_bytes(header, "little")
|
||||||
|
|
||||||
|
offset = n + 8
|
||||||
|
b.seek(offset)
|
||||||
|
for chunk in iter(lambda: b.read(blksize), b""):
|
||||||
|
hash_sha256.update(chunk)
|
||||||
|
|
||||||
|
return hash_sha256.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_sha256(filename) -> str:
|
||||||
|
hash_sha256 = hashlib.sha256()
|
||||||
blksize = 1024 * 1024
|
blksize = 1024 * 1024
|
||||||
|
|
||||||
with open(filename, "rb") as f:
|
with open(filename, "rb") as f:
|
||||||
for chunk in iter(lambda: f.read(blksize), b""):
|
for chunk in iter(lambda: f.read(blksize), b""):
|
||||||
hash_sha256.update(chunk)
|
hash_sha256.update(chunk)
|
||||||
|
|
||||||
res = hash_sha256.hexdigest()
|
return hash_sha256.hexdigest()
|
||||||
return res[:length] if length else res
|
|
||||||
|
|
||||||
|
|
||||||
def quote(text):
|
def quote(text):
|
||||||
@@ -343,6 +371,9 @@ def is_json(data: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def get_file_from_folder_list(name, folders):
|
def get_file_from_folder_list(name, folders):
|
||||||
|
if not isinstance(folders, list):
|
||||||
|
folders = [folders]
|
||||||
|
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
filename = os.path.abspath(os.path.realpath(os.path.join(folder, name)))
|
filename = os.path.abspath(os.path.realpath(os.path.join(folder, name)))
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@
|
|||||||
"default_sampler": "dpmpp_2m_sde_gpu",
|
"default_sampler": "dpmpp_2m_sde_gpu",
|
||||||
"default_scheduler": "karras",
|
"default_scheduler": "karras",
|
||||||
"default_performance": "Speed",
|
"default_performance": "Speed",
|
||||||
"default_prompt": "1girl, ",
|
"default_prompt": "",
|
||||||
"default_prompt_negative": "",
|
"default_prompt_negative": "",
|
||||||
"default_styles": [
|
"default_styles": [
|
||||||
"Fooocus V2",
|
"Fooocus V2",
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ The first time you launch the software, it will automatically download models:
|
|||||||
|
|
||||||
After Fooocus 2.1.60, you will also have `run_anime.bat` and `run_realistic.bat`. They are different model presets (and require different models, but they will be automatically downloaded). [Check here for more details](https://github.com/lllyasviel/Fooocus/discussions/679).
|
After Fooocus 2.1.60, you will also have `run_anime.bat` and `run_realistic.bat`. They are different model presets (and require different models, but they will be automatically downloaded). [Check here for more details](https://github.com/lllyasviel/Fooocus/discussions/679).
|
||||||
|
|
||||||
|
After Fooocus 2.3.0 you can also switch presets directly in the browser. Keep in mind to add these arguments if you want to change the default behavior:
|
||||||
|
* Use `--disable-preset-selection` to disable preset selection in the browser.
|
||||||
|
* Use `--always-download-new-model` to download missing models on preset switch. Default is fallback to `previous_default_models` defined in the corresponding preset, also see terminal output.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you already have these files, you can copy them to the above locations to speed up installation.
|
If you already have these files, you can copy them to the above locations to speed up installation.
|
||||||
@@ -115,7 +119,7 @@ See also the common problems and troubleshoots [here](troubleshoot.md).
|
|||||||
|
|
||||||
### Colab
|
### Colab
|
||||||
|
|
||||||
(Last tested - 2024 Mar 11)
|
(Last tested - 2024 Mar 18 by [mashb1t](https://github.com/mashb1t))
|
||||||
|
|
||||||
| Colab | Info
|
| Colab | Info
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@@ -123,11 +127,13 @@ See also the common problems and troubleshoots [here](troubleshoot.md).
|
|||||||
|
|
||||||
In Colab, you can modify the last line to `!python entry_with_update.py --share --always-high-vram` or `!python entry_with_update.py --share --always-high-vram --preset anime` or `!python entry_with_update.py --share --always-high-vram --preset realistic` for Fooocus Default/Anime/Realistic Edition.
|
In Colab, you can modify the last line to `!python entry_with_update.py --share --always-high-vram` or `!python entry_with_update.py --share --always-high-vram --preset anime` or `!python entry_with_update.py --share --always-high-vram --preset realistic` for Fooocus Default/Anime/Realistic Edition.
|
||||||
|
|
||||||
|
You can also change the preset in the UI. Please be aware that this may lead to timeouts after 60 seconds. If this is the case, please wait until the download has finished, change the preset to initial and back to the one you've selected or reload the page.
|
||||||
|
|
||||||
Note that this Colab will disable refiner by default because Colab free's resources are relatively limited (and some "big" features like image prompt may cause free-tier Colab to disconnect). We make sure that basic text-to-image is always working on free-tier Colab.
|
Note that this Colab will disable refiner by default because Colab free's resources are relatively limited (and some "big" features like image prompt may cause free-tier Colab to disconnect). We make sure that basic text-to-image is always working on free-tier Colab.
|
||||||
|
|
||||||
Using `--always-high-vram` shifts resource allocation from RAM to VRAM and achieves the overall best balance between performance, flexibility and stability on the default T4 instance.
|
Using `--always-high-vram` shifts resource allocation from RAM to VRAM and achieves the overall best balance between performance, flexibility and stability on the default T4 instance. Please find more information [here](https://github.com/lllyasviel/Fooocus/pull/1710#issuecomment-1989185346).
|
||||||
|
|
||||||
Thanks to [camenduru](https://github.com/camenduru)!
|
Thanks to [camenduru](https://github.com/camenduru) for the template!
|
||||||
|
|
||||||
### Linux (Using Anaconda)
|
### Linux (Using Anaconda)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
# [2.3.1](https://github.com/lllyasviel/Fooocus/releases/tag/2.3.1)
|
||||||
|
|
||||||
|
* Remove positive prompt from anime prefix to not reset prompt after switching presets
|
||||||
|
* Fix image number being reset to 1 when switching preset, now doesn't reset anymore
|
||||||
|
* Fix outpainting dimension calculation when extending left/right
|
||||||
|
* Fix LoRA compatibility for LoRAs in a1111 metadata scheme
|
||||||
|
|
||||||
|
# [2.3.0](https://github.com/lllyasviel/Fooocus/releases/tag/2.3.0)
|
||||||
|
|
||||||
|
* Add performance "lightning" (based on [SDXL-Lightning 4 step LoRA](https://huggingface.co/ByteDance/SDXL-Lightning/blob/main/sdxl_lightning_4step_lora.safetensors))
|
||||||
|
* Add preset selection to UI, disable with argument `--disable-preset-selection`. Use `--always-download-new-model` to download missing models on preset switch.
|
||||||
|
* Improve face swap consistency by switching later in the process to (synthetic) refiner
|
||||||
|
* Add temp path cleanup on startup
|
||||||
|
* Add support for wildcard subdirectories
|
||||||
|
* Add scrollable 2 column layout for styles for better structure
|
||||||
|
* Improve Colab resource needs for T4 instances (default), positively tested with all image prompt features
|
||||||
|
* Improve anime preset, now uses style `Fooocus Semi Realistic` instead of `Fooocus Negative` (less wet look images)
|
||||||
|
|
||||||
# [2.2.1](https://github.com/lllyasviel/Fooocus/releases/tag/2.2.1)
|
# [2.2.1](https://github.com/lllyasviel/Fooocus/releases/tag/2.2.1)
|
||||||
|
|
||||||
* Fix some small bugs (e.g. image grid, upscale fast 2x, LoRA weight width in Firefox)
|
* Fix some small bugs (e.g. image grid, upscale fast 2x, LoRA weight width in Firefox)
|
||||||
|
|||||||
@@ -406,6 +406,8 @@ with shared.gradio_root:
|
|||||||
value=modules.config.default_sampler)
|
value=modules.config.default_sampler)
|
||||||
scheduler_name = gr.Dropdown(label='Scheduler', choices=flags.scheduler_list,
|
scheduler_name = gr.Dropdown(label='Scheduler', choices=flags.scheduler_list,
|
||||||
value=modules.config.default_scheduler)
|
value=modules.config.default_scheduler)
|
||||||
|
vae_name = gr.Dropdown(label='VAE', choices=[modules.flags.default_vae] + modules.config.vae_filenames,
|
||||||
|
value=modules.config.default_vae, show_label=True)
|
||||||
|
|
||||||
generate_image_grid = gr.Checkbox(label='Generate Image Grid for Each Batch',
|
generate_image_grid = gr.Checkbox(label='Generate Image Grid for Each Batch',
|
||||||
info='(Experimental) This may cause performance problems on some computers and certain internet conditions.',
|
info='(Experimental) This may cause performance problems on some computers and certain internet conditions.',
|
||||||
@@ -528,6 +530,7 @@ with shared.gradio_root:
|
|||||||
modules.config.update_files()
|
modules.config.update_files()
|
||||||
results = [gr.update(choices=modules.config.model_filenames)]
|
results = [gr.update(choices=modules.config.model_filenames)]
|
||||||
results += [gr.update(choices=['None'] + modules.config.model_filenames)]
|
results += [gr.update(choices=['None'] + modules.config.model_filenames)]
|
||||||
|
results += [gr.update(choices=['None'] + modules.config.vae_filenames)]
|
||||||
if not args_manager.args.disable_preset_selection:
|
if not args_manager.args.disable_preset_selection:
|
||||||
results += [gr.update(choices=modules.config.available_presets)]
|
results += [gr.update(choices=modules.config.available_presets)]
|
||||||
for i in range(modules.config.default_max_lora_number):
|
for i in range(modules.config.default_max_lora_number):
|
||||||
@@ -535,7 +538,7 @@ with shared.gradio_root:
|
|||||||
gr.update(choices=['None'] + modules.config.lora_filenames), gr.update()]
|
gr.update(choices=['None'] + modules.config.lora_filenames), gr.update()]
|
||||||
return results
|
return results
|
||||||
|
|
||||||
refresh_files_output = [base_model, refiner_model]
|
refresh_files_output = [base_model, refiner_model, vae_name]
|
||||||
if not args_manager.args.disable_preset_selection:
|
if not args_manager.args.disable_preset_selection:
|
||||||
refresh_files_output += [preset_selection]
|
refresh_files_output += [preset_selection]
|
||||||
refresh_files.click(refresh_files_clicked, [], refresh_files_output + lora_ctrls,
|
refresh_files.click(refresh_files_clicked, [], refresh_files_output + lora_ctrls,
|
||||||
@@ -547,8 +550,8 @@ with shared.gradio_root:
|
|||||||
performance_selection, overwrite_step, overwrite_switch, aspect_ratios_selection,
|
performance_selection, overwrite_step, overwrite_switch, aspect_ratios_selection,
|
||||||
overwrite_width, overwrite_height, guidance_scale, sharpness, adm_scaler_positive,
|
overwrite_width, overwrite_height, guidance_scale, sharpness, adm_scaler_positive,
|
||||||
adm_scaler_negative, adm_scaler_end, refiner_swap_method, adaptive_cfg, base_model,
|
adm_scaler_negative, adm_scaler_end, refiner_swap_method, adaptive_cfg, base_model,
|
||||||
refiner_model, refiner_switch, sampler_name, scheduler_name, seed_random, image_seed,
|
refiner_model, refiner_switch, sampler_name, scheduler_name, vae_name, seed_random,
|
||||||
generate_button, load_parameter_button] + freeu_ctrls + lora_ctrls
|
image_seed, generate_button, load_parameter_button] + freeu_ctrls + lora_ctrls
|
||||||
|
|
||||||
if not args_manager.args.disable_preset_selection:
|
if not args_manager.args.disable_preset_selection:
|
||||||
def preset_selection_change(preset, is_generating):
|
def preset_selection_change(preset, is_generating):
|
||||||
@@ -634,7 +637,7 @@ with shared.gradio_root:
|
|||||||
ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt, inpaint_mask_image]
|
ctrls += [outpaint_selections, inpaint_input_image, inpaint_additional_prompt, inpaint_mask_image]
|
||||||
ctrls += [disable_preview, disable_intermediate_results, disable_seed_increment]
|
ctrls += [disable_preview, disable_intermediate_results, disable_seed_increment]
|
||||||
ctrls += [adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adaptive_cfg]
|
ctrls += [adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adaptive_cfg]
|
||||||
ctrls += [sampler_name, scheduler_name]
|
ctrls += [sampler_name, scheduler_name, vae_name]
|
||||||
ctrls += [overwrite_step, overwrite_switch, overwrite_width, overwrite_height, overwrite_vary_strength]
|
ctrls += [overwrite_step, overwrite_switch, overwrite_width, overwrite_height, overwrite_vary_strength]
|
||||||
ctrls += [overwrite_upscale_strength, mixing_image_prompt_and_vary_upscale, mixing_image_prompt_and_inpaint]
|
ctrls += [overwrite_upscale_strength, mixing_image_prompt_and_vary_upscale, mixing_image_prompt_and_inpaint]
|
||||||
ctrls += [debugging_cn_preprocessor, skipping_cn_preprocessor, canny_low_threshold, canny_high_threshold]
|
ctrls += [debugging_cn_preprocessor, skipping_cn_preprocessor, canny_low_threshold, canny_high_threshold]
|
||||||
|
|||||||
Reference in New Issue
Block a user