Noo88ear commited on
Commit
57ccf92
Β·
verified Β·
1 Parent(s): 557a7db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +416 -158
app.py CHANGED
@@ -1,17 +1,18 @@
1
  """
2
- All-in-One Marketing Image Generator with Proper A2A Architecture
3
- Includes A2A Orchestrator + Agent1 (MCP-Imagen3) + Agent2 (Reviewer) + Gradio Interface
 
4
  """
5
 
6
  import gradio as gr
7
  import os
8
  import logging
9
- import asyncio
10
  import json
11
- from typing import Dict, Any
 
 
12
  from PIL import Image
13
  import io
14
- import base64
15
 
16
  # Google Service Account Authentication Setup
17
  def setup_google_credentials():
@@ -44,29 +45,391 @@ def setup_google_credentials():
44
  # Setup Google credentials on startup
45
  setup_google_credentials()
46
 
47
- # A2A imports
48
  try:
49
- from a2a_orchestrator import A2AOrchestrator
50
- A2A_AVAILABLE = True
 
51
  except ImportError:
52
- A2A_AVAILABLE = False
53
 
54
  # Configure logging
55
  logging.basicConfig(level=logging.INFO)
56
  logger = logging.getLogger(__name__)
57
 
58
- # Initialize A2A Orchestrator
59
- if A2A_AVAILABLE:
60
- orchestrator = A2AOrchestrator()
61
- logger.info("βœ… A2A Orchestrator initialized")
62
- else:
63
- orchestrator = None
64
- logger.warning("⚠️ A2A not available - will use fallback mode")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- def process_generated_image_and_results(api_response):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  """Process API response and return image and review text for Gradio display"""
68
  try:
69
- response_data = api_response
70
 
71
  if not response_data.get('success', False):
72
  return None, f"❌ Generation failed: {response_data.get('error', 'Unknown error')}"
@@ -91,7 +454,6 @@ def process_generated_image_and_results(api_response):
91
  quality_score = review_data.get('quality_score', 0)
92
  passed = review_data.get('passed', False)
93
  final_status = review_data.get('final_status', 'unknown')
94
- iterations = review_data.get('iterations', 0)
95
  recommendations = review_data.get('recommendations', [])
96
 
97
  status_emoji = "🟒" if passed else "πŸ”΄"
@@ -99,23 +461,19 @@ def process_generated_image_and_results(api_response):
99
  # Extract metadata about generation method
100
  metadata = response_data.get('metadata', {})
101
  generation_method = metadata.get('generation_method', 'unknown')
102
- real_ai = metadata.get('real_ai_generation', False)
103
 
104
  generation_info = ""
105
- if generation_method == "imagen3-mcp":
106
- generation_info = "🎨 **Generated with**: Imagen3-MCP (Real AI)\n"
107
- elif generation_method == "google-genai-sdk":
108
- generation_info = "🎨 **Generated with**: Google Genai SDK (Real AI)\n"
109
  elif generation_method == "placeholder":
110
  generation_info = "🎨 **Generated with**: Placeholder (Fallback)\n"
111
 
112
- review_text = f"""**πŸ” A2A Marketing Review Results**
113
 
114
  {generation_info}
115
  **Quality Score:** {quality_score:.2f}/1.0
116
  **Status:** {status_emoji} {final_status.upper()}
117
- **Iterations:** {iterations}
118
- **Architecture:** A2A Agent Communication
119
 
120
  **πŸ’‘ Recommendations:**
121
  """
@@ -125,15 +483,7 @@ def process_generated_image_and_results(api_response):
125
  review_text += f"{i}. {rec}\n"
126
  else:
127
  review_text += "β€’ Image meets quality standards\n"
128
-
129
- # Add workflow history
130
- workflow_history = review_data.get('workflow_history', [])
131
- if workflow_history and len(workflow_history) > 1:
132
- review_text += "\n**πŸ“‹ A2A Workflow History:**\n"
133
- for item in workflow_history:
134
- iteration = item.get('iteration', 'N/A')
135
- score = item.get('review_score', 'N/A')
136
- review_text += f"β€’ Iteration {iteration}: Score {score:.2f}\n"
137
  else:
138
  review_text = "⚠️ Review data not available"
139
 
@@ -142,80 +492,21 @@ def process_generated_image_and_results(api_response):
142
  except Exception as e:
143
  return None, f"❌ Error processing results: {str(e)}"
144
 
