Noo88ear commited on
Commit
b9bbafd
Β·
verified Β·
1 Parent(s): 9e6ba7a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +584 -28
app.py CHANGED
@@ -1,9 +1,71 @@
1
  import gradio as gr
2
  from PIL import Image, ImageDraw, ImageFont
3
- import random
 
 
 
 
 
 
 
 
4
 
5
- def create_image(prompt, style):
6
- """Create a demo image"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  colors = {"Professional": "#3B82F6", "Creative": "#8B5CF6", "Minimalist": "#6B7280", "Corporate": "#1E40AF", "Modern": "#059669"}
8
  color = colors.get(style, "#3B82F6")
9
  rgb = tuple(int(color[i:i+2], 16) for i in (1, 4, 7))
@@ -15,59 +77,553 @@ def create_image(prompt, style):
15
  draw.text((50, 200), "Marketing Image", fill="white", font=font)
16
  draw.text((50, 230), f"{style} Style", fill="white", font=font)
17
  draw.text((50, 260), prompt[:35] + "..." if len(prompt) > 35 else prompt, fill=(200, 200, 200), font=font)
 
18
 
19
  return img
20
 
21
- def generate_and_review(prompt, style):
22
- """Generate image and review"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  if not prompt.strip():
24
  return None, "Please enter a prompt"
25
 
26
- image = create_image(prompt, style)
27
- word_count = len(prompt.split())
28
- quality = "Excellent" if word_count > 15 else "Good" if word_count > 8 else "Basic"
 
 
 
 
 
 
 
 
29
 
