v
File size: 5,545 Bytes
a31f912
517884f
 
76d2d1f
517884f
 
a31f912
517884f
a65577b
0fb6958
517884f
 
45467a5
517884f
e516d53
a31f912
 
 
517884f
45467a5
eb622d3
 
e516d53
517884f
76d2d1f
517884f
76d2d1f
 
 
106d834
 
 
c1070ee
0667bea
106d834
 
493a0ac
d574430
 
 
106d834
 
 
 
 
 
 
 
 
 
45467a5
76d2d1f
0f07342
517884f
a65577b
3571587
a65577b
 
3571587
a65577b
 
 
3571587
0fb6958
 
3571587
0fb6958
3571587
 
 
 
 
a65577b
a31f912
3571587
517884f
 
 
 
3571587
493a0ac
106d834
493a0ac
3571587
493a0ac
0f07342
3571587
517884f
76d2d1f
517884f
 
 
 
76d2d1f
517884f
 
a65577b
 
 
 
 
 
 
 
 
 
0fb6958
 
3571587
0fb6958
3571587
 
 
 
 
 
0fb6958
 
3571587
0fb6958
 
 
a65577b
e516d53
a31f912
45467a5
a31f912
 
155091c
 
517884f
2c6d0ee
45467a5
 
 
3020f2c
a65577b
2c6d0ee
517884f
45467a5
155091c
3571587
3020f2c
493a0ac
155091c
2c6d0ee
517884f
2c6d0ee
517884f
3571587
517884f
 
3571587
a31f912
517884f
 
 
155091c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import spaces
import gradio as gr
import torch
from PIL import Image
from diffusers import DiffusionPipeline
import random
import os
import json
import io
import uuid
from gradio_client import Client as client_gradio
from supabase import create_client, Client
from datetime import datetime

# Inicializa Supabase
url: str = os.getenv('SUPABASE_URL')
key: str = os.getenv('SUPABASE_KEY')
supabase: Client = create_client(url, key)

# Obtém token da Hugging Face
hf_token = os.getenv("HF_TOKEN")

# Inicializa o modelo base FLUX.1-dev
base_model = "black-forest-labs/FLUX.1-dev"
pipe = DiffusionPipeline.from_pretrained(base_model, torch_dtype=torch.float16, use_safetensors=True)

# Move o modelo para GPU
pipe.to("cuda")

# Definição dos LoRA e Trigger Words
lora_models = {
    "AndroFlux": {
        "repo": "vcollos/Nanda",
        "weights": "lora.safetensors",
        "trigger_word": ""  # Sem trigger word específica
    },
    "vgnCollos": {
        "repo": "vcollos/VitorCollos",
        "weights": "Vitor.safetensors",
        "trigger_word": "A photo of Vitor,"
    }
}

# Carrega os LoRAs
for name, details in lora_models.items():
    try:
        pipe.load_lora_weights(details["repo"], weight_name=details["weights"], adapter_name=name)
        print(f"✅ LoRA {name} carregado")
    except Exception as e:
        print(f"❌ Erro ao carregar o LoRA {name}: {e}")

# Define seed máximo
MAX_SEED = 2**32 - 1

def upload_image_to_supabase(image, filename):
    """ Faz upload da imagem para o Supabase Storage e retorna a URL pública. """
    img_bytes = io.BytesIO()
    image.save(img_bytes, format="PNG")
    img_bytes.seek(0)  # Move para o início do arquivo

    storage_path = f"images/{filename}"

    try:
        # Upload da imagem
        supabase.storage.from_("images").upload(storage_path, img_bytes.getvalue(), {"content-type": "image/png"})

        # Retorna a URL pública
        base_url = f"{url}/storage/v1/object/public/images"
        return f"{base_url}/{filename}"
    except Exception as e:
        print(f"❌ Erro no upload da imagem: {e}")
        return None

@spaces.GPU(duration=80)
def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora_scale_1, lora_scale_2, progress=gr.Progress(track_tqdm=True)):
    if randomize_seed:
        seed = random.randint(0, MAX_SEED)
    generator = torch.Generator(device="cuda").manual_seed(seed)

    # Aplica os dois LoRAs combinados
    pipe.set_adapters(["AndroFlux", "vgnCollos"], adapter_weights=[lora_scale_1, lora_scale_2])

    # Adiciona trigger words apenas se vgnCollos estiver ativado
    if lora_scale_2 > 0:
        prompt = f"{lora_models['vgnCollos']['trigger_word']} {prompt}"

    # Gera a imagem
    image = pipe(
        prompt=prompt,
        num_inference_steps=steps,
        guidance_scale=cfg_scale,
        width=width,
        height=height,
        generator=generator
    ).images[0]

    # Define um nome único para a imagem
    filename = f"image_{seed}_{datetime.utcnow().strftime('%Y%m%d%H%M%S')}.png"

    try:
        image_url = upload_image_to_supabase(image, filename)
        print(f"✅ Imagem salva no Supabase: {image_url}")
    except Exception as e:
        print(f"❌ Erro ao fazer upload da imagem: {e}")
        image_url = None

    # Salva os metadados no banco de dados Supabase
    try:
        supabase.table("images").insert({
            "id": str(uuid.uuid4()),  # ID único
            "prompt": prompt,
            "cfg_scale": cfg_scale,
            "steps": steps,
            "seed": seed,
            "lora_scale_1": lora_scale_1,
            "lora_scale_2": lora_scale_2,
            "image_url": image_url,
            "created_at": datetime.utcnow().isoformat()
        }).execute()
        print("✅ Metadados salvos no Supabase")
    except Exception as e:
        print(f"❌ Erro ao salvar metadados no Supabase: {e}")

    return image, seed

# Interface Gradio
gr_theme = os.getenv("THEME")
with gr.Blocks(theme=gr_theme) as app:
    gr.Markdown("# Androflux Image Generator")
    
    with gr.Row():
        with gr.Column(scale=2):
            prompt = gr.TextArea(label="Prompt", placeholder="Digite um prompt (máx 77 caracteres)", lines=3)
            generate_button = gr.Button("Gerar")
            cfg_scale = gr.Slider(label="CFG Scale", minimum=1, maximum=20, step=0.5, value=3.5)
            steps = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=32)
            width = gr.Slider(label="Width", minimum=256, maximum=1024, step=64, value=768)  
            height = gr.Slider(label="Height", minimum=256, maximum=1024, step=64, value=1024)  
            randomize_seed = gr.Checkbox(False, label="Randomize seed")
            seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=556215326)

            # Sliders para os pesos dos LoRAs
            lora_scale_1 = gr.Slider(label="LoRA Scale (AndroFlux)", minimum=0, maximum=1, step=0.01, value=0.1)
            lora_scale_2 = gr.Slider(label="LoRA Scale (vgnCollos)", minimum=0, maximum=1, step=0.01, value=1)

        with gr.Column(scale=2):
            result = gr.Image(label="Generated Image")
            gr.Markdown("Gere imagens usando Collos LoRA e um prompt de texto.")

    # Botão para gerar imagem combinando os LoRAs
    generate_button.click(
        run_lora,
        inputs=[prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora_scale_1, lora_scale_2],
        outputs=[result, seed],
    )

app.queue()
app.launch(share=True)