faizee07 commited on
Commit
11b31df
Β·
verified Β·
1 Parent(s): 9fd1ca7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -58
app.py CHANGED
@@ -5,6 +5,7 @@ import requests
5
  import random
6
  import re
7
  import tempfile
 
8
 
9
  # --- CORE FUNCTIONS ---
10
 
@@ -18,81 +19,101 @@ def get_client():
18
  return None, "❌ **HuggingFace Token Required**\n\n**Setup:**\n1. Go to Space Settings β†’ Repository Secrets\n2. Add secret: Name=`HF_TOKEN`, Value=(your HF token)\n3. Get token: https://huggingface.co/settings/tokens\n4. Restart Space"
19
  return InferenceClient(token=token), None
20
 
21
- def generate_meme_text(idea: str):
22
- """Generate meme text by trying a list of models using the correct chat API."""
 
 
 
23
  client, error = get_client()
24
- if error: return None, None, error, None
25
 
26
- MODELS_TO_TRY = ["mistralai/Mistral-7B-Instruct-v0.2", "HuggingFaceH4/zephyr-7b-beta", "google/flan-t5-large"]
 
 
 
27
  failed_models = []
28
 
29
  for model_id in MODELS_TO_TRY:
30
  try:
31
- prompt = f"""Task: Create a funny, two-line meme caption for the idea: "{idea}".
 
 
 
 
 
 
 
32
 
33
- Format your response exactly like this, with no extra text:
34
- Top: [The first line of the meme]
35
- Bottom: [The second line, the punchline]"""
 
 
 
 
 
 
 
36
 
37
  messages = [{"role": "user", "content": prompt}]
38
-
39
  response_stream = client.chat_completion(
40
- messages, model=model_id, max_tokens=60, temperature=0.8, stream=False
41
  )
42
- response = response_stream.choices[0].message.content
43
-
44
- top_text, bottom_text = "",""
45
- top_match = re.search(r"Top:\s*(.*)", response, re.IGNORECASE)
46
- bottom_match = re.search(r"Bottom:\s*(.*)", response, re.IGNORECASE)
47
 
48
- if top_match: top_text = top_match.group(1).strip().strip('[]"')
49
- if bottom_match: bottom_text = bottom_match.group(1).strip().strip('[]"')
50
-
51
- if not top_text or not bottom_text:
52
- lines = response.strip().split('\n')
53
- if len(lines) >= 1: top_text = lines[0].replace("Top:", "").strip()
54
- if len(lines) >= 2: bottom_text = lines[1].replace("Bottom:", "").strip()
55
 
56
- if not top_text.strip() or not bottom_text.strip(): continue
 
 
 
 
 
 
 
 
57
 
58
- return top_text.strip(), bottom_text.strip(), None, model_id
 
59
 
60
  except Exception as e:
61
  error_msg = str(e).lower()
62
- if "404" in error_msg or "503" in error_msg or "is currently loading" in error_msg:
63
  failed_models.append(model_id.split('/')[-1])
64
  continue
65
  else:
66
- return None, None, f"❌ **AI Error:** {str(e)[:250]}", model_id
67
 
68
- return None, None, f"❌ **All AI Models Are Offline**\n\n**Models Tried:** {', '.join(failed_models)}", None
69
 
70
 
71
- def create_meme(idea: str, template: str):
72
- """Main function to generate the complete meme."""
73
  if not idea or len(idea.strip()) < 3:
74
  return None, "❌ Please enter a meme idea (at least 3 characters)!"
75
 
76
- # --- FINAL FIX: Check for ImgFlip credentials ---
77
  imgflip_user = os.environ.get("IMGFLIP_USERNAME")
78
  imgflip_pass = os.environ.get("IMGFLIP_PASSWORD")
79
-
80
  if not imgflip_user or not imgflip_pass:
81
- return None, "❌ **ImgFlip Credentials Required**\n\n**Setup:**\n1. Create a free account at Imgflip.com\n2. Go to Space Settings β†’ Repository Secrets\n3. Add `IMGFLIP_USERNAME` and `IMGFLIP_PASSWORD` secrets\n4. Restart Space."
82
 
83
- top, bottom, error, model_used = generate_meme_text(idea)
84
- if error: return None, error
 
 
85
 
86
- template_id = MEME_TEMPLATES.get(template, "181913649")
87
  url = "https://api.imgflip.com/caption_image"
88
 
