Malaji71 commited on
Commit
b3f99d4
·
verified ·
1 Parent(s): ce98582

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -167
app.py CHANGED
@@ -37,18 +37,6 @@ class FluxRulesEngine:
37
 
38
  def __init__(self):
39
  self.forbidden_elements = ["++", "weights", "white background [en dev]"]
40
- self.structure_order = {
41
- 1: "article",
42
- 2: "descriptive_adjectives",
43
- 3: "main_subject",
44
- 4: "verb_action",
45
- 5: "context_location",
46
- 6: "environmental_details",
47
- 7: "materials_textures",
48
- 8: "lighting_effects",
49
- 9: "technical_specs",
50
- 10: "quality_style"
51
- }
52
 
53
  self.articles = ["a", "an", "the"]
54
  self.quality_adjectives = [
@@ -129,7 +117,7 @@ class FluxRulesEngine:
129
  components.append(article)
130
 
131
  # 2. Descriptive adjectives (max 2-3)
132
- adjectives = np.random.choice(self.quality_adjectives, size=2, replace=False)
133
  components.extend(adjectives)
134
 
135
  # 3. Main subject
@@ -153,21 +141,17 @@ class FluxRulesEngine:
153
  components.append(context_map.get(setting, "in a carefully composed scene"))
154
 
155
  # 6. Environmental details
156
- env_details = ["with subtle atmospheric effects", "surrounded by carefully balanced elements"]
157
- components.append(np.random.choice(env_details))
158
 
159
  # 7. Materials/Textures (if applicable)
160
  if any(mat in base_prompt.lower() for mat in ["car", "vehicle", "metal"]):
161
- material = np.random.choice(["with metallic surfaces", "featuring chrome details"])
162
- components.append(material)
163
 
164
  # 8. Lighting effects
165
- lighting = np.random.choice(self.lighting_types)
166
- components.append(f"illuminated by {lighting}")
167
 
168
  # 9. Technical specs
169
- tech_spec = np.random.choice(self.technical_specs)
170
- components.append(tech_spec)
171
 
172
  # 10. Quality/Style
173
  if style_preference == "cinematic":
@@ -190,19 +174,11 @@ class FluxRulesEngine:
190
  def get_optimization_score(self, prompt):
191
  """Calculate optimization score for Flux compatibility"""
192
  score = 0
193
- max_score = 100
194
 
195
  # Structure check (order compliance)
196
  if prompt.startswith(("A", "An", "The")):
197
  score += 15
198
 
199
- # Adjective count (optimal 2-3)
200
- adj_count = len([adj for adj in self.quality_adjectives if adj in prompt.lower()])
201
- if 2 <= adj_count <= 3:
202
- score += 15
203
- elif adj_count == 1:
204
- score += 10
205
-
206
  # Technical specs presence
207
  if any(spec in prompt for spec in self.technical_specs):
208
  score += 20
@@ -216,17 +192,17 @@ class FluxRulesEngine:
216
  score += 15
217
 
218
  # Proper punctuation and structure
219
- if "," in prompt and prompt.endswith(("photography", "composition", "quality")):
220
  score += 10
221
 
222
- # Length optimization (Flux works best with detailed but not excessive prompts)
223
  word_count = len(prompt.split())
224
  if 15 <= word_count <= 35:
225
- score += 10
226
  elif 10 <= word_count <= 45:
227
- score += 5
228
 
229
- return min(score, max_score)
230
 
231
  class FluxPromptOptimizer:
232
  def __init__(self):
@@ -236,14 +212,11 @@ class FluxPromptOptimizer:
236
  self.device = DEVICE
237
  self.is_initialized = False
238
 
239
- def initialize_model(self, progress_callback=None):
240
  if self.is_initialized:
241
  return True
242
 
243
  try:
244
- if progress_callback:
245
- progress_callback("Initializing CLIP model...")
246
-
247
  config = Config(
248
  clip_model_name="ViT-L-14/openai",
249
  download_cache=True,
@@ -286,26 +259,20 @@ class FluxPromptOptimizer:
286
  return image
287
 
288
  @spaces.GPU
289
- def generate_optimized_prompt(self, image, style_preference="professional", mode="best", progress_callback=None):
290
  try:
291
  if not self.is_initialized:
292
- if not self.initialize_model(progress_callback):
293
- return "❌ Model initialization failed.", "", 0
294
 
295
  if image is None:
296
- return "❌ Please upload an image.", "", 0
297
 
298
  self.usage_count += 1
299
 
300
- if progress_callback:
301
- progress_callback("Analyzing image content...")
302
-
303
  image = self.optimize_image(image)
304
  if image is None:
305
- return "❌ Image processing failed.", "", 0
306
-
307
- if progress_callback:
308
- progress_callback("Extracting visual features...")
309
 
310
  start_time = datetime.now()
311
 
@@ -320,9 +287,6 @@ class FluxPromptOptimizer:
320
  except Exception as e:
321
  base_prompt = self.interrogator.interrogate_fast(image)
322
 
323
- if progress_callback:
324
- progress_callback("Applying Flux optimization rules...")
325
-
326
  # Apply Flux-specific optimization
327
  optimized_prompt = self.flux_engine.optimize_for_flux(base_prompt, style_preference)
328
 
@@ -341,8 +305,7 @@ class FluxPromptOptimizer:
341
  # Generate analysis info
342
  gpu_status = "⚡ ZeroGPU" if torch.cuda.is_available() else "💻 CPU"
343
 
344
- analysis_info = f"""
345
- **Analysis Complete**
346
 
347
  **Processing:** {gpu_status} • {duration:.1f}s • {mode.title()} mode
348
  **Style:** {style_preference.title()} photography
@@ -350,37 +313,41 @@ class FluxPromptOptimizer:
350
  **Generation:** #{self.usage_count}
351
 
352
  **Base Analysis:** {base_prompt[:100]}...
353
- **Enhancement:** Applied Flux-specific structure and terminology
354
- """
355
 
356
  return optimized_prompt, analysis_info, score
357
 
358
  except Exception as e:
359
- return f" Error: {str(e)}", "Please try with a different image or contact support.", 0
 
360
 
361
  optimizer = FluxPromptOptimizer()
362
 
363
- @spaces.GPU
364
- def process_image_with_progress(image, style_preference, mode):
365
- def progress_callback(message):
366
- return message
367
-
368
- yield "🚀 Initializing Flux Optimizer...", """
369
- **Flux Prompt Optimizer**
370
-
371
- Analyzing image with advanced computer vision
372
- Applying research-based optimization rules
373
- Generating Flux-compatible prompt structure
374
- """, 0
375
-
376
- prompt, info, score = optimizer.generate_optimized_prompt(image, style_preference, mode, progress_callback)
377
- yield prompt, info, score
 
 
 
 
378
 
379
  def clear_outputs():
380
  gc.collect()
381
  if torch.cuda.is_available():
382
  torch.cuda.empty_cache()
383
- return "", "", 0
384
 
385
  def create_interface():
386
  # Professional CSS with elegant typography
@@ -421,15 +388,6 @@ def create_interface():
421
  margin: 0 !important;
422
  }
423
 
424
- .section-header {
425
- font-size: 1.25rem !important;
426
- font-weight: 600 !important;
427
- color: #1e293b !important;
428
- margin: 0 0 1rem 0 !important;
429
- padding-bottom: 0.5rem !important;
430
- border-bottom: 2px solid #e2e8f0 !important;
431
- }
432
-
433
  .prompt-output {
434
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace !important;
435
  font-size: 14px !important;
@@ -440,39 +398,6 @@ def create_interface():
440
  padding: 1.5rem !important;
441
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) !important;
442
  }
