YUVALON commited on
Commit
8da7a7f
Β·
verified Β·
1 Parent(s): 8d4b46f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -371
app.py CHANGED
@@ -1,426 +1,298 @@
1
  import gradio as gr
2
  import torch
3
- from transformers import GPT2LMHeadModel, GPT2Tokenizer
4
- import random
5
  import re
6
- import os
7
-
8
- # Initialize model and tokenizer
9
- print("Loading GPT-2 model...")
10
- model_name = "gpt2"
11
- tokenizer = GPT2Tokenizer.from_pretrained(model_name)
12
- model = GPT2LMHeadModel.from_pretrained(model_name)
13
 
14
- # Add padding token
15
- if tokenizer.pad_token is None:
16
- tokenizer.pad_token = tokenizer.eos_token
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # Set model to evaluation mode for better performance
19
- model.eval()
 
 
 
 
20
 
21
- def clean_caption(text):
22
- """Clean and format generated caption"""
23
- # Remove extra whitespace
24
- text = re.sub(r'\s+', ' ', text.strip())
25
-
26
- # Split into sentences and take the first complete one
27
- sentences = re.split(r'[.!?]+', text)
28
- if sentences:
29
- caption = sentences[0].strip()
30
- else:
31
- caption = text
32
-
33
- # Remove incomplete thoughts and weird artifacts
34
- caption = re.sub(r'\b(the|and|or|but|so|if|when|where|who|what|why|how)\s*$', '', caption, flags=re.IGNORECASE)
35
 
36
- # Ensure it's not too short or too long
37
- if len(caption) < 10:
38
- return None
39
- if len(caption) > 200:
40
- caption = caption[:200]
41
 
42
- # Capitalize first letter
43
- if caption:
44
- caption = caption[0].upper() + caption[1:]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- # Add punctuation if missing
47
- if not caption.endswith(('.', '!', '?')):
48
- caption += '.'
49
 
50
- return caption
51
-
52
- def generate_instagram_caption(prompt, temperature=0.8, max_length=60):
53
- """Generate a single Instagram caption"""
54
- # Create input prompt
55
- input_text = f"Instagram caption for {prompt}: "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
- # Tokenize
58
- inputs = tokenizer.encode(input_text, return_tensors="pt", max_length=512, truncation=True)
 
 
 
 
 
 
59
 
60
- # Generate with controlled parameters for speed
61
- with torch.no_grad():
62
- outputs = model.generate(
63
- inputs,
64
- max_length=inputs.shape[1] + max_length,
65
- num_return_sequences=1,
66
- temperature=temperature,
67
- do_sample=True,
68
- top_p=0.9,
69
- top_k=40,
70
- pad_token_id=tokenizer.eos_token_id,
71
- repetition_penalty=1.1,
72
- no_repeat_ngram_size=2
73
- )
74
 
75
- # Decode and clean
76
- generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
77
- caption = generated_text.replace(input_text, "").strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
- return clean_caption(caption)
80
-
81
- def add_instagram_flair(caption):
82
- """Add Instagram-style elements to caption"""
83
- if not caption:
84
- return caption
 
85
 
86
- # Instagram-style emojis
87
- emojis = ["✨", "🌟", "πŸ’«", "πŸ”₯", "πŸ’―", "πŸ™Œ", "❀️", "🌈", "β˜€οΈ", "πŸŒ™", "πŸ’•", "πŸŽ‰", "🌸", "πŸ¦‹", "πŸ’Ž", "🌊", "πŸ–οΈ", "πŸŒ…", "πŸ“Έ", "πŸ’ͺ"]
 
 
 
 
 
 
 
 
 
 
 
88
 
89
- # Add emoji with 40% chance
90
- if random.random() < 0.4:
91
- emoji = random.choice(emojis)
92
- caption = f"{caption} {emoji}"
 
 
93
 
94
- return caption
95
-
96
- def generate_captions(description):
97
- """Generate 5 Instagram captions"""
98
- if not description.strip():
99
- return "Please enter a description to generate captions! πŸ“"
100
 