89
- # --- FINAL FIX: Use your credentials from the secrets ---
90
  payload = {
91
- 'template_id': template_id,
92
- 'username': imgflip_user,
93
- 'password': imgflip_pass,
94
- 'text0': top,
95
- 'text1': bottom
96
  }
97
 
98
  try:
@@ -110,9 +131,10 @@ def create_meme(idea: str, template: str):
110
  temp_path = tmpfile.name
111
 
112
  status_message = (f"βœ… **Success!**\n\n"
 
113
  f"πŸ“ **Top Text:** {top}\n"
114
  f"πŸ“ **Bottom Text:** {bottom}\n\n"
115
- f"πŸ€– **AI Model Used:** {model_used.split('/')[-1] if model_used else 'N/A'}")
116
  return temp_path, status_message
117
  else:
118
  return None, f"❌ **ImgFlip API Error:** {data.get('error_message', 'Unknown error')}"
@@ -122,53 +144,67 @@ def create_meme(idea: str, template: str):
122
  except Exception as e:
123
  return None, f"❌ **An unexpected error occurred:** {str(e)}"
124
 
125
- # --- CONFIGURATION & UI (No changes needed) ---
126
- # [UI code remains the same]
127
 
 
128
  MEME_TEMPLATES = {
129
  "Drake": "181913649", "Distracted Boyfriend": "112126428", "Two Buttons": "87743020",
130
  "Expanding Brain": "93895088", "Success Kid": "61544", "Batman Slapping Robin": "438680",
131
  "Change My Mind": "129242436", "Woman Yelling at a Cat": "188390779", "Surprised Pikachu": "155067746",
132
  }
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  examples = [
135
  ["When you fix a bug you don't understand"], ["My plans for the weekend vs. what I actually do"],
136
  ["Saying you'll just have one slice of pizza"], ["Me pretending to be productive in a Zoom meeting"],
137
- ["Checking my bank account after a long weekend"], ["Trying to assemble IKEA furniture with the instructions"],
138
  ]
139
 
140
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), title="AI Meme Generator") as demo:
141
 
142
  gr.HTML("""
143
  <div style='text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
144
  padding: 30px; border-radius: 15px; color: white; margin-bottom: 20px;'>
145
- <h1>πŸ₯Έ AI Meme Generator</h1>
146
- <h3>Auto-Healing AI that ALWAYS Finds a Working Model πŸ€—</h3>
147
  </div>
148
  """)
149
 
150
  with gr.Row():
151
  with gr.Column(scale=2):
152
- idea_input = gr.Textbox(label="🎨 Your Meme Idea", placeholder="Example: When the CI/CD pipeline finally passes...", lines=3)
153
- template_dropdown = gr.Dropdown(choices=list(MEME_TEMPLATES.keys()), value="Drake", label="πŸ–ΌοΈ Meme Template")
154
  generate_button = gr.Button("πŸš€ Generate Meme", variant="primary", size="lg")
 
 
 
 
 
 
 
 
155
 
156
  with gr.Column(scale=1):
157
  output_image = gr.Image(label="πŸ–ΌοΈ Your Generated Meme", type="filepath", show_download_button=True)
158
 
159
- output_status = gr.Textbox(label="πŸ“Š Status & Details", lines=4, show_copy_button=True)
160
 
161
- with gr.Accordion("How does this work?", open=False):
162
- gr.Markdown("""
163
- This app is **resilient**. It has a list of reliable free models from Hugging Face and automatically tries them until it finds one that is online and working.
164
- If your `HF_TOKEN` is set up correctly in your Space Secrets, this app should always work.
165
- """)
166
-
167
  gr.Examples(examples=examples, inputs=[idea_input], label="πŸ’‘ Meme Ideas to Try")
168
 
 
169
  generate_button.click(
170
  fn=create_meme,
171
- inputs=[idea_input, template_dropdown],
172
  outputs=[output_image, output_status]
173
  )
174
 
 
5
  import random
6
  import re
7
  import tempfile
8
+ import json
9
 
10
  # --- CORE FUNCTIONS ---
11
 
 
19
  return None, "❌ **HuggingFace Token Required**\n\n**Setup:**\n1. Go to Space Settings β†’ Repository Secrets\n2. Add secret: Name=`HF_TOKEN`, Value=(your HF token)\n3. Get token: https://huggingface.co/settings/tokens\n4. Restart Space"