443
-
444
- .info-panel {
445
- background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%) !important;
446
- border: 1px solid #0ea5e9 !important;
447
- border-radius: 12px !important;
448
- padding: 1.25rem !important;
449
- font-size: 0.875rem !important;
450
- line-height: 1.5 !important;
451
- }
452
-
453
- .score-display {
454
- text-align: center !important;
455
- padding: 1rem !important;
456
- background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%) !important;
457
- border: 2px solid #22c55e !important;
458
- border-radius: 12px !important;
459
- margin: 1rem 0 !important;
460
- }
461
-
462
- .score-number {
463
- font-size: 2rem !important;
464
- font-weight: 700 !important;
465
- color: #16a34a !important;
466
- margin: 0 !important;
467
- }
468
-
469
- .score-label {
470
- font-size: 0.875rem !important;
471
- color: #15803d !important;
472
- margin: 0 !important;
473
- text-transform: uppercase !important;
474
- letter-spacing: 0.05em !important;
475
- }
476
  """
477
 
478
  with gr.Blocks(
@@ -490,29 +415,26 @@ def create_interface():
490
 
491
  with gr.Row():
492
  with gr.Column(scale=1):
493
- gr.Markdown("## 📷 Image Input", elem_classes=["section-header"])
494
 
495
  image_input = gr.Image(
496
  label="Upload your image",
497
  type="pil",
498
- height=320,
499
- show_label=False
500
  )
501
 
502
- gr.Markdown("## ⚙️ Optimization Settings", elem_classes=["section-header"])
503
 
504
  style_selector = gr.Dropdown(
505
  choices=["professional", "cinematic", "commercial", "artistic"],
506
  value="professional",
507
- label="Photography Style",
508
- info="Select the target style for prompt optimization"
509
  )
510
 
511
  mode_selector = gr.Dropdown(
512
  choices=["fast", "classic", "best"],
513
  value="best",
514
- label="Analysis Mode",
515
- info="Balance between speed and detail"
516
  )
517
 
518
  optimize_btn = gr.Button(
@@ -520,20 +442,9 @@ def create_interface():
520
  variant="primary",
521
  size="lg"
522
  )
523
-
524
- gr.Markdown("""
525
- ### About Flux Optimization
526
-
527
- This tool applies research-validated rules for Flux prompt generation:
528
-
529
- • **Structured composition** following optimal element order
530
- • **Technical specifications** for professional results
531
- • **Lighting and material** terminology optimization
532
- • **Quality markers** specific to Flux model architecture
533
- """)
534
 
535
  with gr.Column(scale=1):
536
- gr.Markdown("## 📝 Optimized Prompt", elem_classes=["section-header"])
537
 
538
  prompt_output = gr.Textbox(
539
  label="Generated Prompt",
@@ -541,23 +452,17 @@ def create_interface():
541
  lines=6,
542
  max_lines=10,
543
  elem_classes=["prompt-output"],
544
- show_copy_button=True,
545
- show_label=False
546
  )
547
 
548
- # Score display
549
  score_output = gr.HTML(
550
- value='<div class="score-display"><div class="score-number">--</div><div class="score-label">Optimization Score</div></div>'
551
  )
552
 
553
- info_output = gr.Markdown(
554
- value="",
555
- elem_classes=["info-panel"]
556
- )
557
 
558
  with gr.Row():
559
  clear_btn = gr.Button("🗑️ Clear", size="sm")
560
- copy_btn = gr.Button("📋 Copy Prompt", size="sm")
561
 
562
  gr.Markdown("""
