|
""" |
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
credentials_dict = json.loads(service_account_json) |
|
|
|
|
|
credentials = service_account.Credentials.from_service_account_info(credentials_dict) |
|
|
|
|
|
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() |
|
|
|
|
|
try: |
|
from a2a_orchestrator import A2AOrchestrator |
|
A2A_AVAILABLE = True |
|
except ImportError: |
|
A2A_AVAILABLE = False |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
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')}" |
|
|
|
|
|
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)}") |
|
|
|
|
|
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 "π΄" |
|
|
|
|
|
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" |
|
|
|
|
|
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}") |
|
|
|
|
|
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)}" |
|
|
|
|
|
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") |
|
} |
|
|
|
|
|
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") |
|
|
|
|
|
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" |
|
) |
|
|
|
|
|
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_btn = gr.Button("π Generate with A2A Architecture", variant="primary", size="lg") |
|
|
|
|
|
gr.Markdown("π **Mode**: A2A Agent-to-Agent Communication") |
|
|
|
|
|
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): |
|
|
|
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" |
|
) |
|
|
|
|
|
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] |
|
) |
|
|
|
|
|
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 |
|
) |
|
|
|
|
|
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() |