145
- def generate_marketing_image_a2a(prompt, style, max_retries, review_threshold, review_guidelines):
146
- """Main function for the Gradio interface using A2A Orchestrator"""
147
  if not prompt.strip():
148
  return None, "⚠️ Please enter a prompt to generate an image."
149
 
150
- if not A2A_AVAILABLE or not orchestrator:
151
- return None, "❌ A2A Orchestrator not available. Please check setup."
152
-
153
  try:
154
- logger.info(f"🎭 Starting A2A workflow for: {prompt}")
155
-
156
- # Use the A2A orchestrator to coordinate agents
157
- result = asyncio.run(
158
- orchestrator.generate_image_with_review(
159
- prompt=prompt,
160
- style=style,
161
- max_retries=max_retries,
162
- review_threshold=review_threshold,
163
- review_guidelines=review_guidelines
164
- )
165
- )
166
-
167
- if result["success"]:
168
- image, review_text = process_generated_image_and_results(result)
169
- success_message = f"βœ… A2A Image generation successful!\n\n{review_text}"
170
- return image, success_message
171
- else:
172
- error_message = f"❌ A2A Generation failed: {result.get('error', 'Unknown error')}"
173
- return None, error_message
174
-
175
  except Exception as e:
176
- error_message = f"❌ A2A Error: {str(e)}"
177
  logger.error(error_message)
178
  return None, error_message
179
 
180
- async def check_a2a_agents():
181
- """Check if A2A agents are available"""
182
- if not orchestrator:
183
- return {"agent1": False, "agent2": False, "orchestrator": False}
184
-
185
- try:
186
- health_status = await orchestrator.check_agents_health()
187
- health_status["orchestrator"] = True
188
- return health_status
189
- except Exception as e:
190
- logger.error(f"Error checking agent health: {e}")
191
- return {"agent1": False, "agent2": False, "orchestrator": False}
192
-
193
- def get_a2a_system_status():
194
- """Get A2A system status for display"""
195
- if not A2A_AVAILABLE:
196
- return "**πŸ”§ A2A System Status:**\n\n❌ A2A not available\n⚠️ Install google-a2a to enable A2A functionality"
197
-
198
- try:
199
- health_status = asyncio.run(check_a2a_agents())
200
-
201
- status_text = "**πŸ”§ A2A System Status:**\n\n"
202
- status_text += f"{'βœ…' if health_status.get('orchestrator', False) else '❌'} A2A Orchestrator\n"
203
- status_text += f"{'βœ…' if health_status.get('agent1', False) else '❌'} Agent1 (Image Generator)\n"
204
- status_text += f"{'βœ…' if health_status.get('agent2', False) else '❌'} Agent2 (Marketing Reviewer)\n"
205
-
206
- all_healthy = all(health_status.values())
207
- if all_healthy:
208
- status_text += "\nπŸŽ‰ All A2A agents are running!"
209
- else:
210
- status_text += "\n⚠️ Some A2A agents are not responding."
211
- status_text += "\nRun: `python a2a_servers.py` to start agents"
212
-
213
- return status_text
214
-
215
- except Exception as e:
216
- return f"**πŸ”§ A2A System Status:**\n\n❌ Error checking status: {str(e)}"
217
-
218
- # Define suggested prompts (same as before)
219
  SUGGESTED_PROMPTS = {
220
  "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"),
221
  "Executive boardroom meeting": ("Professional executive boardroom with polished conference table, city skyline view, business documents, English presentations on screens", "realistic"),
@@ -226,12 +517,14 @@ SUGGESTED_PROMPTS = {
226
  }
227
 
228
  # Create Gradio interface
229
- with gr.Blocks(title="A2A Marketing Image Generator", theme=gr.themes.Soft()) as demo:
230
  gr.Markdown("""
231
- # 🎨 A2A Marketing Image Generator
232
- ### Professional AI image generation with proper A2A agent architecture
233
 
234
- **Agent1** (MCP-Imagen3) ↔ **A2A** ↔ **Agent2** (Marketing Reviewer) ↔ **A2A** ↔ **Orchestrator**
 
 
235
  """)
236
 
237
  with gr.Row():
@@ -255,45 +548,21 @@ with gr.Blocks(title="A2A Marketing Image Generator", theme=gr.themes.Soft()) as
255
 
256
  review_guidelines = gr.Textbox(
257
  label="πŸ” Marketing Review Guidelines (Optional)",
258
- placeholder="e.g., All text must be in English only, focus on professional appearance, ensure brand colors are prominent, check accessibility compliance, verify readability",
259
  lines=3,
260
- info="Provide specific marketing guidelines for the Marketing Reviewer to evaluate against your brand standards"
261
  )