563
  ---
@@ -570,24 +475,9 @@ def create_interface():
570
  **Developed by Pariente AI** • Advanced AI Research Laboratory
571
  """)
572
 
573
- # Event handlers
574
- def update_score_display(score):
575
- color = "#22c55e" if score >= 80 else "#f59e0b" if score >= 60 else "#ef4444"
576
- return f'''
577
- <div class="score-display" style="border-color: {color};">
578
- <div class="score-number" style="color: {color};">{score}</div>
579
- <div class="score-label">Optimization Score</div>
580
- </div>
581
- '''
582
-
583
- def copy_prompt_to_clipboard(prompt):
584
- return prompt
585
-
586
  optimize_btn.click(
587
- fn=lambda img, style, mode: [
588
- *process_image_with_progress(img, style, mode),
589
- update_score_display(list(process_image_with_progress(img, style, mode))[-1][2])
590
- ],
591
  inputs=[image_input, style_selector, mode_selector],
592
  outputs=[prompt_output, info_output, score_output]
593
  )
@@ -596,12 +486,6 @@ def create_interface():
596
  fn=clear_outputs,
597
  outputs=[prompt_output, info_output, score_output]
598
  )
599
-
600
- copy_btn.click(
601
- fn=copy_prompt_to_clipboard,
602
- inputs=[prompt_output],
603
- outputs=[]
604
- )
605
 
606
  return interface
607
 
 
37
 
38
  def __init__(self):
39
  self.forbidden_elements = ["++", "weights", "white background [en dev]"]
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  self.articles = ["a", "an", "the"]
42
  self.quality_adjectives = [
 
117
  components.append(article)
118
 
119
  # 2. Descriptive adjectives (max 2-3)
120
+ adjectives = ["elegant", "professional"] # Fixed instead of random
121
  components.extend(adjectives)
122
 
123
  # 3. Main subject
 
141
  components.append(context_map.get(setting, "in a carefully composed scene"))
142
 
143
  # 6. Environmental details
144
+ components.append("with subtle atmospheric effects")
 
145
 
146
  # 7. Materials/Textures (if applicable)
147
  if any(mat in base_prompt.lower() for mat in ["car", "vehicle", "metal"]):
148
+ components.append("featuring metallic surfaces")
 
149
 
150
  # 8. Lighting effects
151
+ components.append("illuminated by golden hour lighting")
 
152
 
153
  # 9. Technical specs
154
+ components.append("Shot on Phase One, f/2.8 aperture")
 
155
 
156
  # 10. Quality/Style
157
  if style_preference == "cinematic":
 
174
  def get_optimization_score(self, prompt):
175
  """Calculate optimization score for Flux compatibility"""
176
  score = 0
 
177
 
178
  # Structure check (order compliance)
179
  if prompt.startswith(("A", "An", "The")):
180
  score += 15
181
 
 
 
 
 
 
 
 
182
  # Technical specs presence
183
  if any(spec in prompt for spec in self.technical_specs):
184
  score += 20
 
192
  score += 15
193
 
194
  # Proper punctuation and structure
195
+ if "," in prompt:
196
  score += 10
197
 
198
+ # Length optimization
199
  word_count = len(prompt.split())
200
  if 15 <= word_count <= 35:
201
+ score += 25
202
  elif 10 <= word_count <= 45:
203
+ score += 15
204
 
205
+ return min(score, 100)
206
 
207
  class FluxPromptOptimizer:
208
  def __init__(self):
 
212
  self.device = DEVICE
213
  self.is_initialized = False
214
 
215
+ def initialize_model(self):
216
  if self.is_initialized:
217
  return True
218
 
219
  try:
 
 
 
220
  config = Config(
221
  clip_model_name="ViT-L-14/openai",
222
  download_cache=True,
 
259
  return image
260
 
261
  @spaces.GPU
262
+ def generate_optimized_prompt(self, image, style_preference="professional", mode="best"):
263
  try:
264
  if not self.is_initialized:
265
+ if not self.initialize_model():
266
+ return "❌ Model initialization failed.", "Please refresh and try again.", 0
267
 
268
  if image is None:
269
+ return "❌ Please upload an image.", "No image provided.", 0
270
 
271
  self.usage_count += 1
272
 
 
 
 
273
  image = self.optimize_image(image)
274
  if image is None:
275
+ return "❌ Image processing failed.", "Invalid image format.", 0
 
 
 
276
 
277
  start_time = datetime.now()
278
 
 
287
  except Exception as e:
288
  base_prompt = self.interrogator.interrogate_fast(image)
289
 
 
 
 
290
  # Apply Flux-specific optimization
291
  optimized_prompt = self.flux_engine.optimize_for_flux(base_prompt, style_preference)
292
 
 
305
  # Generate analysis info
306
  gpu_status = "⚡ ZeroGPU" if torch.cuda.is_available() else "💻 CPU"
307
 
308
+ analysis_info = f"""**Analysis Complete**
 
