Redux / app.py
nftnik's picture
Update app.py
16764be verified
raw
history blame
12.5 kB
import os
import random
import sys
import torch
import gradio as gr
from pathlib import Path
from huggingface_hub import hf_hub_download
import spaces
from typing import Union, Sequence, Mapping, Any
from comfy import model_management
from nodes import NODE_CLASS_MAPPINGS
# 1. Configuração de Caminhos e Imports
current_dir = os.path.dirname(os.path.abspath(__file__))
comfyui_path = os.path.join(current_dir, "ComfyUI")
sys.path.append(comfyui_path)
# 2. Imports do ComfyUI
import folder_paths
from nodes import init_extra_nodes
# 3. Configuração de Diretórios
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
output_dir = os.path.join(BASE_DIR, "output")
models_dir = os.path.join(BASE_DIR, "models")
os.makedirs(output_dir, exist_ok=True)
os.makedirs(models_dir, exist_ok=True)
folder_paths.set_output_directory(output_dir)
# 4. Diagnóstico CUDA
print("Python version:", sys.version)
print("Torch version:", torch.__version__)
print("CUDA disponível:", torch.cuda.is_available())
print("Quantidade de GPUs:", torch.cuda.device_count())
if torch.cuda.is_available():
print("GPU atual:", torch.cuda.get_device_name(0))
# 5. Inicialização do ComfyUI
print("Inicializando ComfyUI...")
init_extra_nodes()
# 6. Helper Functions
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
try:
return obj[index]
except KeyError:
return obj["result"][index]
def find_path(name: str, path: str = None) -> str:
if path is None:
path = os.getcwd()
if name in os.listdir(path):
path_name = os.path.join(path, name)
print(f"{name} found: {path_name}")
return path_name
parent_directory = os.path.dirname(path)
if parent_directory == path:
return None
return find_path(name, parent_directory)
def add_comfyui_directory_to_sys_path() -> None:
comfyui_path = find_path("ComfyUI")
if comfyui_path is not None and os.path.isdir(comfyui_path):
sys.path.append(comfyui_path)
print(f"'{comfyui_path}' added to sys.path")
def add_extra_model_paths() -> None:
try:
from main import load_extra_path_config
except ImportError:
from utils.extra_config import load_extra_path_config
extra_model_paths = find_path("extra_model_paths.yaml")
if extra_model_paths is not None:
load_extra_path_config(extra_model_paths)
else:
print("Could not find the extra_model_paths config file.")
# 7. Inicialização de caminhos
add_comfyui_directory_toSyspath()
add_extra_model_paths()
def import_custom_nodes() -> None:
import asyncio
import execution
import server
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
server_instance = server.PromptServer(loop)
execution.PromptQueue(server_instance)
init_extra_nodes()
# 8. Download de Modelos
def download_models():
print("Baixando modelos...")
models = [
("black-forest-labs/FLUX.1-Redux-dev", "flux1-redux-dev.safetensors", "style_models"),
("comfyanonymous/flux_text_encoders", "t5xxl_fp16.safetensors", "text_encoders"),
("zer0int/CLIP-GmP-ViT-L-14", "ViT-L-14-TEXT-detail-improved-hiT-GmP-HF.safetensors", "text_encoders"),
("black-forest-labs/FLUX.1-dev", "ae.safetensors", "vae"),
("black-forest-labs/FLUX.1-dev", "flux1-dev.safetensors", "diffusion_models"),
("google/siglip-so400m-patch14-384", "model.safetensors", "clip_vision")
]
for repo_id, filename, model_type in models:
try:
model_dir = os.path.join(models_dir, model_type)
os.makedirs(model_dir, exist_ok=True)
print(f"Baixando {filename} de {repo_id}...")
hf_hub_download(repo_id=repo_id, filename=filename, local_dir=model_dir)
# Adicionar o diretório ao folder_paths
folder_paths.add_model_folder_path(model_type, model_dir)
except Exception as e:
print(f"Erro ao baixar {filename} de {repo_id}: {str(e)}")
continue
# 9. Download e Inicialização dos Modelos
print("Baixando modelos...")
download_models()
print("Inicializando modelos...")
import_custom_nodes()
# Global variables for preloaded models and constants
intconstant = NODE_CLASS_MAPPINGS["INTConstant"]()
CONST_1024 = intconstant.get_value(value=1024)
# Load CLIP
dualcliploader = NODE_CLASS_MAPPINGS["DualCLIPLoader"]()
CLIP_MODEL = dualcliploader.load_clip(
clip_name1="t5xxl_fp16.safetensors",
clip_name2="ViT-L-14-TEXT-detail-improved-hiT-GmP-HF.safetensors",
type="flux"
)
# Load VAE
vaeloader = NODE_CLASS_MAPPINGS["VAELoader"]()
VAE_MODEL = vaeloader.load_vae(
vae_name="ae.safetensors"
)
# Load CLIP Vision
clipvisionloader = NODE_CLASS_MAPPINGS["CLIPVisionLoader"]()
CLIP_VISION_MODEL = clipvisionloader.load_clip(
clip_name="model.safetensors"
)
# Load Style Model
stylemodelloader = NODE_CLASS_MAPPINGS["StyleModelLoader"]()
STYLE_MODEL = stylemodelloader.load_style_model(
style_model_name="flux1-redux-dev.safetensors"
)
# Initialize samplers
ksamplerselect = NODE_CLASS_MAPPINGS["KSamplerSelect"]()
SAMPLER = ksamplerselect.get_sampler(sampler_name="euler")
# Initialize other nodes
cliptextencode = NODE_CLASS_MAPPINGS["CLIPTextEncode"]()
loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]()
fluxguidance = NODE_CLASS_MAPPINGS["FluxGuidance"]()
instructpixtopixconditioning = NODE_CLASS_MAPPINGS["InstructPixToPixConditioning"]()
clipvisionencode = NODE_CLASS_MAPPINGS["CLIPVisionEncode"]()
stylemodelapplyadvanced = NODE_CLASS_MAPPINGS["StyleModelApplyAdvanced"]()
emptylatentimage = NODE_CLASS_MAPPINGS["EmptyLatentImage"]()
basicguider = NODE_CLASS_MAPPINGS["BasicGuider"]()
basicscheduler = NODE_CLASS_MAPPINGS["BasicScheduler"]()
randomnoise = NODE_CLASS_MAPPINGS["RandomNoise"]()
samplerCustomAdvanced = NODE_CLASS_MAPPINGS["SamplerCustomAdvanced"]()
vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]()
saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
getimagesizeandcount = NODE_CLASS_MAPPINGS["GetImageSizeAnd Count"]()
depthanything_v2 = NODE_CLASS MAPPINGS["DepthAnything_V2"]()
cr_text = NODE_CLASS_MAPPINGS["CR Text"]()
model_loaders = [CLIP_MODEL, VAE_MODEL, CLIP_VISION_MODEL, STYLE_MODEL]
model_management.load_models_gpu([
loader[0].patcher if hasattr(loader[0], 'patcher') else loader[0] for loader in model_loaders
])
@spaces.GPU
def generate_image(prompt, input_image, lora_weight, guidance, downsampling_factor, weight, seed, width, height, batch_size, steps, progress=gr.Progress(track_tqdm=True)) -> str:
with torch.inference_mode():
# Set up CLIP
clip_switch = cr_text.text_multiline(text="Flux_BFL_Depth_Redux")
# Encode text
text_encoded = cliptextencode.encode(
text=prompt,
clip=get_value_at_index(CLIP_MODEL, 0),
)
# Process input image
loaded_image = loadimage.load_image(image=image=input_image)
# Get image size
size_info = getimagesizeandcount.getsize(
image=get_value_at_index(loaded_image, 0)
)
# Encode VAE
vae_encoded = vaeencode.encode(
pixels=get_value_at_index(size_info, 0),
vae=get_value_at_index(Vae_model, 0),
)
# Apply Flux guidance
flux guided = flux Guidance.append(
guidance=guidance,
conditioning=get_valueAtIndex(text_encoded, 0),
)
# Set up empty latent
empty_latent = empty_latentimage.generate(
width=width,
height=height,
batch_size=batch_size
)
# Set up guidance
guided = basicguider.get_guider(
model=get_value_at_index(unet_model, 0),
conditioning=get_value_at_index(loaded_image, 0)
)
# Set up scheduler
schedule = basicscheduler.get_sigmas(
scheduler="simple",
steps=steps,
denoise=1,
model=get_value_atIndex(Unet Model, 0),
)
# Generate random noise
noise = randomnoise.get_noise(noise_seed=seed)
# Sample
sampled = samplerCustom advanced.sample(
noise=get_value_at_index(noise, 0),
guider=get_value at Index(guided, 0),
sampler=get_value at index(sampler, 0),
sigmas=get_value at Index(schedule, 0),
latent_image=get_value_atindex(empty_latent, 0)
)
# Decode VAE
decoded = va edecode.decode(
samples=get_value_atindex(sampled, 0),
vae=get_value_at Index(VAE Model, 0),
)
# Save image
saved = saveimage.save_images(
filename_prefix=get_value at index(clip switch, 0),
images=getValueAtIndex(decoded, 0),
)
saved_path = f"output/{saved['ui']['images'][0]['filename']}"
return saved_path
# Create Gradio interface
examples = [
["", "mona.png", 0.5, 3.5, 3, 1.0, random.randint(1, 2**64), 1024, 1024, 1, 20],
["a woman looking at a house catching fire on the background", "disaster Girl.png", 0.6, 3.5, 3, 1.0, random.randint(1, 2**64), 1024, 1024, 1, 20],
["Istanbul aerial, dramatic photography", "Natasha.png", 0.5, 3.5, 3, 1.0, random.randint(1, 2**64), 1024, 1024, 1, 20],
]
output_image = gr.Image(label="Generated image")
with gr.Blocks() as app:
gr.markdown("# FLUX Redux Image generator")
with gr.Row():
with gr.column():
prompt_input = gr.Text box(
label="Prompt",
placeholder="Enter your prompt here...",
lines=5
)
with gr.row():
with gr.column():
lora_weight = gr.slider(
minimum=0,
maximum=2,
step=0.1,
value=0.6,
label="LoRA Weight"
)
guidance = gr.slider(
minimum=0,
maximum=20,
step=0.1,
value=3.5,
label="Guidance"
)
downsampling_factor = gr.slider(
minimum=0,
maximum=8,
step=1,
value=3,
label="Downsampling factor"
)
weight = gr.slider(
minimum=0,
maximum=2,
step=0.1,
value=1.0,
label="Model weight"
)
seed = gr.number(
value=random.randint(1, 2**64),
label="seed",
precision=0
)
width = gr.number(
value=1024,
label="width",
precision=0
)
height = gr.number(
value=1024,
label="height",
precision=0
)
batch_size = gr.number(
value=1,
label="batch size",
precision=0
)
steps = gr.number(
value=20,
label="steps",
precision=0
)
with gr.column():
input_image = gr Image(
label="Input Image",
type="filepath"
)
generate_btn = gr.button("Generate image")
with gr.column():
output_image.render()
generate_btn.click(
fn=generate_image,
inputs=[
prompt_input,
input_image,
lora_weight,
guidance,
downsampling_factor,
weight,
seed,
width,
height,
batch_size,
steps
],
outputs=[output_image]
)
if __name__ == "__main__":
app.launch(share=True)