101
- try:
102
- captions = []
103
- max_attempts = 15 # Try up to 15 times to get 5 good captions
104
-
105
- # Different prompt variations for diversity
106
- prompt_variations = [
107
- description,
108
- f"aesthetic {description}",
109
- f"vibes {description}",
110
- f"mood {description}",
111
- f"feeling {description}"
112
- ]
113
-
114
- for i in range(max_attempts):
115
- if len(captions) >= 5:
116
- break
117
-
118
- # Use different prompts and temperatures for variety
119
- prompt = prompt_variations[i % len(prompt_variations)]
120
- temperature = 0.7 + (i % 3) * 0.1 # Vary between 0.7-0.9
121
-
122
- caption = generate_instagram_caption(prompt, temperature)
123
-
124
- if caption and caption not in captions:
125
- # Add Instagram flair
126
- caption = add_instagram_flair(caption)
127
- captions.append(caption)
128
-
129
- # Fill with backup captions if needed
130
- while len(captions) < 5:
131
- backup_captions = [
132
- f"Living my best {description} life ✨",
133
- f"Good vibes and {description} energy 🌟",
134
- f"Making memories with {description} moments πŸ’«",
135
- f"Embracing the {description} aesthetic 🌈",
136
- f"Forever grateful for {description} days πŸ’•"
137
- ]
138
- for backup in backup_captions:
139
- if backup not in captions and len(captions) < 5:
140
- captions.append(backup)
141
-
142
- # Format as numbered list
143
- formatted_output = []
144
- for i, caption in enumerate(captions[:5], 1):
145
- formatted_output.append(f"{i}. {caption}")
146
-
147
- return "\n\n".join(formatted_output)
148
 
149
- except Exception as e:
150
- return f"Oops! Something went wrong: {str(e)} πŸ˜…\nTry a different description!"
151
-
152
- # Custom CSS for Instagram-style design
153
- css = """
154
- /* Import Google Fonts */
155
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
156
-
157
- /* Main gradient background */
158
- .gradio-container {
159
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
160
- font-family: 'Poppins', sans-serif !important;
161
- }
162
-
163
- /* Container styling */
164
- .contain {
165
- background: rgba(255, 255, 255, 0.1) !important;
166
- backdrop-filter: blur(10px) !important;
167
- border-radius: 20px !important;
168
- border: 1px solid rgba(255, 255, 255, 0.2) !important;
169
- box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37) !important;
170
- }
171
-
172
- /* Title styling */
173
- h1 {
174
- background: linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #f9ca24) !important;
175
- -webkit-background-clip: text !important;
176
- -webkit-text-fill-color: transparent !important;
177
- background-clip: text !important;
178
- text-align: center !important;
179
- font-weight: 700 !important;
180
- font-size: 2.5rem !important;
181
- margin-bottom: 1rem !important;
182
- text-shadow: 0 4px 8px rgba(0,0,0,0.1) !important;
183
- }
184
-
185
- /* Input styling */
186
- .gr-textbox {
187
- background: rgba(255, 255, 255, 0.9) !important;
188
- border-radius: 25px !important;
189
- border: 2px solid transparent !important;
190
- background-clip: padding-box !important;
191
- box-shadow: 0 4px 16px rgba(0,0,0,0.1) !important;
192
- font-size: 16px !important;
193
- padding: 15px 20px !important;
194
- transition: all 0.3s ease !important;
195
- }
196
-
197
- .gr-textbox:focus {
198
- border: 2px solid #4ecdc4 !important;
199
- box-shadow: 0 4px 20px rgba(78, 205, 196, 0.3) !important;
200
- transform: translateY(-2px) !important;
201
- }
202
-
203
- /* Button styling */
204
- .gr-button {
205
- background: linear-gradient(45deg, #ff6b6b, #4ecdc4) !important;
206
- border: none !important;
207
- border-radius: 25px !important;
208
- color: white !important;
209
- font-weight: 600 !important;
210
- font-size: 18px !important;
211
- padding: 15px 30px !important;
212
- box-shadow: 0 6px 20px rgba(255, 107, 107, 0.3) !important;
213
- transition: all 0.3s ease !important;
214
- text-transform: uppercase !important;
215
- letter-spacing: 1px !important;
216
- }
217
-
218
- .gr-button:hover {
219
- transform: translateY(-3px) !important;
220
- box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4) !important;
221
- }
222
-
223
- /* Output styling */
224
- .gr-textbox[data-testid="textbox"] {
225
- background: rgba(255, 255, 255, 0.95) !important;
226
- border-radius: 20px !important;
227
- border: 1px solid rgba(255, 255, 255, 0.3) !important;
228
- font-size: 16px !important;
229
- line-height: 1.6 !important;
230
- padding: 20px !important;
231
- }
232
-
233
- /* Examples styling */
234
- .gr-examples {
235
- background: rgba(255, 255, 255, 0.1) !important;
236
- border-radius: 15px !important;
237
- padding: 20px !important;
238
- backdrop-filter: blur(5px) !important;
239
- }
240
-
241
- .gr-examples .gr-button {
242
- background: rgba(255, 255, 255, 0.2) !important;
243
- border: 1px solid rgba(255, 255, 255, 0.3) !important;
244
- border-radius: 20px !important;
245
- color: white !important;
246
- transition: all 0.3s ease !important;
247
- }
248
-
249
- .gr-examples .gr-button:hover {
250
- background: rgba(255, 255, 255, 0.3) !important;
251
- transform: translateY(-1px) !important;
252
- }
253
-
254
- /* Labels */
255
- .gr-label {
256
- color: white !important;
257
- font-weight: 500 !important;
258
- font-size: 16px !important;
259
- margin-bottom: 8px !important;
260
- }
261
-
262
- /* Markdown styling */
263
- .gr-markdown {
264
- color: white !important;
265
- font-size: 16px !important;
266
- line-height: 1.6 !important;
267
- }
268
-
269
- .gr-markdown h3 {
270
- color: #4ecdc4 !important;
271
- font-weight: 600 !important;
272
- margin-top: 20px !important;
273
- }
274
-
275
- /* Copy button */
276
- .gr-copy-button {
277
- background: linear-gradient(45deg, #45b7d1, #f9ca24) !important;
278
- border: none !important;
279
- border-radius: 10px !important;
280
- color: white !important;
281
- font-weight: 500 !important;
282
- }
283
-
284
- /* Scrollbar styling */
285
- ::-webkit-scrollbar {
286
- width: 8px;
287
- }
288
-
289
- ::-webkit-scrollbar-track {
290
- background: rgba(255, 255, 255, 0.1);
291
- border-radius: 10px;
292
- }
293
-
294
- ::-webkit-scrollbar-thumb {
295
- background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
296
- border-radius: 10px;
297
- }
298
-
299
- ::-webkit-scrollbar-thumb:hover {
300
- background: linear-gradient(45deg, #ff5252, #26a69a);
301
- }
302
-
303
- /* Animation */
304
- @keyframes float {
305
- 0% { transform: translateY(0px); }
306
- 50% { transform: translateY(-10px); }
307
- 100% { transform: translateY(0px); }
308
- }
309
-
310
- .gr-button {
311
- animation: float 3s ease-in-out infinite;
312
- }
313
- """
314
 
