3Stark123's picture
Update app.py
3545629 verified
"""
Main Gradio application for Text-to-Infographics Generator
"""
import os
import logging
import gradio as gr
from typing import Dict, List, Tuple, Optional
import tempfile
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Import our modules
from config import Config
from src.text_processor import TextProcessor
from src.gemini_client import GeminiClient
from src.template_manager import TemplateManager
from src.layout_engine import LayoutEngine
from src.color_palette import ColorPalette
from src.image_generator import ImageGenerator
from utils.helpers import sanitize_text, validate_content_length, generate_unique_id
from examples.sample_texts import get_sample_text, get_all_categories
# Initialize components
text_processor = TextProcessor()
gemini_client = GeminiClient()
template_manager = TemplateManager()
layout_engine = LayoutEngine()
color_palette = ColorPalette()
image_generator = ImageGenerator()
def generate_infographic(text: str, template_style: str, custom_color: str,
layout_type: str, progress=gr.Progress()) -> Tuple[str, str, str]:
"""
Main function to generate infographic
Args:
text: Input text content
template_style: Selected template style
custom_color: Custom primary color
layout_type: Layout arrangement type
progress: Gradio progress tracker
Returns:
Tuple of (image_path, status_message, download_file_path)
"""
try:
# Validate inputs
progress(0.1, desc="Validating input...")
if not text or len(text.strip()) < 10:
return None, "❌ Please provide more substantial text content (at least 10 characters)", None
# Sanitize and validate content
text = sanitize_text(text)
content_validation = validate_content_length(text)
if not content_validation['valid']:
return None, f"❌ {content_validation['message']}", None
# Step 1: Process text
progress(0.2, desc="Analyzing text content...")
logger.info("Starting text analysis")
text_analysis = text_processor.analyze_text(text)
# Step 2: Get AI insights
progress(0.3, desc="Getting AI insights...")
logger.info("Getting AI insights from Gemini")
enhanced_analysis = gemini_client.analyze_content(text_analysis)
# Generate title if not present
if not enhanced_analysis.get('title'):
progress(0.35, desc="Generating title...")
enhanced_analysis['title'] = gemini_client.generate_title(text)
# Step 3: Apply template styling
progress(0.4, desc="Applying template styling...")
logger.info(f"Applying {template_style} template")
styled_content = template_manager.apply_template_to_content(
enhanced_analysis, template_style, custom_color, layout_type
)
# Step 4: Create layout
progress(0.6, desc="Creating layout...")
logger.info("Generating layout")
layout_data = layout_engine.create_layout(styled_content)
# Optimize layout
progress(0.7, desc="Optimizing layout...")
layout_data = layout_engine.optimize_layout(layout_data)
# Step 5: Generate image
progress(0.8, desc="Generating infographic image...")
logger.info("Creating final image")
export_data = layout_engine.export_layout_data(layout_data)
image_path = image_generator.create_infographic(export_data)
# Step 6: Create downloadable file
progress(0.9, desc="Preparing download...")
download_path = _prepare_download_file(image_path, template_style)
progress(1.0, desc="Complete!")
success_message = f"βœ… Infographic generated successfully!\nπŸ“Š Template: {template_style}\nπŸ“ Layout: {layout_type}\nπŸ“ {len(text.split())} words processed"
return image_path, success_message, download_path
except Exception as e:
logger.error(f"Error generating infographic: {e}")
error_message = f"❌ Error generating infographic: {str(e)}"
return None, error_message, None
def _prepare_download_file(image_path: str, template_style: str) -> str:
"""Prepare downloadable file"""
try:
if not image_path or not os.path.exists(image_path):
return None
# Create a copy for download with better filename
download_filename = f"infographic_{template_style.lower()}_{generate_unique_id()}.png"
download_path = os.path.join(tempfile.gettempdir(), download_filename)
# Copy file
import shutil
shutil.copy2(image_path, download_path)
return download_path
except Exception as e:
logger.error(f"Error preparing download file: {e}")
return image_path # Return original if copy fails
def load_sample_text(category: str) -> str:
"""Load sample text by category"""
try:
return get_sample_text(category)
except Exception as e:
logger.error(f"Error loading sample text: {e}")
return ""
def get_template_info(template_name: str) -> str:
"""Get template information"""
try:
info = template_manager.get_template_preview_data(template_name)
if info:
description = info.get('description', 'Professional infographic template')
best_for = ', '.join(info.get('best_for', ['General use']))
return f"**{template_name}**: {description}\n**Best for**: {best_for}"
return f"**{template_name}**: Professional infographic template"
except Exception as e:
logger.error(f"Error getting template info: {e}")
return f"**{template_name}**: Professional template"
def create_interface():
"""Create the main Gradio interface"""
# Custom CSS for better styling
css = """
.gradio-container {
max-width: 1400px !important;
margin: auto;
}
.main-header {
text-align: center;
margin-bottom: 2rem;
}
.feature-box {
padding: 1rem;
border-radius: 8px;
margin: 0.5rem 0;
}
.status-box {
padding: 1rem;
border-radius: 8px;
margin-top: 1rem;
}
"""
with gr.Blocks(
theme=gr.themes.Soft(
primary_hue="blue",
secondary_hue="gray",
neutral_hue="gray",
),
css=css,
title="AI Text-to-Infographics Generator"
) as app:
# Header
gr.HTML("""
<div class="main-header">
<h1>🎨 AI Text-to-Infographics Generator</h1>
<p>Transform your text into stunning, professional infographics with the power of AI</p>
</div>
""")
with gr.Row():
# Left Column - Input and Controls
with gr.Column(scale=1):
gr.Markdown("## πŸ“ Input Content")
# Text input with sample loader
with gr.Group():
text_input = gr.Textbox(
label="Your Text Content",
placeholder="Paste your content here... (articles, reports, data, etc.)",
lines=12,
max_lines=20,
show_label=True
)
# Sample text loader
with gr.Row():
sample_category = gr.Dropdown(
choices=get_all_categories(),
label="Load Sample Text",
value="business_report",
scale=2
)
load_sample_btn = gr.Button("Load Sample", scale=1, size="sm")
gr.Markdown("## 🎨 Customization")
# Template selection with preview
template_choice = gr.Dropdown(
choices=Config.TEMPLATES,
value="Modern",
label="Template Style",
info="Choose the visual style for your infographic"
)
template_info = gr.Markdown(
get_template_info("Modern"),
elem_classes=["feature-box"]
)
# Color customization
custom_color = gr.ColorPicker(
label="Primary Color",
value="#3498db",
info="Choose your brand or preferred color"
)
# Layout options
layout_type = gr.Radio(
choices=Config.LAYOUTS,
value="Vertical",
label="Layout Arrangement",
info="How content should be arranged"
)
# Generate button
generate_btn = gr.Button(
"πŸš€ Generate Infographic",
variant="primary",
size="lg",
scale=1
)
# Right Column - Output and Results
with gr.Column(scale=1):
gr.Markdown("## πŸ–ΌοΈ Generated Infographic")
# Output image
output_image = gr.Image(
label="Your Infographic",
show_label=False,
height=600,
show_download_button=True
)
# Status and download
with gr.Group():
status_output = gr.Textbox(
label="Generation Status",
interactive=False,
show_label=True,
elem_classes=["status-box"]
)
download_file = gr.File(
label="Download High Resolution",
visible=True,
show_label=True
)
# Examples section
gr.Markdown("## πŸ“š Examples & Tips")
with gr.Row():
with gr.Column():
gr.Examples(
examples=[
[
get_sample_text("business_report")[:500] + "...",
"Corporate",
"#2c3e50",
"Horizontal"
],
[
get_sample_text("technology_overview")[:500] + "...",
"Modern",
"#3498db",
"Vertical"
],
[
get_sample_text("health_wellness")[:500] + "...",
"Creative",
"#27ae60",
"Grid"
]
],
inputs=[text_input, template_choice, custom_color, layout_type],
label="Example Configurations"
)
with gr.Column():
gr.Markdown("""
### πŸ’‘ Tips for Better Results
- **Length**: 200-2000 words work best
- **Structure**: Use clear paragraphs and sections
- **Data**: Include numbers and statistics for visual impact
- **Keywords**: Use descriptive keywords for better AI analysis
- **Format**: Bullet points and lists enhance visual appeal
""")
# Footer
gr.HTML("""
<div style="text-align: center; margin-top: 2rem; padding: 1rem; border-top: 1px solid #eee;">
<p>Built with ❀️ using <strong>Gradio</strong>, <strong>Google Gemini</strong>, and <strong>Hugging Face Spaces</strong></p>
<p><small>Transform your ideas into visual stories β€’ Perfect for presentations, social media, and reports</small></p>
</div>
""")
# Event handlers
generate_btn.click(
fn=generate_infographic,
inputs=[text_input, template_choice, custom_color, layout_type],
outputs=[output_image, status_output, download_file],
show_progress=True
)
load_sample_btn.click(
fn=load_sample_text,
inputs=[sample_category],
outputs=[text_input]
)
template_choice.change(
fn=get_template_info,
inputs=[template_choice],
outputs=[template_info]
)
return app
def main():
"""Main application entry point"""
try:
logger.info("Initializing Text-to-Infographics Generator")
# Check API key
if not Config.GEMINI_API_KEY:
logger.warning("Gemini API key not found. AI features will be limited.")
# Create and launch interface
app = create_interface()
# FIXED: Removed show_tips parameter
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
except Exception as e:
logger.error(f"Failed to launch application: {e}")
raise
if __name__ == "__main__":
main()