ZENLLC commited on
Commit
ec81fd1
·
verified ·
1 Parent(s): 9597acb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -81
app.py CHANGED
@@ -1,134 +1,196 @@
1
- import os, json
 
 
 
 
 
2
  import gradio as gr
3
- from openai import OpenAI
4
  import plotly.graph_objects as go
 
 
5
 
6
- client = OpenAI()
7
 
8
  SYSTEM_PROMPT = """
9
  You are OmniGen AI.
10
 
11
- You must choose ONLY ONE output mode:
 
 
12
 
13
- 1. IMAGE → if visual needed
14
- Return JSON:
15
- {"type":"image","prompt":"detailed prompt for image generation"}
16
 
17
- 2. CHART → if data visualization needed
18
- Return JSON:
19
- {"type":"chart","title":"...","data":[{"x":[...],"y":[...],"label":"..."}]}
20
 
21
- 3. TEXT → otherwise
22
- Return plain text only (no JSON)
23
 
24
- Do NOT explain your choice.
 
 
 
 
 
 
25
  """
26
 
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 run_agent(api_key, user_msg, history, mode):
37
- if not api_key:
38
  raise gr.Error("Please enter your OpenAI API key.")
 
39
 
40
- client.api_key = api_key
41
- history = history or []
42
-
43
- messages = build_messages(history, user_msg)
44
 
 
45
  response = client.chat.completions.create(
46
  model="gpt-4.1",
47
  messages=messages,
48
- temperature=0.7,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  )
50
 
51
- content = response.choices[0].message.content.strip()
 
 
52
 
53
- img, fig = None, None
 
54
 
55
- try:
56
- parsed = json.loads(content)
57
 
58
- if parsed["type"] == "image":
59
- img_resp = client.images.generate(
60
- model="gpt-image-1",
61
- prompt=parsed["prompt"],
62
- size="1024x1024"
 
 
 
 
 
 
 
 
 
 
 
 
63
  )
