X-HighVoltage-X commited on
Commit
1a47adc
·
verified ·
1 Parent(s): c146dbe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -138
app.py CHANGED
@@ -1,7 +1,4 @@
1
- import json
2
- import os
3
  import random
4
- from dataclasses import field
5
  from typing import List
6
 
7
  import gradio as gr
@@ -9,7 +6,6 @@ import numpy as np
9
  import spaces
10
  import torch
11
  from diffusers import FluxFillPipeline
12
-
13
  from loras import LoRA, loras
14
 
15
  MAX_SEED = np.iinfo(np.int32).max
@@ -18,7 +14,6 @@ pipe = FluxFillPipeline.from_pretrained(
18
  "black-forest-labs/FLUX.1-Fill-dev", torch_dtype=torch.bfloat16
19
  ).to("cuda")
20
 
21
-
22
  # Flux system keywords list
23
  flux_keywords_available = [
24
  "IMG_1025.HEIC",
@@ -32,13 +27,14 @@ flux_keywords_available = [
32
  ]
33
 
34
 
35
- def activate_loras(pipe, loras_with_weights):
36
  """
37
  Loads the selected LoRAs into the pipeline with the specified weights.
38
  """
39
- for repo, weight in loras_with_weights.items():
40
- print(f"Loading LoRA: {repo} with weight {weight}")
41
- pipe.load_lora_weights(repo, weight=weight)
 
42
  return pipe
43
 
44
 
@@ -51,6 +47,53 @@ def deactivate_loras(pipe):
51
  return pipe
52
 
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  def calculate_optimal_dimensions(image):
55
  # Extract original dimensions
56
  original_width, original_height = image.size
@@ -89,44 +132,6 @@ def calculate_optimal_dimensions(image):
89
  return width, height
90
 
91
 
92
- def parse_ui_inputs(*ui_args):
93
- """
94
- Parses UI inputs and extracts flux keywords and LoRAs with weights.
95
- Returns: (main_inputs, selected_flux_keywords, selected_loras_with_weights)
96
- """
97
- # Extract main inputs (first 6 arguments)
98
- main_inputs = ui_args[:6] # image, mask, prompt, seed, steps, guidance
99
-
100
- # Extract flux keyword selections
101
- num_flux_keywords = len(flux_keywords_available)
102
- flux_keyword_selections = ui_args[6:6 + num_flux_keywords]
103
-
104
- # Extract LoRA selections and weights
105
- lora_args_start = 6 + num_flux_keywords
106
- lora_args = ui_args[lora_args_start:]
107
-
108
- # Process selected flux keywords
109
- selected_flux_keywords = []
110
- for i, selected in enumerate(flux_keyword_selections):
111
- if selected:
112
- selected_flux_keywords.append(flux_keywords_available[i])
113
-
114
- # Process selected LoRAs with weights
115
- selected_loras_with_weights = []
116
- for i, lora_config in enumerate(loras):
117
- checkbox_idx = i * 2
118
- weight_idx = i * 2 + 1
119
-
120
- if checkbox_idx < len(lora_args):
121
- checked = lora_args[checkbox_idx]
122
- weight = lora_args[weight_idx] if weight_idx < len(lora_args) else 0.5
123
-
124
- if checked:
125
- selected_loras_with_weights.append((lora_config, weight))
126
-
127
- return main_inputs, selected_flux_keywords, selected_loras_with_weights
128
-
129
-
130
  @spaces.GPU(duration=30)
131
  def inpaint(
132
  image,
@@ -134,65 +139,22 @@ def inpaint(
134
  prompt="",
135
  seed=0,
136
  num_inference_steps=28,
137
- guidance_scale=50,
138
- flux_keywords: List[str] = None,
139
- loras_with_weights: List[tuple] = None # List of (LoRA, weight) tuples
140
  ):
141
  """
142
  Main inpainting function with selected LoRAs and their keywords.
143
  """
144
- if flux_keywords is None:
145
- flux_keywords = []
146
- if loras_with_weights is None:
147
- loras_with_weights = []
148
-
149
- # Step 1: Reset LoRAs
150
- deactivate_loras(pipe)
151
-
152
- # Step 2: Prepare selected LoRAs and load them
153
- selected_loras = {}
154
- active_loras = []
155
-
156
- for lora, weight in loras_with_weights:
157
- if lora.url:
158
- selected_loras[lora.url] = round(weight, 1)
159
- active_loras.append(lora)
160
-
161
- if selected_loras:
162
- activate_loras(pipe, selected_loras)
163
 
164
  print("ACTIVE ADAPTERS:", pipe.get_active_adapters())
165
 
166
- # Step 3: Prepare prompt
167
  image = image.convert("RGB")
168
  mask = mask.convert("L")
169
  width, height = calculate_optimal_dimensions(image)
170
 
171
- final_prompt = ""
172
-
173
- # Add selected flux keywords
174
- for keyword in flux_keywords:
175
- final_prompt += f"{keyword}, "
176
-
177
- # Add keywords from active LoRAs
178
- for lora in active_loras:
179
- if lora.Keywords:
180
- keywords_str = ", ".join(lora.Keywords)
181
- final_prompt += f"{keywords_str}, "
182
-
183
- if prompt:
184
- final_prompt += "\n\n"
185
- final_prompt += prompt
186
-
187
- # Step 4: Seed handling
188
- if not isinstance(seed, int) or seed <= 0:
189
- seed = random.randint(0, MAX_SEED)
190
-
191
- # Step 5: Run pipeline
192
  result = pipe(
193
  image=image,
194
  mask_image=mask,
195
- prompt=final_prompt,
196
  width=width,
197
  height=height,
198
  num_inference_steps=num_inference_steps,
@@ -200,17 +162,54 @@ def inpaint(
200
  generator=torch.Generator().manual_seed(seed)
201
  ).images[0]
202
 
203
- return result.convert("RGBA"), final_prompt, seed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
 
 
 
 
205
 
206
  def inpaint_ui_wrapper(*ui_args):
207
  """
208
  UI wrapper that processes Gradio inputs and calls the main inpaint function.
209
  """
210
  main_inputs, selected_flux_keywords, selected_loras_with_weights = parse_ui_inputs(*ui_args)
211
-
212
  image, mask, prompt, seed, num_inference_steps, guidance_scale = main_inputs
213
-
214
  return inpaint(
215
  image=image,
216
  mask=mask,
@@ -221,8 +220,27 @@ def inpaint_ui_wrapper(*ui_args):
221
  flux_keywords=selected_flux_keywords,
222
  loras_with_weights=selected_loras_with_weights
223
  )
 
 
 
 
 
 
 
 
 
224
 
 
 
 
 
 
 
 
225
 
 
 
 
226
  def toggle_input(checked, current_value):
227
  """
228
  Enables or disables the Number input based on checkbox status.
@@ -235,7 +253,7 @@ def toggle_input(checked, current_value):
235
  interactive=checked,
236
  label="Adapter weight"
237
  )
238
-
239
 
240
  def create_flux_keyword_components():
241
  """
@@ -257,14 +275,14 @@ def create_lora_components():
257
  """
258
  Creates interface components for each LoRA from the imported loras list.
259
  """
 
260
  components = []
261
 
262
  for lora in loras:
263
  with gr.Row():
264
  # Create checkbox with LoRA title
265
- display_name = lora.title or lora.nombre or "Unnamed LoRA"
266
  checkbox = gr.Checkbox(
267
- label=display_name,
268
  value=False,
269
  info=lora.note or "" # Show note as additional info
270
  )
@@ -278,7 +296,7 @@ def create_lora_components():
278
  interactive=False,
279
  label="Adapter weight"
280
  )
281
-
282
  # Connect checkbox with number input
283
  checkbox.change(
284
  toggle_input,
@@ -286,13 +304,12 @@ def create_lora_components():
286
  outputs=number_input,
287
  api_name=False
288
  )
289
-
290
- components.extend([checkbox, number_input])
291
 
292
  return components
293
 
294
 
295
- # Create main interface
296
  with gr.Blocks(title="Flux.1 Fill dev Inpainting with LoRAs", theme=gr.themes.Soft()) as demo:
297
  with gr.Row():
298
  with gr.Column(scale=2):
@@ -326,12 +343,10 @@ with gr.Blocks(title="Flux.1 Fill dev Inpainting with LoRAs", theme=gr.themes.So
326
  flux_keyword_components = create_flux_keyword_components()
327
 
328
  # LoRAs section
329
- gr.Markdown("### Available LoRAs")
330
  if loras:
 
331
  lora_components = create_lora_components()
332
- else:
333
- gr.Markdown("*No LoRAs found*")
334
- lora_components = []
335
 
336
  with gr.Column(scale=3):
337
  run_btn = gr.Button("Run", variant="primary")
@@ -343,37 +358,22 @@ with gr.Blocks(title="Flux.1 Fill dev Inpainting with LoRAs", theme=gr.themes.So
343
  used_prompt_box = gr.Text(label="Used prompt", lines=4)
344
  used_seed_box = gr.Number(label="Used seed")
345
 
346
- # Connect button with function
347
- all_components = flux_keyword_components + lora_components
348
-
349
- if all_components:
350
- run_btn.click(
351
- inpaint_ui_wrapper,
352
- inputs=[
353
- image_input,
354
- mask_input,
355
- prompt_input,
356
- seed_slider,
357
- num_inference_steps_input,
358
- guidance_scale_input,
359
- *all_components
360
- ],
361
- outputs=[result_image, used_prompt_box, used_seed_box]
362
- )
363
- else:
364
- # If no components, create simplified version
365
- run_btn.click(
366
- lambda *args: (None, "No LoRAs configured", 0),
367
- inputs=[
368
- image_input,
369
- mask_input,
370
- prompt_input,
371
- seed_slider,
372
- num_inference_steps_input,
373
- guidance_scale_input
374
- ],
375
- outputs=[result_image, used_prompt_box, used_seed_box]
376
- )
377
 
378
  if __name__ == "__main__":
379
- demo.launch(share=False, show_error=True)
 
 
 
1
  import random
 
2
  from typing import List
3
 
4
  import gradio as gr
 
6
  import spaces
7
  import torch
8
  from diffusers import FluxFillPipeline
 
9
  from loras import LoRA, loras
10
 
11
  MAX_SEED = np.iinfo(np.int32).max
 
14
  "black-forest-labs/FLUX.1-Fill-dev", torch_dtype=torch.bfloat16
15
  ).to("cuda")
16
 
 
17
  # Flux system keywords list
18
  flux_keywords_available = [
19
  "IMG_1025.HEIC",
 
27
  ]
28
 
29
 
30
+ def activate_loras(pipe: FluxFillPipeline, loras_with_weights: list[tuple[LoRA, float]]):
31
  """
32
  Loads the selected LoRAs into the pipeline with the specified weights.
33
  """
34
+ for lora, weight in loras_with_weights:
35
+ print(f"Loading LoRA: {lora.display_name} with weight {weight}")
36
+ pipe.load_lora_weights(lora.id, weight=weight)
37
+
38
  return pipe
39
 
40
 
 
47
  return pipe
48
 
49
 
50
+ def inpaint_wrapper(
51
+ image,
52
+ mask,
53
+ prompt="",
54
+ seed=0,
55
+ num_inference_steps=28,
56
+ guidance_scale=50,
57
+ flux_keywords: List[str] = None,
58
+ loras_with_weights: List[tuple[LoRA, float]] = None # List of (LoRA, weight) tuples
59
+ ):
60
+
61
+ # Step 1: Reset LoRAs
62
+ deactivate_loras(pipe)
63
+
64
+ # Step 2: Prepare selected LoRAs and load them
65
+ if loras_with_weights:
66
+ activate_loras(pipe, loras_with_weights)
67
+
68
+ # Step 3: Prepare prompt
69
+ final_prompt = ""
70
+
71
+ for keyword in flux_keywords:
72
+ final_prompt += f"{keyword}, "
73
+
74
+ for lora, _ in loras_with_weights:
75
+ if lora.Keyword:
76
+ keywords_str = ", ".join(lora.Keywords)
77
+ final_prompt += f"{keywords_str}, "
78
+
79
+ if prompt:
80
+ final_prompt += "\n\n"
81
+
82
+ final_prompt += prompt
83
+
84
+ # Step 4: Seed handling
85
+ if not isinstance(seed, int) or seed < 0:
86
+ seed = random.randint(0, MAX_SEED)
87
+
88
+ return inpaint(
89
+ image,
90
+ mask,
91
+ prompt=final_prompt,
92
+ seed=seed,
93
+ num_inference_steps=num_inference_steps,
94
+ guidance_scale=guidance_scale,
95
+ )
96
+
97
  def calculate_optimal_dimensions(image):
98
  # Extract original dimensions
99
  original_width, original_height = image.size
 
132
  return width, height
133
 
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  @spaces.GPU(duration=30)
136
  def inpaint(
137
  image,
 
139
  prompt="",
140
  seed=0,
141
  num_inference_steps=28,
142
+ guidance_scale=50
 
 
143
  ):
144
  """
145
  Main inpainting function with selected LoRAs and their keywords.
146
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  print("ACTIVE ADAPTERS:", pipe.get_active_adapters())
149
 
 
150
  image = image.convert("RGB")
151
  mask = mask.convert("L")
152
  width, height = calculate_optimal_dimensions(image)
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  result = pipe(
155
  image=image,
156
  mask_image=mask,
157
+ prompt=prompt,
158
  width=width,
159
  height=height,
160
  num_inference_steps=num_inference_steps,
 
162
  generator=torch.Generator().manual_seed(seed)
163
  ).images[0]
164
 
165
+ return result.convert("RGBA"), prompt, seed
166
+
167
+ '''
168
+ def parse_ui_inputs(*ui_args):
169
+ """
170
+ Parses UI inputs and extracts flux keywords and LoRAs with weights.
171
+ Returns: (main_inputs, selected_flux_keywords, selected_loras_with_weights)
172
+ """
173
+ # Extract main inputs (first 6 arguments)
174
+ main_inputs = ui_args[:6] # image, mask, prompt, seed, steps, guidance
175
+
176
+ # Extract flux keyword selections
177
+ num_flux_keywords = len(flux_keywords_available)
178
+ flux_keyword_selections = ui_args[6:6 + num_flux_keywords]
179
+
180
+ # Extract LoRA selections and weights
181
+ lora_args_start = 6 + num_flux_keywords
182
+ lora_args = ui_args[lora_args_start:]
183
+
184
+ # Process selected flux keywords
185
+ selected_flux_keywords = []
186
+ for i, selected in enumerate(flux_keyword_selections):
187
+ if selected:
188
+ selected_flux_keywords.append(flux_keywords_available[i])
189
+
190
+ # Process selected LoRAs with weights
191
+ selected_loras_with_weights = []
192
+ for i, lora_config in enumerate(loras):
193
+ checkbox_idx = i * 2
194
+ weight_idx = i * 2 + 1
195
+
196
+ if checkbox_idx < len(lora_args):
197
+ checked = lora_args[checkbox_idx]
198
+ weight = lora_args[weight_idx] if weight_idx < len(lora_args) else 0.5
199
 
200
+ if checked:
201
+ selected_loras_with_weights.append((lora_config, weight))
202
+
203
+ return main_inputs, selected_flux_keywords, selected_loras_with_weights
204
 
205
  def inpaint_ui_wrapper(*ui_args):
206
  """
207
  UI wrapper that processes Gradio inputs and calls the main inpaint function.
208
  """
209
  main_inputs, selected_flux_keywords, selected_loras_with_weights = parse_ui_inputs(*ui_args)
210
+
211
  image, mask, prompt, seed, num_inference_steps, guidance_scale = main_inputs
212
+
213
  return inpaint(
214
  image=image,
215
  mask=mask,
 
220
  flux_keywords=selected_flux_keywords,
221
  loras_with_weights=selected_loras_with_weights
222
  )
223
+ '''
224
+ def selected_keywords(keyword_components):
225
+
226
+ keywords = []
227
+ for checkbox in keyword_components:
228
+ if checkbox.value:
229
+ keywords.append(checkbox.label)
230
+
231
+ return keywords
232
 
233
+ def selected_loras(components: list[tuple[gr.Checkbox, gr.Number]]) -> list[tuple[LoRA, float]]:
234
+
235
+ selected_loras_with_weights = []
236
+ for checkbox, number in components:
237
+ for lora in loras:
238
+ if checkbox.value and lora.display_name == checkbox.label:
239
+ selected_loras_with_weights.append((lora, number.value))
240
 
241
+ return selected_loras_with_weights
242
+
243
+ '''
244
  def toggle_input(checked, current_value):
245
  """
246
  Enables or disables the Number input based on checkbox status.
 
253
  interactive=checked,
254
  label="Adapter weight"
255
  )
256
+ '''
257
 
258
  def create_flux_keyword_components():
259
  """
 
275
  """
276
  Creates interface components for each LoRA from the imported loras list.
277
  """
278
+
279
  components = []
280
 
281
  for lora in loras:
282
  with gr.Row():
283
  # Create checkbox with LoRA title
 
284
  checkbox = gr.Checkbox(
285
+ label=lora.display_name,
286
  value=False,
287
  info=lora.note or "" # Show note as additional info
288
  )
 
296
  interactive=False,
297
  label="Adapter weight"
298
  )
299
+ """
300
  # Connect checkbox with number input
301
  checkbox.change(
302
  toggle_input,
 
304
  outputs=number_input,
305
  api_name=False
306
  )
307
+ """
308
+ components.append((checkbox, number_input))
309
 
310
  return components
311
 
312
 
 
313
  with gr.Blocks(title="Flux.1 Fill dev Inpainting with LoRAs", theme=gr.themes.Soft()) as demo:
314
  with gr.Row():
315
  with gr.Column(scale=2):
 
343
  flux_keyword_components = create_flux_keyword_components()
344
 
345
  # LoRAs section
346
+ lora_components = []
347
  if loras:
348
+ gr.Markdown("### Available LoRAs")
349
  lora_components = create_lora_components()
 
 
 
350
 
351
  with gr.Column(scale=3):
352
  run_btn = gr.Button("Run", variant="primary")
 
358
  used_prompt_box = gr.Text(label="Used prompt", lines=4)
359
  used_seed_box = gr.Number(label="Used seed")
360
 
361
+ run_btn.click(
362
+ inpaint_wrapper,
363
+ inputs=[
364
+ image_input,
365
+ mask_input,
366
+ prompt_input,
367
+ seed_slider,
368
+ num_inference_steps_input,
369
+ guidance_scale_input,
370
+ selected_keywords(flux_keyword_components),
371
+ selected_loras(lora_components)
372
+ ],
373
+ outputs=[result_image, used_prompt_box, used_seed_box],
374
+ api_name="/inpaint"
375
+ )
376
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
 
378
  if __name__ == "__main__":
379
+ demo.launch(share=False, show_error=True)