prithivMLmods commited on
Commit
abd2906
·
1 Parent(s): 72fe3f0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -46
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
- ADAPTER_SPECS = {
65
- "Klein-Delight-Style": {
 
 
 
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
- lora_adapter,
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
- if lora_adapter == "None" or lora_adapter is None:
122
- print("Selection is None. Disabling LoRA adapters.")
 
123
  pipe.disable_lora()
124
  else:
125
- spec = ADAPTER_SPECS.get(lora_adapter)
126
- if spec:
 
127
  adapter_name = spec["adapter_name"]
128
 
129
  if adapter_name not in LOADED_ADAPTERS:
130
- print(f"--- Downloading and Loading Adapter: {lora_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 {lora_adapter}: {e}")
140
  else:
141
- print(f"--- Adapter {lora_adapter} is already loaded. ---")
142
 
143
  print(f"Activating LoRA: {adapter_name}")
144
  pipe.set_adapters([adapter_name], adapter_weights=[1.0])
145
  else:
146
- print("Adapter not found in specs. Disabling LoRA.")
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, lora_adapter):
 
 
 
176
  if input_image is None:
177
  return None, 0
178
-
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  image, seed = infer(
180
  input_image=input_image,
181
  prompt=prompt,
182
- lora_adapter=lora_adapter,
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
- gr.Markdown("### Edit Style Gallery")
234
- lora_gallery = gr.Gallery(
235
- label="Choose Editing Style",
236
- value=GALLERY_ITEMS,
237
- selected_index=0,
 
238
  allow_preview=False,
239
- columns=2,
240
- height=220
241
  )
242
- # Hidden textbox to store selection for the inference function
243
- lora_adapter_state = gr.Textbox(value="None", visible=False)
244
-
245
- # Event: Update hidden state when gallery item is selected
246
- lora_gallery.select(
247
- fn=update_gallery_selection,
248
- inputs=None,
249
- outputs=lora_adapter_state
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-Delight-Style"],
255
- ["examples/1.jpg", "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods preserving realistic texture and details", "None"],
256
  ],
257
- inputs=[input_image, prompt, lora_adapter_state],
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, lora_adapter_state, seed, randomize_seed, guidance_scale, steps],
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