309
 
310
  **Processing:** {gpu_status} • {duration:.1f}s • {mode.title()} mode
311
  **Style:** {style_preference.title()} photography
 
313
  **Generation:** #{self.usage_count}
314
 
315
  **Base Analysis:** {base_prompt[:100]}...
316
+ **Enhancement:** Applied Flux-specific structure and terminology"""
 
317
 
318
  return optimized_prompt, analysis_info, score
319
 
320
  except Exception as e:
321
+ logger.error(f"Generation error: {e}")
322
+ return f"❌ Error: {str(e)}", "Please try with a different image.", 0
323
 
324
  optimizer = FluxPromptOptimizer()
325
 
326
+ def process_image_wrapper(image, style_preference, mode):
327
+ """Simple wrapper without progress callbacks"""
328
+ try:
329
+ prompt, info, score = optimizer.generate_optimized_prompt(image, style_preference, mode)
330
+
331
+ # Create score HTML
332
+ color = "#22c55e" if score >= 80 else "#f59e0b" if score >= 60 else "#ef4444"
333
+ score_html = f'''
334
+ <div style="text-align: center; padding: 1rem; background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%); border: 2px solid {color}; border-radius: 12px; margin: 1rem 0;">
335
+ <div style="font-size: 2rem; font-weight: 700; color: {color}; margin: 0;">{score}</div>
336
+ <div style="font-size: 0.875rem; color: #15803d; margin: 0; text-transform: uppercase; letter-spacing: 0.05em;">Optimization Score</div>
337
+ </div>
338
+ '''
339
+
340
+ return prompt, info, score_html
341
+
342
+ except Exception as e:
343
+ logger.error(f"Wrapper error: {e}")
344
+ return "❌ Processing failed", f"Error: {str(e)}", '<div style="text-align: center; color: red;">Error</div>'
345
 
346
  def clear_outputs():
347
  gc.collect()
348
  if torch.cuda.is_available():
349
  torch.cuda.empty_cache()
350
+ return "", "", '<div style="text-align: center; padding: 1rem;"><div style="font-size: 2rem; color: #ccc;">--</div><div style="font-size: 0.875rem; color: #999;">Optimization Score</div></div>'
351
 
352
  def create_interface():
353
  # Professional CSS with elegant typography
 
388
  margin: 0 !important;
389
  }
390
 
 
 
 
 
 
 
 
 
 
391
  .prompt-output {
392
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace !important;
393
  font-size: 14px !important;
 
398
  padding: 1.5rem !important;
399
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) !important;
400
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  """
402
 