262
 
263
- # Advanced settings
264
- with gr.Accordion("πŸ”§ Advanced Settings", open=False):
265
- max_retries = gr.Slider(
266
- minimum=1,
267
- maximum=5,
268
- value=3,
269
- step=1,
270
- label="Max Retries",
271
- info="Maximum number of retry attempts if generation fails"
272
- )
273
-
274
- review_threshold = gr.Slider(
275
- minimum=0.0,
276
- maximum=1.0,
277
- value=0.8,
278
- step=0.1,
279
- label="Quality Threshold",
280
- info="Minimum quality score required for auto-approval"
281
- )
282
-
283
  # Generate button
284
- generate_btn = gr.Button("πŸš€ Generate with A2A Architecture", variant="primary", size="lg")
285
 
286
  # Status
287
- gr.Markdown("πŸ” **Mode**: A2A Agent-to-Agent Communication")
288
-
289
- # System status
290
- with gr.Accordion("πŸ“Š A2A System Status", open=False):
291
- status_display = gr.Markdown(get_a2a_system_status())
292
- refresh_status_btn = gr.Button("πŸ”„ Refresh A2A Status", size="sm")
293
 
294
  with gr.Column(scale=2):
295
  # Results display
296
- gr.Markdown("### πŸ–ΌοΈ Generated Image & A2A Review")
297
 
298
  image_output = gr.Image(
299
  label="Generated Marketing Image",
@@ -303,8 +572,8 @@ with gr.Blocks(title="A2A Marketing Image Generator", theme=gr.themes.Soft()) as
303
  )
304
 
305
  review_output = gr.Markdown(
306
- value="Click **Generate with A2A Architecture** to create your marketing image using agent-to-agent communication",
307
- label="A2A Review Results"
308
  )
309
 
310
  # Suggested prompts section
@@ -334,36 +603,25 @@ with gr.Blocks(title="A2A Marketing Image Generator", theme=gr.themes.Soft()) as
334
 
335
  # Event handlers
336
  generate_btn.click(
337
- fn=generate_marketing_image_a2a,
338
- inputs=[prompt, style, max_retries, review_threshold, review_guidelines],
339
  outputs=[image_output, review_output],
340
  show_progress=True
341
  )
342
 
343
- refresh_status_btn.click(
344
- fn=get_a2a_system_status,
345
- outputs=status_display
346
- )
347
-
348
  # Footer
349
  gr.Markdown("""
350
  ---
351
  <div style='text-align: center; color: #666; font-size: 0.9rem;'>
352
- <p>🎨 A2A Marketing Image Generator | Proper Agent-to-Agent Architecture</p>
353
- <p>Agent1 (MCP-Imagen3) + Agent2 (Reviewer) + A2A Orchestrator + Gradio Interface</p>
354
- <p>Start agents with: <code>python a2a_servers.py</code></p>
355
  </div>
356
  """)
357
 
358
  if __name__ == "__main__":
359
- logger.info("πŸš€ Starting A2A Marketing Image Generator")
360
- logger.info(f"πŸ€– A2A Available: {'βœ… Yes' if A2A_AVAILABLE else '❌ No'}")
361
-
362
- if A2A_AVAILABLE:
363
- logger.info("πŸ’‘ Using proper A2A agent-to-agent communication")
364
- logger.info("πŸ”— Architecture: Gradio β†’ Orchestrator β†’ Agent1 (MCP-Imagen3) β†’ Agent2 (Reviewer)")
365
- logger.info("πŸ“‹ Make sure to start agents: python a2a_servers.py")
366
- else:
367
- logger.warning("πŸ’‘ A2A not available - install google-a2a for full functionality")
368
 
369
- demo.launch()
 
1
  """
2
+ Marketing Image Generator with Gradio MCP Server
3
+ Professional AI image generation using Google Imagen3 with marketing review
4
+ Deployed on HuggingFace Spaces with built-in MCP server support
5
  """
6
 
7
  import gradio as gr
8
  import os
9
  import logging
 
10
  import json
11
+ import base64
12
+ import asyncio
13
+ from typing import Dict, Any, Tuple
14
  from PIL import Image
15
  import io
 
16
 
17
  # Google Service Account Authentication Setup
18
  def setup_google_credentials():
 
45
  # Setup Google credentials on startup