30
- review = f"""**Agent Review Complete**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- Agent1: Generated {style.lower()} marketing image
33
- Agent2: Quality analysis complete
34
 
35
  Prompt Quality: {quality} ({word_count} words)
36
  Style: {style}
37
- Status: Ready for use
38
 
39
  Recommendation: {f"Great detail level!" if word_count > 15 else "Consider adding more descriptive details"}"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  return image, review
42
 
43
- # Create simple interface
44
- with gr.Blocks(title="AI Marketing Generator") as demo:
45
- gr.Markdown("# 🎨 AI Marketing Image Generator")
46
- gr.Markdown("Agent1 creates β†’ Agent2 reviews β†’ Professional results")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  with gr.Row():
49
- with gr.Column():
 
 
 
50
  prompt = gr.Textbox(
51
- label="Marketing Image Description",
52
- placeholder="A professional team meeting in a modern office",
53
- lines=3
 
54
  )
 
55
  style = gr.Dropdown(
56
- choices=["Professional", "Creative", "Minimalist", "Corporate", "Modern"],
57
- value="Professional",
58
- label="Brand Style"
 
 
 
 
 
 
 
 
59
  )
60
- generate_btn = gr.Button("Generate Image", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  with gr.Column():
63
- image_output = gr.Image(label="Generated Image")
64
- review_output = gr.Markdown(value="Click Generate to see review")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- generate_btn.click(
67
  fn=generate_and_review,
68
  inputs=[prompt, style],
69
- outputs=[image_output, review_output]
 
 
 
 
 
 
70
  )
 
 
 
 
 
 
 
 
 
71
 
72
  if __name__ == "__main__":
73
  demo.launch()
 
1
  import gradio as gr
2
  from PIL import Image, ImageDraw, ImageFont
3
+ import requests
4
+ import json
5
+ import base64
6
+ import io
7
+ import asyncio
8
+ import aiohttp
9
+ import os
10
+ import time
11
+ import traceback
12
 
13
+ # Configuration - matching full Streamlit functionality
14
+ ORCHESTRATOR_URL = os.getenv("ORCHESTRATOR_URL", "http://localhost:8000")
15
+ GENERATOR_URL = os.getenv("GENERATOR_URL", "http://localhost:8001")
16
+ REVIEWER_URL = os.getenv("REVIEWER_URL", "http://localhost:8002")
17
+
18
+ # Backward compatibility
19
+ AGENT1_URL = os.getenv("AGENT1_URL", GENERATOR_URL)
20
+ AGENT2_URL = os.getenv("AGENT2_URL", REVIEWER_URL)
21
+
22
+ async def call_agent1_generate(prompt, style):
23
+ """Call Agent1 to generate an image"""
24
+ try:
25
+ payload = {
26
+ "prompt": prompt,
27
+ "style": style.lower(),
28
+ "size": "1024x1024",
29
+ "quality": "standard"
30
+ }
31
+
32
+ async with aiohttp.ClientSession() as session:
33
+ async with session.post(f"{AGENT1_URL}/generate", json=payload, timeout=60) as response:
34
+ if response.status == 200:
35
+ result = await response.json()
36
+ return result
37
+ else:
38
+ error_text = await response.text()
39
+ return {"error": f"Agent1 error {response.status}: {error_text}"}
40
+ except Exception as e:
41
+ return {"error": f"Failed to connect to Agent1: {str(e)}"}
42
+
43
+ async def call_agent2_review(image_url, prompt, review_guidelines=""):
44
+ """Call Agent2 to review the generated image"""
45
+ try:
46
+ payload = {
47
+ "image_url": image_url,
48
+ "original_prompt": prompt,
49
+ "review_criteria": ["quality", "relevance", "safety"]
50
+ }
51
+
52
+ # Add review guidelines if provided
53
+ if review_guidelines.strip():
54
+ payload["review_guidelines"] = review_guidelines
55
+
56
+ async with aiohttp.ClientSession() as session:
57
+ async with session.post(f"{AGENT2_URL}/review", json=payload, timeout=30) as response:
58
+ if response.status == 200:
59
+ result = await response.json()
60
+ return result
61
+ else:
62
+ error_text = await response.text()
63
+ return {"error": f"Agent2 error {response.status}: {error_text}"}
64
+ except Exception as e:
65
+ return {"error": f"Failed to connect to Agent2: {str(e)}"}
66
+
67
+ def create_fallback_image(prompt, style):
68
+ """Create a fallback demo image when agents are unavailable"""
69
  colors = {"Professional": "#3B82F6", "Creative": "#8B5CF6", "Minimalist": "#6B7280", "Corporate": "#1E40AF", "Modern": "#059669"}
70
  color = colors.get(style, "#3B82F6")
71
  rgb = tuple(int(color[i:i+2], 16) for i in (1, 4, 7))
 
77
  draw.text((50, 200), "Marketing Image", fill="white", font=font)
78
  draw.text((50, 230), f"{style} Style", fill="white", font=font)
79
  draw.text((50, 260), prompt[:35] + "..." if len(prompt) > 35 else prompt, fill=(200, 200, 200), font=font)
80
+ draw.text((50, 350), "(Fallback Mode)", fill=(150, 150, 150), font=font)
81
 
82
  return img
83
 
84
+ def generate_image_with_review(prompt, style, max_retries=3, review_threshold=0.8, review_guidelines=""):
85
+ """Generate an image with automated review using Agent1 and Agent2 with retry logic - mirrors Streamlit function"""
86
+ workflow_history = []
87
+
88
+ try:
89
+ for iteration in range(1, max_retries + 1):
90
+ print(f"πŸ”„ Iteration {iteration} of {max_retries}")
91
+
92
+ # Step 1: Call Agent1 to generate the image
93
+ agent1_payload = {
94
+ "prompt": prompt,
95
+ "style": style.lower(),
96
+ "size": "1024x1024",
97
+ "quality": "standard"
98
+ }
99
+
100
+ agent1_response = requests.post(f"{GENERATOR_URL}/generate", json=agent1_payload, timeout=60)
101
+
102
+ if agent1_response.status_code != 200:
103
+ return {"success": False, "error": f"Agent1 failed: {agent1_response.text}"}
104
+
105
+ agent1_result = agent1_response.json()
106
+ image_url = agent1_result.get("image_url", "")
107
+
108
+ if not image_url:
109
+ return {"success": False, "error": "Agent1 did not return an image URL"}
110
+
111
+ # Step 2: Call Agent2 to review the generated image
112
+ agent2_payload = {
113
+ "image_url": image_url,
114
+ "original_prompt": prompt,
115
+ "review_criteria": ["quality", "relevance", "safety"]
116
+ }
117
+
118
+ # Add review guidelines if provided
119
+ if review_guidelines.strip():
120
+ agent2_payload["review_guidelines"] = review_guidelines
121
+
122
+ agent2_response = requests.post(f"{REVIEWER_URL}/review", json=agent2_payload, timeout=30)
123
+
124
+ if agent2_response.status_code != 200:
125
+ # Continue with just the image if review fails
126
+ workflow_history.append({
127
+ "iteration": iteration,
128
+ "agent1_status": "success",
129
+ "agent2_status": "failed",
130
+ "review_score": 0.7,
131
+ "feedback": {"error": "Agent2 review failed"}
132
+ })
133
+
134
+ return {
135
+ "success": True,
136
+ "image": {
137
+ "url": image_url,
138
+ "data": image_url,
139
+ "prompt": prompt,
140
+ "style": style
141
+ },
142
+ "review": {
143
+ "quality_score": 0.7,
144
+ "final_status": "review_failed",
145
+ "iterations": iteration,
146
+ "passed": True,
147
+ "recommendations": ["Agent2 review failed - using generated image"],
148
+ "workflow_history": workflow_history
149
+ },
150
+ "metadata": agent1_result.get("metadata", {})
151
+ }
152
+
153
+ agent2_result = agent2_response.json()
154
+ review_score = agent2_result.get("review_score", 0.7)
155
+
156
+ # Add to workflow history
157
+ workflow_history.append({
158
+ "iteration": iteration,
159
+ "agent1_status": "success",
160
+ "agent2_status": "success",
161
+ "review_score": review_score,
162
+ "feedback": agent2_result.get("feedback", {}),
163
+ "recommendations": agent2_result.get("recommendations", [])
164
+ })
165
+
166
+ # Check if quality threshold is met
167
+ if review_score >= review_threshold:
168
+ print(f"βœ… Quality threshold met on iteration {iteration}!")
169
+
170
+ return {
171
+ "success": True,
172
+ "image": {
173
+ "url": image_url,
174
+ "data": image_url,
175
+ "prompt": prompt,
176
+ "style": style
177
+ },
178
+ "review": {
179
+ "quality_score": review_score,
180
+ "final_status": "passed",
181
+ "iterations": iteration,
182
+ "passed": True,
183
+ "recommendations": agent2_result.get("recommendations", []),
184
+ "workflow_history": workflow_history
185
+ },
186
+ "metadata": agent1_result.get("metadata", {})
187
+ }
188
+ else:
189
+ print(f"⚠️ Quality score {review_score:.2f} below threshold {review_threshold}. Retrying...")
190
+ if iteration < max_retries:
191
+ # Enhance prompt for next iteration based on feedback
192
+ feedback = agent2_result.get("feedback", {})
193
+ if "relevance" in feedback and "missing_elements" in feedback["relevance"]:
194
+ missing = feedback["relevance"]["missing_elements"]
195
+ if missing:
196
+ prompt += f" Including: {', '.join(missing[:3])}"
197
+
198
+ # If we get here, all retries failed to meet threshold
199
+ return {
200
+ "success": True,
201
+ "image": {
202
+ "url": image_url,
203
+ "data": image_url,
204
+ "prompt": prompt,
205
+ "style": style
206
+ },
207
+ "review": {
208
+ "quality_score": review_score,
209
+ "final_status": "needs_improvement",
210
+ "iterations": max_retries,
211
+ "passed": False,
212
+ "recommendations": agent2_result.get("recommendations", []) + [f"Failed to meet quality threshold {review_threshold} after {max_retries} attempts"],
213
+ "workflow_history": workflow_history
214
+ },
215
+ "metadata": agent1_result.get("metadata", {})
216
+ }
217
+
218
+ except Exception as e:
219
+ return {"success": False, "error": f"Unexpected error: {str(e)}"}
220
+
221
+ def process_generated_image_and_results(api_response):
222
+ """Process API response and return image and review text for Gradio display"""
223
+ try:
224
+ # Parse the response if it's a string
225
+ if isinstance(api_response, str):
226
+ response_data = json.loads(api_response)
227
+ else:
228
+ response_data = api_response
229
+
230
+ # Check if the response was successful
231
+ if not response_data.get('success', False):
232
+ return None, f"❌ API call failed: {response_data.get('error', 'Unknown error')}"
233
+
234
+ # Data can be at top level or nested under 'data' key
235
+ data = response_data.get('data', response_data)
236
+
237
+ # Extract image data
238
+ image_info = data.get('image', {})
239
+ image_data_b64 = ""
240
+ image = None
241
+
242
+ # Try different possible image data locations
243
+ if 'data' in image_info:
244
+ image_data_b64 = image_info['data']
245
+ elif 'url' in image_info and image_info['url'].startswith('data:image'):
246
+ image_data_b64 = image_info['url']
247
+ elif 'image_url' in data:
248
+ image_data_b64 = data['image_url']
249
+
250
+ if image_data_b64:
251
+ try:
252
+ # Handle data URL format
253
+ if image_data_b64.startswith('data:image'):
254
+ base64_data = image_data_b64.split(',')[1]
255
+ elif image_data_b64.startswith('http'):
256
+ # Handle regular URL (like picsum.photos)
257
+ response = requests.get(image_data_b64, timeout=10)
258
+ if response.status_code == 200:
259
+ image = Image.open(io.BytesIO(response.content))
260
+ else:
261
+ image = None
262
+ else:
263
+ base64_data = image_data_b64
264
+
265
+ if image is None and 'base64_data' in locals():
266
+ # Decode base64 image
267
+ image_bytes = base64.b64decode(base64_data)
268
+ image = Image.open(io.BytesIO(image_bytes))
269
+
270
+ except Exception as e:
271
+ print(f"Error processing image: {str(e)}")
272
+ image = None
273
+
274
+ # Extract review data
275
+ review_data = data.get('review', {})
276
+ if not review_data:
277
+ review_data = response_data.get('review', {})
278
+
279
+ # Format review text
280
+ if review_data:
281
+ quality_score = review_data.get('quality_score', 0)
282
+ passed = review_data.get('passed', False)
283
+ final_status = review_data.get('final_status', 'unknown')
284
+ iterations = review_data.get('iterations', 0)
285
+ recommendations = review_data.get('recommendations', [])
286
+
287
+ status_emoji = "🟒" if passed else "πŸ”΄"
288
+
289
+ review_text = f"""**πŸ” AI Review Results**
290
+
291
+ **Quality Score:** {quality_score:.2f}/1.0
292
+ **Status:** {status_emoji} {final_status.upper()}
293
+ **Iterations:** {iterations}
294
+
295
+ **πŸ’‘ Recommendations:**
296
+ """
297
+
298
+ if recommendations:
299
+ for i, rec in enumerate(recommendations[:5], 1):
300
+ review_text += f"{i}. {rec}\n"
301
+ else:
302
+ review_text += "β€’ Image meets quality standards\n"
303
+
304
+ # Add workflow history if available
305
+ workflow_history = review_data.get('workflow_history', [])
306
+ if workflow_history and len(workflow_history) > 1:
307
+ review_text += "\n**πŸ“‹ Workflow History:**\n"
308
+ for item in workflow_history:
309
+ iteration = item.get('iteration', 'N/A')
310
+ score = item.get('review_score', 'N/A')
311
+ review_text += f"β€’ Iteration {iteration}: Score {score:.2f}\n"
312
+ else:
313
+ review_text = "⚠️ Review data not available"
314
+
315
+ return image, review_text
316
+
317
+ except Exception as e:
318
+ error_text = f"❌ Error processing results: {str(e)}\n\n**Debug Info:**\n{traceback.format_exc()}"
319
+ return None, error_text
320
+
321
+ async def generate_and_review_async(prompt, style, review_guidelines=""):
322
+ """Generate image with Agent1 and review with Agent2 - legacy function for backward compatibility"""
323
  if not prompt.strip():
324
  return None, "Please enter a prompt"
325
 
326
+ # Step 1: Generate image with Agent1
327
+ agent1_result = await call_agent1_generate(prompt, style)
328
+
329
+ if "error" in agent1_result:
330
+ # Fallback to demo image
331
+ fallback_image = create_fallback_image(prompt, style)
332
+ return fallback_image, f"**Agent1 Unavailable**: {agent1_result['error']}\n\nUsing fallback demo image."
333
+
334
+ # Extract image from Agent1 response
335
+ image_url = agent1_result.get("image_url", "")
336
+ image = None
337
 
338
+ if image_url:
339
+ try:
340
+ if image_url.startswith("data:image"):
341
+ # Handle base64 data URL
342
+ base64_data = image_url.split(',')[1]
343
+ image_bytes = base64.b64decode(base64_data)
344
+ image = Image.open(io.BytesIO(image_bytes))
345
+ elif image_url.startswith("http"):
346
+ # Handle regular URL (like picsum.photos)
347
+ async with aiohttp.ClientSession() as session:
348
+ async with session.get(image_url) as response:
349
+ if response.status == 200:
350
+ image_bytes = await response.read()
351
+ image = Image.open(io.BytesIO(image_bytes))
352
+ except Exception as e:
353
+ print(f"Error loading image: {e}")
354
+
355
+ if image is None:
356
+ image = create_fallback_image(prompt, style)
357
+ image_url = "fallback://demo"
358
+
359
+ # Step 2: Review image with Agent2
360
+ agent2_result = await call_agent2_review(image_url, prompt, review_guidelines)
361
+
362
+ if "error" in agent2_result:
363
+ # Simple review fallback
364
+ word_count = len(prompt.split())
365
+ quality = "Excellent" if word_count > 15 else "Good" if word_count > 8 else "Basic"
366
+
367
+ review = f"""**Agent Review (Fallback Mode)**
368
 
