Spaces:
Running on Zero
Running on Zero
Commit ·
abd2906
1
Parent(s): 72fe3f0
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,7 +6,7 @@ import spaces
|
|
| 6 |
import torch
|
| 7 |
import random
|
| 8 |
from PIL import Image
|
| 9 |
-
from typing import Iterable
|
| 10 |
|
| 11 |
from diffusers import Flux2KleinPipeline
|
| 12 |
from diffusers.utils import load_image
|
|
@@ -61,21 +61,18 @@ class OrangeRedTheme(Soft):
|
|
| 61 |
orange_red_theme = OrangeRedTheme()
|
| 62 |
MAX_SEED = np.iinfo(np.int32).max
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
| 66 |
"repo": "linoyts/Flux2-Klein-Delight-LoRA",
|
| 67 |
"weights": "pytorch_lora_weights.safetensors",
|
| 68 |
"adapter_name": "klein-delight"
|
| 69 |
},
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
GALLERY_ITEMS = [
|
| 73 |
-
("examples/1.jpg", "None"),
|
| 74 |
-
("examples/2.jpg", "Klein-Delight-Style")
|
| 75 |
]
|
| 76 |
|
| 77 |
-
GALLERY_KEYS = ["None", "Klein-Delight-Style"]
|
| 78 |
-
|
| 79 |
LOADED_ADAPTERS = set()
|
| 80 |
|
| 81 |
print("Loading FLUX.2 Klein 9B model base...")
|
|
@@ -101,11 +98,20 @@ def update_dimensions_on_upload(image):
|
|
| 101 |
|
| 102 |
return new_width, new_height
|
| 103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
@spaces.GPU
|
| 105 |
def infer(
|
| 106 |
input_image,
|
| 107 |
prompt,
|
| 108 |
-
|
| 109 |
seed=42,
|
| 110 |
randomize_seed=True,
|
| 111 |
guidance_scale=1.0,
|
|
@@ -118,16 +124,18 @@ def infer(
|
|
| 118 |
if not input_image:
|
| 119 |
raise gr.Error("Please upload an image to apply a style to.")
|
| 120 |
|
| 121 |
-
|
| 122 |
-
|
|
|
|
| 123 |
pipe.disable_lora()
|
| 124 |
else:
|
| 125 |
-
spec
|
| 126 |
-
if
|
|
|
|
| 127 |
adapter_name = spec["adapter_name"]
|
| 128 |
|
| 129 |
if adapter_name not in LOADED_ADAPTERS:
|
| 130 |
-
print(f"--- Downloading and Loading Adapter: {
|
| 131 |
try:
|
| 132 |
pipe.load_lora_weights(
|
| 133 |
spec["repo"],
|
|
@@ -136,14 +144,14 @@ def infer(
|
|
| 136 |
)
|
| 137 |
LOADED_ADAPTERS.add(adapter_name)
|
| 138 |
except Exception as e:
|
| 139 |
-
raise gr.Error(f"Failed to load adapter {
|
| 140 |
else:
|
| 141 |
-
print(f"--- Adapter {
|
| 142 |
|
| 143 |
print(f"Activating LoRA: {adapter_name}")
|
| 144 |
pipe.set_adapters([adapter_name], adapter_weights=[1.0])
|
| 145 |
else:
|
| 146 |
-
print("
|
| 147 |
pipe.disable_lora()
|
| 148 |
|
| 149 |
if randomize_seed:
|
|
@@ -172,14 +180,30 @@ def infer(
|
|
| 172 |
torch.cuda.empty_cache()
|
| 173 |
|
| 174 |
@spaces.GPU
|
| 175 |
-
def infer_example(input_image, prompt,
|
|
|
|
|
|
|
|
|
|
| 176 |
if input_image is None:
|
| 177 |
return None, 0
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
image, seed = infer(
|
| 180 |
input_image=input_image,
|
| 181 |
prompt=prompt,
|
| 182 |
-
|
| 183 |
seed=0,
|
| 184 |
randomize_seed=True,
|
| 185 |
guidance_scale=1.0,
|
|
@@ -187,14 +211,10 @@ def infer_example(input_image, prompt, lora_adapter):
|
|
| 187 |
)
|
| 188 |
return image, seed
|
| 189 |
|
| 190 |
-
def update_gallery_selection(evt: gr.SelectData):
|
| 191 |
-
if evt.index < len(GALLERY_KEYS):
|
| 192 |
-
return GALLERY_KEYS[evt.index]
|
| 193 |
-
return "None"
|
| 194 |
-
|
| 195 |
css="""
|
| 196 |
#col-container { margin: 0 auto; max-width: 960px; }
|
| 197 |
#main-title h1 { font-size: 2.2em !important; }
|
|
|
|
| 198 |
"""
|
| 199 |
|
| 200 |
with gr.Blocks() as demo:
|
|
@@ -202,6 +222,9 @@ with gr.Blocks() as demo:
|
|
| 202 |
gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
|
| 203 |
gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
|
| 204 |
|
|
|
|
|
|
|
|
|
|
| 205 |
with gr.Row(equal_height=True):
|
| 206 |
with gr.Column():
|
| 207 |
input_image = gr.Image(
|
|
@@ -230,31 +253,39 @@ with gr.Blocks() as demo:
|
|
| 230 |
output_image = gr.Image(label="Output Image", interactive=False, format="png", height=358)
|
| 231 |
used_seed = gr.Textbox(label="Used Seed", interactive=False, visible=False)
|
| 232 |
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
|
|
|
| 238 |
allow_preview=False,
|
| 239 |
-
|
| 240 |
-
|
| 241 |
)
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
#
|
| 246 |
-
|
| 247 |
-
fn=
|
| 248 |
-
inputs=
|
| 249 |
-
outputs=
|
| 250 |
)
|
| 251 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 252 |
gr.Examples(
|
| 253 |
examples=[
|
| 254 |
-
["examples/2.jpg", "Relight the image to remove all existing lighting conditions and replace them with neutral, uniform illumination. Apply soft, evenly distributed lighting with no directional shadows, no harsh highlights, and no dramatic contrast. Maintain the original identity of all subjects exactly—preserve facial structure, skin tone, proportions, expressions, hair, clothing, and textures. Do not alter pose, camera angle, background geometry, or image composition. Lighting should appear balanced, and studio-neutral, similar to diffuse overcast or a soft lightbox setup. Ensure consistent exposure across the entire image with realistic depth and subtle shading only where necessary for form.", "Klein
|
| 255 |
-
["examples/1.jpg", "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods preserving realistic texture and details",
|
| 256 |
],
|
| 257 |
-
inputs=[input_image, prompt,
|
| 258 |
outputs=[output_image, used_seed],
|
| 259 |
fn=infer_example,
|
| 260 |
cache_examples=False,
|
|
@@ -264,7 +295,7 @@ with gr.Blocks() as demo:
|
|
| 264 |
|
| 265 |
run_button.click(
|
| 266 |
fn=infer,
|
| 267 |
-
inputs=[input_image, prompt,
|
| 268 |
outputs=[output_image, used_seed]
|
| 269 |
)
|
| 270 |
|
|
|
|
| 6 |
import torch
|
| 7 |
import random
|
| 8 |
from PIL import Image
|
| 9 |
+
from typing import Iterable, List, Dict
|
| 10 |
|
| 11 |
from diffusers import Flux2KleinPipeline
|
| 12 |
from diffusers.utils import load_image
|
|
|
|
| 61 |
orange_red_theme = OrangeRedTheme()
|
| 62 |
MAX_SEED = np.iinfo(np.int32).max
|
| 63 |
|
| 64 |
+
# Defined LoRA List for Gallery
|
| 65 |
+
loras = [
|
| 66 |
+
{
|
| 67 |
+
"image": "examples/2.jpg",
|
| 68 |
+
"title": "Klein Delight",
|
| 69 |
"repo": "linoyts/Flux2-Klein-Delight-LoRA",
|
| 70 |
"weights": "pytorch_lora_weights.safetensors",
|
| 71 |
"adapter_name": "klein-delight"
|
| 72 |
},
|
| 73 |
+
# Add more LoRAs here in the future
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
]
|
| 75 |
|
|
|
|
|
|
|
| 76 |
LOADED_ADAPTERS = set()
|
| 77 |
|
| 78 |
print("Loading FLUX.2 Klein 9B model base...")
|
|
|
|
| 98 |
|
| 99 |
return new_width, new_height
|
| 100 |
|
| 101 |
+
def update_selection(evt: gr.SelectData):
|
| 102 |
+
if evt.index is not None and evt.index < len(loras):
|
| 103 |
+
selected_lora = loras[evt.index]
|
| 104 |
+
return evt.index, f"Selected Style: {selected_lora['title']}"
|
| 105 |
+
return None, "Selected Style: None (Base Model)"
|
| 106 |
+
|
| 107 |
+
def clear_selection():
|
| 108 |
+
return None, "Selected Style: None (Base Model)", gr.Gallery(selected_index=None)
|
| 109 |
+
|
| 110 |
@spaces.GPU
|
| 111 |
def infer(
|
| 112 |
input_image,
|
| 113 |
prompt,
|
| 114 |
+
selected_index,
|
| 115 |
seed=42,
|
| 116 |
randomize_seed=True,
|
| 117 |
guidance_scale=1.0,
|
|
|
|
| 124 |
if not input_image:
|
| 125 |
raise gr.Error("Please upload an image to apply a style to.")
|
| 126 |
|
| 127 |
+
# LoRA Loading Logic
|
| 128 |
+
if selected_index is None:
|
| 129 |
+
print("No selection or cleared. Disabling LoRA adapters.")
|
| 130 |
pipe.disable_lora()
|
| 131 |
else:
|
| 132 |
+
# Get spec from list using index
|
| 133 |
+
if 0 <= selected_index < len(loras):
|
| 134 |
+
spec = loras[selected_index]
|
| 135 |
adapter_name = spec["adapter_name"]
|
| 136 |
|
| 137 |
if adapter_name not in LOADED_ADAPTERS:
|
| 138 |
+
print(f"--- Downloading and Loading Adapter: {spec['title']} ---")
|
| 139 |
try:
|
| 140 |
pipe.load_lora_weights(
|
| 141 |
spec["repo"],
|
|
|
|
| 144 |
)
|
| 145 |
LOADED_ADAPTERS.add(adapter_name)
|
| 146 |
except Exception as e:
|
| 147 |
+
raise gr.Error(f"Failed to load adapter {spec['title']}: {e}")
|
| 148 |
else:
|
| 149 |
+
print(f"--- Adapter {spec['title']} is already loaded. ---")
|
| 150 |
|
| 151 |
print(f"Activating LoRA: {adapter_name}")
|
| 152 |
pipe.set_adapters([adapter_name], adapter_weights=[1.0])
|
| 153 |
else:
|
| 154 |
+
print("Invalid selection index. Disabling LoRA.")
|
| 155 |
pipe.disable_lora()
|
| 156 |
|
| 157 |
if randomize_seed:
|
|
|
|
| 180 |
torch.cuda.empty_cache()
|
| 181 |
|
| 182 |
@spaces.GPU
|
| 183 |
+
def infer_example(input_image, prompt, selected_index_dummy):
|
| 184 |
+
# This wrapper allows examples to run.
|
| 185 |
+
# Note: Examples usually pass static values. Logic adapted to assume specific style for examples if needed.
|
| 186 |
+
# For now, we run base model (None) for examples unless specific index provided.
|
| 187 |
if input_image is None:
|
| 188 |
return None, 0
|
| 189 |
+
|
| 190 |
+
# Map string name from example to index if necessary, or just use 0 (Delight)
|
| 191 |
+
# For the example 1 (Delight), index is 0. For example 2 (Polaroid), index is None.
|
| 192 |
+
|
| 193 |
+
target_index = None
|
| 194 |
+
if isinstance(selected_index_dummy, str):
|
| 195 |
+
# Reverse lookup for examples compatibility
|
| 196 |
+
for i, item in enumerate(loras):
|
| 197 |
+
if item["title"] == selected_index_dummy or item["adapter_name"] == selected_index_dummy:
|
| 198 |
+
target_index = i
|
| 199 |
+
break
|
| 200 |
+
else:
|
| 201 |
+
target_index = selected_index_dummy
|
| 202 |
+
|
| 203 |
image, seed = infer(
|
| 204 |
input_image=input_image,
|
| 205 |
prompt=prompt,
|
| 206 |
+
selected_index=target_index,
|
| 207 |
seed=0,
|
| 208 |
randomize_seed=True,
|
| 209 |
guidance_scale=1.0,
|
|
|
|
| 211 |
)
|
| 212 |
return image, seed
|
| 213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
css="""
|
| 215 |
#col-container { margin: 0 auto; max-width: 960px; }
|
| 216 |
#main-title h1 { font-size: 2.2em !important; }
|
| 217 |
+
#gallery-label { font-size: 0.9em; font-weight: bold; margin-bottom: 5px; }
|
| 218 |
"""
|
| 219 |
|
| 220 |
with gr.Blocks() as demo:
|
|
|
|
| 222 |
gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
|
| 223 |
gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
|
| 224 |
|
| 225 |
+
# State to store selected LoRA index (Default None)
|
| 226 |
+
selected_index = gr.State(None)
|
| 227 |
+
|
| 228 |
with gr.Row(equal_height=True):
|
| 229 |
with gr.Column():
|
| 230 |
input_image = gr.Image(
|
|
|
|
| 253 |
output_image = gr.Image(label="Output Image", interactive=False, format="png", height=358)
|
| 254 |
used_seed = gr.Textbox(label="Used Seed", interactive=False, visible=False)
|
| 255 |
|
| 256 |
+
# Replaced Dropdown with Gallery
|
| 257 |
+
gr.Markdown("Edit Style Gallery", elem_id="gallery-label")
|
| 258 |
+
gallery = gr.Gallery(
|
| 259 |
+
[(item["image"], item["title"]) for item in loras],
|
| 260 |
+
label="Edit Style Gallery",
|
| 261 |
+
columns=3,
|
| 262 |
allow_preview=False,
|
| 263 |
+
show_label=False,
|
| 264 |
+
elem_id="gallery"
|
| 265 |
)
|
| 266 |
+
selected_info = gr.Markdown("Selected Style: None (Base Model)")
|
| 267 |
+
clear_btn = gr.Button("Clear Style Selection", size="sm", variant="secondary")
|
| 268 |
+
|
| 269 |
+
# Update selection when gallery is clicked
|
| 270 |
+
gallery.select(
|
| 271 |
+
fn=update_selection,
|
| 272 |
+
inputs=[],
|
| 273 |
+
outputs=[selected_index, selected_info]
|
| 274 |
)
|
| 275 |
|
| 276 |
+
# Clear selection logic
|
| 277 |
+
clear_btn.click(
|
| 278 |
+
fn=clear_selection,
|
| 279 |
+
inputs=[],
|
| 280 |
+
outputs=[selected_index, selected_info, gallery]
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
gr.Examples(
|
| 284 |
examples=[
|
| 285 |
+
["examples/2.jpg", "Relight the image to remove all existing lighting conditions and replace them with neutral, uniform illumination. Apply soft, evenly distributed lighting with no directional shadows, no harsh highlights, and no dramatic contrast. Maintain the original identity of all subjects exactly—preserve facial structure, skin tone, proportions, expressions, hair, clothing, and textures. Do not alter pose, camera angle, background geometry, or image composition. Lighting should appear balanced, and studio-neutral, similar to diffuse overcast or a soft lightbox setup. Ensure consistent exposure across the entire image with realistic depth and subtle shading only where necessary for form.", "Klein Delight"],
|
| 286 |
+
["examples/1.jpg", "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods preserving realistic texture and details", None],
|
| 287 |
],
|
| 288 |
+
inputs=[input_image, prompt, selected_index], # Maps string to index in infer_example wrapper
|
| 289 |
outputs=[output_image, used_seed],
|
| 290 |
fn=infer_example,
|
| 291 |
cache_examples=False,
|
|
|
|
| 295 |
|
| 296 |
run_button.click(
|
| 297 |
fn=infer,
|
| 298 |
+
inputs=[input_image, prompt, selected_index, seed, randomize_seed, guidance_scale, steps],
|
| 299 |
outputs=[output_image, used_seed]
|
| 300 |
)
|
| 301 |
|