20
  return InferenceClient(token=token), None
21
 
22
+ def generate_meme_content(idea: str):
23
+ """
24
+ NEW: In a single AI call, choose the best template AND generate the text.
25
+ Returns: template_name, top_text, bottom_text, error, model_used
26
+ """
27
  client, error = get_client()
28
+ if error: return None, None, None, error, None
29
 
30
+ # We "teach" the AI about our templates
31
+ template_descriptions = "\n".join([f"- {name}: {desc}" for name, desc in TEMPLATE_GUIDANCE.items()])
32
+
33
+ MODELS_TO_TRY = ["mistralai/Mistral-7B-Instruct-v0.2", "HuggingFaceH4/zephyr-7b-beta"]
34
  failed_models = []
35
 
36
  for model_id in MODELS_TO_TRY:
37
  try:
38
+ prompt = f"""You are an AI expert in meme culture. Your task is to analyze an idea, choose the best meme template, and generate a funny caption.
39
+
40
+ **1. Analyze the user's idea:** "{idea}"
41
+
42
+ **2. Choose the single best meme template from this list:**
43
+ {template_descriptions}
44
+
45
+ **3. Generate a funny, two-line caption for the chosen template.**
46
 
47
+ **4. Format your response as a valid JSON object with three keys: "template", "top_text", "bottom_text".**
48
+
49
+ Example Response:
50
+ {{
51
+ "template": "Drake",
52
+ "top_text": "Manually selecting a meme template",
53
+ "bottom_text": "Letting the AI choose the template automatically"
54
+ }}
55
+
56
+ Your JSON response:"""
57
 
58
  messages = [{"role": "user", "content": prompt}]
 
59
  response_stream = client.chat_completion(
60
+ messages, model=model_id, max_tokens=150, temperature=0.8, stream=False
61
  )
62
+ response_text = response_stream.choices[0].message.content
 
 
 
 
63
 
64
+ # --- Robust JSON Parsing ---
65
+ # The model might sometimes add extra text or code blocks around the JSON
66
+ json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
67
+ if not json_match:
68
+ failed_models.append(f"{model_id.split('/')[-1]} (bad format)")
69
+ continue
 
70
 
71
+ parsed_json = json.loads(json_match.group(0))
72
+ template = parsed_json.get("template")
73
+ top_text = parsed_json.get("top_text")
74
+ bottom_text = parsed_json.get("bottom_text")
75
+
76
+ # Validate the response
77
+ if not all([template, top_text, bottom_text]) or template not in MEME_TEMPLATES:
78
+ failed_models.append(f"{model_id.split('/')[-1]} (invalid content)")
79
+ continue
80
 
81
+ # SUCCESS!
82
+ return template, top_text, bottom_text, None, model_id
83
 
84
  except Exception as e:
85
  error_msg = str(e).lower()
86
+ if "404" in error_msg or "503" in error_msg or "is currently loading" in error_msg or "invalid json" in error_msg:
87
  failed_models.append(model_id.split('/')[-1])
88
  continue
89
  else:
90
+ return None, None, None, f"❌ **AI Error:** {str(e)[:250]}", model_id
91
 
92
+ return None, None, None, f"❌ **All AI Models Are Offline or Failing**\n\n**Models Tried:** {', '.join(failed_models)}", None
93
 
94
 
95
+ def create_meme(idea: str):
96
+ """Main function to generate the complete meme, now without a template input."""
97
  if not idea or len(idea.strip()) < 3:
98
  return None, "❌ Please enter a meme idea (at least 3 characters)!"
99
 
100
+ # Check for ImgFlip credentials
101
  imgflip_user = os.environ.get("IMGFLIP_USERNAME")
102
  imgflip_pass = os.environ.get("IMGFLIP_PASSWORD")
 
103
  if not imgflip_user or not imgflip_pass:
104
+ return None, "❌ **ImgFlip Credentials Required in Secrets**"
105
 
106
+ # Call the new intelligent function
107
+ template_name, top, bottom, error, model_used = generate_meme_content(idea)
108
+ if error:
109
+ return None, error
110
 
111
+ template_id = MEME_TEMPLATES.get(template_name)
112
  url = "https://api.imgflip.com/caption_image"
113
 
 
114
  payload = {
115
+ 'template_id': template_id, 'username': imgflip_user,
116
+ 'password': imgflip_pass, 'text0': top, 'text1': bottom
 
 
 
117
  }
