YUVALON commited on
Commit
03140c5
Β·
verified Β·
1 Parent(s): 4bdf3da

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +334 -118
app.py CHANGED
@@ -1,188 +1,394 @@
1
  import gradio as gr
2
  import torch
3
- from transformers import GPT2LMHeadModel, GPT2Tokenizer, set_seed
4
  import random
5
  import re
 
6
 
7
- # Load the model and tokenizer
 
8
  model_name = "gpt2"
9
  tokenizer = GPT2Tokenizer.from_pretrained(model_name)
10
  model = GPT2LMHeadModel.from_pretrained(model_name)
11
 
12
  # Add padding token
13
- tokenizer.pad_token = tokenizer.eos_token
 
14
 
15
- def clean_caption(caption):
16
- """Clean and format the generated caption"""
17
- # Remove any leading/trailing whitespace
18
- caption = caption.strip()
 
 
 
19
 
20
- # Remove incomplete sentences at the end
21
- sentences = caption.split('.')
22
- if len(sentences) > 1:
23
- caption = sentences[0] + '.'
 
 
24
 
25
- # Ensure it ends with proper punctuation
26
- if not caption.endswith(('.', '!', '?')):
27
- caption += '.'
28
 
29
- # Remove extra spaces
30
- caption = re.sub(r'\s+', ' ', caption)
 
 
 
31
 
32
  # Capitalize first letter
33
  if caption:
34
  caption = caption[0].upper() + caption[1:]
35
 
 
 
 
 
36
  return caption
37
 
38
- def generate_instagram_captions(description, num_captions=5):
39
- """Generate Instagram-style captions based on description"""
 
 
40
 
41
- # Different prompt templates for variety
42
- prompt_templates = [
43
- f"Instagram caption about {description}:",
44
- f"Perfect caption for {description}:",
45
- f"Instagram post about {description}:",
46
- f"Caption for a photo of {description}:",
47
- f"Social media caption about {description}:"
48
- ]
49
 
50
- captions = []
51
-
52
- for i in range(num_captions):
53
- # Use different prompt templates for variety
54
- prompt = prompt_templates[i % len(prompt_templates)]
55
-
56
- # Set different seeds for variety
57
- set_seed(42 + i * 10)
58
-
59
- # Tokenize the prompt
60
- inputs = tokenizer.encode(prompt, return_tensors="pt")
61
-
62
- # Generate text
63
- with torch.no_grad():
64
- outputs = model.generate(
65
- inputs,
66
- max_length=inputs.shape[1] + 50,
67
- num_return_sequences=1,
68
- temperature=0.8 + (i * 0.1), # Vary temperature for diversity
69
- do_sample=True,
70
- top_p=0.9,
71
- top_k=50,
72
- pad_token_id=tokenizer.eos_token_id,
73
- repetition_penalty=1.2
74
- )
75
-
76
- # Decode the generated text
77
- generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
78
-
79
- # Extract caption (remove the prompt)
80
- caption = generated_text.replace(prompt, "").strip()
81
-
82
- # Clean and format the caption
83
- caption = clean_caption(caption)
84
-
85
- # Add some Instagram-style elements randomly
86
- instagram_elements = ["✨", "🌟", "πŸ’«", "πŸ”₯", "πŸ’―", "πŸ™Œ", "❀️", "🌈", "β˜€οΈ", "πŸŒ™"]
87
- if random.random() < 0.3: # 30% chance to add an emoji
88
- caption = caption.rstrip('.!?') + f" {random.choice(instagram_elements)}"
89
-
90
- captions.append(caption)
91
 
92
- return captions
93
 
94
- def generate_captions_interface(description):
95
- """Interface function for Gradio"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  if not description.strip():
97
- return "Please enter a description to generate captions!"
98
 
99
  try:
100
- captions = generate_instagram_captions(description.strip())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- # Format captions as numbered list
103
- formatted_captions = []
104
- for i, caption in enumerate(captions, 1):
105
- formatted_captions.append(f"{i}. {caption}")
106
 
107
- return "\n\n".join(formatted_captions)
108
 
109
  except Exception as e:
110
- return f"Error generating captions: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  # Create the Gradio interface
113
- with gr.Blocks(
114
- theme=gr.themes.Soft(
115
- primary_hue="blue",
116
- secondary_hue="purple"
117
- ),
118
- title="πŸ“Έ Instacap – AI Instagram Caption Generator"
119
- ) as app:
120
 
121
  gr.Markdown(
122
  """
123
  # πŸ“Έ Instacap – AI Instagram Caption Generator
124
 
125
- Transform your photo descriptions into catchy Instagram captions!
126
- Simply describe your photo or the vibe you're going for, and get 5 unique, engaging captions.
127
 
128
- **Examples:** "beach sunset", "coffee and books", "city nightlife", "cozy home vibes"
129
  """
130
  )
131
 
132
  with gr.Row():
133
- with gr.Column(scale=2):
134
  description_input = gr.Textbox(
135
- label="Photo Description or Vibe",
136
- placeholder="e.g., beach, sea & sun",
137
- lines=2,
138
- max_lines=3
139
  )
140
 
141
  generate_btn = gr.Button(
142
- "Generate Captions",
143
  variant="primary",
144
  size="lg"
145
  )
 
 
 
 
 
 
 
 
 
146
 
147
- with gr.Column(scale=3):
148
  output_captions = gr.Textbox(
149
- label="Generated Instagram Captions",
150
- lines=10,
151
  max_lines=15,
152
- show_copy_button=True
 
153
  )
154
 
155
  # Examples section
156
- gr.Markdown("### πŸ’‘ Try these examples:")
157
 
158
  examples = [
159
- "beach sunset vibes",
160
- "coffee morning routine",
161
- "city lights at night",
162
- "cozy reading corner",
163
- "workout motivation",
164
- "food photography",
165
- "travel adventure",
166
- "friendship moments"
167
  ]
168
 
169
  gr.Examples(
170
  examples=examples,
171
  inputs=description_input,
172
  outputs=output_captions,
173
- fn=generate_captions_interface,
174
  cache_examples=False
175
  )
176
 
177
- # Set up the event handlers
178
  generate_btn.click(
179
- fn=generate_captions_interface,
180
  inputs=description_input,
181
  outputs=output_captions
182
  )
183
 
184
  description_input.submit(
185
- fn=generate_captions_interface,
186
  inputs=description_input,
187
  outputs=output_captions
188
  )
@@ -191,13 +397,21 @@ with gr.Blocks(
191
  """
192
  ---
193
 
194
- **Tips for better captions:**
195
- - Be specific with your description
196
- - Include emotions or moods
197
- - Mention key visual elements
198
- - Try different variations of the same concept
 
 
 
 
 
 
 
 
199
 
200
- *Generated captions are AI-created and may need editing for your specific needs.*
201
  """
202
  )
203
 
@@ -206,5 +420,7 @@ if __name__ == "__main__":
206
  app.launch(
207
  share=True,
208
  server_name="0.0.0.0",
209
- server_port=7860
 
 
210
  )
 
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
  )
 
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
 
 
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
  )