|
|
""" |
|
|
Comic Generator with Character Consistency Integration |
|
|
Safe wrapper that integrates character consistency system with automatic fallback to legacy system |
|
|
""" |
|
|
|
|
|
import asyncio |
|
|
import os |
|
|
from typing import Dict, List, Optional, Union |
|
|
from PIL import Image |
|
|
from config import Config |
|
|
|
|
|
|
|
|
try: |
|
|
from character_consistency_manager import CharacterConsistencyManager |
|
|
CHARACTER_CONSISTENCY_AVAILABLE = True |
|
|
print("✓ Character Consistency system available") |
|
|
except ImportError as e: |
|
|
CHARACTER_CONSISTENCY_AVAILABLE = False |
|
|
print(f"⚠️ Character Consistency not available - using legacy system") |
|
|
print(f" Import error: {e}") |
|
|
|
|
|
|
|
|
class ComicGeneratorWithConsistency: |
|
|
""" |
|
|
Unified comic generator with character consistency support and legacy fallback |
|
|
|
|
|
This class provides a safe integration layer between the new character consistency |
|
|
system and the existing comic generation logic in app_comic.py |
|
|
|
|
|
Behavior: |
|
|
- If ENABLE_NANO_BANANA=true AND system available: Use character consistency |
|
|
- If character consistency fails OR disabled: Automatic fallback to legacy system |
|
|
- Legacy system always available as safety net |
|
|
""" |
|
|
|
|
|
def __init__(self): |
|
|
"""Initialize comic generator with optional character consistency""" |
|
|
self.consistency_enabled = ( |
|
|
CHARACTER_CONSISTENCY_AVAILABLE and |
|
|
Config.ENABLE_NANO_BANANA |
|
|
) |
|
|
|
|
|
self.consistency_manager = None |
|
|
|
|
|
if self.consistency_enabled: |
|
|
try: |
|
|
self.consistency_manager = CharacterConsistencyManager() |
|
|
print("✓ Character Consistency Manager initialized") |
|
|
except Exception as e: |
|
|
print(f"⚠️ Failed to initialize Character Consistency: {e}") |
|
|
print("🔄 Will use legacy system") |
|
|
self.consistency_enabled = False |
|
|
|
|
|
|
|
|
self.consistency_success_count = 0 |
|
|
self.consistency_failure_count = 0 |
|
|
self.fallback_count = 0 |
|
|
|
|
|
async def generate_comic_from_prompt( |
|
|
self, |
|
|
story_prompt: str, |
|
|
num_panels: int = 3, |
|
|
art_style: str = "manga", |
|
|
include_surprise_character: bool = True, |
|
|
force_legacy: bool = False, |
|
|
output_dir: Optional[str] = None |
|
|
) -> Dict: |
|
|
""" |
|
|
Generate comic with automatic character consistency or legacy fallback |
|
|
|
|
|
Args: |
|
|
story_prompt: User's story prompt |
|
|
num_panels: Number of panels to generate |
|
|
art_style: Art style for the comic |
|
|
include_surprise_character: Add AI-generated surprise character |
|
|
force_legacy: Force use of legacy system (for testing) |
|
|
output_dir: Output directory for generated files |
|
|
|
|
|
Returns: |
|
|
Dictionary with generation results: |
|
|
{ |
|
|
"success": bool, |
|
|
"method": str, # "character_consistency" or "legacy" |
|
|
"panels": List[Image], |
|
|
"characters": Dict[str, str], # Only if character_consistency used |
|
|
"output_dir": str, |
|
|
"panel_info": List[Dict], # Panel metadata |
|
|
"error": Optional[str] |
|
|
} |
|
|
""" |
|
|
|
|
|
|
|
|
use_consistency = ( |
|
|
self.consistency_enabled and |
|
|
not force_legacy and |
|
|
self.consistency_manager is not None |
|
|
) |
|
|
|
|
|
if use_consistency: |
|
|
print(f"\n🎨 Generating comic with CHARACTER CONSISTENCY system...") |
|
|
print(f" Story: {story_prompt[:100]}...") |
|
|
print(f" Panels: {num_panels}, Style: {art_style}") |
|
|
|
|
|
try: |
|
|
result = await self._generate_with_consistency( |
|
|
story_prompt=story_prompt, |
|
|
num_panels=num_panels, |
|
|
art_style=art_style, |
|
|
include_surprise_character=include_surprise_character, |
|
|
output_dir=output_dir |
|
|
) |
|
|
|
|
|
if result["success"]: |
|
|
self.consistency_success_count += 1 |
|
|
print(f"✓ Character consistency generation successful!") |
|
|
return result |
|
|
else: |
|
|
print(f"⚠️ Character consistency failed: {result.get('error')}") |
|
|
print(f"🔄 Falling back to legacy system...") |
|
|
self.consistency_failure_count += 1 |
|
|
|
|
|
except Exception as e: |
|
|
print(f"⚠️ Character consistency exception: {e}") |
|
|
print(f"🔄 Falling back to legacy system...") |
|
|
self.consistency_failure_count += 1 |
|
|
|
|
|
|
|
|
self.fallback_count += 1 |
|
|
print(f"\n🎨 Generating comic with LEGACY system...") |
|
|
|
|
|
return await self._generate_with_legacy( |
|
|
story_prompt=story_prompt, |
|
|
num_panels=num_panels, |
|
|
art_style=art_style, |
|
|
output_dir=output_dir |
|
|
) |
|
|
|
|
|
async def _generate_with_consistency( |
|
|
self, |
|
|
story_prompt: str, |
|
|
num_panels: int, |
|
|
art_style: str, |
|
|
include_surprise_character: bool, |
|
|
output_dir: Optional[str] |
|
|
) -> Dict: |
|
|
""" |
|
|
Generate comic using character consistency system |
|
|
|
|
|
This wraps the CharacterConsistencyManager.generate_comic_from_prompt method |
|
|
in a safe async context with proper error handling |
|
|
""" |
|
|
|
|
|
try: |
|
|
|
|
|
loop = asyncio.get_event_loop() |
|
|
result = await loop.run_in_executor( |
|
|
None, |
|
|
self.consistency_manager.generate_comic_from_prompt, |
|
|
story_prompt, |
|
|
num_panels, |
|
|
art_style, |
|
|
include_surprise_character, |
|
|
output_dir or "./auto_generated_comics" |
|
|
) |
|
|
|
|
|
|
|
|
result["success"] = True |
|
|
result["method"] = "character_consistency" |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
return { |
|
|
"success": False, |
|
|
"method": "character_consistency", |
|
|
"error": str(e), |
|
|
"panels": [], |
|
|
"characters": {}, |
|
|
"panel_info": [] |
|
|
} |
|
|
|
|
|
async def _generate_with_legacy( |
|
|
self, |
|
|
story_prompt: str, |
|
|
num_panels: int, |
|
|
art_style: str, |
|
|
output_dir: Optional[str] |
|
|
) -> Dict: |
|
|
""" |
|
|
Generate comic using legacy system (placeholder for app_comic.py integration) |
|
|
|
|
|
NOTE: This is a placeholder. In actual integration, this would call the |
|
|
existing comic generation logic from app_comic.py |
|
|
|
|
|
For now, returns a structure indicating legacy mode was used |
|
|
""" |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"method": "legacy", |
|
|
"panels": [], |
|
|
"characters": {}, |
|
|
"panel_info": [ |
|
|
{ |
|
|
"panel_number": i + 1, |
|
|
"characters": [], |
|
|
"filename": f"legacy_panel_{i+1}.png" |
|
|
} |
|
|
for i in range(num_panels) |
|
|
], |
|
|
"output_dir": output_dir or "./generated_comics", |
|
|
"note": "Legacy system placeholder - integrate with app_comic.py logic" |
|
|
} |
|
|
|
|
|
def get_stats(self) -> Dict: |
|
|
"""Get generation statistics""" |
|
|
total = self.consistency_success_count + self.consistency_failure_count + self.fallback_count |
|
|
|
|
|
return { |
|
|
"total_generations": total, |
|
|
"consistency_enabled": self.consistency_enabled, |
|
|
"consistency_available": CHARACTER_CONSISTENCY_AVAILABLE, |
|
|
"consistency_successes": self.consistency_success_count, |
|
|
"consistency_failures": self.consistency_failure_count, |
|
|
"legacy_fallbacks": self.fallback_count, |
|
|
"consistency_rate": ( |
|
|
f"{(self.consistency_success_count / total * 100):.1f}%" |
|
|
if total > 0 else "N/A" |
|
|
) |
|
|
} |
|
|
|
|
|
def print_stats(self): |
|
|
"""Print generation statistics""" |
|
|
stats = self.get_stats() |
|
|
|
|
|
print("\n" + "="*70) |
|
|
print(" COMIC GENERATOR STATISTICS") |
|
|
print("="*70) |
|
|
print(f"Character Consistency Available: {stats['consistency_available']}") |
|
|
print(f"Character Consistency Enabled: {stats['consistency_enabled']}") |
|
|
print(f"\nTotal Generations: {stats['total_generations']}") |
|
|
print(f" ✓ Consistency Successes: {stats['consistency_successes']}") |
|
|
print(f" ⚠ Consistency Failures: {stats['consistency_failures']}") |
|
|
print(f" 🔄 Legacy Fallbacks: {stats['legacy_fallbacks']}") |
|
|
print(f"\nConsistency Success Rate: {stats['consistency_rate']}") |
|
|
print("="*70) |
|
|
|
|
|
|
|
|
|
|
|
async def test_comic_generator(): |
|
|
"""Test the comic generator with both systems""" |
|
|
|
|
|
print("\n" + "="*70) |
|
|
print(" COMIC GENERATOR TEST") |
|
|
print("="*70) |
|
|
|
|
|
generator = ComicGeneratorWithConsistency() |
|
|
|
|
|
test_prompt = "A yogi teaching a young aspirant the rules of meditation and mindfulness leading to levitation by his own example in a beautiful vibrant colorful jungle" |
|
|
|
|
|
|
|
|
print("\n--- Test 1: Character Consistency Mode ---") |
|
|
result1 = await generator.generate_comic_from_prompt( |
|
|
story_prompt=test_prompt, |
|
|
num_panels=3, |
|
|
art_style="manga", |
|
|
include_surprise_character=True |
|
|
) |
|
|
|
|
|
print(f"\nResult: {result1['method']}") |
|
|
print(f"Success: {result1['success']}") |
|
|
if result1.get('characters'): |
|
|
print(f"Characters: {list(result1['characters'].keys())}") |
|
|
|
|
|
|
|
|
print("\n--- Test 2: Forced Legacy Mode ---") |
|
|
result2 = await generator.generate_comic_from_prompt( |
|
|
story_prompt=test_prompt, |
|
|
num_panels=3, |
|
|
art_style="manga", |
|
|
force_legacy=True |
|
|
) |
|
|
|
|
|
print(f"\nResult: {result2['method']}") |
|
|
print(f"Success: {result2['success']}") |
|
|
|
|
|
|
|
|
generator.print_stats() |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
asyncio.run(test_comic_generator()) |
|
|
|