315
  # Create the Gradio interface
316
- with gr.Blocks(css=css, theme=gr.themes.Soft(), title="πŸ“Έ Instacap – AI Instagram Caption Generator") as app:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
- gr.Markdown(
319
- """
320
- # πŸ“Έ Instacap – AI Instagram Caption Generator
321
-
322
- Transform your photo descriptions into viral Instagram captions! ✨
323
-
324
- **Powered by GPT-2 AI** β€’ **Instant Generation** β€’ **100% Unique Captions**
325
- """
326
- )
327
 
328
  with gr.Row():
329
  with gr.Column(scale=1):
330
  description_input = gr.Textbox(
331
- label="🎯 Describe Your Photo or Vibe",
332
- placeholder="beach sunset, coffee morning, city lights...",
333
  lines=3,
334
- max_lines=4
335
  )
336
 
337
  generate_btn = gr.Button(
338
- "✨ Generate Captions",
339
  variant="primary",
340
- size="lg"
341
- )
342
-
343
- gr.Markdown(
344
- """
345
- ### πŸ’‘ **Pro Tips:**
346
- - Be specific: "golden hour beach" vs "beach"
347
- - Include emotions: "cozy rainy day vibes"
348
- - Mention key elements: "coffee, books, morning light"
349
- """
350
  )
351
 
352
  with gr.Column(scale=1):
353
- output_captions = gr.Textbox(
354
- label="πŸ”₯ Your Instagram Captions",
355
- lines=12,
356
- max_lines=15,
357
- show_copy_button=True,
358
- placeholder="Your amazing captions will appear here... ✨"
359
  )