46
  setup_google_credentials()
47
 
48
+ # Google AI imports
49
  try:
50
+ import google.generativeai as genai
51
+ from google import genai as genai_sdk
52
+ GEMINI_AVAILABLE = True
53
  except ImportError:
54
+ GEMINI_AVAILABLE = False
55
 
56
  # Configure logging
57
  logging.basicConfig(level=logging.INFO)
58
  logger = logging.getLogger(__name__)
59
 
60
+ # Get API keys - prioritize HuggingFace Secrets
61
+ GCP_KEYS = [
62
+ # Hugging Face Secrets (these are the primary ones for HF deployment)
63
+ os.getenv("GOOGLE_API_KEY"),
64
+ os.getenv("GEMINI_API_KEY"),
65
+ os.getenv("GCP_API_KEY"),
66
+ # Local development keys (fallback for local testing)
67
+ os.getenv("GCP_KEY_1"),
68
+ os.getenv("GCP_KEY_2"),
69
+ os.getenv("GCP_KEY_3"),
70
+ os.getenv("GCP_KEY_4"),
71
+ os.getenv("GCP_KEY_5"),
72
+ os.getenv("GCP_KEY_6")
73
+ ]
74
+
75
+ GOOGLE_API_KEY = next((key for key in GCP_KEYS if key), None)
76
+
77
+ if GOOGLE_API_KEY and GEMINI_AVAILABLE:
78
+ genai.configure(api_key=GOOGLE_API_KEY)
79
+ logger.info("βœ… Google AI configured successfully")
80
+
81
+ # MCP-enabled functions for Agent1 (Image Generator)
82
+ def enhance_prompt_with_gemini(prompt: str, style: str) -> str:
83
+ """
84
+ Use Gemini to enhance the user's prompt for better image generation.
85
+
86
+ Args:
87
+ prompt (str): The original marketing prompt
88
+ style (str): The desired image style
89
+
90
+ Returns:
91
+ str: Enhanced prompt optimized for image generation
92
+ """
93
+ if not GEMINI_AVAILABLE or not GOOGLE_API_KEY:
94
+ # Basic enhancement without Gemini
95
+ style_enhancers = {
96
+ "realistic": "photorealistic, high detail, professional photography, sharp focus",
97
+ "artistic": "artistic masterpiece, creative composition, painterly style",
98
+ "cartoon": "cartoon style, vibrant colors, playful, animated character design",
99
+ "photographic": "professional photograph, high quality, detailed, commercial photography",
100
+ "illustration": "digital illustration, clean vector art, modern design"
101
+ }
102
+ enhancer = style_enhancers.get(style.lower(), "high quality, detailed")
103
+ return f"{prompt}, {enhancer}"
104
+
105
+ try:
106
+ enhancement_prompt = f"""
107
+ You are an expert prompt engineer for AI image generation. Take this marketing prompt and enhance it for optimal results.
108
+
109
+ Original prompt: "{prompt}"
110
+ Desired style: "{style}"
111
+
112
+ Please provide an enhanced version that:
113
+ 1. Maintains the core marketing intent
114
+ 2. Adds specific technical details for better image quality
115
+ 3. Includes appropriate style descriptors for "{style}" style
116
+ 4. Adds professional marketing composition guidance
117
+ 5. Keeps the enhanced prompt under 150 words
118
+
119
+ Return only the enhanced prompt without explanation.
120
+ """
121
+
122
+ model = genai.GenerativeModel('gemini-1.5-flash')
123
+ response = model.generate_content(enhancement_prompt)
124
+ enhanced = response.text.strip()
125
+
126
+ logger.info(f"Gemini enhanced prompt: {enhanced}")
127
+ return enhanced
128
+
129
+ except Exception as e:
130
+ logger.warning(f"Failed to enhance prompt with Gemini: {e}")
131
+ style_enhancers = {
132
+ "realistic": "photorealistic, high detail, professional photography",
133
+ "artistic": "artistic masterpiece, creative composition",
134
+ "cartoon": "cartoon style, vibrant colors, playful",
135
+ "photographic": "professional photograph, high quality, detailed",
136
+ "illustration": "digital illustration, clean design"
137
+ }
138
+ enhancer = style_enhancers.get(style.lower(), "high quality")
139
+ return f"{prompt}, {enhancer}"
140
+
141
+ def generate_marketing_image(prompt: str, style: str = "realistic") -> str:
142
+ """
143
+ Generate a professional marketing image using Google Imagen3.
144
+
145
+ Args:
146
+ prompt (str): Description of the marketing image to generate
147
+ style (str): Art style for the image (realistic, artistic, cartoon, photographic, illustration)
148
+
149
+ Returns:
150
+ str: JSON string containing image data and metadata
151
+ """
152
+ logger.info(f"🎨 Generating marketing image: {prompt}")
153
+
154
+ try:
155
+ # Enhance the prompt
156
+ enhanced_prompt = enhance_prompt_with_gemini(prompt, style)
157
+
158
+ # Try to generate with Google Genai SDK
159
+ if GEMINI_AVAILABLE and GOOGLE_API_KEY:
160
+ try:
161
+ logger.info("🎨 Using Google Genai SDK for image generation")
162
+
163
+ # Initialize the genai SDK client
164
+ client = genai_sdk.Client(api_key=GOOGLE_API_KEY)
165
+
166
+ # Generate image using Imagen 3 via SDK
167
+ result = client.models.generate_images(
168
+ model="imagen-3.0-generate-002",
169
+ prompt=enhanced_prompt,
170
+ config={
171
+ "number_of_images": 1,
172
+ "output_mime_type": "image/png"
173
+ }
174
+ )
175
+
176
+ # Check if we got a valid response with images
177
+ if result and hasattr(result, 'generated_images') and len(result.generated_images) > 0:
178
+ generated_image = result.generated_images[0]
179
+
180
+ if hasattr(generated_image, 'image') and hasattr(generated_image.image, 'image_bytes'):
181
+ # Convert image bytes to base64 data URL
182
+ image_bytes = generated_image.image.image_bytes
183
+ img_base64 = base64.b64encode(image_bytes).decode('utf-8')
184
+
185
+ # Determine MIME type from the response or default to PNG
186
+ mime_type = getattr(generated_image.image, 'mime_type', 'image/png')
187
+ image_url = f"data:{mime_type};base64,{img_base64}"
188
+
189
+ response_data = {
190
+ "success": True,
191
+ "image_url": image_url,
192
+ "prompt": prompt,
193
+ "enhanced_prompt": enhanced_prompt,
194
+ "style": style,
195
+ "generation_method": "google-genai-sdk",
196
+ "real_ai_generation": True
197
+ }
198
+
199
+ logger.info("βœ… Successfully generated real AI image with Google SDK!")
200
+ return json.dumps(response_data)
201
+
202
+ except Exception as e:
203
+ logger.error(f"Google SDK generation failed: {e}")
204
+
205
+ # Fallback: Generate a deterministic placeholder
206
+ logger.info("πŸ”„ Using placeholder URL fallback")
207
+ prompt_hash = abs(hash(enhanced_prompt)) % 10000
208
+ image_url = f"https://picsum.photos/seed/{prompt_hash}/1024/1024"
209
+
210
+ response_data = {
211
+ "success": True,
212
+ "image_url": image_url,
213
+ "prompt": prompt,
214
+ "enhanced_prompt": enhanced_prompt,
215
+ "style": style,
216
+ "generation_method": "placeholder",
217
+ "real_ai_generation": False
218
+ }
219
+
220
+ return json.dumps(response_data)
221
+
222
+ except Exception as e:
223
+ logger.error(f"Image generation failed: {e}")
224
+ return json.dumps({
225
+ "success": False,
226
+ "error": f"Generation failed: {str(e)}",
227
+ "prompt": prompt,
228
+ "style": style
229
+ })
230
 
