YUVALON commited on
Commit
12b1982
·
verified ·
1 Parent(s): 326ed5f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -81
app.py CHANGED
@@ -4,6 +4,7 @@ from transformers import pipeline, set_seed
4
  import re
5
  import random
6
  import os
 
7
 
8
  # Set up the text generation pipeline with better error handling
9
  def initialize_model():
@@ -158,6 +159,27 @@ def generate_short_caption(description, max_retries=5):
158
 
159
  return ""
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  def generate_instagram_captions(description):
162
  """Generate 5 short, catchy Instagram captions (max 5 words each)"""
163
  if not description.strip():
@@ -224,60 +246,6 @@ def generate_instagram_captions(description):
224
  "business": ["Business mode activated", "Entrepreneur life chosen", "Success is planned", "Building empire daily", "Boss moves only"]
225
  }
226
 
227
- # Enhanced cool captions database with complete, meaningful phrases
228
- cool_captions = [
229
- "Squad goals right here",
230
- "Good vibes only today",
231
- "Living our best life",
232
- "Making memories with favorites",
233
- "Caught in the moment",
234
- "Friends like these matter",
235
- "Energy levels unmatched today",
236
- "Vibes on point always",
237
- "Good times roll forever",
238
- "Squad up for success",
239
- "Living for these moments",
240
- "Making magic happen daily",
241
- "Catching feelings and sunsets",
242
- "Good company great memories",
243
- "Squad deeper than ocean",
244
- "Vibes immaculate as always",
245
- "Energy infectious spread everywhere",
246
- "Good times never ending",
247
- "Making waves together always",
248
- "Caught smiling too much",
249
- "Living life in color",
250
- "Squad goals achieved today",
251
- "Good vibes attract everything",
252
- "Making moments matter most",
253
- "Catching dreams with crew",
254
- "Living loud loving harder",
255
- "Squad tight bond stronger",
256
- "Good energy good people",
257
- "Making memories worth keeping",
258
- "Caught being absolutely legendary",
259
- "Weekend warriors in action",
260
- "Sunshine mixed with chaos",
261
- "Creating our own magic",
262
- "Adventure awaits us always",
263
- "Blessed with the best",
264
- "Chaos and we prosper",
265
- "Dreams do come true",
266
- "Forever young at heart",
267
- "Golden hour golden friends",
268
- "Happiness looks like this",
269
- "Peace love and yoga",
270
- "Zen mode activated today",
271
- "Morning ritual pure bliss",
272
- "Mindful moments matter most",
273
- "Grateful for this peace",
274
- "Serenity found in stillness",
275
- "Balance restored through practice",
276
- "Inner peace outer strength",
277
- "Breathe deeply live fully",
278
- "Namaste all day long"
279
- ]
280
-
281
  # Find keyword-specific captions
282
  description_lower = description.lower()
283
  keyword_specific_captions = []
@@ -290,18 +258,18 @@ def generate_instagram_captions(description):
290
  ai_captions = []
291
  if generator is not None:
292
  attempts = 0
293
- while len(ai_captions) < 2 and attempts < 10: # Try to get at least 2 good AI captions
294
  caption = generate_short_caption(description)
295
  if caption and caption not in ai_captions and is_valid_caption(caption):
296
  ai_captions.append(caption)
297
  attempts += 1
298
 
299
- # Combine keyword-specific, AI and predefined captions
300
  # Prioritize keyword-specific captions if found
301
  if keyword_specific_captions:
302
- all_captions = keyword_specific_captions + ai_captions + cool_captions
303
  else:
304
- all_captions = ai_captions + cool_captions
305
 
306
  # Remove duplicates while preserving order
307
  seen = set()
@@ -311,8 +279,24 @@ def generate_instagram_captions(description):
311
  seen.add(caption)
312
  unique_captions.append(caption)
313
 
314
- # Select 5 random captions
315
- selected_captions = random.sample(unique_captions, min(5, len(unique_captions)))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
 
317
  # Ensure each caption is max 5 words and properly formatted
318
  final_captions = []
@@ -321,15 +305,7 @@ def generate_instagram_captions(description):
321
  if len(words) >= 2:
322
  final_captions.append(" ".join(words))
323
 
324
- # Fill with defaults if needed
325
- while len(final_captions) < 5:
326
- fallback = random.choice(cool_captions)
327
- words = fallback.split()[:5]
328
- final_caption = " ".join(words)
329
- if final_caption not in final_captions:
330
- final_captions.append(final_caption)
331
-
332
- # Format as simple numbered list (removed "Your Instagram Captions" text)
333
  result = ""
334
  emojis = ["🎯", "⚡", "🌟", "🔥", "💫"]
335
 
@@ -338,7 +314,7 @@ def generate_instagram_captions(description):
338
 
