Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -21,15 +21,13 @@ def get_client():
|
|
| 21 |
|
| 22 |
def generate_meme_content(idea: str):
|
| 23 |
"""
|
| 24 |
-
|
| 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 |
|
|
@@ -44,7 +42,7 @@ def generate_meme_content(idea: str):
|
|
| 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 |
{{
|
|
@@ -61,9 +59,8 @@ Your JSON response:"""
|
|
| 61 |
)
|
| 62 |
response_text = response_stream.choices[0].message.content
|
| 63 |
|
| 64 |
-
# ---
|
| 65 |
-
|
| 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
|
|
@@ -73,18 +70,16 @@ Your JSON response:"""
|
|
| 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
|
|
@@ -93,20 +88,17 @@ Your JSON response:"""
|
|
| 93 |
|
| 94 |
|
| 95 |
def create_meme(idea: str):
|
| 96 |
-
"""Main function to generate the complete meme
|
| 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"
|
|
@@ -144,16 +136,14 @@ def create_meme(idea: str):
|
|
| 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.",
|
|
@@ -201,7 +191,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), ti
|
|
| 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],
|
|
|
|
| 21 |
|
| 22 |
def generate_meme_content(idea: str):
|
| 23 |
"""
|
| 24 |
+
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 |
template_descriptions = "\n".join([f"- {name}: {desc}" for name, desc in TEMPLATE_GUIDANCE.items()])
|
|
|
|
| 31 |
MODELS_TO_TRY = ["mistralai/Mistral-7B-Instruct-v0.2", "HuggingFaceH4/zephyr-7b-beta"]
|
| 32 |
failed_models = []
|
| 33 |
|
|
|
|
| 42 |
|
| 43 |
**3. Generate a funny, two-line caption for the chosen template.**
|
| 44 |
|
| 45 |
+
**4. Format your response as a single, valid JSON object with three keys: "template", "top_text", "bottom_text". Do not add any extra text or explanations outside of the JSON object.**
|
| 46 |
|
| 47 |
Example Response:
|
| 48 |
{{
|
|
|
|
| 59 |
)
|
| 60 |
response_text = response_stream.choices[0].message.content
|
| 61 |
|
| 62 |
+
# --- FINAL FIX: Use a non-greedy regex to find the first JSON object ---
|
| 63 |
+
json_match = re.search(r'\{.*?\}', response_text, re.DOTALL)
|
|
|
|
| 64 |
if not json_match:
|
| 65 |
failed_models.append(f"{model_id.split('/')[-1]} (bad format)")
|
| 66 |
continue
|
|
|
|
| 70 |
top_text = parsed_json.get("top_text")
|
| 71 |
bottom_text = parsed_json.get("bottom_text")
|
| 72 |
|
|
|
|
| 73 |
if not all([template, top_text, bottom_text]) or template not in MEME_TEMPLATES:
|
| 74 |
failed_models.append(f"{model_id.split('/')[-1]} (invalid content)")
|
| 75 |
continue
|
| 76 |
|
|
|
|
| 77 |
return template, top_text, bottom_text, None, model_id
|
| 78 |
|
| 79 |
+
except (Exception, json.JSONDecodeError) as e:
|
| 80 |
error_msg = str(e).lower()
|
| 81 |
if "404" in error_msg or "503" in error_msg or "is currently loading" in error_msg or "invalid json" in error_msg:
|
| 82 |
+
failed_models.append(f"{model_id.split('/')[-1]} ({type(e).__name__})")
|
| 83 |
continue
|
| 84 |
else:
|
| 85 |
return None, None, None, f"❌ **AI Error:** {str(e)[:250]}", model_id
|
|
|
|
| 88 |
|
| 89 |
|
| 90 |
def create_meme(idea: str):
|
| 91 |
+
"""Main function to generate the complete meme."""
|
| 92 |
if not idea or len(idea.strip()) < 3:
|
| 93 |
return None, "❌ Please enter a meme idea (at least 3 characters)!"
|
| 94 |
|
|
|
|
| 95 |
imgflip_user = os.environ.get("IMGFLIP_USERNAME")
|
| 96 |
imgflip_pass = os.environ.get("IMGFLIP_PASSWORD")
|
| 97 |
if not imgflip_user or not imgflip_pass:
|
| 98 |
return None, "❌ **ImgFlip Credentials Required in Secrets**"
|
| 99 |
|
|
|
|
| 100 |
template_name, top, bottom, error, model_used = generate_meme_content(idea)
|
| 101 |
+
if error: return None, error
|
|
|
|
| 102 |
|
| 103 |
template_id = MEME_TEMPLATES.get(template_name)
|
| 104 |
url = "https://api.imgflip.com/caption_image"
|
|
|
|
| 136 |
except Exception as e:
|
| 137 |
return None, f"❌ **An unexpected error occurred:** {str(e)}"
|
| 138 |
|
| 139 |
+
# --- CONFIGURATION & UI (No changes needed) ---
|
| 140 |
|
|
|
|
| 141 |
MEME_TEMPLATES = {
|
| 142 |
"Drake": "181913649", "Distracted Boyfriend": "112126428", "Two Buttons": "87743020",
|
| 143 |
"Expanding Brain": "93895088", "Success Kid": "61544", "Batman Slapping Robin": "438680",
|
| 144 |
"Change My Mind": "129242436", "Woman Yelling at a Cat": "188390779", "Surprised Pikachu": "155067746",
|
| 145 |
}
|
| 146 |
|
|
|
|
| 147 |
TEMPLATE_GUIDANCE = {
|
| 148 |
"Drake": "Represents choosing one thing (good) over another (bad). Good for showing preference.",
|
| 149 |
"Distracted Boyfriend": "Represents being tempted by something new while neglecting something you already have.",
|
|
|
|
| 191 |
|
| 192 |
gr.Examples(examples=examples, inputs=[idea_input], label="💡 Meme Ideas to Try")
|
| 193 |
|
|
|
|
| 194 |
generate_button.click(
|
| 195 |
fn=create_meme,
|
| 196 |
inputs=[idea_input],
|