231
+ def analyze_marketing_prompt(prompt: str, review_guidelines: str = "") -> str:
232
+ """
233
+ Analyze a marketing prompt for quality, relevance, and compliance.
234
+
235
+ Args:
236
+ prompt (str): The marketing prompt to analyze
237
+ review_guidelines (str): Specific guidelines to check against
238
+
239
+ Returns:
240
+ str: JSON string containing detailed analysis and recommendations
241
+ """
242
+ logger.info(f"πŸ” Analyzing marketing prompt: {prompt[:50]}...")
243
+
244
+ try:
245
+ word_count = len(prompt.split())
246
+
247
+ # Check for marketing-specific elements
248
+ marketing_keywords = [
249
+ "professional", "corporate", "business", "marketing", "brand", "commercial",
250
+ "office", "team", "collaboration", "presentation", "meeting", "workplace",
251
+ "customer", "service", "product", "showcase", "display", "advertising"
252
+ ]
253
+
254
+ style_keywords = [
255
+ "realistic", "photographic", "artistic", "creative", "modern", "clean",
256
+ "minimalist", "professional", "high-quality", "detailed", "sharp"
257
+ ]
258
+
259
+ composition_keywords = [
260
+ "lighting", "composition", "background", "foreground", "perspective",
261
+ "angle", "framing", "focus", "depth", "contrast", "colors"
262
+ ]
263
+
264
+ # Count keyword categories
265
+ marketing_score = sum(1 for word in marketing_keywords if word.lower() in prompt.lower()) / len(marketing_keywords)
266
+ style_score = sum(1 for word in style_keywords if word.lower() in prompt.lower()) / len(style_keywords)
267
+ composition_score = sum(1 for word in composition_keywords if word.lower() in prompt.lower()) / len(composition_keywords)
268
+
269
+ # Base quality assessment
270
+ if word_count < 5:
271
+ base_quality = 0.3
272
+ quality_issues = ["Prompt is too short and lacks detail"]
273
+ elif word_count < 10:
274
+ base_quality = 0.5
275
+ quality_issues = ["Prompt could benefit from more descriptive details"]
276
+ elif word_count < 20:
277
+ base_quality = 0.7
278
+ quality_issues = []
279
+ elif word_count < 40:
280
+ base_quality = 0.8
281
+ quality_issues = []
282
+ else:
283
+ base_quality = 0.6
284
+ quality_issues = ["Prompt might be too complex - consider simplifying"]
285
+
286
+ # Adjust based on keyword presence
287
+ quality_adjustment = (marketing_score * 0.2 + style_score * 0.15 + composition_score * 0.15)
288
+ final_quality = min(1.0, base_quality + quality_adjustment)
289
+
290
+ # Generate specific feedback
291
+ missing_elements = []
292
+ if marketing_score < 0.1:
293
+ missing_elements.append("marketing context or business relevance")
294
+ if style_score < 0.1:
295
+ missing_elements.append("artistic style or visual quality descriptors")
296
+ if "english" in review_guidelines.lower() and "english" not in prompt.lower():
297
+ missing_elements.append("English language specification for text/signage")
298
+
299
+ present_elements = []
300
+ if marketing_score > 0.1:
301
+ present_elements.append("marketing/business context")
302
+ if style_score > 0.1:
303
+ present_elements.append("style descriptors")
304
+ if composition_score > 0.1:
305
+ present_elements.append("composition guidance")
306
+
307
+ # Calculate overall scores
308
+ relevance_score = min(1.0, final_quality + (marketing_score * 0.2))
309
+ safety_score = 0.95 # Generally high for marketing prompts
310
+
311
+ # Check for potentially problematic content
312
+ problematic_terms = ["violence", "inappropriate", "offensive", "controversial"]
313
+ for term in problematic_terms:
314
+ if term in prompt.lower():
315
+ safety_score = 0.7
316
+ break
317
+
318
+ overall_score = (final_quality * 0.4 + relevance_score * 0.4 + safety_score * 0.2)
319
+
320
+ # Generate recommendations
321
+ recommendations = []
322
+
323
+ if final_quality < 0.6:
324
+ recommendations.append("Consider adding more descriptive details about the desired image")
325
+
326
+ if marketing_score < 0.1:
327
+ recommendations.append("Add marketing context (e.g., professional, business, corporate)")
328
+
329
+ if "english" in review_guidelines.lower() and "english" not in prompt.lower():
330
+ recommendations.append("Add 'English signage' or 'English text' to meet language requirements")
331
+
332
+ if word_count < 10:
333
+ recommendations.append("Expand prompt with lighting, composition, or environmental details")
334
+ elif word_count > 50:
335
+ recommendations.append("Consider simplifying prompt while keeping key elements")
336
+
337
+ if not recommendations:
338
+ if overall_score > 0.8:
339
+ recommendations.append("Excellent prompt! Should generate high-quality marketing image")
340
+ else:
341
+ recommendations.append("Good prompt foundation - image should meet basic requirements")
342
+
343
+ analysis_result = {
344
+ "success": True,
345
+ "quality_score": round(final_quality, 2),
346
+ "relevance_score": round(relevance_score, 2),
347
+ "safety_score": round(safety_score, 2),
348
+ "overall_score": round(overall_score, 2),
349
+ "word_count": word_count,
350
+ "missing_elements": missing_elements,
351
+ "present_elements": present_elements,
352
+ "recommendations": recommendations[:5],
353
+ "analysis_method": "prompt_analysis"
354
+ }
355
+
356
+ return json.dumps(analysis_result)
357
+
358
+ except Exception as e:
359
+ logger.error(f"Prompt analysis failed: {e}")
360
+ return json.dumps({
361
+ "success": False,
362
+ "error": f"Analysis failed: {str(e)}",
363
+ "prompt": prompt
364
+ })
365
+
366
+ def generate_and_review_marketing_image(prompt: str, style: str = "realistic", review_guidelines: str = "") -> str:
367
+ """
368
+ Complete workflow: Generate a marketing image and provide quality review.
369
+
370
+ Args:
371
+ prompt (str): Description of the marketing image to generate
372
+ style (str): Art style for the image (realistic, artistic, cartoon, photographic, illustration)
373
+ review_guidelines (str): Specific guidelines for marketing review
374
+
375
+ Returns:
376
+ str: JSON string containing image, review, and recommendations
377
+ """
378
+ logger.info(f"🎭 Starting complete marketing workflow for: {prompt}")
379
+
380
+ try:
381
+ # Step 1: Generate the image
382
+ generation_response = generate_marketing_image(prompt, style)
383
+ generation_data = json.loads(generation_response)
384
+
385
+ if not generation_data.get("success", False):
386
+ return generation_response # Return error
387
+
388
+ # Step 2: Analyze the prompt (marketing review)
389
+ analysis_response = analyze_marketing_prompt(prompt, review_guidelines)
390
+ analysis_data = json.loads(analysis_response)
391
+
392
+ # Combine results
393
+ workflow_result = {
394
+ "success": True,
395
+ "image": {
396
+ "url": generation_data.get("image_url", ""),
397
+ "data": generation_data.get("image_url", ""),
398
+ "prompt": prompt,
399
+ "style": style
400
+ },
401
+ "review": {
402
+ "quality_score": analysis_data.get("overall_score", 0.7),
403
+ "final_status": "passed" if analysis_data.get("overall_score", 0) > 0.7 else "needs_improvement",
404
+ "iterations": 1,
405
+ "passed": analysis_data.get("overall_score", 0) > 0.7,
406
+ "recommendations": analysis_data.get("recommendations", []),
407
+ "analysis_details": analysis_data
408
+ },
409
+ "metadata": {
410
+ "generation_method": generation_data.get("generation_method", "unknown"),
411
+ "real_ai_generation": generation_data.get("real_ai_generation", False),
412
+ "workflow_type": "gradio_mcp_server"
413
+ }
414
+ }
415
+
416
+ logger.info("βœ… Complete marketing workflow successful!")
417
+ return json.dumps(workflow_result)
418
+
419
+ except Exception as e:
420
+ logger.error(f"Complete workflow failed: {e}")
421
+ return json.dumps({
422
+ "success": False,
423
+ "error": f"Workflow failed: {str(e)}",
424
+ "prompt": prompt,
425
+ "style": style
426
+ })
427
+
428
+ # Gradio interface functions
429
+ def process_generated_image_and_results(api_response_str: str) -> Tuple[Image.Image, str]:
430
  """Process API response and return image and review text for Gradio display"""
