Files changed (1) hide show
  1. app.py +130 -65
app.py CHANGED
@@ -5,6 +5,41 @@ import streamlit as st
5
 
6
  from graph import run_graph
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  # -------------------------------------------------------
9
  # PAGE CONFIG
10
  # -------------------------------------------------------
@@ -16,6 +51,7 @@ st.set_page_config(
16
 
17
  st.title("🧠 AI Image Studio (Agents + LangGraph)")
18
 
 
19
  # -------------------------------------------------------
20
  # SESSION STATE
21
  # -------------------------------------------------------
@@ -32,6 +68,7 @@ if "analysis" not in st.session_state:
32
  if "last_uploaded" not in st.session_state:
33
  st.session_state.last_uploaded = []
34
 
 
35
  # -------------------------------------------------------
36
  # SIDEBAR
37
  # -------------------------------------------------------
@@ -44,6 +81,7 @@ uploaded_files = st.sidebar.file_uploader(
44
  accept_multiple_files=True
45
  )
46
 
 
47
  # -------------------------------------------------------
48
  # SAVE FILES
49
  # -------------------------------------------------------
@@ -56,20 +94,16 @@ if uploaded_files:
56
 
57
  for file in uploaded_files:
58
 
59
- file_path = os.path.join("uploads", file.name)
60
 
61
- with open(file_path, "wb") as f:
62
  f.write(file.getbuffer())
63
 
64
- paths.append(file_path)
65
 
66
- # Save paths
67
  st.session_state.uploaded_paths = paths
68
 
69
- # ---------------------------------------------------
70
- # AUTO ANALYZE ONLY IF NEW IMAGE
71
- # ---------------------------------------------------
72
-
73
  if paths != st.session_state.last_uploaded:
74
 
75
  st.session_state.last_uploaded = paths
@@ -87,10 +121,7 @@ if uploaded_files:
87
 
88
  if isinstance(analysis, dict):
89
 
90
- description = analysis.get(
91
- "description",
92
- "Image analyzed."
93
- )
94
 
95
  resolution = analysis.get("resolution", "")
96
 
@@ -98,48 +129,77 @@ if uploaded_files:
98
 
99
  lighting = analysis.get("lighting", "")
100
 
101
- objects = analysis.get("objects", [])
102
 
103
- message = f"""📷 **Image Analysis**
104
 
105
- **Description**
106
 
107
- {description}
108
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  if resolution:
111
- message += f"\n**Resolution:** {resolution}"
112
 
113
  if style:
114
- message += f"\n\n**Style:** {style}"
115
 
116
  if lighting:
117
- message += f"\n\n**Lighting:** {lighting}"
118
 
119
- if objects:
120
- message += f"\n\n**Objects:** {', '.join(objects)}"
121
 
122
- message += """
 
123
 
124
- ---
 
125
 
126
- ### What would you like to do?
 
127
 
128
- Remove background
 
129
 
130
- Make it Anime
 
131
 
132
- Make it Pixar style
133
 
134
- Enhance quality
135
 
136
- Replace objects
 
137
 
138
- • Change colors
139
 
140
- Add new objects
 
141
 
142
- Extract text
 
 
 
 
 
143
  """
144
 
145
  st.session_state.messages.append(
@@ -158,6 +218,7 @@ if uploaded_files:
158
  }
159
  )
160
 
 
161
  # -------------------------------------------------------
162
  # SIDEBAR PREVIEW
163
  # -------------------------------------------------------
@@ -166,19 +227,20 @@ if st.session_state.uploaded_paths:
166
 
167
  st.sidebar.subheader("🖼 Preview")
168
 
169
- for img in st.session_state.uploaded_paths:
170
 
171
  st.sidebar.image(
172
- img,
173
- caption=os.path.basename(img),
174
  use_container_width=True
175
  )
176
 
 
177
  # -------------------------------------------------------
178
- # CHAT
179
  # -------------------------------------------------------
180
 
181
- st.subheader("💬 Chat with AI Agent")
182
 
183
  for msg in st.session_state.messages:
184
 
@@ -186,14 +248,16 @@ for msg in st.session_state.messages:
186
 
187
  st.markdown(msg["content"])
188
 
 
189
  # -------------------------------------------------------
190
- # USER INPUT
191
  # -------------------------------------------------------
192
 
193
  user_input = st.chat_input(
194
- "Generate / Edit / Analyze image..."
195
  )
196
 
 
197
  # -------------------------------------------------------
198
  # RUN AGENT
199
  # -------------------------------------------------------
@@ -213,7 +277,7 @@ if user_input:
213
 
214
  with st.chat_message("assistant"):
215
 
216
- with st.spinner("🤖 AI Agent thinking..."):
217
 
218
  result = run_graph(
219
  user_input,
@@ -222,59 +286,60 @@ if user_input:
222
 
223
  output = result.get("result")
224
 
225
- assistant_message = ""
226
 
227
- # ------------------------------------------------
228
- # IMAGE OUTPUT
229
- # ------------------------------------------------
230
 
231
  if isinstance(output, Image.Image):
232
 
233
  st.image(
234
  output,
235
- caption="Generated Image",
236
  use_container_width=True
237
  )
238
 
239
- buffer = io.BytesIO()
240
 
241
- output.save(buffer, format="PNG")
 
 
 
242
 
243
  st.download_button(
244
- "⬇ Download Image",
245
- buffer.getvalue(),
246
- "result.png",
247
  "image/png"
248
  )
249
 
250
- assistant_message = "✅ Image generated successfully."
251
 
252
- # ------------------------------------------------
253
- # DICTIONARY OUTPUT
254
- # ------------------------------------------------
255
 
256
  elif isinstance(output, dict):
257
 
258
- st.json(output)
259
 
260
- assistant_message = output.get(
261
- "description",
262
- str(output)
263
- )
 
 
 
 
 
264
 
265
- # ------------------------------------------------
266
- # TEXT OUTPUT
267
- # ------------------------------------------------
268
 
269
  else:
270
 
271
  st.markdown(str(output))
272
 
273
- assistant_message = str(output)
274
 
275
  st.session_state.messages.append(
276
  {
277
  "role": "assistant",
278
- "content": assistant_message
279
  }
280
  )
 
5
 
6
  from graph import run_graph
7
 
8
+
9
+ # -------------------------------------------------------
10
+ # HELPER FUNCTIONS
11
+ # -------------------------------------------------------
12
+
13
+ def format_items(items):
14
+ """Safely convert lists containing strings/dicts into text."""
15
+
16
+ if not items:
17
+ return ""
18
+
19
+ output = []
20
+
21
+ for item in items:
22
+
23
+ if isinstance(item, dict):
24
+
25
+ if "name" in item:
26
+ output.append(str(item["name"]))
27
+
28
+ elif "label" in item:
29
+ output.append(str(item["label"]))
30
+
31
+ elif "text" in item:
32
+ output.append(str(item["text"]))
33
+
34
+ else:
35
+ output.append(str(item))
36
+
37
+ else:
38
+ output.append(str(item))
39
+
40
+ return ", ".join(output)
41
+
42
+
43
  # -------------------------------------------------------
44
  # PAGE CONFIG
45
  # -------------------------------------------------------
 
51
 
52
  st.title("🧠 AI Image Studio (Agents + LangGraph)")
53
 
54
+
55
  # -------------------------------------------------------
56
  # SESSION STATE
57
  # -------------------------------------------------------
 
68
  if "last_uploaded" not in st.session_state:
69
  st.session_state.last_uploaded = []
70
 
71
+
72
  # -------------------------------------------------------
73
  # SIDEBAR
74
  # -------------------------------------------------------
 
81
  accept_multiple_files=True
82
  )
83
 
84
+
85
  # -------------------------------------------------------
86
  # SAVE FILES
87
  # -------------------------------------------------------
 
94
 
95
  for file in uploaded_files:
96
 
97
+ path = os.path.join("uploads", file.name)
98
 
99
+ with open(path, "wb") as f:
100
  f.write(file.getbuffer())
101
 
102
+ paths.append(path)
103
 
 
104
  st.session_state.uploaded_paths = paths
105
 
106
+ # Only analyze if a different image is uploaded
 
 
 
107
  if paths != st.session_state.last_uploaded:
108
 
109
  st.session_state.last_uploaded = paths
 
121
 
122
  if isinstance(analysis, dict):
123
 
124
+ description = analysis.get("description", "")
 
 
 
125
 
126
  resolution = analysis.get("resolution", "")
127
 
 
129
 
130
  lighting = analysis.get("lighting", "")
131
 
132
+ people = analysis.get("people", "")
133
 
134
+ background = analysis.get("background", "")
135
 
136
+ quality = analysis.get("quality", "")
137
 
138
+ camera = analysis.get("camera_angle", "")
139
+
140
+ objects = format_items(
141
+ analysis.get("objects", [])
142
+ )
143
+
144
+ colors = format_items(
145
+ analysis.get("colors", [])
146
+ )
147
+
148
+ suggestions = analysis.get(
149
+ "suggestions",
150
+ []
151
+ )
152
+
153
+ message = "📷 **Image Analysis**\n\n"
154
+
155
+ if description:
156
+ message += f"### Description\n{description}\n\n"
157
 
158
  if resolution:
159
+ message += f"**Resolution:** {resolution}\n\n"
160
 
161
  if style:
162
+ message += f"**Style:** {style}\n\n"
163
 
164
  if lighting:
165
+ message += f"**Lighting:** {lighting}\n\n"
166
 
167
+ if people:
168
+ message += f"**People:** {people}\n\n"
169
 
170
+ if background:
171
+ message += f"**Background:** {background}\n\n"
172
 
173
+ if camera:
174
+ message += f"**Camera Angle:** {camera}\n\n"
175
 
176
+ if quality:
177
+ message += f"**Quality:** {quality}\n\n"
178
 
179
+ if colors:
180
+ message += f"**Colors:** {colors}\n\n"
181
 
182
+ if objects:
183
+ message += f"**Objects:** {objects}\n\n"
184
 
185
+ if suggestions:
186
 
187
+ message += "### Suggested Actions\n"
188
 
189
+ for s in suggestions:
190
+ message += f"• {s}\n"
191
 
192
+ else:
193
 
194
+ message += """
195
+ ### Suggested Actions
196
 
197
+ Remove background
198
+ • Make it Anime
199
+ • Pixar Style
200
+ • Change Background
201
+ • Replace Object
202
+ • Enhance Quality
203
  """
204
 
205
  st.session_state.messages.append(
 
218
  }
219
  )
220
 
221
+
222
  # -------------------------------------------------------
223
  # SIDEBAR PREVIEW
224
  # -------------------------------------------------------
 
227
 
228
  st.sidebar.subheader("🖼 Preview")
229
 
230
+ for path in st.session_state.uploaded_paths:
231
 
232
  st.sidebar.image(
233
+ path,
234
+ caption=os.path.basename(path),
235
  use_container_width=True
236
  )
237
 
238
+
239
  # -------------------------------------------------------
240
+ # CHAT HISTORY
241
  # -------------------------------------------------------
242
 
243
+ st.subheader("💬 Chat")
244
 
245
  for msg in st.session_state.messages:
246
 
 
248
 
249
  st.markdown(msg["content"])
250
 
251
+
252
  # -------------------------------------------------------
253
+ # CHAT INPUT
254
  # -------------------------------------------------------
255
 
256
  user_input = st.chat_input(
257
+ "Ask AI to edit, analyze or generate..."
258
  )
259
 
260
+
261
  # -------------------------------------------------------
262
  # RUN AGENT
263
  # -------------------------------------------------------
 
277
 
278
  with st.chat_message("assistant"):
279
 
280
+ with st.spinner("🤖 Thinking..."):
281
 
282
  result = run_graph(
283
  user_input,
 
286
 
287
  output = result.get("result")
288
 
289
+ assistant_text = ""
290
 
291
+ # ---------------- IMAGE ----------------
 
 
292
 
293
  if isinstance(output, Image.Image):
294
 
295
  st.image(
296
  output,
 
297
  use_container_width=True
298
  )
299
 
300
+ buf = io.BytesIO()
301
 
302
+ output.save(
303
+ buf,
304
+ format="PNG"
305
+ )
306
 
307
  st.download_button(
308
+ "⬇ Download",
309
+ buf.getvalue(),
310
+ "edited_image.png",
311
  "image/png"
312
  )
313
 
314
+ assistant_text = "✅ Image edited successfully."
315
 
316
+ # ---------------- JSON ----------------
 
 
317
 
318
  elif isinstance(output, dict):
319
 
320
+ if "description" in output:
321
 
322
+ st.markdown(output["description"])
323
+
324
+ assistant_text = output["description"]
325
+
326
+ else:
327
+
328
+ st.json(output)
329
+
330
+ assistant_text = str(output)
331
 
332
+ # ---------------- TEXT ----------------
 
 
333
 
334
  else:
335
 
336
  st.markdown(str(output))
337
 
338
+ assistant_text = str(output)
339
 
340
  st.session_state.messages.append(
341
  {
342
  "role": "assistant",
343
+ "content": assistant_text
344
  }
345
  )