360
 
361
- # Examples section
362
- gr.Markdown("### 🌟 **Try These Trending Vibes:**")
363
-
364
- examples = [
365
- "golden hour beach sunset",
366
- "cozy coffee shop morning",
367
- "city lights night photography",
368
- "aesthetic workout motivation",
369
- "minimalist home decor",
370
- "travel adventure mountains",
371
- "friend group birthday party",
372
- "food photography brunch"
373
- ]
374
-
375
  gr.Examples(
376
- examples=examples,
 
 
 
 
 
 
 
 
 
377
  inputs=description_input,
378
- outputs=output_captions,
379
- fn=generate_captions,
380
  cache_examples=False
381
  )
382
 
383
- # Event handlers
384
  generate_btn.click(
385
- fn=generate_captions,
386
  inputs=description_input,
387
- outputs=output_captions
388
  )
389
 
 
390
  description_input.submit(
391
- fn=generate_captions,
392
  inputs=description_input,
393
- outputs=output_captions
394
  )
395
 
396
- gr.Markdown(
397
  """
398
- ---
399
-
400
- ### πŸš€ **What Makes Instacap Special:**
401
-
402
- **πŸ€– AI-Powered:** Advanced GPT-2 model trained on millions of social media posts
403
-
404
- **⚑ Lightning Fast:** Optimized for instant caption generation
405
-
406
- **🎨 Instagram-Ready:** Perfect length, tone, and style for maximum engagement
407
-
408
- **πŸ”„ Always Unique:** Get different captions every time you generate
409
-
410
- **πŸ“± Mobile Friendly:** Works perfectly on all devices
411
-
412
- ---
413
-
414
- *Built with ❀️ for content creators, influencers, and anyone who wants to level up their Instagram game!*
415
  """
416
  )
417
 
418
  # Launch the app
419
  if __name__ == "__main__":
420
- app.launch(
421
- share=True,
422
- server_name="0.0.0.0",
423
- server_port=7860,
424
- favicon_path=None,
425
- show_error=True
426
- )
 
1
  import gradio as gr
2
  import torch
3
+ from transformers import pipeline, set_seed
 
4
  import re
5
+ import random
 
 
 
 
 
 
6
 
7
+ # Set up the text generation pipeline
8
+ try:
9
+ # Try to use GPU if available, otherwise fallback to CPU
10
+ device = 0 if torch.cuda.is_available() else -1
11
+ generator = pipeline(
12
+ "text-generation",
13
+ model="gpt2-medium",
14
+ device=device,
15
+ pad_token_id=50256
16
+ )
17
+ except Exception as e:
18
+ print(f"Error loading model: {e}")
19
+ # Fallback to CPU with smaller model
20
+ generator = pipeline(
21
+ "text-generation",
22
+ model="gpt2",
23
+ device=-1,
24
+ pad_token_id=50256
25
+ )
26
 
27
+ def create_short_caption(text, max_words=5):
28
+ """Ensure caption is max 5 words"""
29
+ words = text.split()
30
+ if len(words) <= max_words:
31
+ return text
32
+ return ' '.join(words[:max_words])
33
 
34
+ def generate_instagram_caption(description):
35
+ """Generate 5 short, catchy Instagram captions (max 5 words each)"""
36
+ if not description.strip():
37
+ return "Please enter a description of your photo!"
 
 
 
 
 
 
 
 
 
 
38
 
39
+ # Set a random seed for variety
40
+ set_seed(random.randint(1, 10000))
 
 
 
41
 
42
+ # Cool and catchy caption templates (will be trimmed to 5 words)
43
+ cool_templates = [
44
+ "Squad goals right here",
45
+ "Living our best life",
46
+ "Good vibes only always",
47
+ "Making memories with favorites",
48
+ "This crew hits different",
49
+ "Unstoppable energy with besties",
50
+ "Main character energy activated",
51
+ "Plot twist we're legendary",
52
+ "Caught being absolutely iconic",
53
+ "Serving looks and laughs",
54
+ "That golden hour magic",
55
+ "Friendship level absolutely maximum",
56
+ "Current mood pure happiness",
57
+ "Creating chaos looking cute",
58
+ "Weekend warriors in action",
59
+ "Living proof dreams work",
60
+ "Grateful for these humans",
61
+ "When life gets good",
62
+ "Positive vibes attract everything",
63
+ "Making ordinary moments special"
64
+ ]
65
 