339
  return result.strip()
340
 
341
- # Enhanced Instagram-inspired theme with custom CSS
342
  instagram_css = """
343
  /* Instagram color scheme and modern design */
344
  :root {
@@ -353,6 +329,14 @@ instagram_css = """
353
  --ig-light: #FFFFFF;
354
  }
355
 
 
 
 
 
 
 
 
 
356
  /* Main container styling */
357
  .gradio-container {
358
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
@@ -360,15 +344,19 @@ instagram_css = """
360
  font-family: 'Instagram Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
361
  }
362
 
363
- /* Header styling - Modified to be regular black text */
364
  .main-header {
365
  text-align: center;
366
- color: #000000 !important;
 
 
 
 
367
  font-size: 3em;
368
  font-weight: 400;
369
  margin-bottom: 0.5em;
370
  padding: 1rem 0;
371
- background: rgba(255, 255, 255, 0.9);
372
  border-radius: 15px;
373
  margin: 1rem;
374
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
@@ -438,6 +426,74 @@ instagram_css = """
438
  transform: translateY(-1px) !important;
439
  }
440
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
  /* Output styling */
442
  .output-box {
443
  background: rgba(255, 255, 255, 0.9) !important;
@@ -513,6 +569,14 @@ instagram_css = """
513
  font-size: 1.1em !important;
514
  padding: 12px 25px !important;
515
  }
 
 
 
 
 
 
 
 
516
  }
517
 
518
  /* Loading animation */
@@ -524,6 +588,98 @@ instagram_css = """
524
  .loading {
525
  animation: pulse 2s infinite;
526
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  """
528
 
529
  # Create the Gradio interface
@@ -534,7 +690,8 @@ with gr.Blocks(
534
  neutral_hue="gray"
535
  ),
536
  css=instagram_css,
537
- title="InstaCap - AI Caption Generator"
 
538
  ) as demo:
539
 
540
  # Move title to the front and make it regular black
@@ -567,22 +724,25 @@ with gr.Blocks(
567
  elem_classes="output-box"
568
  )
569
 
570
- # Examples are kept in code but not shown in UI
571
-
572
- # Connect the button to the function
573
  generate_btn.click(
574
- fn=generate_instagram_captions,
575
  inputs=description_input,
576
- outputs=caption_output
 
577
  )
578
 
579
  # Also trigger on Enter key
580
  description_input.submit(
581
- fn=generate_instagram_captions,
582
  inputs=description_input,
583
- outputs=caption_output
 
584
  )
585
 
 
 
 
586
  gr.HTML(
587
  """
588
  <div class="tips-section">
 
4
  import re
5
  import random
6
  import os
7
+ import time
8
 
9
  # Set up the text generation pipeline with better error handling
10
  def initialize_model():
 
159
 
160
  return ""
161
 
162
+ def generate_instagram_captions_with_loading(description, progress=gr.Progress()):
163
+ """Generate 5 short, catchy Instagram captions with loading animation"""
164
+ if not description.strip():
165
+ return "Please enter a description of your photo! 📸"
166
+
167
+ # Show loading messages with progress
168
+ loading_messages = [
169
+ "🤖 Analyzing your photo description...",
170
+ "✨ Generating creative captions...",
171
+ "🎯 Finding the perfect words...",
172
+ "🔥 Adding some Instagram magic...",
173
+ "📱 Finalizing your captions..."
174
+ ]
175
+
176
+ for i, message in enumerate(loading_messages):
177
+ progress((i + 1) / len(loading_messages), desc=message)
178
+ time.sleep(0.5) # Small delay to show loading progression
179
+
180
+ # Generate captions (using the existing logic)
181
+ return generate_instagram_captions(description)
182
+
183
  def generate_instagram_captions(description):
184
  """Generate 5 short, catchy Instagram captions (max 5 words each)"""
185
  if not description.strip():
 
246
  "business": ["Business mode activated", "Entrepreneur life chosen", "Success is planned", "Building empire daily", "Boss moves only"]
247
  }
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  # Find keyword-specific captions
250
  description_lower = description.lower()
251
  keyword_specific_captions = []
 
258
  ai_captions = []
259
  if generator is not None:
260
  attempts = 0
261
+ while len(ai_captions) < 5 and attempts < 15: # Try to get 5 AI captions
262
  caption = generate_short_caption(description)
263
  if caption and caption not in ai_captions and is_valid_caption(caption):
264
  ai_captions.append(caption)
265
  attempts += 1
266
 
267
+ # Combine keyword-specific and AI captions
268
  # Prioritize keyword-specific captions if found
269
  if keyword_specific_captions:
270
+ all_captions = keyword_specific_captions + ai_captions
271
  else:
272
+ all_captions = ai_captions
273
 
274
  # Remove duplicates while preserving order
275
  seen = set()
 
279
  seen.add(caption)
280
  unique_captions.append(caption)
281
 
282
+ # If we don't have enough captions, create basic fallbacks
283
+ if len(unique_captions) < 5:
284
+ basic_fallbacks = [
285
+ "Picture perfect moment",
286
+ "Living my best life",
287
+ "Good vibes only",
288
+ "Making memories today",
289
+ "Life is beautiful"
290
+ ]
291
+
292
+ for fallback in basic_fallbacks:
293
+ if fallback not in unique_captions:
294
+ unique_captions.append(fallback)
295
+ if len(unique_captions) >= 5:
296
+ break
297
+
298
+ # Select 5 captions
299
+ selected_captions = unique_captions[:5]
300
 
301
  # Ensure each caption is max 5 words and properly formatted
302
  final_captions = []
 
305
  if len(words) >= 2:
306
  final_captions.append(" ".join(words))
307
 
308
+ # Format as simple numbered list
 
 
 
 
 
 
 
 
309
  result = ""
310
  emojis = ["🎯", "⚡", "🌟", "🔥", "💫"]
311
 
 
314
 
315
  return result.strip()
316
 
317
+ # Enhanced Instagram-inspired theme with custom CSS and loading animation
318
  instagram_css = """
319
  /* Instagram color scheme and modern design */
320
  :root {
 
329
  --ig-light: #FFFFFF;
330
  }
331
 
332
+ /* Hide default gradio progress indicators */
333
+ .gradio-container .progress-bar,
334
+ .gradio-container .eta,
335
+ .gradio-container .generating,
336
+ .gradio-container footer {
337
+ display: none !important;
338
+ }
339
+
340
  /* Main container styling */
341
  .gradio-container {
342
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
 
344
  font-family: 'Instagram Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
345
  }
346
 
347
+ /* Header styling - Same gradient as generate button */
348
  .main-header {
349
  text-align: center;
350
+ background: linear-gradient(45deg, var(--ig-primary), var(--ig-secondary));
351
+ -webkit-background-clip: text;
352
+ -webkit-text-fill-color: transparent;
353
+ background-clip: text;
354
+ color: transparent;
355
  font-size: 3em;
356
  font-weight: 400;
357
  margin-bottom: 0.5em;
358
  padding: 1rem 0;
359
+ background-color: rgba(255, 255, 255, 0.9);
360
  border-radius: 15px;
361
  margin: 1rem;
362
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
 
426
  transform: translateY(-1px) !important;
427
  }
428
 
429
+ /* Loading animation styles */
430
+ .loading-overlay {
431
+ position: fixed;
432
+ top: 0;
433
+ left: 0;
434
+ right: 0;
435
+ bottom: 0;
436
+ background: linear-gradient(135deg,
437
+ rgba(228, 64, 95, 0.9) 0%,
438
+ rgba(131, 58, 180, 0.9) 25%,
439
+ rgba(247, 119, 55, 0.9) 50%,
440
+ rgba(252, 175, 69, 0.9) 75%,
441
+ rgba(64, 93, 230, 0.9) 100%);
442
+ z-index: 9999;
443
+ display: flex;
444
+ flex-direction: column;
445
+ justify-content: center;
446
+ align-items: center;
447
+ backdrop-filter: blur(10px);
448
+ }
449
+
450
+ .loading-spinner {
451
+ width: 60px;
452
+ height: 60px;
453
+ border: 4px solid rgba(255, 255, 255, 0.3);
454
+ border-top: 4px solid white;
455
+ border-radius: 50%;
456
+ animation: spin 1s linear infinite;
457
+ margin-bottom: 20px;
458
+ }
459
+
460
+ .loading-text {
461
+ color: white;
462
+ font-size: 1.5em;
463
+ font-weight: bold;
464
+ text-align: center;
465
+ margin-bottom: 10px;
466
+ text-shadow: 0 2px 4px rgba(0,0,0,0.3);
467
+ }
468
+
469
+ .loading-subtext {
470
+ color: rgba(255, 255, 255, 0.8);
471
+ font-size: 1em;
472
+ text-align: center;
473
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
474
+ }
475
+
476
+ @keyframes spin {
477
+ 0% { transform: rotate(0deg); }
478
+ 100% { transform: rotate(360deg); }
479
+ }
480
+
481
+ /* Instagram-style pulse animation */
482
+ .ig-pulse {
483
+ animation: igPulse 2s ease-in-out infinite;
484
+ }
485
+
486
+ @keyframes igPulse {
487
+ 0%, 100% {
488
+ transform: scale(1);
489
+ opacity: 1;
490
+ }
491
+ 50% {
492
+ transform: scale(1.05);
493
+ opacity: 0.8;
494
+ }
495
+ }
496
+
497
  /* Output styling */
498
  .output-box {
499
  background: rgba(255, 255, 255, 0.9) !important;
 
569
  font-size: 1.1em !important;
570
  padding: 12px 25px !important;
571
  }
572
+
573
+ .loading-text {
574
+ font-size: 1.2em !important;
575
+ }
576
+
577
+ .loading-subtext {
578
+ font-size: 0.9em !important;
579
+ }
580
  }
581
 
582
  /* Loading animation */
 
588
  .loading {
589
  animation: pulse 2s infinite;
590
  }
591
+
592
+ /* Hide progress bar completely */
593
+ .wrap.svelte-1116j96 {
594
+ display: none !important;
595
+ }
596
+
597
+ /* Additional progress bar hiding */
598
+ .gradio-container .progress-text,
599
+ .gradio-container .progress-level,
600
+ .gradio-container .progress-bar-wrap {
601
+ display: none !important;
602
+ }
603
+ """
604
+
605
+ # JavaScript for loading overlay
606
+ loading_js = """
607
+ <script>
608
+ function showLoading() {
609
+ // Create loading overlay
610
+ const overlay = document.createElement('div');
611
+ overlay.id = 'loading-overlay';
612
+ overlay.className = 'loading-overlay';
613
+ overlay.innerHTML = `
614
+ <div class="loading-spinner"></div>
615
+ <div class="loading-text ig-pulse">✨ Creating Magic...</div>
616
+ <div class="loading-subtext">Generating your perfect Instagram captions</div>
617
+ `;
618
+ document.body.appendChild(overlay);
619
+
620
+ // Update loading text dynamically
621
+ const messages = [
622
+ "🤖 Analyzing your photo...",
623
+ "✨ Crafting catchy captions...",
624
+ "🎯 Finding perfect words...",
625
+ "🔥 Adding Instagram magic...",
626
+ "📱 Almost ready..."
627
+ ];
628
+
629
+ let index = 0;
630
+ const interval = setInterval(() => {
631
+ const textElement = overlay.querySelector('.loading-text');
632
+ if (textElement && index < messages.length) {
633
+ textElement.textContent = messages[index];
634
+ index++;
635
+ } else {
636
+ clearInterval(interval);
637
+ }
638
+ }, 800);
639
+
640
+ return overlay;
641
+ }
642
+
643
+ function hideLoading() {
644
+ const overlay = document.getElementById('loading-overlay');
645
+ if (overlay) {
646
+ overlay.style.opacity = '0';
647
+ setTimeout(() => {
648
+ overlay.remove();
649
+ }, 300);
650
+ }
651
+ }
652
+
653
+ // Override the generate function to show loading
654
+ let originalGenerate = null;
655
+
656
+ function setupLoadingEvents() {
657
+ const generateBtn = document.querySelector('.generate-btn');
658
+ const textInput = document.querySelector('textarea');
659
+
660
+ if (generateBtn) {
661
+ generateBtn.addEventListener('click', function() {
662
+ if (textInput && textInput.value.trim()) {
663
+ showLoading();
664
+ setTimeout(hideLoading, 4000); // Hide after 4 seconds
665
+ }
666
+ });
667
+ }
668
+
669
+ if (textInput) {
670
+ textInput.addEventListener('keypress', function(e) {
671
+ if (e.key === 'Enter' && !e.shiftKey && textInput.value.trim()) {
672
+ showLoading();
673
+ setTimeout(hideLoading, 4000); // Hide after 4 seconds
674
+ }
675
+ });
676
+ }
677
+ }
678
+
679
+ // Initialize when DOM is ready
680
+ document.addEventListener('DOMContentLoaded', setupLoadingEvents);
681
+ setTimeout(setupLoadingEvents, 1000); // Backup initialization
682
+ </script>
683
  """
684
 
685
  # Create the Gradio interface
 
690
  neutral_hue="gray"
691
  ),
692
  css=instagram_css,
693
+ title="InstaCap - AI Caption Generator",
694
+ js=loading_js
695
  ) as demo:
696
 
697
  # Move title to the front and make it regular black
 
724
  elem_classes="output-box"
725
  )
726
 
727
+ # Connect the button to the function with loading
 
 
728
  generate_btn.click(
729
+ fn=generate_instagram_captions_with_loading,
730
  inputs=description_input,
731
+ outputs=caption_output,
732
+ show_progress=True
733
  )
734
 
735
  # Also trigger on Enter key
736
  description_input.submit(
737
+ fn=generate_instagram_captions_with_loading,
738
  inputs=description_input,
739
+ outputs=caption_output,
740
+ show_progress=True
741
  )
742
 
743
+ # Add JavaScript for loading overlay
744
+ gr.HTML(loading_js)
745
+
746
  gr.HTML(
747
  """
748
  <div class="tips-section">