64
- img = img_resp.data[0].url
65
- history.append([user_msg, f"![image]({img})"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- elif parsed["type"] == "chart":
68
- fig = go.Figure()
69
- for s in parsed["data"]:
70
- fig.add_trace(go.Scatter(
71
- x=s["x"],
72
- y=s["y"],
73
- mode="lines+markers",
74
- name=s.get("label", "")
75
- ))
76
- fig.update_layout(title=parsed.get("title", "Chart"))
77
- history.append([user_msg, parsed.get("title", "Chart generated")])
78
 
79
- else:
80
- history.append([user_msg, content])
81
 
82
- except:
83
- history.append([user_msg, content])
 
84
 
85
- return history, img, fig
 
 
 
 
 
86
 
 
 
 
 
87
 
88
- with gr.Blocks(css="style.css") as demo:
 
89
 
 
 
 
 
90
  gr.Markdown(
91
- "# 🧠 OmniGen AI Studio\n"
92
- "Generate text, images, or charts from one prompt.\n"
93
- "Powered by GPT-4.1"
 
94
  )
95
 
96
- with gr.Row():
97
- api_key = gr.Textbox(label="OpenAI API Key", type="password")
 
 
 
98
 
99
- chatbot = gr.Chatbot(height=400)
100
 
101
  with gr.Row():
102
- user_msg = gr.Textbox(label="Your Prompt", scale=4)
103
- mode = gr.Radio(
104
- ["Auto", "Force Text", "Force Image", "Force Chart"],
105
- value="Auto",
106
- label="Mode"
107
  )
108
- send = gr.Button("Generate", variant="primary")
109
-
110
- img_out = gr.Image(label="Generated Image")
111
- chart_out = gr.Plot(label="Generated Chart")
112
 
113
- def respond(api_key, user_msg, history, mode):
114
- history, img, fig = run_agent(api_key, user_msg, history, mode)
 
115
 
116
- return (
117
- history,
118
- gr.update(value=img) if img else gr.update(value=None),
119
- gr.update(value=fig) if fig else gr.update(value=None),
120
- )
121
 
122
- send.click(
123
- respond,
124
- inputs=[api_key, user_msg, chatbot, mode],
125
- outputs=[chatbot, img_out, chart_out]
126
  )
127
 
128
  user_msg.submit(
129
- respond,
130
- inputs=[api_key, user_msg, chatbot, mode],
131
- outputs=[chatbot, img_out, chart_out]
132
  )
133
 
134
 
 
1
+ import os
2
+ import io
3
+ import json
4
+ import base64
5
+ from typing import Any, Dict, List, Tuple
6
+
7
  import gradio as gr
 
8
  import plotly.graph_objects as go
9
+ from PIL import Image
10
+ from openai import OpenAI
11
 
 
12
 
13
  SYSTEM_PROMPT = """
14
  You are OmniGen AI.
15
 
16
+ Decide the single best response mode for the user's request.
17
+
18
+ Return one of these formats only:
19
 
20
+ For text:
21
+ {"type":"text","content":"<helpful answer>"}
 
22
 
23
+ For image:
24
+ {"type":"image","prompt":"<clear image generation prompt>"}
 
25
 
26
+ For chart:
27
+ {"type":"chart","title":"<chart title>","data":[{"x":[...],"y":[...],"label":"<series label>"}]}
28
 
29
+ Rules:
30
+ - Return valid JSON only.
31
+ - Choose exactly one type.
32
+ - Use chart only when a chart is genuinely appropriate.
33
+ - Use image only when a visual is genuinely appropriate.
34
+ - Otherwise use text.
35
+ - Do not wrap output in markdown fences.
36
  """
37
 
38
+
39
+ def build_messages(history: List[Dict[str, Any]], user_msg: str) -> List[Dict[str, str]]:
40
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
41
+ for item in history:
42
+ role = item.get("role")
43
+ content = item.get("content")
44
+ if role in {"user", "assistant"} and isinstance(content, str):
45
+ messages.append({"role": role, "content": content})
46
  messages.append({"role": "user", "content": user_msg})
47
  return messages
48
 
49
 
50
+ def make_client(api_key: str) -> OpenAI:
51
+ if not api_key or not api_key.strip():
52
  raise gr.Error("Please enter your OpenAI API key.")
53
+ return OpenAI(api_key=api_key.strip())
54
 
 
 
 
 
55
 
56
+ def generate_router_response(client: OpenAI, messages: List[Dict[str, str]]) -> Dict[str, Any]:
57
  response = client.chat.completions.create(
58
  model="gpt-4.1",
59
  messages=messages,
60
+ temperature=0.5,
61
+ response_format={"type": "json_object"},
62
+ )
63
+ content = response.choices[0].message.content or ""
64
+ try:
65
+ parsed = json.loads(content)
66
+ except json.JSONDecodeError as exc:
67
+ raise gr.Error(f"Model returned invalid JSON: {exc}") from exc
68
+
69
+ if "type" not in parsed:
70
+ raise gr.Error("Model response did not include a type field.")
71
+ return parsed
72
+
73
+
74
+ def generate_image(client: OpenAI, prompt: str) -> Image.Image:
75
+ img_response = client.images.generate(
76
+ model="gpt-image-1",
77
+ prompt=prompt,
78
+ size="1024x1024",
79
  )
80
 
81
+ image_base64 = img_response.data[0].b64_json
82
+ if not image_base64:
83
+ raise gr.Error("Image generation returned no image data.")
84
 
85
+ image_bytes = base64.b64decode(image_base64)
86
+ return Image.open(io.BytesIO(image_bytes))
87
 
 
 
88
 
89
+ def generate_chart(chart_payload: Dict[str, Any]) -> go.Figure:
90
+ fig = go.Figure()
91
+ series_list = chart_payload.get("data", [])
92
+
93
+ if not isinstance(series_list, list) or not series_list:
94
+ raise gr.Error("Chart response did not include usable data.")
95
+
96
+ for series in series_list:
97
+ x = series.get("x", [])
98
+ y = series.get("y", [])
99
+ label = series.get("label", "Series")
100
+ fig.add_trace(
101
+ go.Scatter(
102
+ x=x,
103
+ y=y,
104
+ mode="lines+markers",
105
+ name=label,
106
  )
107
+ )
108
+
109
+ fig.update_layout(
110
+ title=chart_payload.get("title", "Generated Chart"),
111
+ template="plotly_white",
112
+ margin=dict(l=40, r=40, t=60, b=40),
113
+ )
114
+ return fig
115
+
116
+
117
+ def respond(api_key: str, user_msg: str, history: List[Dict[str, Any]]):
118
+ if not user_msg or not user_msg.strip():
119
+ raise gr.Error("Please enter a prompt.")
120
+
121
+ history = history or []
122
+ client = make_client(api_key)
123
+ messages = build_messages(history, user_msg.strip())
124
+ routed = generate_router_response(client, messages)
125
 
126
+ result_type = routed.get("type")
127
+ image_output = None
128
+ chart_output = None
 
 
 
 
 
 
 
 
129
 
130
+ history.append({"role": "user", "content": user_msg.strip()})
 
131
 
132
+ if result_type == "text":
133
+ text = routed.get("content", "").strip() or "No text was generated."
134
+ history.append({"role": "assistant", "content": text})
135
 
136
+ elif result_type == "image":
137
+ prompt = routed.get("prompt", "").strip()
138
+ if not prompt:
139
+ raise gr.Error("Image mode selected, but no prompt was returned.")
140
+ image_output = generate_image(client, prompt)
141
+ history.append({"role": "assistant", "content": f"Generated an image for: {prompt}"})
142
 
143
+ elif result_type == "chart":
144
+ chart_output = generate_chart(routed)
145
+ title = routed.get("title", "Generated Chart")
146
+ history.append({"role": "assistant", "content": f"Generated chart: {title}"})
147
 
148
+ else:
149
+ raise gr.Error(f"Unsupported response type: {result_type}")
150
 
151
+ return history, history, image_output, chart_output, ""
152
+
153
+
154
+ with gr.Blocks(css_paths="style.css") as demo:
155
  gr.Markdown(
156
+ """
157
+ # 🧠 OmniGen AI Studio
158
+ Generate text, images, or charts from a single prompt using GPT-4.1.
159
+ """
160
  )
161
 
162
+ api_key = gr.Textbox(
163
+ label="OpenAI API Key",
164
+ type="password",
165
+ placeholder="sk-...",
166
+ )
167
 
168
+ chatbot = gr.Chatbot(label="Conversation", type="messages", height=420)
169
 
170
  with gr.Row():
171
+ user_msg = gr.Textbox(
172
+ label="Your Prompt",
173
+ placeholder="Ask for a blog paragraph, a logo concept, or a chart of quarterly revenue...",
174
+ scale=5,
 
175
  )
176
+ send_btn = gr.Button("Generate", variant="primary")
 
 
 
177
 
178
+ with gr.Row():
179
+ image_out = gr.Image(label="Generated Image", type="pil")
180
+ chart_out = gr.Plot(label="Generated Chart")
181
 
182
+ state = gr.State([])
 
 
 
 
183
 
184
+ send_btn.click(
185
+ fn=respond,
186
+ inputs=[api_key, user_msg, state],
187
+ outputs=[chatbot, state, image_out, chart_out, user_msg],
188
  )
189
 
190
  user_msg.submit(
191
+ fn=respond,
192
+ inputs=[api_key, user_msg, state],
193
+ outputs=[chatbot, state, image_out, chart_out, user_msg],
194
  )
195
 
196