431
  try:
432
+ response_data = json.loads(api_response_str)
433
 
434
  if not response_data.get('success', False):
435
  return None, f"❌ Generation failed: {response_data.get('error', 'Unknown error')}"
 
454
  quality_score = review_data.get('quality_score', 0)
455
  passed = review_data.get('passed', False)
456
  final_status = review_data.get('final_status', 'unknown')
 
457
  recommendations = review_data.get('recommendations', [])
458
 
459
  status_emoji = "🟒" if passed else "πŸ”΄"
 
461
  # Extract metadata about generation method
462
  metadata = response_data.get('metadata', {})
463
  generation_method = metadata.get('generation_method', 'unknown')
 
464
 
465
  generation_info = ""
466
+ if generation_method == "google-genai-sdk":
467
+ generation_info = "🎨 **Generated with**: Google Imagen3 SDK (Real AI)\n"
 
 
468
  elif generation_method == "placeholder":
469
  generation_info = "🎨 **Generated with**: Placeholder (Fallback)\n"
470
 
471
+ review_text = f"""**πŸ” Marketing Review Results**
472
 
473
  {generation_info}
474
  **Quality Score:** {quality_score:.2f}/1.0
475
  **Status:** {status_emoji} {final_status.upper()}
476
+ **Architecture:** Gradio MCP Server
 
477
 
478
  **πŸ’‘ Recommendations:**
479
  """
 
