ZENLLC commited on
Commit
1cca399
·
verified ·
1 Parent(s): 83beef9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -0
app.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai, gradio as gr, json, plotly.graph_objects as go
2
+
3
+ SYSTEM_PROMPT = """
4
+ You are ZEN Multimodal Assistant created by ZEN AI Co.
5
+ Choose the single best modality for each reply:
6
+
7
+ 1. Image – when an illustration, diagram, or photo-realistic scene answers best.
8
+ Respond **only** with JSON:
9
+ {"type":"image","prompt":"<detailed prompt for DALL-E-3>"}
10
+
11
+ 2. Chart – when the user requests or clearly needs data-visualisation.
12
+ Respond **only** with JSON:
13
+ {"type":"chart",
14
+ "title":"<chart title>",
15
+ "data":[
16
+ {"x":[...], "y":[...], "label":"<series name>"},
17
+ ...
18
+ ]}
19
+
20
+ 3. Text – for every other case.
21
+ Respond with plain language (no JSON).
22
+
23
+ Never wrap JSON in markdown fences and never add comments.
24
+ """
25
+
26
+ # ---------- Helper functions ---------- #
27
+ def build_messages(history, user_msg):
28
+ messages = [{"role": "system", "content": SYSTEM_PROMPT}]
29
+ for u, a in history:
30
+ messages.append({"role": "user", "content": u})
31
+ messages.append({"role": "assistant", "content": a})
32
+ messages.append({"role": "user", "content": user_msg})
33
+ return messages
34
+
35
+
36
+ def multimodal_chat(api_key, user_msg, history):
37
+ if not api_key:
38
+ raise gr.Error("🔑 Please paste your OpenAI API key first.")
39
+ openai.api_key = api_key
40
+
41
+ history = history or []
42
+ messages = build_messages(history, user_msg)
43
+
44
+ response = openai.chat.completions.create(
45
+ model="gpt-4o-mini",
46
+ messages=messages,
47
+ temperature=0.7,
48
+ )
49
+ assistant_content = response.choices[0].message.content.strip()
50
+
51
+ img_url, fig = None, None
52
+ try: # JSON branch (image or chart)
53
+ parsed = json.loads(assistant_content)
54
+ if parsed.get("type") == "image":
55
+ dalle = openai.images.generate(
56
+ model="dall-e-3",
57
+ prompt=parsed.get("prompt", "high-quality illustration"),
58
+ n=1,
59
+ size="1024x1024",
60
+ )
61
+ img_url = dalle.data[0].url
62
+ history.append([user_msg, f"![generated image]({img_url})"])
63
+
64
+ elif parsed.get("type") == "chart":
65
+ fig = go.Figure()
66
+ for s in parsed["data"]:
67
+ fig.add_trace(
68
+ go.Scatter(
69
+ x=s["x"],
70
+ y=s["y"],
71
+ mode="lines+markers",
72
+ name=s.get("label", ""),
73
+ )
74
+ )
75
+ fig.update_layout(title=parsed.get("title", "Chart"))
76
+ history.append([user_msg, parsed.get("title", "Chart below")])
77
+
78
+ else: # fallback to text
79
+ history.append([user_msg, assistant_content])
80
+
81
+ except (json.JSONDecodeError, KeyError, TypeError): # plain-text branch
82
+ history.append([user_msg, assistant_content])
83
+
84
+ return history, img_url, fig
85
+
86
+
87
+ # ---------- Gradio UI ---------- #
88
+ with gr.Blocks(title="ZEN Multimodal Assistant") as demo:
89
+ gr.Markdown(
90
+ """
91
+ # 🧠 ZEN Multimodal Assistant
92
+ Paste your OpenAI API key once per session and chat freely –
93
+ the assistant decides whether to answer with **text, an image, or an interactive chart**.
94
+ """
95
+ )
96
+
97
+ api_key = gr.Textbox(label="OpenAI API Key", type="password", placeholder="sk-...")
98
+ chatbot = gr.Chatbot(label="Conversation")
99
+ with gr.Row():
100
+ user_msg = gr.Textbox(placeholder="Ask me anything…", label="Your message", scale=4)
101
+ send_btn = gr.Button("Send", variant="primary")
102
+
103
+ img_out = gr.Image(label="Generated image")
104
+ chart_out = gr.Plot(label="Interactive chart")
105
+
106
+ def respond(api_key, user_msg, chat_history):
107
+ chat_history, img_url, fig = multimodal_chat(api_key, user_msg, chat_history)
108
+
109
+ img_update = gr.update(value=img_url) if img_url else gr.update(value=None)
110
+ fig_update = gr.update(value=fig) if fig else gr.update(value=None)
111
+
112
+ return chat_history, img_update, fig_update
113
+
114
+ send_btn.click(
115
+ respond,
116
+ inputs=[api_key, user_msg, chatbot],
117
+ outputs=[chatbot, img_out, chart_out],
118
+ )
119
+ user_msg.submit(
120
+ respond,
121
+ inputs=[api_key, user_msg, chatbot],
122
+ outputs=[chatbot, img_out, chart_out],
123
+ )
124
+
125
+ if __name__ == "__main__":
126
+ demo.queue(max_size=50).launch()