File size: 15,776 Bytes
7e8adfc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6fc21ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7e8adfc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
"""
All-in-One Marketing Image Generator with Proper A2A Architecture
Includes A2A Orchestrator + Agent1 (MCP-Imagen3) + Agent2 (Reviewer) + Gradio Interface
"""

import gradio as gr
import os
import logging
import asyncio
import json
from typing import Dict, Any
from PIL import Image
import io
import base64

# Google Service Account Authentication Setup
def setup_google_credentials():
    """Setup Google credentials from service account JSON"""
    try:
        service_account_json = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
        if service_account_json:
            import tempfile
            from google.oauth2 import service_account
            
            # Parse the JSON credentials
            credentials_dict = json.loads(service_account_json)
            
            # Create credentials from service account info
            credentials = service_account.Credentials.from_service_account_info(credentials_dict)
            
            # Set the credentials in environment
            with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
                json.dump(credentials_dict, f)
                os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = f.name
            
            print("βœ… Google Cloud service account configured")
            return True
    except Exception as e:
        print(f"⚠️ Google Cloud service account setup failed: {e}")
    
    print("⚠️ Google Cloud service account not found")
    return False

# Setup Google credentials on startup
setup_google_credentials()

# A2A imports
try:
    from a2a_orchestrator import A2AOrchestrator
    A2A_AVAILABLE = True
except ImportError:
    A2A_AVAILABLE = False

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize A2A Orchestrator
if A2A_AVAILABLE:
    orchestrator = A2AOrchestrator()
    logger.info("βœ… A2A Orchestrator initialized")
else:
    orchestrator = None
    logger.warning("⚠️ A2A not available - will use fallback mode")

def process_generated_image_and_results(api_response):
    """Process API response and return image and review text for Gradio display"""
    try:
        response_data = api_response
        
        if not response_data.get('success', False):
            return None, f"❌ Generation failed: {response_data.get('error', 'Unknown error')}"
        
        # Extract image data
        image_info = response_data.get('image', {})
        image_data_b64 = image_info.get('data', image_info.get('url', ''))
        
        image = None
        if image_data_b64 and image_data_b64.startswith('data:image'):
            try:
                base64_data = image_data_b64.split(',')[1]
                image_bytes = base64.b64decode(base64_data)
                image = Image.open(io.BytesIO(image_bytes))
            except Exception as e:
                logger.error(f"Error processing image: {str(e)}")
        
        # Extract review data
        review_data = response_data.get('review', {})
        
        if review_data:
            quality_score = review_data.get('quality_score', 0)
            passed = review_data.get('passed', False)
            final_status = review_data.get('final_status', 'unknown')
            iterations = review_data.get('iterations', 0)
            recommendations = review_data.get('recommendations', [])
            
            status_emoji = "🟒" if passed else "πŸ”΄"
            
            # Extract metadata about generation method
            metadata = response_data.get('metadata', {})
            generation_method = metadata.get('generation_method', 'unknown')
            real_ai = metadata.get('real_ai_generation', False)
            
            generation_info = ""
            if generation_method == "imagen3-mcp":
                generation_info = "🎨 **Generated with**: Imagen3-MCP (Real AI)\n"
            elif generation_method == "google-genai-sdk":
                generation_info = "🎨 **Generated with**: Google Genai SDK (Real AI)\n"
            elif generation_method == "placeholder":
                generation_info = "🎨 **Generated with**: Placeholder (Fallback)\n"
            
            review_text = f"""**πŸ” A2A Marketing Review Results**

{generation_info}
**Quality Score:** {quality_score:.2f}/1.0
**Status:** {status_emoji} {final_status.upper()}
**Iterations:** {iterations}
**Architecture:** A2A Agent Communication

**πŸ’‘ Recommendations:**
"""
            
            if recommendations:
                for i, rec in enumerate(recommendations[:5], 1):
                    review_text += f"{i}. {rec}\n"
            else:
                review_text += "β€’ Image meets quality standards\n"
            
            # Add workflow history
            workflow_history = review_data.get('workflow_history', [])
            if workflow_history and len(workflow_history) > 1:
                review_text += "\n**πŸ“‹ A2A Workflow History:**\n"
                for item in workflow_history:
                    iteration = item.get('iteration', 'N/A')
                    score = item.get('review_score', 'N/A')
                    review_text += f"β€’ Iteration {iteration}: Score {score:.2f}\n"
        else:
            review_text = "⚠️ Review data not available"
        
        return image, review_text
        
    except Exception as e:
        return None, f"❌ Error processing results: {str(e)}"