369
+ Agent1: Generated {style.lower()} marketing image βœ…
370
+ Agent2: Unavailable - {agent2_result['error']}
371
 
372
  Prompt Quality: {quality} ({word_count} words)
373
  Style: {style}
374
+ Status: Image generated but not reviewed
375
 
376
  Recommendation: {f"Great detail level!" if word_count > 15 else "Consider adding more descriptive details"}"""
377
+ else:
378
+ # Format Agent2 review results
379
+ review_score = agent2_result.get("review_score", 0)
380
+ feedback = agent2_result.get("feedback", {})
381
+ recommendations = agent2_result.get("recommendations", [])
382
+
383
+ quality_feedback = feedback.get("quality", {})
384
+ relevance_feedback = feedback.get("relevance", {})
385
+ safety_feedback = feedback.get("safety", {})
386
+
387
+ review = f"""**πŸ€– AI Agent Review Complete**
388
+
389
+ **Agent1**: Generated {style.lower()} marketing image βœ…
390
+ **Agent2**: Quality analysis complete βœ…
391
+
392
+ **Overall Score**: {review_score:.2f}/1.0
393
+ **Quality**: {quality_feedback.get('score', 'N/A')}
394
+ **Relevance**: {relevance_feedback.get('score', 'N/A')}
395
+ **Safety**: {safety_feedback.get('score', 'N/A')}
396
+
397
+ **Status**: {'βœ… Approved' if review_score > 0.7 else '⚠️ Needs Improvement'}
398
+
399
+ **Recommendations**:
400
+ {chr(10).join(f"β€’ {rec}" for rec in recommendations[:3]) if recommendations else "β€’ Image meets quality standards"}"""
401
 
402
  return image, review
403
 
404
+ def check_service_health():
405
+ """Check the health of all agent services"""
406
+ health_status = {}
407
+
408
+ # Check Agent1 (Image Generator)
409
+ try:
410
+ response = requests.get(f"{GENERATOR_URL}/health", timeout=5)
411
+ health_status["Agent1 (Generator)"] = response.status_code == 200
412
+ except:
413
+ health_status["Agent1 (Generator)"] = False
414
+
415
+ # Check Agent2 (Reviewer)
416
+ try:
417
+ response = requests.get(f"{REVIEWER_URL}/health", timeout=5)
418
+ health_status["Agent2 (Marketing Reviewer)"] = response.status_code == 200
419
+ except:
420
+ health_status["Agent2 (Marketing Reviewer)"] = False
421
+
422
+ # Check Orchestrator (if available)
423
+ try:
424
+ response = requests.get(f"{ORCHESTRATOR_URL}/health", timeout=5)
425
+ health_status["Orchestrator"] = response.status_code == 200
426
+ except:
427
+ health_status["Orchestrator"] = False
428
+
429
+ return health_status
430
+
431
+ def get_system_status():
432
+ """Get system status for display"""
433
+ health_status = check_service_health()
434
+
435
+ status_text = "**πŸ”§ System Status:**\n\n"
436
+ for service_name, is_healthy in health_status.items():
437
+ status_emoji = "βœ…" if is_healthy else "❌"
438
+ status_text += f"{status_emoji} {service_name}\n"
439
+
440
+ all_healthy = all(health_status.values())
441
+ if all_healthy:
442
+ status_text += "\nπŸŽ‰ All services are running!"
443
+ else:
444
+ status_text += "\n⚠️ Some services are not responding."
445
+
446
+ return status_text
447
+
448
+ def generate_marketing_image(prompt, style, max_retries, review_threshold, review_guidelines):
449
+ """Main function called by Gradio interface - enhanced version"""
450
+ if not prompt.strip():
451
+ return None, "⚠️ Please enter a prompt to generate an image."
452
+
453
+ try:
454
+ # Call the same backend function as Streamlit
455
+ result = generate_image_with_review(prompt, style, max_retries, review_threshold, review_guidelines)
456
+
457
+ if result["success"]:
458
+ # Process the results for display
459
+ image, review_text = process_generated_image_and_results(result)
460
+
461
+ success_message = f"βœ… Image generated successfully!\n\n{review_text}"
462
+ return image, success_message
463
+ else:
464
+ error_message = f"❌ Generation failed: {result.get('error', 'Unknown error')}"
465
+ return None, error_message
466
+
467
+ except Exception as e:
468
+ error_message = f"❌ Error generating image: {str(e)}\n\n**Debug Info:**\n{traceback.format_exc()}"
469
+ return None, error_message
470
+
471
+ def generate_and_review(prompt, style):
472
+ """Sync wrapper for async function - legacy compatibility"""
473
+ loop = asyncio.new_event_loop()
474
+ asyncio.set_event_loop(loop)
475
+ try:
476
+ return loop.run_until_complete(generate_and_review_async(prompt, style))
477
+ finally:
478
+ loop.close()
479
+
480
+ def use_suggested_prompt(suggested_prompt, suggested_style):
481
+ """Update prompt and style with suggested values"""
482
+ return suggested_prompt, suggested_style
483
+
484
+ # Define suggested prompts (matching Streamlit app)
485
+ SUGGESTED_PROMPTS = {
486
+ "Modern office team collaboration": ("A modern office space with diverse professionals collaborating around a sleek conference table, natural lighting, professional attire, English signage visible", "realistic"),
487
+ "Executive boardroom meeting": ("Professional executive boardroom with polished conference table, city skyline view, business documents, English presentations on screens", "realistic"),
488
+ "Customer service excellence": ("Professional customer service representative with headset in modern call center, English signage, clean corporate environment", "realistic"),
489
+ "Product showcase display": ("Clean product showcase on white background with professional lighting, English product labels, minimalist marketing aesthetic", "realistic"),
490
+ "Creative workspace design": ("Creative workspace with colorful design elements, inspirational English quotes on walls, modern furniture, artistic marketing materials", "artistic"),
491
+ "Brand presentation setup": ("Professional brand presentation setup with English branded materials, corporate colors, marketing displays, conference room setting", "realistic")
492
+ }
493
+
494
+ # Create enhanced Gradio interface
495
+ with gr.Blocks(title="Marketing Image Generator", theme=gr.themes.Soft()) as demo:
496
+ gr.Markdown("""
497
+ # 🎨 Marketing Image Generator with Marketing Review
498
+ ### Create stunning marketing images with AI-powered Marketing Reviewer
499
+
500
+ Agent1 creates β†’ Agent2 reviews β†’ Professional results with automated quality assurance
501
+ """)
502
 
503
  with gr.Row():
504
+ with gr.Column(scale=1):
505
+ gr.Markdown("### βš™οΈ Configuration")
506
+
507
+ # Main inputs
508
  prompt = gr.Textbox(
509
+ label="Describe your marketing image",
510
+ placeholder="e.g., A modern office space with natural lighting, featuring diverse professionals collaborating around a sleek conference table",
511
+ lines=4,
512
+ info="Be specific about the scene, style, mood, and any marketing elements you want to include"
513
  )
514
+
515
  style = gr.Dropdown(
516
+ choices=["realistic", "artistic", "cartoon", "photographic", "illustration"],
517
+ value="realistic",
518
+ label="Art Style",
519
+ info="Choose the artistic style for your generated image"
520
+ )
521
+
522
+ review_guidelines = gr.Textbox(
523
+ label="πŸ” Marketing Review Guidelines (Optional)",
524
+ placeholder="e.g., All text must be in English only, focus on professional appearance, ensure brand colors are prominent, check accessibility compliance, verify readability",
525
+ lines=3,
526
+ info="Provide specific marketing guidelines for the Marketing Reviewer to evaluate against your brand standards"
527
  )
528
+
529
+ # Advanced settings
530
+ with gr.Accordion("πŸ”§ Advanced Settings", open=False):
531
+ max_retries = gr.Slider(
532
+ minimum=1,
533
+ maximum=5,
534
+ value=3,
535
+ step=1,
536
+ label="Max Retries",
537
+ info="Maximum number of retry attempts if generation fails"
538
+ )
539
+
540
+ review_threshold = gr.Slider(
541
+ minimum=0.0,
542
+ maximum=1.0,
543
+ value=0.8,
544
+ step=0.1,
545
+ label="Quality Threshold",
546
+ info="Minimum quality score required for auto-approval"
547
+ )
548
+
549
+ # Generate buttons
550
+ generate_enhanced_btn = gr.Button("πŸš€ Generate with Full Review", variant="primary", size="lg")
551
+ generate_simple_btn = gr.Button("⚑ Quick Generate", variant="secondary", size="sm")
552
+
553
+ # System status
554
+ with gr.Accordion("πŸ“Š System Status", open=False):
555
+ status_display = gr.Markdown(get_system_status())
556
+ refresh_status_btn = gr.Button("πŸ”„ Refresh Status", size="sm")
557
+
558
+ with gr.Column(scale=2):
559
+ # Results display
560
+ gr.Markdown("### πŸ–ΌοΈ Generated Image & Review")
561
+
562
+ image_output = gr.Image(
563
+ label="Generated Marketing Image",
564
+ type="pil",
565
+ height=400,
566
+ show_download_button=True
567
+ )
568
+
569
+ review_output = gr.Markdown(
570
+ value="Click **Generate** to create your marketing image with AI review",
571
+ label="AI Review Results"
572
+ )
573
+
574
+ # Suggested prompts section
575
+ gr.Markdown("---")
576
+ gr.Markdown("### πŸ’‘ Suggested Marketing Prompts")
577
+
578
+ with gr.Row():
579
+ with gr.Column():
580
+ gr.Markdown("**🏒 Professional/Corporate**")
581
+ for prompt_name in ["Modern office team collaboration", "Executive boardroom meeting", "Customer service excellence"]:
582
+ suggested_prompt, suggested_style = SUGGESTED_PROMPTS[prompt_name]
583
+ btn = gr.Button(prompt_name, size="sm")
584
+ btn.click(
585
+ fn=lambda p=suggested_prompt, s=suggested_style: (p, s),
586
+ outputs=[prompt, style]
587
+ )
588
 
589
  with gr.Column():
590
+ gr.Markdown("**🎨 Creative/Marketing**")
591
+ for prompt_name in ["Product showcase display", "Creative workspace design", "Brand presentation setup"]:
592
+ suggested_prompt, suggested_style = SUGGESTED_PROMPTS[prompt_name]
593
+ btn = gr.Button(prompt_name, size="sm")
594
+ btn.click(
595
+ fn=lambda p=suggested_prompt, s=suggested_style: (p, s),
596
+ outputs=[prompt, style]
597
+ )
598
+
599
+ # Event handlers
600
+ generate_enhanced_btn.click(
601
+ fn=generate_marketing_image,
602
+ inputs=[prompt, style, max_retries, review_threshold, review_guidelines],
603
+ outputs=[image_output, review_output],
604
+ show_progress=True
605
+ )
606
 
607
+ generate_simple_btn.click(
608
  fn=generate_and_review,
609
  inputs=[prompt, style],
610
+ outputs=[image_output, review_output],
611
+ show_progress=True
612
+ )
613
+
614
+ refresh_status_btn.click(
615
+ fn=get_system_status,
616
+ outputs=status_display
617
  )
618
+
619
+ # Footer
620
+ gr.Markdown("""
621
+ ---
622
+ <div style='text-align: center; color: #666; font-size: 0.9rem;'>
623
+ <p>🎨 Marketing Image Generator with Agent Review | Powered by Google Imagen3 & AI Agents</p>
624
+ <p>Create professional marketing images with automated quality assurance</p>
625
+ </div>
626
+ """)
627
 
628
  if __name__ == "__main__":
629
  demo.launch()