66
+ # Generate captions based on description context
67
+ captions = []
 
68
 
69
+ # Try to generate some with AI
70
+ for i in range(3):
71
+ try:
72
+ prompt = f"Cool Instagram caption for {description}:"
73
+ generated = generator(
74
+ prompt,
75
+ max_length=len(prompt.split()) + 8,
76
+ num_return_sequences=1,
77
+ temperature=0.9,
78
+ do_sample=True,
79
+ top_p=0.95,
80
+ repetition_penalty=1.2,
81
+ pad_token_id=50256
82
+ )
83
+
84
+ full_text = generated[0]['generated_text']
85
+ caption_text = full_text.replace(prompt, "").strip()
86
+
87
+ # Clean and shorten
88
+ caption_text = caption_text.strip('"\'').strip()
89
+ if caption_text and len(caption_text) > 3:
90
+ short_caption = create_short_caption(caption_text, 5)
91
+ if short_caption not in captions:
92
+ captions.append(short_caption)
93
+
94
+ except Exception as e:
95
+ print(f"Generation error: {e}")
96
+ continue
97
 
98
+ # Add cool predefined captions
99
+ random.shuffle(cool_templates)
100
+ for template in cool_templates:
101
+ if len(captions) >= 5:
102
+ break
103
+ short_caption = create_short_caption(template, 5)
104
+ if short_caption not in captions:
105
+ captions.append(short_caption)
106
 
107
+ # Context-specific captions based on description
108
+ context_captions = []
109
+ desc_lower = description.lower()
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ if any(word in desc_lower for word in ['friend', 'group', 'squad', 'crew', 'team', 'gang']):
112
+ context_captions = [
113
+ "Squad goals achieved today",
114
+ "Friends who slay together",
115
+ "Main character energy activated",
116
+ "Chaos creators looking cute",
117
+ "Weekend warriors in action"
118
+ ]
119
+ elif any(word in desc_lower for word in ['sunset', 'beach', 'ocean', 'water']):
120
+ context_captions = [
121
+ "Chasing sunsets and dreams",
122
+ "Salt air good vibes",
123
+ "Beach therapy session complete",
124
+ "Ocean child energy activated",
125
+ "Waves and good times"
126
+ ]
127
+ elif any(word in desc_lower for word in ['coffee', 'morning', 'work', 'laptop']):
128
+ context_captions = [
129
+ "Morning hustle mode on",
130
+ "Coffee powered productivity session",
131
+ "Grinding with good vibes",
132
+ "Main character work energy",
133
+ "Caffeine and determination daily"
134
+ ]
135
+ elif any(word in desc_lower for word in ['food', 'dinner', 'eating', 'restaurant']):
136
+ context_captions = [
137
+ "Good food better company",
138
+ "Eating our way happy",
139
+ "Dinner dates hit different",
140
+ "Food coma incoming soon",
141
+ "Taste buds officially satisfied"
142
+ ]
143
+ elif any(word in desc_lower for word in ['adventure', 'hiking', 'mountain', 'nature']):
144
+ context_captions = [
145
+ "Adventure mode fully activated",
146
+ "Mountain therapy session complete",
147
+ "Nature calls we answer",
148
+ "Hiking boots happy feet",
149
+ "Views and good vibes"
150
+ ]
151
 
152
+ # Add context-specific captions
153
+ for context_cap in context_captions:
154
+ if len(captions) >= 5:
155
+ break
156
+ short_caption = create_short_caption(context_cap, 5)
157
+ if short_caption not in captions:
158
+ captions.append(short_caption)
159
 
160
+ # Ensure we have exactly 5 captions
161
+ universal_captions = [
162
+ "Living our best life",
163
+ "Good vibes only always",
164
+ "Making memories count today",
165
+ "Plot twist we're iconic",
166
+ "Current mood pure happiness",
167
+ "Grateful for these moments",
168
+ "Creating magic happening now",
169
+ "Weekend warrior energy activated",
170
+ "Positive vibes attract everything",
171
+ "This crew hits different"
172
+ ]
173
 
174
+ for universal_cap in universal_captions:
175
+ if len(captions) >= 5:
176
+ break
177
+ short_caption = create_short_caption(universal_cap, 5)
178
+ if short_caption not in captions:
179
+ captions.append(short_caption)
180
 