483
  review_text += f"{i}. {rec}\n"
484
  else:
485
  review_text += "β€’ Image meets quality standards\n"
486
+
 
 
 
 
 
 
 
 
487
  else:
488
  review_text = "⚠️ Review data not available"
489
 
 
492
  except Exception as e:
493
  return None, f"❌ Error processing results: {str(e)}"
494
 
495
+ def gradio_generate_marketing_image(prompt: str, style: str, review_guidelines: str) -> Tuple[Image.Image, str]:
496
+ """Gradio interface wrapper for complete marketing image generation"""
497
  if not prompt.strip():
498
  return None, "⚠️ Please enter a prompt to generate an image."
499
 
 
 
 
500
  try:
501
+ # Use the complete workflow function
502
+ result_json = generate_and_review_marketing_image(prompt, style, review_guidelines)
503
+ return process_generated_image_and_results(result_json)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  except Exception as e:
505
+ error_message = f"❌ Error: {str(e)}"
506
  logger.error(error_message)
507
  return None, error_message
508
 
509
+ # Define suggested prompts
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  SUGGESTED_PROMPTS = {
511
  "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"),
512
  "Executive boardroom meeting": ("Professional executive boardroom with polished conference table, city skyline view, business documents, English presentations on screens", "realistic"),
 