118
 
119
  try:
 
131
  temp_path = tmpfile.name
132
 
133
  status_message = (f"βœ… **Success!**\n\n"
134
+ f"🧠 **AI Chose:** {template_name}\n"
135
  f"πŸ“ **Top Text:** {top}\n"
136
  f"πŸ“ **Bottom Text:** {bottom}\n\n"
137
+ f"πŸ€– **Model Used:** {model_used.split('/')[-1] if model_used else 'N/A'}")
138
  return temp_path, status_message
139
  else:
140
  return None, f"❌ **ImgFlip API Error:** {data.get('error_message', 'Unknown error')}"
 
144
  except Exception as e:
145
  return None, f"❌ **An unexpected error occurred:** {str(e)}"
146
 
147
+ # --- CONFIGURATION & UI ---
 
148
 
149
+ # Maps template names to their ImgFlip IDs
150
  MEME_TEMPLATES = {
151
  "Drake": "181913649", "Distracted Boyfriend": "112126428", "Two Buttons": "87743020",
152
  "Expanding Brain": "93895088", "Success Kid": "61544", "Batman Slapping Robin": "438680",
153
  "Change My Mind": "129242436", "Woman Yelling at a Cat": "188390779", "Surprised Pikachu": "155067746",
154
  }
155
 
156
+ # NEW: Guidance for the AI on what each template means
157
+ TEMPLATE_GUIDANCE = {
158
+ "Drake": "Represents choosing one thing (good) over another (bad). Good for showing preference.",
159
+ "Distracted Boyfriend": "Represents being tempted by something new while neglecting something you already have.",
160
+ "Two Buttons": "Represents a difficult choice, a dilemma, or inner conflict.",
161
+ "Expanding Brain": "Shows increasing levels of enlightenment or absurdity on a topic.",
162
+ "Success Kid": "Represents a small victory, unexpected success, or relief.",
163
+ "Batman Slapping Robin": "Represents a sharp rebuke or correction of a silly idea.",
164
+ "Change My Mind": "For presenting a controversial opinion that you are confident about.",
165
+ "Woman Yelling at a Cat": "Represents a misunderstanding, with one side angry and the other confused.",
166
+ "Surprised Pikachu": "Represents feigned surprise at an obvious outcome.",
167
+ }
168
+
169
  examples = [
170
  ["When you fix a bug you don't understand"], ["My plans for the weekend vs. what I actually do"],
171
  ["Saying you'll just have one slice of pizza"], ["Me pretending to be productive in a Zoom meeting"],
 
172
  ]
173
 
174
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), title="Intelligent AI Meme Generator") as demo:
175
 
176
  gr.HTML("""
177
  <div style='text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
178
  padding: 30px; border-radius: 15px; color: white; margin-bottom: 20px;'>
179
+ <h1>🧠 Intelligent AI Meme Generator</h1>
180
+ <h3>Enter an idea and let the AI choose the best meme template for you!</h3>
181
  </div>
182
  """)
183
 
184
  with gr.Row():
185
  with gr.Column(scale=2):
186
+ idea_input = gr.Textbox(label="🎨 Your Meme Idea", placeholder="Example: When the CI/CD pipeline finally passes...", lines=4)
 
187
  generate_button = gr.Button("πŸš€ Generate Meme", variant="primary", size="lg")
188
+
189
+ with gr.Accordion("How does this work?", open=False):
190
+ gr.Markdown("""
191
+ This app is **intelligent and resilient**. When you click generate:
192
+ 1. The AI analyzes your idea and chooses the best meme template from its knowledge base.
193
+ 2. It then generates a funny caption for that specific template.
194
+ 3. It automatically finds a working AI model from a list of free options.
195
+ """)
196
 
197
  with gr.Column(scale=1):
198
  output_image = gr.Image(label="πŸ–ΌοΈ Your Generated Meme", type="filepath", show_download_button=True)
199
 
200
+ output_status = gr.Textbox(label="πŸ“Š Status & Details", lines=5, show_copy_button=True)
201
 
 
 
 
 
 
 
202
  gr.Examples(examples=examples, inputs=[idea_input], label="πŸ’‘ Meme Ideas to Try")
203
 
204
+ # UPDATED: The click function no longer needs the template dropdown
205
  generate_button.click(
206
  fn=create_meme,
207
+ inputs=[idea_input],
208
  outputs=[output_image, output_status]
209
  )
210