def generate_marketing_image_a2a(prompt, style, max_retries, review_threshold, review_guidelines):
    """Main function for the Gradio interface using A2A Orchestrator"""
    if not prompt.strip():
        return None, "⚠️ Please enter a prompt to generate an image."
    
    if not A2A_AVAILABLE or not orchestrator:
        return None, "❌ A2A Orchestrator not available. Please check setup."
    
    try:
        logger.info(f"🎭 Starting A2A workflow for: {prompt}")
        
        # Use the A2A orchestrator to coordinate agents
        result = asyncio.run(
            orchestrator.generate_image_with_review(
                prompt=prompt,
                style=style,
                max_retries=max_retries,
                review_threshold=review_threshold,
                review_guidelines=review_guidelines
            )
        )
        
        if result["success"]:
            image, review_text = process_generated_image_and_results(result)
            success_message = f"βœ… A2A Image generation successful!\n\n{review_text}"
            return image, success_message
        else:
            error_message = f"❌ A2A Generation failed: {result.get('error', 'Unknown error')}"
            return None, error_message
            
    except Exception as e:
        error_message = f"❌ A2A Error: {str(e)}"
        logger.error(error_message)
        return None, error_message

async def check_a2a_agents():
    """Check if A2A agents are available"""
    if not orchestrator:
        return {"agent1": False, "agent2": False, "orchestrator": False}
    
    try:
        health_status = await orchestrator.check_agents_health()
        health_status["orchestrator"] = True
        return health_status
    except Exception as e:
        logger.error(f"Error checking agent health: {e}")
        return {"agent1": False, "agent2": False, "orchestrator": False}

def get_a2a_system_status():
    """Get A2A system status for display"""
    if not A2A_AVAILABLE:
        return "**πŸ”§ A2A System Status:**\n\n❌ A2A not available\n⚠️ Install google-a2a to enable A2A functionality"
    
    try:
        health_status = asyncio.run(check_a2a_agents())
        
        status_text = "**πŸ”§ A2A System Status:**\n\n"
        status_text += f"{'βœ…' if health_status.get('orchestrator', False) else '❌'} A2A Orchestrator\n"
        status_text += f"{'βœ…' if health_status.get('agent1', False) else '❌'} Agent1 (Image Generator)\n"
        status_text += f"{'βœ…' if health_status.get('agent2', False) else '❌'} Agent2 (Marketing Reviewer)\n"
        
        all_healthy = all(health_status.values())
        if all_healthy:
            status_text += "\nπŸŽ‰ All A2A agents are running!"
        else:
            status_text += "\n⚠️ Some A2A agents are not responding."
            status_text += "\nRun: `python a2a_servers.py` to start agents"
        
        return status_text
        
    except Exception as e:
        return f"**πŸ”§ A2A System Status:**\n\n❌ Error checking status: {str(e)}"

# Define suggested prompts (same as before)
SUGGESTED_PROMPTS = {
    "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"),
    "Executive boardroom meeting": ("Professional executive boardroom with polished conference table, city skyline view, business documents, English presentations on screens", "realistic"),
    "Customer service excellence": ("Professional customer service representative with headset in modern call center, English signage, clean corporate environment", "realistic"),
    "Product showcase display": ("Clean product showcase on white background with professional lighting, English product labels, minimalist marketing aesthetic", "realistic"),
    "Creative workspace design": ("Creative workspace with colorful design elements, inspirational English quotes on walls, modern furniture, artistic marketing materials", "artistic"),
    "Brand presentation setup": ("Professional brand presentation setup with English branded materials, corporate colors, marketing displays, conference room setting", "realistic")
}