517
  }
518
 
519
  # Create Gradio interface
520
+ with gr.Blocks(title="Marketing Image Generator MCP", theme=gr.themes.Soft()) as demo:
521
  gr.Markdown("""
522
+ # 🎨 Marketing Image Generator
523
+ ### Professional AI image generation with built-in MCP server support
524
 
525
+ **Gradio MCP Server** β†’ **Google Imagen3** β†’ **Marketing Review** β†’ **Results**
526
+
527
+ *MCP Server available at: `/gradio_api/mcp/sse`*
528
  """)
529
 
530
  with gr.Row():
 
548
 
549
  review_guidelines = gr.Textbox(
550
  label="πŸ” Marketing Review Guidelines (Optional)",
551
+ placeholder="e.g., All text must be in English only, focus on professional appearance, ensure brand colors are prominent",
552
  lines=3,
553
+ info="Provide specific marketing guidelines for review"
554
  )
555
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  # Generate button
557
+ generate_btn = gr.Button("πŸš€ Generate Marketing Image", variant="primary", size="lg")
558
 
559
  # Status
560
+ gr.Markdown("πŸ” **Mode**: Gradio MCP Server")
561
+ gr.Markdown(f"πŸ”‘ **API Status**: {'βœ… Configured' if GOOGLE_API_KEY else '❌ No API Key'}")
 
 
 
 
562
 
563
  with gr.Column(scale=2):
564
  # Results display
565
+ gr.Markdown("### πŸ–ΌοΈ Generated Image & Review")
566
 
567
  image_output = gr.Image(
568
  label="Generated Marketing Image",
 
572
  )
573
 
574
  review_output = gr.Markdown(
575
+ value="Click **Generate Marketing Image** to create your marketing image with automated review",
576
+ label="Marketing Review Results"
577
  )
578
 
579
  # Suggested prompts section
 
603
 
604
  # Event handlers
605
  generate_btn.click(
606
+ fn=gradio_generate_marketing_image,
607
+ inputs=[prompt, style, review_guidelines],
608
  outputs=[image_output, review_output],
609
  show_progress=True
610
  )
611
 
 
 
 
 
 
612
  # Footer
613
  gr.Markdown("""
614
  ---
615
  <div style='text-align: center; color: #666; font-size: 0.9rem;'>
616
+ <p>🎨 Marketing Image Generator | Gradio MCP Server</p>
617
+ <p>Image Generation + Marketing Review + MCP API</p>
618
+ <p>MCP Endpoint: <code>/gradio_api/mcp/sse</code></p>
619
  </div>
620
  """)
621
 
622
  if __name__ == "__main__":
623
+ logger.info("πŸš€ Starting Marketing Image Generator with MCP Server")
624
+ logger.info(f"πŸ”‘ Google AI: {'βœ… Configured' if GOOGLE_API_KEY else '❌ No API Key'}")
625
+ logger.info("πŸ”— MCP Server will be available at /gradio_api/mcp/sse")
 
 
 
 
 
 
626
 
627
+ demo.launch(mcp_server=True)