Spaces:
Running
on
Zero
Running
on
Zero
Upload 4 files
Browse files
app.py
CHANGED
@@ -2,10 +2,12 @@ import spaces
|
|
2 |
import gradio as gr
|
3 |
import json
|
4 |
import torch
|
5 |
-
from diffusers import DiffusionPipeline, AutoencoderTiny, AutoencoderKL, AutoPipelineForImage2Image, AutoPipelineForInpainting
|
6 |
from live_preview_helpers import calculate_shift, retrieve_timesteps, flux_pipe_call_that_returns_an_iterable_of_images
|
7 |
from diffusers.utils import load_image
|
8 |
-
from diffusers import FluxControlNetPipeline, FluxControlNetModel, FluxMultiControlNetModel, FluxControlNetImg2ImgPipeline,
|
|
|
|
|
9 |
from huggingface_hub import hf_hub_download, HfFileSystem, ModelCard, snapshot_download, HfApi
|
10 |
import os
|
11 |
import copy
|
@@ -16,10 +18,10 @@ import pandas as pd
|
|
16 |
import numpy as np
|
17 |
from pathlib import Path
|
18 |
|
19 |
-
from env import models, num_loras, num_cns, HF_TOKEN, single_file_base_models
|
20 |
from mod import (clear_cache, get_repo_safetensors, is_repo_name, is_repo_exists, get_model_trigger,
|
21 |
-
description_ui, compose_lora_json, is_valid_lora, fuse_loras, save_image, preprocess_i2i_image,
|
22 |
-
get_trigger_word, enhance_prompt, set_control_union_image,
|
23 |
get_control_union_mode, set_control_union_mode, get_control_params, translate_to_en)
|
24 |
from modutils import (search_civitai_lora, select_civitai_lora, search_civitai_lora_json,
|
25 |
download_my_lora_flux, get_all_lora_tupled_list, apply_lora_prompt_flux,
|
@@ -42,39 +44,33 @@ controlnet_model_union_repo = 'InstantX/FLUX.1-dev-Controlnet-Union'
|
|
42 |
#controlnet_model_union_repo = 'Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro'
|
43 |
dtype = torch.bfloat16
|
44 |
#dtype = torch.float8_e4m3fn
|
45 |
-
CACHE_MODEL = False
|
46 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
47 |
taef1 = AutoencoderTiny.from_pretrained("madebyollin/taef1", torch_dtype=dtype, token=HF_TOKEN)
|
48 |
good_vae = AutoencoderKL.from_pretrained(base_model, subfolder="vae", torch_dtype=dtype, token=HF_TOKEN)
|
49 |
pipe = DiffusionPipeline.from_pretrained(base_model, torch_dtype=dtype, vae=taef1, token=HF_TOKEN)
|
50 |
-
if CACHE_MODEL:
|
51 |
-
taef1.to(device)
|
52 |
-
good_vae.to(device)
|
53 |
-
pipe.to(device)
|
54 |
-
pipe.transformer.to("cpu")
|
55 |
pipe_i2i = AutoPipelineForImage2Image.from_pretrained(base_model, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
56 |
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
57 |
-
pipe_ip = AutoPipelineForInpainting.from_pretrained(base_model, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
58 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
59 |
controlnet_union = None
|
60 |
controlnet = None
|
61 |
last_model = models[0]
|
62 |
last_cn_on = False
|
|
|
|
|
63 |
#controlnet_union = FluxControlNetModel.from_pretrained(controlnet_model_union_repo, torch_dtype=dtype)
|
64 |
#controlnet = FluxMultiControlNetModel([controlnet_union])
|
65 |
#controlnet.config = controlnet_union.config
|
66 |
|
67 |
MAX_SEED = 2**32-1
|
|
|
|
|
68 |
|
69 |
def unload_lora():
|
70 |
-
global pipe, pipe_i2i
|
71 |
try:
|
72 |
#pipe.unfuse_lora()
|
73 |
pipe.unload_lora_weights()
|
74 |
#pipe_i2i.unfuse_lora()
|
75 |
pipe_i2i.unload_lora_weights()
|
76 |
-
#pipe_ip.unfuse_lora()
|
77 |
-
pipe_ip.unload_lora_weights()
|
78 |
except Exception as e:
|
79 |
print(e)
|
80 |
|
@@ -83,90 +79,104 @@ def download_file_mod(url, directory=os.getcwd()):
|
|
83 |
if not path: raise Exception(f"Download error: {url}")
|
84 |
return path
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
# https://huggingface.co/InstantX/FLUX.1-dev-Controlnet-Union
|
87 |
# https://huggingface.co/spaces/jiuface/FLUX.1-dev-Controlnet-Union
|
88 |
# https://huggingface.co/docs/diffusers/main/en/api/pipelines/flux
|
89 |
#@spaces.GPU()
|
90 |
-
def change_base_model(repo_id: str, cn_on: bool, disable_model_cache: bool, model_type: str, progress=gr.Progress(track_tqdm=True)):
|
91 |
-
global pipe, pipe_i2i,
|
92 |
-
safetensors_file = None
|
93 |
-
single_file_base_model = single_file_base_models.get(model_type, models[0])
|
94 |
try:
|
95 |
-
|
96 |
-
|
97 |
unload_lora()
|
98 |
pipe.to("cpu")
|
99 |
pipe_i2i.to("cpu")
|
100 |
-
pipe_ip.to("cpu")
|
101 |
good_vae.to("cpu")
|
102 |
taef1.to("cpu")
|
103 |
if controlnet is not None: controlnet.to("cpu")
|
104 |
if controlnet_union is not None: controlnet_union.to("cpu")
|
105 |
clear_cache()
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
controlnet.config = controlnet_union.config
|
112 |
-
if ".safetensors" in repo_id:
|
113 |
-
safetensors_file = download_file_mod(repo_id)
|
114 |
-
transformer = FluxTransformer2DModel.from_single_file(safetensors_file, subfolder="transformer", torch_dtype=dtype, config=single_file_base_model)
|
115 |
-
if CACHE_MODEL:
|
116 |
-
pipe = FluxControlNetPipeline.from_pretrained(single_file_base_model, controlnet=controlnet, vae=good_vae, transformer=transformer, text_encoder=pipe.text_encoder,
|
117 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
118 |
-
else: pipe = FluxControlNetPipeline.from_pretrained(single_file_base_model, transformer=transformer, controlnet=controlnet, torch_dtype=dtype, token=HF_TOKEN)
|
119 |
-
pipe_i2i = FluxControlNetImg2ImgPipeline.from_pretrained(single_file_base_model, controlnet=controlnet, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
120 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
121 |
-
pipe_ip = FluxControlNetInpaintPipeline.from_pretrained(single_file_base_model, controlnet=controlnet, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
122 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
123 |
-
else:
|
124 |
-
if CACHE_MODEL:
|
125 |
-
transformer = FluxTransformer2DModel.from_pretrained(repo_id, subfolder="transformer", torch_dtype=dtype, token=HF_TOKEN)
|
126 |
-
pipe = FluxControlNetPipeline.from_pretrained(repo_id, controlnet=controlnet, vae=good_vae, transformer=transformer, text_encoder=pipe.text_encoder,
|
127 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
128 |
-
pipe = FluxControlNetPipeline.from_pretrained(repo_id, controlnet=controlnet, torch_dtype=dtype, token=HF_TOKEN)
|
129 |
-
pipe_i2i = FluxControlNetImg2ImgPipeline.from_pretrained(repo_id, controlnet=controlnet, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
130 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
131 |
-
pipe_ip = FluxControlNetInpaintPipeline.from_pretrained(repo_id, controlnet=controlnet, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
132 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
133 |
-
last_model = repo_id
|
134 |
-
last_cn_on = cn_on
|
135 |
-
progress(1, desc=f"Model loaded: {repo_id} / ControlNet Loaded: {controlnet_model_union_repo}")
|
136 |
-
print(f"Model loaded: {repo_id} / ControlNet Loaded: {controlnet_model_union_repo}")
|
137 |
-
else:
|
138 |
-
progress(0, desc=f"Loading model: {repo_id}")
|
139 |
-
print(f"Loading model: {repo_id}")
|
140 |
-
if ".safetensors" in repo_id:
|
141 |
-
safetensors_file = download_file_mod(repo_id)
|
142 |
-
transformer = FluxTransformer2DModel.from_single_file(safetensors_file, subfolder="transformer", torch_dtype=dtype, config=single_file_base_model, token=HF_TOKEN)
|
143 |
-
if CACHE_MODEL:
|
144 |
-
pipe = DiffusionPipeline.from_pretrained(single_file_base_model, vae=taef1, transformer=transformer, text_encoder=pipe.text_encoder,
|
145 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
146 |
-
else: pipe = DiffusionPipeline.from_pretrained(single_file_base_model, transformer=transformer, torch_dtype=dtype, token=HF_TOKEN)
|
147 |
-
pipe_i2i = AutoPipelineForImage2Image.from_pretrained(single_file_base_model, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
148 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
149 |
-
pipe_ip = AutoPipelineForInpainting.from_pretrained(single_file_base_model, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
150 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
151 |
-
else:
|
152 |
-
if CACHE_MODEL:
|
153 |
-
transformer = FluxTransformer2DModel.from_pretrained(repo_id, subfolder="transformer", torch_dtype=dtype, token=HF_TOKEN)
|
154 |
-
pipe = DiffusionPipeline.from_pretrained(repo_id, vae=taef1, transformer=transformer, text_encoder=pipe.text_encoder,
|
155 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
156 |
-
else: pipe = DiffusionPipeline.from_pretrained(repo_id, torch_dtype=dtype, token=HF_TOKEN)
|
157 |
-
pipe_i2i = AutoPipelineForImage2Image.from_pretrained(repo_id, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
158 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
159 |
-
pipe_ip = AutoPipelineForInpainting.from_pretrained(repo_id, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
160 |
-
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
161 |
-
last_model = repo_id
|
162 |
-
last_cn_on = cn_on
|
163 |
-
progress(1, desc=f"Model loaded: {repo_id}")
|
164 |
-
print(f"Model loaded: {repo_id}")
|
165 |
except Exception as e:
|
166 |
print(f"Model load Error: {repo_id} {e}")
|
167 |
raise gr.Error(f"Model load Error: {repo_id} {e}") from e
|
168 |
-
finally:
|
169 |
-
if safetensors_file and Path(safetensors_file).exists(): Path(safetensors_file).unlink()
|
170 |
return gr.update()
|
171 |
|
172 |
change_base_model.zerogpu = True
|
@@ -441,7 +451,7 @@ def remove_custom_lora(selected_indices, current_loras, gallery):
|
|
441 |
|
442 |
@spaces.GPU(duration=70)
|
443 |
@torch.inference_mode()
|
444 |
-
def generate_image(prompt_mash, steps, seed, cfg_scale, width, height, sigmas_factor, cn_on, progress=gr.Progress(track_tqdm=True)):
|
445 |
global pipe, taef1, good_vae, controlnet, controlnet_union
|
446 |
try:
|
447 |
good_vae.to(device)
|
@@ -452,11 +462,11 @@ def generate_image(prompt_mash, steps, seed, cfg_scale, width, height, sigmas_fa
|
|
452 |
with calculateDuration("Generating image"):
|
453 |
# Generate image
|
454 |
modes, images, scales = get_control_params()
|
455 |
-
if not cn_on or len(modes) == 0:
|
456 |
pipe.to(device)
|
457 |
pipe.vae = taef1
|
458 |
pipe.flux_pipe_call_that_returns_an_iterable_of_images = flux_pipe_call_that_returns_an_iterable_of_images.__get__(pipe)
|
459 |
-
|
460 |
for img in pipe.flux_pipe_call_that_returns_an_iterable_of_images(
|
461 |
prompt=prompt_mash,
|
462 |
num_inference_steps=steps,
|
@@ -470,13 +480,13 @@ def generate_image(prompt_mash, steps, seed, cfg_scale, width, height, sigmas_fa
|
|
470 |
sigmas=sigmas,
|
471 |
):
|
472 |
yield img
|
473 |
-
else:
|
474 |
pipe.to(device)
|
475 |
pipe.vae = good_vae
|
476 |
if controlnet_union is not None: controlnet_union.to(device)
|
477 |
if controlnet is not None: controlnet.to(device)
|
478 |
pipe.enable_model_cpu_offload()
|
479 |
-
|
480 |
for img in pipe(
|
481 |
prompt=prompt_mash,
|
482 |
control_image=images,
|
@@ -497,122 +507,94 @@ def generate_image(prompt_mash, steps, seed, cfg_scale, width, height, sigmas_fa
|
|
497 |
|
498 |
@spaces.GPU(duration=70)
|
499 |
@torch.inference_mode()
|
500 |
-
def generate_image_to_image(prompt_mash, image_input_path_dict, image_strength
|
501 |
-
sigmas_factor, seed, cn_on, progress=gr.Progress(track_tqdm=True)):
|
502 |
-
global pipe_i2i,
|
503 |
try:
|
504 |
good_vae.to(device)
|
505 |
generator = torch.Generator(device=device).manual_seed(int(float(seed)))
|
506 |
image_input_path = image_input_path_dict['background']
|
507 |
mask_path = image_input_path_dict['layers'][0]
|
508 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
509 |
|
510 |
with calculateDuration("Generating image"):
|
511 |
# Generate image
|
512 |
modes, images, scales = get_control_params()
|
513 |
-
if not cn_on or len(modes) == 0:
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
mask_input = load_image(mask_path)
|
519 |
-
if blur_mask: mask_input =
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
joint_attention_kwargs={"scale": 1.0},
|
551 |
-
output_type="pil",
|
552 |
-
#sigmas=sigmas,
|
553 |
-
).images[0]
|
554 |
-
return final_image
|
555 |
-
else:
|
556 |
-
if is_inpaint: # Inpainting
|
557 |
-
pipe_ip.to(device)
|
558 |
-
pipe_ip.vae = good_vae
|
559 |
-
image_input = load_image(image_input_path)
|
560 |
mask_input = load_image(mask_path)
|
561 |
-
if blur_mask: mask_input =
|
562 |
-
|
563 |
-
if
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
return final_image
|
584 |
-
else:
|
585 |
-
pipe_i2i.to(device)
|
586 |
-
pipe_i2i.vae = good_vae
|
587 |
-
image_input = load_image(image_input_path['background'])
|
588 |
-
if controlnet_union is not None: controlnet_union.to(device)
|
589 |
-
if controlnet is not None: controlnet.to(device)
|
590 |
-
pipe_i2i.enable_model_cpu_offload()
|
591 |
-
progress(0, desc="Start I2I Inference with ControlNet.")
|
592 |
-
final_image = pipe_i2i(
|
593 |
-
prompt=prompt_mash,
|
594 |
-
control_image=images,
|
595 |
-
control_mode=modes,
|
596 |
-
image=image_input,
|
597 |
-
strength=image_strength,
|
598 |
-
num_inference_steps=steps,
|
599 |
-
guidance_scale=cfg_scale,
|
600 |
-
width=width,
|
601 |
-
height=height,
|
602 |
-
controlnet_conditioning_scale=scales,
|
603 |
-
generator=generator,
|
604 |
-
joint_attention_kwargs={"scale": 1.0},
|
605 |
-
output_type="pil",
|
606 |
-
#sigmas=sigmas,
|
607 |
-
).images[0]
|
608 |
-
return final_image
|
609 |
except Exception as e:
|
610 |
print(e)
|
611 |
raise gr.Error(f"I2I Inference Error: {e}") from e
|
612 |
|
613 |
-
def run_lora(prompt, image_input, image_strength, task_type
|
614 |
-
|
615 |
-
|
|
|
|
|
616 |
if not selected_indices and not is_valid_lora(lora_json):
|
617 |
gr.Info("LoRA isn't selected.")
|
618 |
# raise gr.Error("You must select a LoRA before proceeding.")
|
@@ -620,16 +602,8 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
620 |
|
621 |
selected_loras = [loras_state[idx] for idx in selected_indices]
|
622 |
|
623 |
-
if task_type
|
624 |
-
|
625 |
-
is_i2i = True
|
626 |
-
elif task_type == "Image-to-Image":
|
627 |
-
is_inpaint = False
|
628 |
-
is_i2i = True
|
629 |
-
else: # "Text-to-Image"
|
630 |
-
is_inpaint = False
|
631 |
-
is_i2i = False
|
632 |
-
|
633 |
if translate_on: prompt = translate_to_en(prompt)
|
634 |
|
635 |
# Build the prompt with trigger words
|
@@ -651,7 +625,6 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
651 |
|
652 |
print(pipe.get_active_adapters()) #
|
653 |
print(pipe_i2i.get_active_adapters()) #
|
654 |
-
print(pipe_ip.get_active_adapters()) #
|
655 |
|
656 |
clear_cache() #
|
657 |
|
@@ -659,13 +632,16 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
659 |
prompt_mash = prompt_mash + get_model_trigger(last_model)
|
660 |
lora_names = []
|
661 |
lora_weights = []
|
662 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
663 |
with calculateDuration("Loading External LoRA weights"):
|
664 |
-
if
|
665 |
-
|
666 |
-
elif is_i2i:
|
667 |
-
pipe_i2i, lora_names, lora_weights = fuse_loras(pipe_i2i, lora_json)
|
668 |
-
else: pipe, lora_names, lora_weights = fuse_loras(pipe, lora_json)
|
669 |
trigger_word = get_trigger_word(lora_json)
|
670 |
prompt_mash = f"{prompt_mash} {trigger_word}"
|
671 |
print("Prompt Mash: ", prompt_mash) #
|
@@ -681,15 +657,7 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
681 |
lora_path = lora['repo']
|
682 |
weight_name = lora.get("weights")
|
683 |
print(f"Lora Path: {lora_path}")
|
684 |
-
if
|
685 |
-
pipe_ip.load_lora_weights(
|
686 |
-
lora_path,
|
687 |
-
weight_name=weight_name if weight_name else None,
|
688 |
-
low_cpu_mem_usage=False,
|
689 |
-
adapter_name=lora_name,
|
690 |
-
token=HF_TOKEN
|
691 |
-
)
|
692 |
-
elif is_i2i:
|
693 |
pipe_i2i.load_lora_weights(
|
694 |
lora_path,
|
695 |
weight_name=weight_name if weight_name else None,
|
@@ -707,16 +675,11 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
707 |
)
|
708 |
print("Loaded LoRAs:", lora_names)
|
709 |
if selected_indices or is_valid_lora(lora_json):
|
710 |
-
if
|
711 |
-
|
712 |
-
elif is_i2i:
|
713 |
-
pipe_i2i.set_adapters(lora_names, adapter_weights=lora_weights)
|
714 |
-
else:
|
715 |
-
pipe.set_adapters(lora_names, adapter_weights=lora_weights)
|
716 |
|
717 |
print(pipe.get_active_adapters()) #
|
718 |
print(pipe_i2i.get_active_adapters()) #
|
719 |
-
print(pipe_ip.get_active_adapters()) #
|
720 |
|
721 |
# Set random seed for reproducibility
|
722 |
with calculateDuration("Randomizing seed"):
|
@@ -726,7 +689,7 @@ def run_lora(prompt, image_input, image_strength, task_type, blur_mask, blur_fac
|
|
726 |
# Generate image
|
727 |
progress(0, desc="Running Inference.")
|
728 |
if is_i2i:
|
729 |
-
final_image = generate_image_to_image(prompt_mash, image_input, image_strength,
|
730 |
steps, cfg_scale, width, height, sigmas_factor, seed, cn_on)
|
731 |
yield save_image(final_image, None, last_model, prompt_mash, height, width, steps, cfg_scale, seed), seed, gr.update(visible=False)
|
732 |
else:
|
@@ -898,7 +861,6 @@ with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', fill_width=True, css=css, delete_ca
|
|
898 |
show_share_button=False, show_download_button=True)
|
899 |
history_clear_button = gr.Button(value="Clear History", variant="secondary")
|
900 |
history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False, show_api=False)
|
901 |
-
|
902 |
with gr.Row():
|
903 |
with gr.Accordion("Advanced Settings", open=True):
|
904 |
with gr.Tab("Generation Settings"):
|
@@ -906,9 +868,9 @@ with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', fill_width=True, css=css, delete_ca
|
|
906 |
with gr.Group():
|
907 |
with gr.Row():
|
908 |
model_name = gr.Dropdown(label="Base Model", info="You can enter a huggingface model repo_id or path of single safetensors file to want to use.",
|
909 |
-
|
910 |
model_type = gr.Radio(label="Model type", info="Model type of single safetensors file",
|
911 |
-
|
912 |
model_info = gr.Markdown(elem_classes="info")
|
913 |
with gr.Row():
|
914 |
width = gr.Slider(label="Width", minimum=256, maximum=1536, step=64, value=1024)
|
@@ -918,17 +880,21 @@ with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', fill_width=True, css=css, delete_ca
|
|
918 |
with gr.Row():
|
919 |
randomize_seed = gr.Checkbox(True, label="Randomize seed")
|
920 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0, randomize=True)
|
|
|
|
|
921 |
sigmas_factor = gr.Slider(label="Sigmas factor", minimum=0.01, maximum=1.00, step=0.01, value=0.95)
|
|
|
922 |
disable_model_cache = gr.Checkbox(False, label="Disable model caching")
|
923 |
with gr.Tab("Image-to-Image"):
|
924 |
with gr.Row():
|
925 |
with gr.Column():
|
926 |
#input_image = gr.Image(label="Input image", type="filepath", height=256, sources=["upload", "clipboard"], show_share_button=False)
|
927 |
input_image = gr.ImageEditor(label='Input image', type='filepath', sources=["upload", "clipboard"], image_mode='RGB', show_share_button=False, show_fullscreen_button=False,
|
928 |
-
|
929 |
-
|
930 |
with gr.Column():
|
931 |
-
|
|
|
932 |
image_strength = gr.Slider(label="Strength", info="Lower means more image influence in I2I, opposite in Inpaint", minimum=0.01, maximum=1.0, step=0.01, value=0.75)
|
933 |
blur_mask = gr.Checkbox(label="Blur mask", value=False)
|
934 |
blur_factor = gr.Slider(label="Blur factor", minimum=0, maximum=50, step=1, value=33)
|
@@ -1033,27 +999,23 @@ with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', fill_width=True, css=css, delete_ca
|
|
1033 |
gr.on(
|
1034 |
triggers=[generate_button.click, prompt.submit],
|
1035 |
fn=change_base_model,
|
1036 |
-
inputs=[model_name, cn_on, disable_model_cache, model_type],
|
1037 |
outputs=[result],
|
1038 |
queue=True,
|
1039 |
show_api=False,
|
1040 |
trigger_mode="once",
|
1041 |
).success(
|
1042 |
fn=run_lora,
|
1043 |
-
inputs=[prompt, input_image, image_strength, task_type, blur_mask, blur_factor, cfg_scale, steps, selected_indices, lora_scale_1, lora_scale_2,
|
1044 |
randomize_seed, seed, width, height, sigmas_factor, loras_state, lora_repo_json, cn_on, auto_trans],
|
1045 |
outputs=[result, seed, progress_bar],
|
1046 |
queue=True,
|
1047 |
show_api=True,
|
1048 |
-
#).then( # Update the history gallery
|
1049 |
-
# fn=lambda x, history: update_history(x, history),
|
1050 |
-
# inputs=[result, history_gallery],
|
1051 |
-
# outputs=history_gallery,
|
1052 |
).success(save_image_history, [result, history_gallery, history_files, model_name], [history_gallery, history_files], queue=False, show_api=False)
|
1053 |
|
1054 |
input_image.clear(lambda: gr.update(value="Text-to-Image"), None, [task_type], queue=False, show_api=False)
|
1055 |
-
input_image.upload(preprocess_i2i_image, [input_image, input_image_preprocess, height, width], [input_image], queue=False, show_api=False)
|
1056 |
-
|
1057 |
gr.on(
|
1058 |
triggers=[model_name.change, cn_on.change],
|
1059 |
fn=get_t2i_model_info,
|
@@ -1062,7 +1024,7 @@ with gr.Blocks(theme='NoCrypt/miku@>=1.2.2', fill_width=True, css=css, delete_ca
|
|
1062 |
queue=False,
|
1063 |
show_api=False,
|
1064 |
trigger_mode="once",
|
1065 |
-
)
|
1066 |
prompt_enhance.click(enhance_prompt, [prompt], [prompt], queue=False, show_api=False)
|
1067 |
|
1068 |
gr.on(
|
|
|
2 |
import gradio as gr
|
3 |
import json
|
4 |
import torch
|
5 |
+
from diffusers import DiffusionPipeline, AutoencoderTiny, AutoencoderKL, AutoPipelineForImage2Image, AutoPipelineForInpainting, GGUFQuantizationConfig
|
6 |
from live_preview_helpers import calculate_shift, retrieve_timesteps, flux_pipe_call_that_returns_an_iterable_of_images
|
7 |
from diffusers.utils import load_image
|
8 |
+
from diffusers import (FluxControlNetPipeline, FluxControlNetModel, FluxMultiControlNetModel, FluxControlNetImg2ImgPipeline,
|
9 |
+
FluxTransformer2DModel, FluxControlNetInpaintPipeline, FluxImg2ImgPipeline, FluxInpaintPipeline, FluxFillPipeline, FluxControlPipeline)
|
10 |
+
from transformers import T5EncoderModel
|
11 |
from huggingface_hub import hf_hub_download, HfFileSystem, ModelCard, snapshot_download, HfApi
|
12 |
import os
|
13 |
import copy
|
|
|
18 |
import numpy as np
|
19 |
from pathlib import Path
|
20 |
|
21 |
+
from env import models, models_dev, models_schnell, models_fill, models_canny, models_depth, num_loras, num_cns, HF_TOKEN, single_file_base_models
|
22 |
from mod import (clear_cache, get_repo_safetensors, is_repo_name, is_repo_exists, get_model_trigger,
|
23 |
+
description_ui, compose_lora_json, is_valid_lora, fuse_loras, turbo_loras, save_image, preprocess_i2i_image,
|
24 |
+
get_trigger_word, enhance_prompt, set_control_union_image, get_canny_image, get_depth_image,
|
25 |
get_control_union_mode, set_control_union_mode, get_control_params, translate_to_en)
|
26 |
from modutils import (search_civitai_lora, select_civitai_lora, search_civitai_lora_json,
|
27 |
download_my_lora_flux, get_all_lora_tupled_list, apply_lora_prompt_flux,
|
|
|
44 |
#controlnet_model_union_repo = 'Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro'
|
45 |
dtype = torch.bfloat16
|
46 |
#dtype = torch.float8_e4m3fn
|
|
|
47 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
48 |
taef1 = AutoencoderTiny.from_pretrained("madebyollin/taef1", torch_dtype=dtype, token=HF_TOKEN)
|
49 |
good_vae = AutoencoderKL.from_pretrained(base_model, subfolder="vae", torch_dtype=dtype, token=HF_TOKEN)
|
50 |
pipe = DiffusionPipeline.from_pretrained(base_model, torch_dtype=dtype, vae=taef1, token=HF_TOKEN)
|
|
|
|
|
|
|
|
|
|
|
51 |
pipe_i2i = AutoPipelineForImage2Image.from_pretrained(base_model, vae=good_vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
52 |
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=HF_TOKEN)
|
|
|
|
|
53 |
controlnet_union = None
|
54 |
controlnet = None
|
55 |
last_model = models[0]
|
56 |
last_cn_on = False
|
57 |
+
last_task = "Text-to-Image"
|
58 |
+
last_dtype_str = "BF16"
|
59 |
#controlnet_union = FluxControlNetModel.from_pretrained(controlnet_model_union_repo, torch_dtype=dtype)
|
60 |
#controlnet = FluxMultiControlNetModel([controlnet_union])
|
61 |
#controlnet.config = controlnet_union.config
|
62 |
|
63 |
MAX_SEED = 2**32-1
|
64 |
+
TASK_TYPE_T2I = ["Text-to-Image"]
|
65 |
+
TASK_TYPE_I2I = ["Image-to-Image", "Inpainting", "Flux Fill"] # , "Canny", "Depth"
|
66 |
|
67 |
def unload_lora():
|
68 |
+
global pipe, pipe_i2i
|
69 |
try:
|
70 |
#pipe.unfuse_lora()
|
71 |
pipe.unload_lora_weights()
|
72 |
#pipe_i2i.unfuse_lora()
|
73 |
pipe_i2i.unload_lora_weights()
|
|
|
|
|
74 |
except Exception as e:
|
75 |
print(e)
|
76 |
|
|
|
79 |
if not path: raise Exception(f"Download error: {url}")
|
80 |
return path
|
81 |
|
82 |
+
def print_progress(desc: str, proceed: float=0.0, progress=gr.Progress(track_tqdm=True)):
|
83 |
+
progress(proceed, desc=desc)
|
84 |
+
print(desc)
|
85 |
+
|
86 |
+
#@spaces.GPU(duration=30)
|
87 |
+
def load_quantized_control(control_repo: str, dtype, hf_token):
|
88 |
+
transformer = FluxTransformer2DModel.from_pretrained(control_repo, subfolder="transformer", torch_dtype=dtype, token=hf_token).to("cpu")
|
89 |
+
text_encoder_2 = T5EncoderModel.from_pretrained(control_repo, subfolder="text_encoder_2", torch_dtype=dtype, token=hf_token).to("cpu")
|
90 |
+
return transformer, text_encoder_2
|
91 |
+
|
92 |
+
def load_pipeline(repo_id: str, cn_on: bool, model_type: str, task: str, dtype_str: str, hf_token: str, progress=gr.Progress(track_tqdm=True)):
|
93 |
+
pipe = None
|
94 |
+
pipe_i2i = None
|
95 |
+
try:
|
96 |
+
controlnet_model_union_repo = 'InstantX/FLUX.1-dev-Controlnet-Union'
|
97 |
+
if task == "Flux Fill" or repo_id in models_fill:
|
98 |
+
model_type = "fill"
|
99 |
+
if repo_id in set(models_dev + models_schnell): repo_id = models_fill[0]
|
100 |
+
if dtype_str == "BF16": dtype = torch.bfloat16
|
101 |
+
else: dtype = torch.bfloat16
|
102 |
+
single_file_base_model = single_file_base_models.get(model_type, models[0])
|
103 |
+
kwargs = {}
|
104 |
+
transformer_model = FluxTransformer2DModel
|
105 |
+
t5_model = T5EncoderModel
|
106 |
+
if task == "Flux Fill":
|
107 |
+
pipeline = FluxFillPipeline
|
108 |
+
pipeline_i2i = FluxFillPipeline
|
109 |
+
elif task == "Canny" or task == "Depth":
|
110 |
+
pipeline = DiffusionPipeline
|
111 |
+
pipeline_i2i = FluxControlPipeline
|
112 |
+
elif cn_on: # with ControlNet
|
113 |
+
print_progress(f"Loading model: {repo_id} / Loading ControlNet: {controlnet_model_union_repo}", 0, progress)
|
114 |
+
controlnet_union = FluxControlNetModel.from_pretrained(controlnet_model_union_repo, torch_dtype=dtype, token=hf_token)
|
115 |
+
controlnet = FluxMultiControlNetModel([controlnet_union])
|
116 |
+
controlnet.config = controlnet_union.config
|
117 |
+
pipeline = FluxControlNetPipeline
|
118 |
+
pipeline_i2i = FluxControlNetInpaintPipeline if task == "Inpainting" else FluxControlNetImg2ImgPipeline
|
119 |
+
kwargs["controlnet"] = controlnet
|
120 |
+
else: # without ControlNet
|
121 |
+
print_progress(f"Loading model: {repo_id}", 0, progress)
|
122 |
+
pipeline = DiffusionPipeline
|
123 |
+
pipeline_i2i = AutoPipelineForInpainting if task == "Inpainting" else AutoPipelineForImage2Image
|
124 |
+
if task == "Canny" or task == "Depth": # FluxControlPipeline
|
125 |
+
if task == "Canny": control_repo = models_canny[0]
|
126 |
+
elif task == "Depth": control_repo = models_depth[0]
|
127 |
+
transformer = transformer_model.from_pretrained(control_repo, subfolder="transformer", torch_dtype=dtype, token=hf_token)
|
128 |
+
text_encoder_2 = t5_model.from_pretrained(control_repo, subfolder="text_encoder_2", torch_dtype=dtype, token=hf_token)
|
129 |
+
#transformer, text_encoder_2 = load_quantized_control(control_repo, dtype, hf_token)
|
130 |
+
pipe = pipeline.from_pretrained(models_dev[0], transformer=transformer, text_encoder_2=text_encoder_2, torch_dtype=dtype, token=hf_token)
|
131 |
+
pipe_i2i = pipeline_i2i.from_pipe(pipe, transformer=transformer, text_encoder_2=text_encoder_2, torch_dtype=dtype)
|
132 |
+
elif ".safetensors" in repo_id or ".gguf" in repo_id: # from single file
|
133 |
+
file_url = repo_id.replace("/resolve/main/", "/blob/main/").replace("?download=true", "")
|
134 |
+
if ".gguf" in file_url: transformer_model.from_single_file(file_url, subfolder="transformer",
|
135 |
+
quantization_config=GGUFQuantizationConfig(compute_dtype=dtype), torch_dtype=dtype, config=single_file_base_model)
|
136 |
+
else: transformer = transformer_model.from_single_file(file_url, subfolder="transformer", torch_dtype=dtype, config=single_file_base_model)
|
137 |
+
pipe = pipeline.from_pretrained(single_file_base_model, transformer=transformer, torch_dtype=dtype, token=hf_token, **kwargs)
|
138 |
+
pipe_i2i = pipeline_i2i.from_pretrained(single_file_base_model, vae=pipe.vae, transformer=pipe.transformer,
|
139 |
+
text_encoder=pipe.text_encoder, tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2,
|
140 |
+
torch_dtype=dtype, token=hf_token, **kwargs)
|
141 |
+
else: # from diffusers repo
|
142 |
+
pipe = pipeline.from_pretrained(repo_id, torch_dtype=dtype, token=hf_token, **kwargs)
|
143 |
+
pipe_i2i = pipeline_i2i.from_pretrained(repo_id, vae=pipe.vae, transformer=pipe.transformer, text_encoder=pipe.text_encoder,
|
144 |
+
tokenizer=pipe.tokenizer, text_encoder_2=pipe.text_encoder_2, tokenizer_2=pipe.tokenizer_2, torch_dtype=dtype, token=hf_token, **kwargs)
|
145 |
+
if cn_on: print_progress(f"Model loaded: {repo_id} / ControlNet Loaded: {controlnet_model_union_repo}", 1, progress)
|
146 |
+
else: print_progress(f"Model loaded: {repo_id}", 1, progress)
|
147 |
+
except Exception as e:
|
148 |
+
print(e)
|
149 |
+
gr.Warning(f"Failed to load pipeline: {e}")
|
150 |
+
finally:
|
151 |
+
return pipe, pipe_i2i
|
152 |
+
|
153 |
+
#load_pipeline.zerogpu = True
|
154 |
+
|
155 |
# https://huggingface.co/InstantX/FLUX.1-dev-Controlnet-Union
|
156 |
# https://huggingface.co/spaces/jiuface/FLUX.1-dev-Controlnet-Union
|
157 |
# https://huggingface.co/docs/diffusers/main/en/api/pipelines/flux
|
158 |
#@spaces.GPU()
|
159 |
+
def change_base_model(repo_id: str, cn_on: bool, disable_model_cache: bool, model_type: str, task: str, dtype_str: str, progress=gr.Progress(track_tqdm=True)):
|
160 |
+
global pipe, pipe_i2i, taef1, good_vae, controlnet_union, controlnet, last_model, last_cn_on, last_task, last_dtype_str, dtype
|
|
|
|
|
161 |
try:
|
162 |
+
if not disable_model_cache and (repo_id == last_model and cn_on is last_cn_on and task == last_task and dtype_str == last_dtype_str)\
|
163 |
+
or ((not is_repo_name(repo_id) or not is_repo_exists(repo_id)) and not ".safetensors" in repo_id): return gr.update()
|
164 |
unload_lora()
|
165 |
pipe.to("cpu")
|
166 |
pipe_i2i.to("cpu")
|
|
|
167 |
good_vae.to("cpu")
|
168 |
taef1.to("cpu")
|
169 |
if controlnet is not None: controlnet.to("cpu")
|
170 |
if controlnet_union is not None: controlnet_union.to("cpu")
|
171 |
clear_cache()
|
172 |
+
pipe, pipe_i2i = load_pipeline(repo_id, cn_on, model_type, task, dtype_str, HF_TOKEN, progress)
|
173 |
+
last_model = repo_id
|
174 |
+
last_cn_on = cn_on
|
175 |
+
last_task = task
|
176 |
+
last_dtype_str = dtype_str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
except Exception as e:
|
178 |
print(f"Model load Error: {repo_id} {e}")
|
179 |
raise gr.Error(f"Model load Error: {repo_id} {e}") from e
|
|
|
|
|
180 |
return gr.update()
|
181 |
|
182 |
change_base_model.zerogpu = True
|
|
|
451 |
|
452 |
@spaces.GPU(duration=70)
|
453 |
@torch.inference_mode()
|
454 |
+
def generate_image(prompt_mash: str, steps: int, seed: int, cfg_scale: float, width: int, height: int, sigmas_factor: float, cn_on: bool, progress=gr.Progress(track_tqdm=True)):
|
455 |
global pipe, taef1, good_vae, controlnet, controlnet_union
|
456 |
try:
|
457 |
good_vae.to(device)
|
|
|
462 |
with calculateDuration("Generating image"):
|
463 |
# Generate image
|
464 |
modes, images, scales = get_control_params()
|
465 |
+
if not cn_on or len(modes) == 0: # without ControlNet
|
466 |
pipe.to(device)
|
467 |
pipe.vae = taef1
|
468 |
pipe.flux_pipe_call_that_returns_an_iterable_of_images = flux_pipe_call_that_returns_an_iterable_of_images.__get__(pipe)
|
469 |
+
print_progress("Start Inference.")
|
470 |
for img in pipe.flux_pipe_call_that_returns_an_iterable_of_images(
|
471 |
prompt=prompt_mash,
|
472 |
num_inference_steps=steps,
|
|
|
480 |
sigmas=sigmas,
|
481 |
):
|
482 |
yield img
|
483 |
+
else: # with ControlNet
|
484 |
pipe.to(device)
|
485 |
pipe.vae = good_vae
|
486 |
if controlnet_union is not None: controlnet_union.to(device)
|
487 |
if controlnet is not None: controlnet.to(device)
|
488 |
pipe.enable_model_cpu_offload()
|
489 |
+
print_progress("Start Inference with ControlNet.")
|
490 |
for img in pipe(
|
491 |
prompt=prompt_mash,
|
492 |
control_image=images,
|
|
|
507 |
|
508 |
@spaces.GPU(duration=70)
|
509 |
@torch.inference_mode()
|
510 |
+
def generate_image_to_image(prompt_mash: str, image_input_path_dict: dict, image_strength: float, task_type: str, blur_mask: bool, blur_factor: float,
|
511 |
+
steps: int, cfg_scale: float, width: int, height: int, sigmas_factor: float, seed: int, cn_on: bool, progress=gr.Progress(track_tqdm=True)):
|
512 |
+
global pipe_i2i, good_vae, controlnet, controlnet_union
|
513 |
try:
|
514 |
good_vae.to(device)
|
515 |
generator = torch.Generator(device=device).manual_seed(int(float(seed)))
|
516 |
image_input_path = image_input_path_dict['background']
|
517 |
mask_path = image_input_path_dict['layers'][0]
|
518 |
+
is_mask = True if task_type == "Inpainting" or task_type == "Flux Fill" else False
|
519 |
+
is_fill = True if task_type == "Flux Fill" else False
|
520 |
+
is_depth = True if task_type == "Depth" else False
|
521 |
+
is_canny = True if task_type == "Canny" else False
|
522 |
+
kwargs = {}
|
523 |
+
if not is_fill: kwargs["strength"] = image_strength
|
524 |
+
if sigmas_factor < 1.0 and task_type != "Image-to-Image": kwargs["sigmas"] = calc_sigmas(steps, sigmas_factor)
|
525 |
|
526 |
with calculateDuration("Generating image"):
|
527 |
# Generate image
|
528 |
modes, images, scales = get_control_params()
|
529 |
+
if not cn_on or len(modes) == 0: # without ControlNet
|
530 |
+
pipe_i2i.to(device)
|
531 |
+
pipe_i2i.vae = good_vae
|
532 |
+
image_input = load_image(image_input_path)
|
533 |
+
if is_mask:
|
534 |
mask_input = load_image(mask_path)
|
535 |
+
if blur_mask: mask_input = pipe_i2i.mask_processor.blur(mask_input, blur_factor=blur_factor)
|
536 |
+
kwargs["mask_image"] = mask_input
|
537 |
+
if is_fill: print_progress("Start Flux Fill Inference.")
|
538 |
+
else: print_progress("Start Inpainting Inference.")
|
539 |
+
elif is_canny:
|
540 |
+
image_input = get_canny_image(image_input, height, width)
|
541 |
+
print_progress("Start Canny Inference.")
|
542 |
+
elif is_depth:
|
543 |
+
image_input = get_depth_image(image_input, height, width)
|
544 |
+
print_progress("Start Depth Inference.")
|
545 |
+
else: print_progress("Start I2I Inference.")
|
546 |
+
final_image = pipe_i2i(
|
547 |
+
prompt=prompt_mash,
|
548 |
+
image=image_input,
|
549 |
+
num_inference_steps=steps,
|
550 |
+
guidance_scale=cfg_scale,
|
551 |
+
#width=width,
|
552 |
+
#height=height,
|
553 |
+
generator=generator,
|
554 |
+
joint_attention_kwargs={"scale": 1.0},
|
555 |
+
output_type="pil",
|
556 |
+
**kwargs,
|
557 |
+
).images[0]
|
558 |
+
return final_image
|
559 |
+
else: # with ControlNet
|
560 |
+
pipe_i2i.to(device)
|
561 |
+
pipe_i2i.vae = good_vae
|
562 |
+
image_input = load_image(image_input_path)
|
563 |
+
if controlnet_union is not None: controlnet_union.to(device)
|
564 |
+
if controlnet is not None: controlnet.to(device)
|
565 |
+
if is_mask:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
566 |
mask_input = load_image(mask_path)
|
567 |
+
if blur_mask: mask_input = pipe_i2i.mask_processor.blur(mask_input, blur_factor=blur_factor)
|
568 |
+
kwargs["mask_image"] = mask_input
|
569 |
+
if is_fill: print_progress("Start Flux Fill Inference with ControlNet.")
|
570 |
+
else: print_progress("Start Inpainting Inference with ControlNet.")
|
571 |
+
else: print_progress("Start I2I Inference with ControlNet.")
|
572 |
+
pipe_i2i.enable_model_cpu_offload()
|
573 |
+
final_image = pipe_i2i(
|
574 |
+
prompt=prompt_mash,
|
575 |
+
control_image=images,
|
576 |
+
control_mode=modes,
|
577 |
+
image=image_input,
|
578 |
+
num_inference_steps=steps,
|
579 |
+
guidance_scale=cfg_scale,
|
580 |
+
#width=width,
|
581 |
+
#height=height,
|
582 |
+
controlnet_conditioning_scale=scales,
|
583 |
+
generator=generator,
|
584 |
+
joint_attention_kwargs={"scale": 1.0},
|
585 |
+
output_type="pil",
|
586 |
+
**kwargs,
|
587 |
+
).images[0]
|
588 |
+
return final_image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
589 |
except Exception as e:
|
590 |
print(e)
|
591 |
raise gr.Error(f"I2I Inference Error: {e}") from e
|
592 |
|
593 |
+
def run_lora(prompt: str, image_input: dict, image_strength: float, task_type: str, turbo_mode: str, blur_mask: bool, blur_factor: float,
|
594 |
+
cfg_scale: float, steps: int, selected_indices, lora_scale_1: float, lora_scale_2: float,
|
595 |
+
randomize_seed: bool, seed: int, width: int, height: int, sigmas_factor: float, loras_state,
|
596 |
+
lora_json, cn_on: bool, translate_on: bool, progress=gr.Progress(track_tqdm=True)):
|
597 |
+
global pipe, pipe_i2i
|
598 |
if not selected_indices and not is_valid_lora(lora_json):
|
599 |
gr.Info("LoRA isn't selected.")
|
600 |
# raise gr.Error("You must select a LoRA before proceeding.")
|
|
|
602 |
|
603 |
selected_loras = [loras_state[idx] for idx in selected_indices]
|
604 |
|
605 |
+
if task_type in set(TASK_TYPE_I2I): is_i2i = True
|
606 |
+
else: is_i2i = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
if translate_on: prompt = translate_to_en(prompt)
|
608 |
|
609 |
# Build the prompt with trigger words
|
|
|
625 |
|
626 |
print(pipe.get_active_adapters()) #
|
627 |
print(pipe_i2i.get_active_adapters()) #
|
|
|
628 |
|
629 |
clear_cache() #
|
630 |
|
|
|
632 |
prompt_mash = prompt_mash + get_model_trigger(last_model)
|
633 |
lora_names = []
|
634 |
lora_weights = []
|
635 |
+
# Load Turbo LoRA weights
|
636 |
+
if turbo_mode != "None":
|
637 |
+
if is_i2i: pipe_i2i, lora_names, lora_weights, steps = turbo_loras(pipe_i2i, turbo_mode, lora_names, lora_weights)
|
638 |
+
else: pipe, lora_names, lora_weights, steps = turbo_loras(pipe, turbo_mode, lora_names, lora_weights)
|
639 |
+
|
640 |
+
# Load External LoRA weights
|
641 |
+
if is_valid_lora(lora_json):
|
642 |
with calculateDuration("Loading External LoRA weights"):
|
643 |
+
if is_i2i: pipe_i2i, lora_names, lora_weights = fuse_loras(pipe_i2i, lora_json, lora_names, lora_weights)
|
644 |
+
else: pipe, lora_names, lora_weights = fuse_loras(pipe, lora_json, lora_names, lora_weights)
|
|
|
|
|
|
|
645 |
trigger_word = get_trigger_word(lora_json)
|
646 |
prompt_mash = f"{prompt_mash} {trigger_word}"
|
647 |
print("Prompt Mash: ", prompt_mash) #
|
|
|
657 |
lora_path = lora['repo']
|
658 |
weight_name = lora.get("weights")
|
659 |
print(f"Lora Path: {lora_path}")
|
660 |
+
if is_i2i:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
pipe_i2i.load_lora_weights(
|
662 |
lora_path,
|
663 |
weight_name=weight_name if weight_name else None,
|
|
|
675 |
)
|
676 |
print("Loaded LoRAs:", lora_names)
|
677 |
if selected_indices or is_valid_lora(lora_json):
|
678 |
+
if is_i2i: pipe_i2i.set_adapters(lora_names, adapter_weights=lora_weights)
|
679 |
+
else: pipe.set_adapters(lora_names, adapter_weights=lora_weights)
|
|
|
|
|
|
|
|
|
680 |
|
681 |
print(pipe.get_active_adapters()) #
|
682 |
print(pipe_i2i.get_active_adapters()) #
|
|
|
683 |
|
684 |
# Set random seed for reproducibility
|
685 |
with calculateDuration("Randomizing seed"):
|
|
|
689 |
# Generate image
|
690 |
progress(0, desc="Running Inference.")
|
691 |
if is_i2i:
|
692 |
+
final_image = generate_image_to_image(prompt_mash, image_input, image_strength, task_type, blur_mask, blur_factor,
|
693 |
steps, cfg_scale, width, height, sigmas_factor, seed, cn_on)
|
694 |
yield save_image(final_image, None, last_model, prompt_mash, height, width, steps, cfg_scale, seed), seed, gr.update(visible=False)
|
695 |
else:
|
|
|
861 |
show_share_button=False, show_download_button=True)
|
862 |
history_clear_button = gr.Button(value="Clear History", variant="secondary")
|
863 |
history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False, show_api=False)
|
|
|
864 |
with gr.Row():
|
865 |
with gr.Accordion("Advanced Settings", open=True):
|
866 |
with gr.Tab("Generation Settings"):
|
|
|
868 |
with gr.Group():
|
869 |
with gr.Row():
|
870 |
model_name = gr.Dropdown(label="Base Model", info="You can enter a huggingface model repo_id or path of single safetensors file to want to use.",
|
871 |
+
choices=models, value=models[0], allow_custom_value=True, min_width=320, scale=5)
|
872 |
model_type = gr.Radio(label="Model type", info="Model type of single safetensors file",
|
873 |
+
choices=list(single_file_base_models.keys()), value=list(single_file_base_models.keys())[0], scale=1)
|
874 |
model_info = gr.Markdown(elem_classes="info")
|
875 |
with gr.Row():
|
876 |
width = gr.Slider(label="Width", minimum=256, maximum=1536, step=64, value=1024)
|
|
|
880 |
with gr.Row():
|
881 |
randomize_seed = gr.Checkbox(True, label="Randomize seed")
|
882 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0, randomize=True)
|
883 |
+
with gr.Row():
|
884 |
+
turbo_mode = gr.Radio(label="Turbo mode", choices=["None", "Hyper-FLUX.1-dev-8steps", "Hyper-FLUX.1-dev-16steps", "FLUX.1-Turbo-Alpha 8-steps"], value="None")
|
885 |
sigmas_factor = gr.Slider(label="Sigmas factor", minimum=0.01, maximum=1.00, step=0.01, value=0.95)
|
886 |
+
data_type = gr.Radio(label="Data type", choices=["BF16"], value="BF16", visible=False)
|
887 |
disable_model_cache = gr.Checkbox(False, label="Disable model caching")
|
888 |
with gr.Tab("Image-to-Image"):
|
889 |
with gr.Row():
|
890 |
with gr.Column():
|
891 |
#input_image = gr.Image(label="Input image", type="filepath", height=256, sources=["upload", "clipboard"], show_share_button=False)
|
892 |
input_image = gr.ImageEditor(label='Input image', type='filepath', sources=["upload", "clipboard"], image_mode='RGB', show_share_button=False, show_fullscreen_button=False,
|
893 |
+
layers=False, brush=gr.Brush(colors=["white"], color_mode="fixed", default_size=32), eraser=gr.Eraser(default_size="32"), value=None,
|
894 |
+
canvas_size=(384, 384), width=384, height=512)
|
895 |
with gr.Column():
|
896 |
+
|
897 |
+
task_type = gr.Radio(label="Task", choices=TASK_TYPE_T2I+TASK_TYPE_I2I, value=TASK_TYPE_T2I[0])
|
898 |
image_strength = gr.Slider(label="Strength", info="Lower means more image influence in I2I, opposite in Inpaint", minimum=0.01, maximum=1.0, step=0.01, value=0.75)
|
899 |
blur_mask = gr.Checkbox(label="Blur mask", value=False)
|
900 |
blur_factor = gr.Slider(label="Blur factor", minimum=0, maximum=50, step=1, value=33)
|
|
|
999 |
gr.on(
|
1000 |
triggers=[generate_button.click, prompt.submit],
|
1001 |
fn=change_base_model,
|
1002 |
+
inputs=[model_name, cn_on, disable_model_cache, model_type, task_type, data_type],
|
1003 |
outputs=[result],
|
1004 |
queue=True,
|
1005 |
show_api=False,
|
1006 |
trigger_mode="once",
|
1007 |
).success(
|
1008 |
fn=run_lora,
|
1009 |
+
inputs=[prompt, input_image, image_strength, task_type, turbo_mode, blur_mask, blur_factor, cfg_scale, steps, selected_indices, lora_scale_1, lora_scale_2,
|
1010 |
randomize_seed, seed, width, height, sigmas_factor, loras_state, lora_repo_json, cn_on, auto_trans],
|
1011 |
outputs=[result, seed, progress_bar],
|
1012 |
queue=True,
|
1013 |
show_api=True,
|
|
|
|
|
|
|
|
|
1014 |
).success(save_image_history, [result, history_gallery, history_files, model_name], [history_gallery, history_files], queue=False, show_api=False)
|
1015 |
|
1016 |
input_image.clear(lambda: gr.update(value="Text-to-Image"), None, [task_type], queue=False, show_api=False)
|
1017 |
+
input_image.upload(preprocess_i2i_image, [input_image, input_image_preprocess, height, width], [input_image], queue=False, show_api=False)#\
|
1018 |
+
#.success(lambda: gr.update(value="Image-to-Image"), None, [task_type], queue=False, show_api=False)
|
1019 |
gr.on(
|
1020 |
triggers=[model_name.change, cn_on.change],
|
1021 |
fn=get_t2i_model_info,
|
|
|
1024 |
queue=False,
|
1025 |
show_api=False,
|
1026 |
trigger_mode="once",
|
1027 |
+
)
|
1028 |
prompt_enhance.click(enhance_prompt, [prompt], [prompt], queue=False, show_api=False)
|
1029 |
|
1030 |
gr.on(
|
env.py
CHANGED
@@ -10,9 +10,8 @@ num_loras = 3
|
|
10 |
num_cns = 2
|
11 |
|
12 |
|
13 |
-
|
14 |
"camenduru/FLUX.1-dev-diffusers",
|
15 |
-
"black-forest-labs/FLUX.1-schnell",
|
16 |
"sayakpaul/FLUX.1-merged",
|
17 |
"ostris/OpenFLUX.1",
|
18 |
"multimodalart/FLUX.1-dev2pro-full",
|
@@ -63,11 +62,27 @@ models = [
|
|
63 |
"John6666/xe-asian-flux-01-fp8-flux",
|
64 |
"John6666/fluxescore-dev-v10fp16-fp8-flux",
|
65 |
"John6666/2758-flux-asian-utopian-v30fp8noclip-fp8-flux",
|
|
|
66 |
"https://huggingface.co/StableDiffusionVN/SDVN11-Ghibli-Flux/blob/main/SDVN11-Ghibli-Flux_fp8-hyper.safetensors",
|
67 |
"https://huggingface.co/datasets/John6666/flux1-backup-202410/blob/main/iniverseMixXLSFWNSFW_f1dFP16V10.safetensors",
|
|
|
68 |
# "",
|
69 |
]
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
model_trigger = {
|
72 |
"Raelina/Raemu-Flux": "anime",
|
73 |
"John6666/raemu-flux-v10-fp8-flux": "anime",
|
@@ -77,6 +92,7 @@ model_trigger = {
|
|
77 |
single_file_base_models = {
|
78 |
"dev": "camenduru/FLUX.1-dev-diffusers",
|
79 |
"schnell": "black-forest-labs/FLUX.1-schnell",
|
|
|
80 |
}
|
81 |
|
82 |
# List all Models for specified user
|
|
|
10 |
num_cns = 2
|
11 |
|
12 |
|
13 |
+
models_dev = [
|
14 |
"camenduru/FLUX.1-dev-diffusers",
|
|
|
15 |
"sayakpaul/FLUX.1-merged",
|
16 |
"ostris/OpenFLUX.1",
|
17 |
"multimodalart/FLUX.1-dev2pro-full",
|
|
|
62 |
"John6666/xe-asian-flux-01-fp8-flux",
|
63 |
"John6666/fluxescore-dev-v10fp16-fp8-flux",
|
64 |
"John6666/2758-flux-asian-utopian-v30fp8noclip-fp8-flux",
|
65 |
+
"trongg/FLUX_dev2pro_nsfw_context_lora",
|
66 |
"https://huggingface.co/StableDiffusionVN/SDVN11-Ghibli-Flux/blob/main/SDVN11-Ghibli-Flux_fp8-hyper.safetensors",
|
67 |
"https://huggingface.co/datasets/John6666/flux1-backup-202410/blob/main/iniverseMixXLSFWNSFW_f1dFP16V10.safetensors",
|
68 |
+
"https://huggingface.co/city96/FLUX.1-dev-gguf/blob/main/flux1-dev-Q2_K.gguf",
|
69 |
# "",
|
70 |
]
|
71 |
|
72 |
+
models_schnell = [
|
73 |
+
"black-forest-labs/FLUX.1-schnell",
|
74 |
+
]
|
75 |
+
|
76 |
+
models_fill = ["fuliucansheng/FLUX.1-Fill-dev-diffusers"]
|
77 |
+
|
78 |
+
models_dedistill = []
|
79 |
+
|
80 |
+
models_canny = ["sayakpaul/FLUX.1-Canny-dev-nf4"]
|
81 |
+
|
82 |
+
models_depth = ["sayakpaul/FLUX.1-Depth-dev-nf4"]
|
83 |
+
|
84 |
+
models = models_dev + models_schnell + models_fill
|
85 |
+
|
86 |
model_trigger = {
|
87 |
"Raelina/Raemu-Flux": "anime",
|
88 |
"John6666/raemu-flux-v10-fp8-flux": "anime",
|
|
|
92 |
single_file_base_models = {
|
93 |
"dev": "camenduru/FLUX.1-dev-diffusers",
|
94 |
"schnell": "black-forest-labs/FLUX.1-schnell",
|
95 |
+
"fill": "fuliucansheng/FLUX.1-Fill-dev-diffusers",
|
96 |
}
|
97 |
|
98 |
# List all Models for specified user
|
mod.py
CHANGED
@@ -8,7 +8,7 @@ import subprocess
|
|
8 |
import os
|
9 |
import re
|
10 |
from translatepy import Translator
|
11 |
-
from huggingface_hub import HfApi
|
12 |
from env import num_cns, model_trigger, HF_TOKEN, CIVITAI_API_KEY, DOWNLOAD_LORA_LIST, DIRECTORY_LORAS
|
13 |
from modutils import download_things
|
14 |
|
@@ -232,6 +232,14 @@ def set_control_union_image(i: int, mode: str, image: Image.Image | None, height
|
|
232 |
return control_images[i]
|
233 |
|
234 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
def preprocess_i2i_image(image_path_dict: dict, is_preprocess: bool, height: int, width: int):
|
236 |
try:
|
237 |
if not is_preprocess: return gr.update()
|
@@ -275,24 +283,22 @@ def get_model_trigger(model_name: str):
|
|
275 |
|
276 |
# https://huggingface.co/docs/diffusers/v0.23.1/en/api/loaders#diffusers.loaders.LoraLoaderMixin.fuse_lora
|
277 |
# https://github.com/huggingface/diffusers/issues/4919
|
278 |
-
def fuse_loras(pipe, lorajson: list[dict]):
|
279 |
try:
|
280 |
-
if not lorajson or not isinstance(lorajson, list): return pipe,
|
281 |
-
a_list = []
|
282 |
-
w_list = []
|
283 |
for d in lorajson:
|
284 |
if not d or not isinstance(d, dict) or not d["name"] or d["name"] == "None": continue
|
285 |
k = d["name"]
|
286 |
if is_repo_name(k) and is_repo_exists(k):
|
287 |
a_name = Path(k).stem
|
288 |
-
pipe.load_lora_weights(k, weight_name=d["filename"], adapter_name = a_name, low_cpu_mem_usage=
|
289 |
elif not Path(k).exists():
|
290 |
print(f"LoRA not found: {k}")
|
291 |
continue
|
292 |
else:
|
293 |
w_name = Path(k).name
|
294 |
a_name = Path(k).stem
|
295 |
-
pipe.load_lora_weights(k, weight_name = w_name, adapter_name = a_name, low_cpu_mem_usage=
|
296 |
a_list.append(a_name)
|
297 |
w_list.append(d["scale"])
|
298 |
if not a_list: return pipe, [], []
|
@@ -305,6 +311,25 @@ def fuse_loras(pipe, lorajson: list[dict]):
|
|
305 |
raise Exception(f"External LoRA Error: {e}") from e
|
306 |
|
307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
def description_ui():
|
309 |
gr.Markdown(
|
310 |
"""
|
|
|
8 |
import os
|
9 |
import re
|
10 |
from translatepy import Translator
|
11 |
+
from huggingface_hub import HfApi, hf_hub_download
|
12 |
from env import num_cns, model_trigger, HF_TOKEN, CIVITAI_API_KEY, DOWNLOAD_LORA_LIST, DIRECTORY_LORAS
|
13 |
from modutils import download_things
|
14 |
|
|
|
232 |
return control_images[i]
|
233 |
|
234 |
|
235 |
+
def get_canny_image(image: Image.Image, height: int, width: int):
|
236 |
+
return preprocess_image(image, "canny", height, width, 384)
|
237 |
+
|
238 |
+
|
239 |
+
def get_depth_image(image: Image.Image, height: int, width: int):
|
240 |
+
return preprocess_image(image, "depth_midas", height, width, 384)
|
241 |
+
|
242 |
+
|
243 |
def preprocess_i2i_image(image_path_dict: dict, is_preprocess: bool, height: int, width: int):
|
244 |
try:
|
245 |
if not is_preprocess: return gr.update()
|
|
|
283 |
|
284 |
# https://huggingface.co/docs/diffusers/v0.23.1/en/api/loaders#diffusers.loaders.LoraLoaderMixin.fuse_lora
|
285 |
# https://github.com/huggingface/diffusers/issues/4919
|
286 |
+
def fuse_loras(pipe, lorajson: list[dict], a_list: list, w_list: list):
|
287 |
try:
|
288 |
+
if not lorajson or not isinstance(lorajson, list): return pipe, a_list, w_list
|
|
|
|
|
289 |
for d in lorajson:
|
290 |
if not d or not isinstance(d, dict) or not d["name"] or d["name"] == "None": continue
|
291 |
k = d["name"]
|
292 |
if is_repo_name(k) and is_repo_exists(k):
|
293 |
a_name = Path(k).stem
|
294 |
+
pipe.load_lora_weights(k, weight_name=d["filename"], adapter_name = a_name, low_cpu_mem_usage=False)
|
295 |
elif not Path(k).exists():
|
296 |
print(f"LoRA not found: {k}")
|
297 |
continue
|
298 |
else:
|
299 |
w_name = Path(k).name
|
300 |
a_name = Path(k).stem
|
301 |
+
pipe.load_lora_weights(k, weight_name = w_name, adapter_name = a_name, low_cpu_mem_usage=False)
|
302 |
a_list.append(a_name)
|
303 |
w_list.append(d["scale"])
|
304 |
if not a_list: return pipe, [], []
|
|
|
311 |
raise Exception(f"External LoRA Error: {e}") from e
|
312 |
|
313 |
|
314 |
+
def turbo_loras(pipe, turbo_mode: str, lora_names: list, lora_weights: list):
|
315 |
+
if turbo_mode == "Hyper-FLUX.1-dev-8steps":
|
316 |
+
lora_names.append("Hyper-FLUX1-dev-8steps")
|
317 |
+
lora_weights.append(0.125)
|
318 |
+
pipe.load_lora_weights(hf_hub_download("ByteDance/Hyper-SD", "Hyper-FLUX.1-dev-8steps-lora.safetensors"), adapter_name=lora_names[-1], low_cpu_mem_usage=False)
|
319 |
+
steps = 8
|
320 |
+
elif turbo_mode == "Hyper-FLUX.1-dev-16steps":
|
321 |
+
lora_names.append("Hyper-FLUX1-dev-16steps")
|
322 |
+
lora_weights.append(0.125)
|
323 |
+
pipe.load_lora_weights(hf_hub_download("ByteDance/Hyper-SD", "Hyper-FLUX.1-dev-16steps-lora.safetensors"), adapter_name=lora_names[-1], low_cpu_mem_usage=False)
|
324 |
+
steps = 16
|
325 |
+
elif turbo_mode == "FLUX.1-Turbo-Alpha 8-steps":
|
326 |
+
lora_names.append("FLUX1-Turbo-Alpha 8-steps")
|
327 |
+
lora_weights.append(1.0)
|
328 |
+
pipe.load_lora_weights("alimama-creative/FLUX.1-Turbo-Alpha", adapter_name=lora_names[-1], low_cpu_mem_usage=False)
|
329 |
+
steps = 8
|
330 |
+
return pipe, lora_names, lora_weights, steps
|
331 |
+
|
332 |
+
|
333 |
def description_ui():
|
334 |
gr.Markdown(
|
335 |
"""
|
requirements.txt
CHANGED
@@ -16,4 +16,7 @@ deepspeed
|
|
16 |
mediapipe
|
17 |
openai>=1.37.0
|
18 |
translatepy
|
19 |
-
unidecode
|
|
|
|
|
|
|
|
16 |
mediapipe
|
17 |
openai>=1.37.0
|
18 |
translatepy
|
19 |
+
unidecode
|
20 |
+
optimum-quanto
|
21 |
+
bitsandbytes
|
22 |
+
gguf
|