403
  with gr.Blocks(
 
415
 
416
  with gr.Row():
417
  with gr.Column(scale=1):
418
+ gr.Markdown("## 📷 Image Input")
419
 
420
  image_input = gr.Image(
421
  label="Upload your image",
422
  type="pil",
423
+ height=320
 
424
  )
425
 
426
+ gr.Markdown("## ⚙️ Settings")
427
 
428
  style_selector = gr.Dropdown(
429
  choices=["professional", "cinematic", "commercial", "artistic"],
430
  value="professional",
431
+ label="Photography Style"
 
432
  )
433
 
434
  mode_selector = gr.Dropdown(
435
  choices=["fast", "classic", "best"],
436
  value="best",
437
+ label="Analysis Mode"
 
438
  )
439
 
440
  optimize_btn = gr.Button(
 
442
  variant="primary",
443
  size="lg"
444
  )
 
 
 
 
 
 
 
 
 
 
 
445
 
446
  with gr.Column(scale=1):
447
+ gr.Markdown("## 📝 Optimized Prompt")
448
 
449
  prompt_output = gr.Textbox(
450
  label="Generated Prompt",
 
452
  lines=6,
453
  max_lines=10,
454
  elem_classes=["prompt-output"],
455
+ show_copy_button=True
 
456
  )
457
 
 
458
  score_output = gr.HTML(
459
+ value='<div style="text-align: center; padding: 1rem;"><div style="font-size: 2rem; color: #ccc;">--</div><div style="font-size: 0.875rem; color: #999;">Optimization Score</div></div>'
460
  )
461
 
462
+ info_output = gr.Markdown(value="")
 
 
 
463
 
464
  with gr.Row():
465
  clear_btn = gr.Button("🗑️ Clear", size="sm")
 
466
 
467
  gr.Markdown("""
468
  ---
 
475
  **Developed by Pariente AI** • Advanced AI Research Laboratory
476
  """)
477
 
478
+ # Event handlers - FIXED
 
 
 
 
 
 
 
 
 
 
 
 
479
  optimize_btn.click(
480
+ fn=process_image_wrapper,
 
 
 
481
  inputs=[image_input, style_selector, mode_selector],
482
  outputs=[prompt_output, info_output, score_output]
483
  )
 
486
  fn=clear_outputs,
487
  outputs=[prompt_output, info_output, score_output]
488
  )
 
 
 
 
 
 
489
 
490
  return interface
491