# Create Gradio interface
with gr.Blocks(title="A2A Marketing Image Generator", theme=gr.themes.Soft()) as demo:
    gr.Markdown("""
    # 🎨 A2A Marketing Image Generator
    ### Professional AI image generation with proper A2A agent architecture
    
    **Agent1** (MCP-Imagen3) ↔ **A2A** ↔ **Agent2** (Marketing Reviewer) ↔ **A2A** ↔ **Orchestrator**
    """)
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### βš™οΈ Configuration")
            
            # Main inputs
            prompt = gr.Textbox(
                label="Describe your marketing image",
                placeholder="e.g., A modern office space with natural lighting, featuring diverse professionals collaborating around a sleek conference table",
                lines=4,
                info="Be specific about the scene, style, mood, and any marketing elements you want to include"
            )
            
            style = gr.Dropdown(
                choices=["realistic", "artistic", "cartoon", "photographic", "illustration"],
                value="realistic",
                label="Art Style",
                info="Choose the artistic style for your generated image"
            )
            
            review_guidelines = gr.Textbox(
                label="πŸ” Marketing Review Guidelines (Optional)",
                placeholder="e.g., All text must be in English only, focus on professional appearance, ensure brand colors are prominent, check accessibility compliance, verify readability",
                lines=3,
                info="Provide specific marketing guidelines for the Marketing Reviewer to evaluate against your brand standards"
            )
            
            # Advanced settings
            with gr.Accordion("πŸ”§ Advanced Settings", open=False):
                max_retries = gr.Slider(
                    minimum=1,
                    maximum=5,
                    value=3,
                    step=1,
                    label="Max Retries",
                    info="Maximum number of retry attempts if generation fails"
                )
                
                review_threshold = gr.Slider(
                    minimum=0.0,
                    maximum=1.0,
                    value=0.8,
                    step=0.1,
                    label="Quality Threshold",
                    info="Minimum quality score required for auto-approval"
                )
            
            # Generate button
            generate_btn = gr.Button("πŸš€ Generate with A2A Architecture", variant="primary", size="lg")
            
            # Status
            gr.Markdown("πŸ” **Mode**: A2A Agent-to-Agent Communication")
            
            # System status
            with gr.Accordion("πŸ“Š A2A System Status", open=False):
                status_display = gr.Markdown(get_a2a_system_status())
                refresh_status_btn = gr.Button("πŸ”„ Refresh A2A Status", size="sm")
        
        with gr.Column(scale=2):
            # Results display
            gr.Markdown("### πŸ–ΌοΈ Generated Image & A2A Review")
            
            image_output = gr.Image(
                label="Generated Marketing Image",
                type="pil",
                height=400,
                show_download_button=True
            )
            
            review_output = gr.Markdown(
                value="Click **Generate with A2A Architecture** to create your marketing image using agent-to-agent communication",
                label="A2A Review Results"
            )
    
    # Suggested prompts section
    gr.Markdown("---")
    gr.Markdown("### πŸ’‘ Suggested Marketing Prompts")
    
    with gr.Row():
        with gr.Column():
            gr.Markdown("**🏒 Professional/Corporate**")
            for prompt_name in ["Modern office team collaboration", "Executive boardroom meeting", "Customer service excellence"]:
                suggested_prompt, suggested_style = SUGGESTED_PROMPTS[prompt_name]
                btn = gr.Button(prompt_name, size="sm")
                btn.click(
                    fn=lambda p=suggested_prompt, s=suggested_style: (p, s),
                    outputs=[prompt, style]
                )
        
        with gr.Column():
            gr.Markdown("**🎨 Creative/Marketing**")
            for prompt_name in ["Product showcase display", "Creative workspace design", "Brand presentation setup"]:
                suggested_prompt, suggested_style = SUGGESTED_PROMPTS[prompt_name]
                btn = gr.Button(prompt_name, size="sm")
                btn.click(
                    fn=lambda p=suggested_prompt, s=suggested_style: (p, s),
                    outputs=[prompt, style]
                )
    
    # Event handlers
    generate_btn.click(
        fn=generate_marketing_image_a2a,
        inputs=[prompt, style, max_retries, review_threshold, review_guidelines],
        outputs=[image_output, review_output],
        show_progress=True
    )
    
    refresh_status_btn.click(
        fn=get_a2a_system_status,
        outputs=status_display
    )
    
    # Footer
    gr.Markdown("""
    ---
    <div style='text-align: center; color: #666; font-size: 0.9rem;'>
        <p>🎨 A2A Marketing Image Generator | Proper Agent-to-Agent Architecture</p>
        <p>Agent1 (MCP-Imagen3) + Agent2 (Reviewer) + A2A Orchestrator + Gradio Interface</p>
        <p>Start agents with: <code>python a2a_servers.py</code></p>
    </div>
    """)

if __name__ == "__main__":
    logger.info("πŸš€ Starting A2A Marketing Image Generator")
    logger.info(f"πŸ€– A2A Available: {'βœ… Yes' if A2A_AVAILABLE else '❌ No'}")
    
    if A2A_AVAILABLE:
        logger.info("πŸ’‘ Using proper A2A agent-to-agent communication")
        logger.info("πŸ”— Architecture: Gradio β†’ Orchestrator β†’ Agent1 (MCP-Imagen3) β†’ Agent2 (Reviewer)")
        logger.info("πŸ“‹ Make sure to start agents: python a2a_servers.py")
    else:
        logger.warning("πŸ’‘ A2A not available - install google-a2a for full functionality")
    
    demo.launch()