viveksil commited on
Commit
68ccda2
·
verified ·
1 Parent(s): 1f361f0

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -0
app.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import json
4
+ import gradio as gr
5
+ import requests
6
+ from groq import Groq
7
+ from dotenv import load_dotenv
8
+ from io import BytesIO
9
+ from PIL import Image
10
+
11
+ load_dotenv()
12
+
13
+ # Setup clients and credentials
14
+ IMGFLIP_USERNAME = os.getenv("IMGFLIP_USERNAME")
15
+ IMGFLIP_PASSWORD = os.getenv("IMGFLIP_PASSWORD")
16
+ client = Groq(api_key=os.getenv("GROQ_API_KEY"))
17
+
18
+ # Load memes from Imgflip API
19
+ def list_memes():
20
+ # r = requests.get("https://api.imgflip.com/get_memes")
21
+ # data = r.json()
22
+ # if not data["success"]:
23
+ # return {}
24
+ data = json.loads(open("./metadata.json","r").read())
25
+ return {meme["name"]: {"id": meme["id"], "url": meme["url"]} for meme in data["data"]["memes"]}
26
+
27
+ MEME_DATABASE = list_memes()
28
+
29
+ # Llama-4-Scout selects the meme template + captions
30
+ def pick_meme_and_params(prompt: str) -> dict:
31
+ meme_names = list(MEME_DATABASE.keys())
32
+ meme_list_string = "\n".join(f"- {name}" for name in meme_names)
33
+
34
+ system_message = "You are a JSON-output assistant that selects the best meme template and generates top and bottom captions."
35
+ user_message = (
36
+ f"Here is the list of available meme templates:\n{meme_list_string}\n\n"
37
+ f"Based on this list, choose the most suitable meme template for the prompt: '{prompt}'.\n\n"
38
+ f"Return your answer in this JSON format:\n"
39
+ "{\n"
40
+ "\"template_name\": \"template name from the list\",\n"
41
+ "\"top_text\": \"top caption\",\n"
42
+ "\"bottom_text\": \"bottom caption\",\n"
43
+ "\"font\": \"optional font (default to impact)\",\n"
44
+ "\"max_font_size\": integer between 10 and 100 (optional)\n"
45
+ "}"
46
+ "Only return JSON, not extra information, no delimiter, only JSON"
47
+ )
48
+ print("preresponse")
49
+ response = client.chat.completions.create(
50
+ model="meta-llama/llama-4-scout-17b-16e-instruct",
51
+ messages=[{"role": "system", "content": system_message}, {"role": "user", "content": user_message}],
52
+ # response_format="json"
53
+ )
54
+ # print(response.choices[0].message.content)
55
+ json_response = json.loads(response.choices[0].message.content)
56
+ return json_response
57
+
58
+ # Call Imgflip API to generate the meme
59
+ # def make_meme(config: dict) -> str:
60
+ # template = MEME_DATABASE.get(config["template_name"])
61
+ # if not template:
62
+ # return f"Error: Meme template '{config['template_name']}' not found."
63
+
64
+ # payload = {
65
+ # "template_id": template["id"],
66
+ # "username": IMGFLIP_USERNAME,
67
+ # "password": IMGFLIP_PASSWORD,
68
+ # "text0": config["top_text"],
69
+ # "text1": config["bottom_text"]
70
+ # }
71
+
72
+ # if config.get("font"):
73
+ # payload["font"] = config["font"]
74
+ # if config.get("max_font_size"):
75
+ # payload["max_font_size"] = config["max_font_size"]
76
+
77
+ # r = requests.post("https://api.imgflip.com/caption_image", data=payload)
78
+ # d = r.json()
79
+ # return d["data"]["url"] if d.get("success") else f"Error: {d.get('error_message')}"
80
+
81
+ def make_meme(config: dict):
82
+ template = MEME_DATABASE.get(config["template_name"])
83
+ if not template:
84
+ raise ValueError(f"Meme template '{config['template_name']}' not found.")
85
+
86
+ payload = {
87
+ "template_id": template["id"],
88
+ "username": IMGFLIP_USERNAME,
89
+ "password": IMGFLIP_PASSWORD,
90
+ "text0": config["top_text"],
91
+ "text1": config["bottom_text"]
92
+ }
93
+
94
+ if config.get("font"):
95
+ payload["font"] = config["font"]
96
+ if config.get("max_font_size"):
97
+ payload["max_font_size"] = config["max_font_size"]
98
+
99
+ r = requests.post("https://api.imgflip.com/caption_image", data=payload)
100
+ d = r.json()
101
+ print(d)
102
+ # with open("response.json","w") as f:
103
+ # json.dump(d,f)
104
+ if not d.get("success"):
105
+ raise ValueError(f"Error from Imgflip API: {d.get('error_message')}")
106
+
107
+ meme_url = d["data"]["url"]
108
+
109
+ # Fetch the generated image from the returned URL
110
+ img_response = requests.get(meme_url)
111
+ if img_response.status_code != 200:
112
+ raise ValueError("Failed to fetch the generated meme image.")
113
+
114
+ # Convert image bytes to PIL image for Gradio
115
+ image = Image.open(BytesIO(img_response.content))
116
+ image.save("./img.png")
117
+ return image
118
+
119
+ # Full meme generation pipeline
120
+ def generate_meme(prompt):
121
+ try:
122
+ config = pick_meme_and_params(prompt)
123
+ print(type(config))
124
+ print(config)
125
+ return make_meme(config)
126
+ except Exception as e:
127
+ return f"Error generating meme: {e}"
128
+
129
+ # Gradio + MCP interface
130
+ with gr.Blocks() as demo:
131
+ gr.Markdown("# 🖼️ Meme Comtext Protocol Tool")
132
+ prompt_in = gr.Textbox(label="Enter your meme idea")
133
+ out_img = gr.Image(label="Generated Meme")
134
+ btn = gr.Button("Generate Meme")
135
+
136
+ btn.click(fn=generate_meme, inputs=prompt_in, outputs=out_img)
137
+
138
+ if __name__ == "__main__":
139
+ demo.launch(mcp_server=True)