| import os |
| import time |
| import json |
| import gradio as gr |
| import requests |
| from groq import Groq |
| from dotenv import load_dotenv |
| from io import BytesIO |
| from PIL import Image |
|
|
| load_dotenv() |
|
|
| |
| IMGFLIP_USERNAME = os.getenv("IMGFLIP_USERNAME") |
| IMGFLIP_PASSWORD = os.getenv("IMGFLIP_PASSWORD") |
| client = Groq(api_key=os.getenv("GROQ_API_KEY")) |
|
|
| |
| def list_memes(): |
| |
| |
| |
| |
| data = json.loads(open("./metadata.json","r").read()) |
| return {meme["name"]: {"id": meme["id"], "url": meme["url"]} for meme in data["data"]["memes"]} |
|
|
| MEME_DATABASE = list_memes() |
|
|
| |
| def pick_meme_and_params(prompt: str) -> dict: |
| meme_names = list(MEME_DATABASE.keys()) |
| meme_list_string = "\n".join(f"- {name}" for name in meme_names) |
|
|
| system_message = "You are a JSON-output assistant that selects the best meme template and generates top and bottom captions. Make them funny and creative" |
| user_message = ( |
| f"Here is the list of available meme templates:\n{meme_list_string}\n\n" |
| f"Based on this list, choose the most suitable meme template for the prompt: '{prompt}'.\n\n" |
| f"Return your answer in this JSON format:\n" |
| "{\n" |
| "\"template_name\": \"template name from the list\",\n" |
| "\"top_text\": \"top caption\",\n" |
| "\"bottom_text\": \"bottom caption\",\n" |
| "\"font\": \"optional font (default to impact)\",\n" |
| "\"max_font_size\": integer between 10 and 100 (optional)\n" |
| "}" |
| "Only return JSON, not extra information, no delimiter, only JSON" |
| ) |
| print("preresponse") |
| response = client.chat.completions.create( |
| |
| model="llama3-70b-8192", |
| messages=[{"role": "system", "content": system_message}, {"role": "user", "content": user_message}], |
| |
| ) |
| |
| json_response = json.loads(response.choices[0].message.content) |
| return json_response |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| def make_meme(config: dict): |
| template = MEME_DATABASE.get(config["template_name"]) |
| if not template: |
| raise ValueError(f"Meme template '{config['template_name']}' not found.") |
|
|
| payload = { |
| "template_id": template["id"], |
| "username": IMGFLIP_USERNAME, |
| "password": IMGFLIP_PASSWORD, |
| "text0": config["top_text"], |
| "text1": config["bottom_text"] |
| } |
|
|
| if config.get("font"): |
| payload["font"] = config["font"] |
| if config.get("max_font_size"): |
| payload["max_font_size"] = config["max_font_size"] |
|
|
| r = requests.post("https://api.imgflip.com/caption_image", data=payload) |
| d = r.json() |
| print(d) |
| |
| |
| if not d.get("success"): |
| raise ValueError(f"Error from Imgflip API: {d.get('error_message')}") |
|
|
| meme_url = d["data"]["url"] |
|
|
| |
| img_response = requests.get(meme_url) |
| if img_response.status_code != 200: |
| raise ValueError("Failed to fetch the generated meme image.") |
|
|
| |
| image = Image.open(BytesIO(img_response.content)) |
| image.save("./img.png") |
| return image |
|
|
| |
| def generate_meme(prompt): |
| try: |
| config = pick_meme_and_params(prompt) |
| print(type(config)) |
| print(config) |
| return make_meme(config) |
| except Exception as e: |
| return f"Error generating meme: {e}" |
|
|
| |
|
|
| with gr.Blocks() as demo: |
| gr.Markdown("# 🖼️ Meme Context Protocol Tool") |
| gr.Markdown(""" |
| **Your personal meme genie!** |
| Drop a prompt, and this meme conjurer uses magic to pick the perfect template and cook up hilarious captions faster than you can say "dank." |
| It’s the ultimate meme-making mischief machine – pun-powered, LLM-fueled, and chaos-approved. |
| Memes so fresh, they might just slap themselves. |
| """) |
| prompt_in = gr.Textbox(label="Enter your meme idea") |
| out_img = gr.Image(label="Generated Meme") |
| btn = gr.Button("Generate Meme") |
|
|
| btn.click(fn=generate_meme, inputs=prompt_in, outputs=out_img) |
|
|
| if __name__ == "__main__": |
| demo.launch(mcp_server=True, ssr_mode=False) |
|
|