181
+ # Return exactly 5 captions
182
+ final_captions = captions[:5]
 
 
 
 
183
 
184
+ # Format as numbered list
185
+ result = ""
186
+ for i, caption in enumerate(final_captions, 1):
187
+ result += f"{i}. {caption}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
 
189
+ return result.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  # Create the Gradio interface
192
+ with gr.Blocks(
193
+ theme=gr.themes.Soft(),
194
+ css="""
195
+ .main-header {
196
+ text-align: center;
197
+ background: linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1);
198
+ -webkit-background-clip: text;
199
+ -webkit-text-fill-color: transparent;
200
+ font-size: 2.5em;
201
+ font-weight: bold;
202
+ margin-bottom: 0.5em;
203
+ }
204
+ .subtitle {
205
+ text-align: center;
206
+ color: #666;
207
+ font-size: 1.1em;
208
+ margin-bottom: 2em;
209
+ }
210
+ .generate-btn {
211
+ background: linear-gradient(45deg, #ff6b6b, #4ecdc4) !important;
212
+ border: none !important;
213
+ color: white !important;
214
+ font-weight: bold !important;
215
+ font-size: 1.1em !important;
216
+ padding: 12px 24px !important;
217
+ border-radius: 25px !important;
218
+ transition: all 0.3s ease !important;
219
+ }
220
+ .generate-btn:hover {
221
+ transform: translateY(-2px) !important;
222
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2) !important;
223
+ }
224
+ """
225
+ ) as demo:
226
 
227
+ gr.HTML('<h1 class="main-header">πŸ“Έ Instacap – AI Instagram Caption Generator</h1>')
228
+ gr.HTML('<p class="subtitle">Transform your photo descriptions into short, catchy Instagram captions!</p>')
 
 
 
 
 
 
 
229
 
230
  with gr.Row():
231
  with gr.Column(scale=1):
232
  description_input = gr.Textbox(
233
+ label="Describe your photo",
234
+ placeholder="E.g., group photo with friends, sunset beach picnic, coffee shop vibes",
235
  lines=3,
236
+ max_lines=5
237
  )
238
 
239
  generate_btn = gr.Button(
240
+ "Generate Caption ✨",
241
  variant="primary",
242
+ elem_classes="generate-btn"
 
 
 
 
 
 
 
 
 
243
  )
244
 
245
  with gr.Column(scale=1):
246
+ caption_output = gr.Textbox(
247
+ label="Your 5 Short & Catchy Captions (Max 5 words each)",
248
+ lines=8,
249
+ max_lines=10,
250
+ interactive=False,
251
+ show_copy_button=True
252
  )
253
 
254
+ # Add some example inputs
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  gr.Examples(
256
+ examples=[
257
+ ["group photo with friends laughing"],
258
+ ["sunset beach picnic, cozy vibe"],
259
+ ["coffee shop laptop work, productive morning"],
260
+ ["hiking mountain trail, adventure time"],
261
+ ["friends dinner party, good food"],
262
+ ["morning yoga session, peaceful zen"],
263
+ ["city skyline night view, urban lights"],
264
+ ["weekend brunch with squad, happy vibes"]
265
+ ],
266
  inputs=description_input,
267
+ outputs=caption_output,
268
+ fn=generate_instagram_caption,
269
  cache_examples=False
270
  )
271
 
272
+ # Connect the button to the function
273
  generate_btn.click(
274
+ fn=generate_instagram_caption,
275
  inputs=description_input,
276
+ outputs=caption_output
277
  )
278
 
279
+ # Also trigger on Enter key
280
  description_input.submit(
281
+ fn=generate_instagram_caption,
282
  inputs=description_input,
283
+ outputs=caption_output
284
  )
285
 
286
+ gr.HTML(
287
  """
288
+ <div style="text-align: center; margin-top: 2em; color: #888; font-size: 0.9em;">
289
+ <p>πŸ’‘ Tip: Be specific for better context-matched captions!</p>
290
+ <p>🎨 Get 5 short, catchy captions (max 5 words each)</p>
291
+ <p>πŸ“‹ Perfect for group photos, adventures, and good vibes!</p>
292
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
293
  """
294
  )
295
 
296
  # Launch the app
297
  if __name__ == "__main__":
298
+ demo.launch()