|
|
""" |
|
|
๐ฑ Instagram Caption Generator - Simplified Version |
|
|
================================================== |
|
|
|
|
|
AI-Powered Instagram Content Creation Suite with SambaNova Integration |
|
|
Multi-Modal AI Analysis (Vision + Text) + Multi-Language Support |
|
|
|
|
|
๐ Key Features: |
|
|
- SambaNova Llama-4-Maverick Integration |
|
|
- Multi-Language Support (German, Chinese, Hindi, Arabic via Hugging Face) |
|
|
- Advanced Gradio Interface |
|
|
- Advanced Error Handling & Security |
|
|
|
|
|
Author: GRADIO AGENTS & MCP HACKATHON 2025 Participant |
|
|
Date: June 2025 |
|
|
""" |
|
|
|
|
|
import os |
|
|
import base64 |
|
|
import json |
|
|
from datetime import datetime, timedelta |
|
|
from typing import List, Dict, Optional, Any |
|
|
import io |
|
|
import re |
|
|
from dataclasses import dataclass |
|
|
import functools |
|
|
import gc |
|
|
|
|
|
|
|
|
if not os.environ.get("HF_TOKEN"): |
|
|
print("โ ๏ธ HF_TOKEN not found - translation features will use fallback mode") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import gradio as gr |
|
|
from PIL import Image |
|
|
from textblob import TextBlob |
|
|
|
|
|
|
|
|
import openai |
|
|
|
|
|
|
|
|
from huggingface_hub import InferenceClient |
|
|
|
|
|
import time |
|
|
import random |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class AnalyticsData: |
|
|
"""Data structure for caption analytics""" |
|
|
readability_score: float |
|
|
engagement_prediction: float |
|
|
sentiment_score: float |
|
|
hashtag_effectiveness: Dict[str, float] |
|
|
best_posting_time: str |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class TrendData: |
|
|
"""Data structure for trend information""" |
|
|
hashtags: List[str] |
|
|
engagement_score: float |
|
|
category: str |
|
|
timestamp: datetime |
|
|
|
|
|
|
|
|
class AdvancedInstagramGenerator: |
|
|
""" |
|
|
๐ฑ Advanced Instagram Caption Generator |
|
|
|
|
|
AI-powered content creation with: |
|
|
- SambaNova Llama-4-Maverick integration |
|
|
- Multi-modal analysis (Vision + Text) |
|
|
- Multi-language translation via Hugging Face |
|
|
""" |
|
|
|
|
|
def __init__(self): |
|
|
"""Initialize the advanced generator with SambaNova API and Hugging Face""" |
|
|
self.setup_sambanova_client() |
|
|
self.setup_huggingface_client() |
|
|
self.setup_trend_analysis() |
|
|
self.performance_cache = {} |
|
|
self.analytics_db = [] |
|
|
|
|
|
def setup_sambanova_client(self): |
|
|
"""Initialize SambaNova OpenAI client""" |
|
|
self.sambanova_api_key = os.environ.get("SAMBANOVA_API_KEY") |
|
|
|
|
|
try: |
|
|
print("๐ Initializing SambaNova client...") |
|
|
self.sambanova_client = openai.OpenAI( |
|
|
api_key=self.sambanova_api_key, |
|
|
base_url="https://api.sambanova.ai/v1" |
|
|
) |
|
|
|
|
|
|
|
|
print("๐ Testing SambaNova connection...") |
|
|
test_response = self.sambanova_client.chat.completions.create( |
|
|
model="Llama-4-Maverick-17B-128E-Instruct", |
|
|
messages=[{"role": "user", "content": "Hello"}], |
|
|
max_tokens=10, |
|
|
temperature=0.1 |
|
|
) |
|
|
|
|
|
if test_response and test_response.choices: |
|
|
print("โ
SambaNova client initialized and tested successfully!") |
|
|
self.sambanova_client_working = True |
|
|
else: |
|
|
print("โ ๏ธ SambaNova client initialized but test failed") |
|
|
self.sambanova_client_working = False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ SambaNova client initialization failed: {e}") |
|
|
print("๐ก Will use fallback methods for caption generation") |
|
|
self.sambanova_client = None |
|
|
self.sambanova_client_working = False |
|
|
|
|
|
|
|
|
self.primary_model = "Llama-4-Maverick-17B-128E-Instruct" |
|
|
self.variation_model = "Meta-Llama-3.2-3B-Instruct" |
|
|
|
|
|
|
|
|
try: |
|
|
import nltk |
|
|
nltk.download('punkt', quiet=True) |
|
|
nltk.download('brown', quiet=True) |
|
|
print("โ
TextBlob dependencies downloaded successfully!") |
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Could not download TextBlob dependencies: {e}") |
|
|
|
|
|
print("โ
AI models setup completed!") |
|
|
|
|
|
def setup_huggingface_client(self): |
|
|
"""Initialize Hugging Face client for translations""" |
|
|
try: |
|
|
|
|
|
hf_token = os.environ.get("HF_TOKEN") |
|
|
if hf_token: |
|
|
self.hf_client = InferenceClient( |
|
|
provider="hf-inference", |
|
|
api_key=hf_token, |
|
|
) |
|
|
print("โ
Hugging Face client initialized successfully!") |
|
|
self.hf_client_working = True |
|
|
else: |
|
|
print("โ ๏ธ HF_TOKEN not found in environment variables") |
|
|
self.hf_client = None |
|
|
self.hf_client_working = False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Hugging Face client initialization failed: {e}") |
|
|
self.hf_client = None |
|
|
self.hf_client_working = False |
|
|
|
|
|
async def translate_to_chinese(self, text: str) -> str: |
|
|
"""Translate text to Chinese using Hugging Face translation API""" |
|
|
try: |
|
|
if not self.hf_client or not self.hf_client_working: |
|
|
print("โ ๏ธ Hugging Face client not available, using fallback Chinese") |
|
|
return self.get_fallback_chinese_translation(text) |
|
|
|
|
|
print("๐ Translating to Chinese via Hugging Face...") |
|
|
|
|
|
|
|
|
result = self.hf_client.translation( |
|
|
text, |
|
|
model="chence08/mt5-small-iwslt2017-zh-en", |
|
|
) |
|
|
|
|
|
if result and hasattr(result, 'translation_text'): |
|
|
translated_text = result.translation_text |
|
|
print("โ
Chinese translation successful!") |
|
|
return translated_text |
|
|
elif isinstance(result, dict) and 'translation_text' in result: |
|
|
translated_text = result['translation_text'] |
|
|
print("โ
Chinese translation successful!") |
|
|
return translated_text |
|
|
else: |
|
|
print("โ ๏ธ Unexpected response format from HF Chinese translation") |
|
|
return self.get_fallback_chinese_translation(text) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Chinese translation error: {e}") |
|
|
return self.get_fallback_chinese_translation(text) |
|
|
|
|
|
async def translate_to_hindi(self, text: str) -> str: |
|
|
"""Translate text to Hindi using Hugging Face translation API""" |
|
|
try: |
|
|
if not self.hf_client or not self.hf_client_working: |
|
|
print("โ ๏ธ Hugging Face client not available, using fallback Hindi") |
|
|
return self.get_fallback_hindi_translation(text) |
|
|
|
|
|
print("๐ Translating to Hindi via Hugging Face...") |
|
|
|
|
|
|
|
|
result = self.hf_client.translation( |
|
|
text, |
|
|
model="Helsinki-NLP/opus-mt-en-hi", |
|
|
) |
|
|
|
|
|
if result and hasattr(result, 'translation_text'): |
|
|
translated_text = result.translation_text |
|
|
print("โ
Hindi translation successful!") |
|
|
return translated_text |
|
|
elif isinstance(result, dict) and 'translation_text' in result: |
|
|
translated_text = result['translation_text'] |
|
|
print("โ
Hindi translation successful!") |
|
|
return translated_text |
|
|
else: |
|
|
print("โ ๏ธ Unexpected response format from HF Hindi translation") |
|
|
return self.get_fallback_hindi_translation(text) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Hindi translation error: {e}") |
|
|
return self.get_fallback_hindi_translation(text) |
|
|
|
|
|
async def translate_to_arabic(self, text: str) -> str: |
|
|
"""Translate text to Arabic using Hugging Face translation API""" |
|
|
try: |
|
|
if not self.hf_client or not self.hf_client_working: |
|
|
print("โ ๏ธ Hugging Face client not available, using fallback Arabic") |
|
|
return self.get_fallback_arabic_translation(text) |
|
|
|
|
|
print("๐ Translating to Arabic via Hugging Face...") |
|
|
|
|
|
|
|
|
result = self.hf_client.translation( |
|
|
text, |
|
|
model="marefa-nlp/marefa-mt-en-ar", |
|
|
) |
|
|
|
|
|
if result and hasattr(result, 'translation_text'): |
|
|
translated_text = result.translation_text |
|
|
print("โ
Arabic translation successful!") |
|
|
return translated_text |
|
|
elif isinstance(result, dict) and 'translation_text' in result: |
|
|
translated_text = result['translation_text'] |
|
|
print("โ
Arabic translation successful!") |
|
|
return translated_text |
|
|
else: |
|
|
print("โ ๏ธ Unexpected response format from HF Arabic translation") |
|
|
return self.get_fallback_arabic_translation(text) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Arabic translation error: {e}") |
|
|
return self.get_fallback_arabic_translation(text) |
|
|
|
|
|
async def translate_to_german(self, text: str) -> str: |
|
|
"""Translate text to German using Hugging Face translation API""" |
|
|
try: |
|
|
if not self.hf_client or not self.hf_client_working: |
|
|
print("โ ๏ธ Hugging Face client not available, using fallback German") |
|
|
return self.get_fallback_german_translation(text) |
|
|
|
|
|
print("๐ Translating to German via Hugging Face...") |
|
|
|
|
|
|
|
|
result = self.hf_client.translation( |
|
|
text, |
|
|
model="google-t5/t5-small", |
|
|
) |
|
|
|
|
|
if result and hasattr(result, 'translation_text'): |
|
|
translated_text = result.translation_text |
|
|
print("โ
German translation successful!") |
|
|
return translated_text |
|
|
elif isinstance(result, dict) and 'translation_text' in result: |
|
|
translated_text = result['translation_text'] |
|
|
print("โ
German translation successful!") |
|
|
return translated_text |
|
|
else: |
|
|
print("โ ๏ธ Unexpected response format from HF translation") |
|
|
return self.get_fallback_german_translation(text) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ German translation error: {e}") |
|
|
return self.get_fallback_german_translation(text) |
|
|
|
|
|
def get_fallback_german_translation(self, text: str) -> str: |
|
|
"""Fallback German translation when HF API fails""" |
|
|
|
|
|
german_translations = { |
|
|
"amazing": "erstaunlich", |
|
|
"beautiful": "schรถn", |
|
|
"love": "liebe", |
|
|
"perfect": "perfekt", |
|
|
"awesome": "fantastisch", |
|
|
"incredible": "unglaublich", |
|
|
"follow": "folgen", |
|
|
"like": "gefรคllt mir", |
|
|
"share": "teilen", |
|
|
"comment": "kommentieren", |
|
|
"today": "heute", |
|
|
"moment": "Moment", |
|
|
"life": "Leben", |
|
|
"inspiration": "Inspiration", |
|
|
"community": "Gemeinschaft", |
|
|
"content": "Inhalt", |
|
|
"check out": "schau dir an", |
|
|
"what do you think": "was denkst du" |
|
|
} |
|
|
|
|
|
|
|
|
translated = text.lower() |
|
|
for english, german in german_translations.items(): |
|
|
translated = translated.replace(english, german) |
|
|
|
|
|
|
|
|
if "#" in translated: |
|
|
translated += " #Deutschland #German #InstaGerman #ContentCreation" |
|
|
|
|
|
return f"๐ฉ๐ช GERMAN VERSION (Fallback):\n{translated}" |
|
|
|
|
|
def get_fallback_chinese_translation(self, text: str) -> str: |
|
|
"""Fallback Chinese translation when HF API fails""" |
|
|
|
|
|
chinese_translations = { |
|
|
"amazing": "ไปคไบบๆๅน็", |
|
|
"beautiful": "็พไธฝ็", |
|
|
"love": "็ฑ", |
|
|
"perfect": "ๅฎ็พ็", |
|
|
"awesome": "ๅคชๆฃไบ", |
|
|
"incredible": "ไธๅฏๆ่ฎฎ็", |
|
|
"follow": "ๅ
ณๆณจ", |
|
|
"like": "็น่ต", |
|
|
"share": "ๅไบซ", |
|
|
"comment": "่ฏ่ฎบ", |
|
|
"today": "ไปๅคฉ", |
|
|
"moment": "ๆถๅป", |
|
|
"life": "็ๆดป", |
|
|
"inspiration": "็ตๆ", |
|
|
"community": "็คพๅบ", |
|
|
"content": "ๅ
ๅฎน", |
|
|
"check out": "็็", |
|
|
"what do you think": "ไฝ ่งๅพๆไนๆ ท" |
|
|
} |
|
|
|
|
|
|
|
|
translated = text.lower() |
|
|
for english, chinese in chinese_translations.items(): |
|
|
translated = translated.replace(english, chinese) |
|
|
|
|
|
|
|
|
if "#" in translated: |
|
|
translated += " #ไธญๅฝ #ไธญๆ #็คพไบคๅชไฝ #ๅ
ๅฎนๅไฝ" |
|
|
|
|
|
return f"๐จ๐ณ CHINESE VERSION (Fallback):\n{translated}" |
|
|
|
|
|
def get_fallback_hindi_translation(self, text: str) -> str: |
|
|
"""Fallback Hindi translation when HF API fails""" |
|
|
|
|
|
hindi_translations = { |
|
|
"amazing": "เค
เคฆเฅเคญเฅเคค", |
|
|
"beautiful": "เคธเฅเคเคฆเคฐ", |
|
|
"love": "เคชเฅเคฐเฅเคฎ", |
|
|
"perfect": "เคชเคฐเคซเฅเคเฅเค", |
|
|
"awesome": "เคถเคพเคจเคฆเคพเคฐ", |
|
|
"incredible": "เค
เคตเคฟเคถเฅเคตเคธเคจเฅเคฏ", |
|
|
"follow": "เคซเฅเคฒเฅ", |
|
|
"like": "เคฒเคพเคเค", |
|
|
"share": "เคถเฅเคฏเคฐ", |
|
|
"comment": "เคเคฎเฅเคเค", |
|
|
"today": "เคเค", |
|
|
"moment": "เคชเคฒ", |
|
|
"life": "เคเคฟเคเคฆเคเฅ", |
|
|
"inspiration": "เคชเฅเคฐเฅเคฐเคฃเคพ", |
|
|
"community": "เคธเคฎเฅเคฆเคพเคฏ", |
|
|
"content": "เคธเคพเคฎเคเฅเคฐเฅ", |
|
|
"check out": "เคฆเฅเคเฅเค", |
|
|
"what do you think": "เคเคชเคเฅ เคเฅเคฏเคพ เคฒเคเคคเคพ เคนเฅ" |
|
|
} |
|
|
|
|
|
|
|
|
translated = text.lower() |
|
|
for english, hindi in hindi_translations.items(): |
|
|
translated = translated.replace(english, hindi) |
|
|
|
|
|
|
|
|
if "#" in translated: |
|
|
translated += " #เคญเคพเคฐเคค #เคนเคฟเคเคฆเฅ #เคธเฅเคถเคฒเคฎเฅเคกเคฟเคฏเคพ #เคเคเคเฅเคเค" |
|
|
|
|
|
return f"๐ฎ๐ณ HINDI VERSION (Fallback):\n{translated}" |
|
|
|
|
|
def get_fallback_arabic_translation(self, text: str) -> str: |
|
|
"""Fallback Arabic translation when HF API fails""" |
|
|
|
|
|
arabic_translations = { |
|
|
"amazing": "ู
ุฐูู", |
|
|
"beautiful": "ุฌู
ูู", |
|
|
"love": "ุญุจ", |
|
|
"perfect": "ู
ุซุงูู", |
|
|
"awesome": "ุฑุงุฆุน", |
|
|
"incredible": "ูุง ูุตุฏู", |
|
|
"follow": "ู
ุชุงุจุนุฉ", |
|
|
"like": "ุฅุนุฌุงุจ", |
|
|
"share": "ู
ุดุงุฑูุฉ", |
|
|
"comment": "ุชุนููู", |
|
|
"today": "ุงูููู
", |
|
|
"moment": "ูุญุธุฉ", |
|
|
"life": "ุญูุงุฉ", |
|
|
"inspiration": "ุฅููุงู
", |
|
|
"community": "ู
ุฌุชู
ุน", |
|
|
"content": "ู
ุญุชูู", |
|
|
"check out": "ุชุญูู ู
ู", |
|
|
"what do you think": "ู
ุง ุฑุฃูู" |
|
|
} |
|
|
|
|
|
|
|
|
translated = text.lower() |
|
|
for english, arabic in arabic_translations.items(): |
|
|
translated = translated.replace(english, arabic) |
|
|
|
|
|
|
|
|
if "#" in translated: |
|
|
translated += " #ุงูุนุฑุจูุฉ #ูุณุงุฆู_ุงูุชูุงุตู #ุฅุจุฏุงุน_ุงูู
ุญุชูู #ู
ุฌุชู
ุน" |
|
|
|
|
|
return f"๐ธ๐ฆ ARABIC VERSION (Fallback):\n{translated}" |
|
|
|
|
|
def setup_trend_analysis(self): |
|
|
"""Initialize basic trend analysis""" |
|
|
self.trending_cache = {} |
|
|
self.last_trend_update = datetime.now() - timedelta(hours=1) |
|
|
|
|
|
def get_trending_hashtags(self, category: str = "general") -> List[TrendData]: |
|
|
"""Get trending hashtags for a category (using mock data)""" |
|
|
try: |
|
|
|
|
|
trending_data = [ |
|
|
TrendData( |
|
|
hashtags=["#AIGenerated", "#TechInnovation", "#FutureNow", "#DigitalArt"], |
|
|
engagement_score=0.92, |
|
|
category="tech", |
|
|
timestamp=datetime.now() |
|
|
), |
|
|
TrendData( |
|
|
hashtags=["#SustainableLiving", "#EcoFriendly", "#GreenTech", "#ClimateAction"], |
|
|
engagement_score=0.87, |
|
|
category="lifestyle", |
|
|
timestamp=datetime.now() |
|
|
), |
|
|
TrendData( |
|
|
hashtags=["#WorkFromHome", "#ProductivityHacks", "#RemoteWork", "#DigitalNomad"], |
|
|
engagement_score=0.85, |
|
|
category="business", |
|
|
timestamp=datetime.now() |
|
|
) |
|
|
] |
|
|
|
|
|
self.trending_cache[category] = trending_data |
|
|
self.last_trend_update = datetime.now() |
|
|
return trending_data |
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Trend analysis error: {e}") |
|
|
return [] |
|
|
|
|
|
def analyze_image_advanced(self, image: Image.Image) -> Dict[str, Any]: |
|
|
"""Advanced image analysis with quality scoring""" |
|
|
analysis = { |
|
|
"objects": [], |
|
|
"colors": [], |
|
|
"mood": "", |
|
|
"composition": "", |
|
|
"quality_score": 0.0, |
|
|
"suggestions": [] |
|
|
} |
|
|
|
|
|
try: |
|
|
|
|
|
analysis["size"] = image.size |
|
|
analysis["format"] = image.format |
|
|
|
|
|
|
|
|
colors = image.getcolors(maxcolors=256*256*256) |
|
|
if colors: |
|
|
dominant_colors = sorted(colors, key=lambda x: x[0], reverse=True)[:5] |
|
|
analysis["colors"] = [f"RGB{color[1]}" for color in dominant_colors] |
|
|
|
|
|
|
|
|
analysis["quality_score"] = self.calculate_realistic_image_quality(image) |
|
|
|
|
|
|
|
|
analysis["suggestions"] = self.get_composition_suggestions(image) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Image analysis error: {e}") |
|
|
|
|
|
return analysis |
|
|
|
|
|
def calculate_realistic_image_quality(self, image: Image.Image) -> float: |
|
|
"""Calculate realistic image quality score with variance""" |
|
|
try: |
|
|
|
|
|
if image.mode != 'RGB': |
|
|
image = image.convert('RGB') |
|
|
|
|
|
width, height = image.size |
|
|
|
|
|
|
|
|
resolution_score = min(0.9, (width * height) / (1920 * 1080)) |
|
|
|
|
|
|
|
|
aspect_ratio = width / height |
|
|
aspect_bonus = 0.1 if 0.8 <= aspect_ratio <= 1.25 else 0.0 |
|
|
|
|
|
|
|
|
size_penalty = 0.0 |
|
|
if width < 500 or height < 500: |
|
|
size_penalty = 0.2 |
|
|
|
|
|
|
|
|
variance = random.uniform(-0.1, 0.1) |
|
|
|
|
|
final_score = max(0.3, min(0.95, resolution_score + aspect_bonus - size_penalty + variance)) |
|
|
return final_score |
|
|
|
|
|
except Exception as e: |
|
|
return random.uniform(0.5, 0.8) |
|
|
|
|
|
def get_composition_suggestions(self, image: Image.Image) -> List[str]: |
|
|
"""Get composition improvement suggestions""" |
|
|
suggestions = [] |
|
|
width, height = image.size |
|
|
|
|
|
|
|
|
ratio = width / height |
|
|
if 0.8 <= ratio <= 1.25: |
|
|
suggestions.append("โ
Great square format for Instagram feed") |
|
|
elif ratio > 1.25: |
|
|
suggestions.append("๐ฑ Consider cropping to square for better feed display") |
|
|
else: |
|
|
suggestions.append("๐ธ Perfect for Instagram Stories format") |
|
|
|
|
|
|
|
|
if width < 1080 or height < 1080: |
|
|
suggestions.append("๐ Consider higher resolution for better quality") |
|
|
|
|
|
return suggestions |
|
|
|
|
|
async def analyze_caption_performance(self, caption: str) -> AnalyticsData: |
|
|
"""Advanced caption performance analysis with realistic metrics""" |
|
|
analytics = AnalyticsData( |
|
|
readability_score=0.0, |
|
|
engagement_prediction=0.0, |
|
|
sentiment_score=0.0, |
|
|
hashtag_effectiveness={}, |
|
|
best_posting_time="" |
|
|
) |
|
|
|
|
|
try: |
|
|
|
|
|
try: |
|
|
blob = TextBlob(caption) |
|
|
sentence_count = len(blob.sentences) |
|
|
word_count = len(blob.words) |
|
|
|
|
|
|
|
|
if word_count < 20: |
|
|
analytics.readability_score = random.uniform(0.6, 0.8) |
|
|
elif word_count < 50: |
|
|
analytics.readability_score = random.uniform(0.7, 0.9) |
|
|
else: |
|
|
analytics.readability_score = random.uniform(0.5, 0.7) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ TextBlob analysis error: {e}") |
|
|
analytics.readability_score = random.uniform(0.6, 0.8) |
|
|
|
|
|
|
|
|
try: |
|
|
positive_words = ["amazing", "awesome", "love", "great", "fantastic", "beautiful", "perfect"] |
|
|
negative_words = ["bad", "terrible", "awful", "hate", "horrible", "worst"] |
|
|
|
|
|
caption_lower = caption.lower() |
|
|
positive_count = sum(1 for word in positive_words if word in caption_lower) |
|
|
negative_count = sum(1 for word in negative_words if word in caption_lower) |
|
|
|
|
|
if positive_count > negative_count: |
|
|
analytics.sentiment_score = random.uniform(0.7, 0.9) |
|
|
elif negative_count > positive_count: |
|
|
analytics.sentiment_score = random.uniform(0.3, 0.5) |
|
|
else: |
|
|
analytics.sentiment_score = random.uniform(0.5, 0.7) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Sentiment analysis error: {e}") |
|
|
analytics.sentiment_score = random.uniform(0.6, 0.8) |
|
|
|
|
|
|
|
|
try: |
|
|
hashtags = re.findall(r'#\w+', caption) |
|
|
for hashtag in hashtags: |
|
|
|
|
|
effectiveness = random.uniform(0.4, 0.9) |
|
|
analytics.hashtag_effectiveness[hashtag] = effectiveness |
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Hashtag analysis error: {e}") |
|
|
|
|
|
|
|
|
try: |
|
|
hashtag_count = len(hashtags) if 'hashtags' in locals() else 0 |
|
|
factors = [ |
|
|
min(0.3, hashtag_count * 0.02), |
|
|
analytics.sentiment_score * 0.3, |
|
|
analytics.readability_score * 0.2, |
|
|
random.uniform(0.1, 0.3) |
|
|
] |
|
|
analytics.engagement_prediction = min(0.95, max(0.3, sum(factors))) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Engagement prediction error: {e}") |
|
|
analytics.engagement_prediction = random.uniform(0.6, 0.8) |
|
|
|
|
|
|
|
|
analytics.best_posting_time = "6-9 PM weekdays, 12-3 PM weekends" |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Analytics error: {e}") |
|
|
|
|
|
analytics.readability_score = random.uniform(0.6, 0.8) |
|
|
analytics.engagement_prediction = random.uniform(0.6, 0.9) |
|
|
analytics.sentiment_score = random.uniform(0.6, 0.8) |
|
|
analytics.best_posting_time = "Peak hours: 6-9 PM" |
|
|
|
|
|
return analytics |
|
|
|
|
|
async def generate_text_with_sambanova(self, prompt: str, image_url: str = None) -> str: |
|
|
"""Generate text using SambaNova API""" |
|
|
try: |
|
|
if not self.sambanova_client or not getattr(self, 'sambanova_client_working', False): |
|
|
print("โ ๏ธ SambaNova client not available or not working, using fallback") |
|
|
return self.generate_fallback_caption(prompt) |
|
|
|
|
|
print("๐ Generating text with SambaNova...") |
|
|
|
|
|
|
|
|
messages = [] |
|
|
|
|
|
if image_url: |
|
|
|
|
|
user_content = [ |
|
|
{ |
|
|
"type": "text", |
|
|
"text": prompt |
|
|
}, |
|
|
{ |
|
|
"type": "image_url", |
|
|
"image_url": { |
|
|
"url": image_url |
|
|
} |
|
|
} |
|
|
] |
|
|
else: |
|
|
|
|
|
user_content = [ |
|
|
{ |
|
|
"type": "text", |
|
|
"text": prompt |
|
|
} |
|
|
] |
|
|
|
|
|
messages.append({ |
|
|
"role": "user", |
|
|
"content": user_content |
|
|
}) |
|
|
|
|
|
|
|
|
response = self.sambanova_client.chat.completions.create( |
|
|
model=self.primary_model, |
|
|
messages=messages, |
|
|
temperature=0.1, |
|
|
top_p=0.1 |
|
|
) |
|
|
|
|
|
if response and response.choices and len(response.choices) > 0: |
|
|
result = response.choices[0].message.content |
|
|
|
|
|
if result and len(result.strip()) > 20: |
|
|
print("โ
SambaNova generation successful") |
|
|
return result |
|
|
else: |
|
|
print("โ ๏ธ Poor response from SambaNova model, using fallback") |
|
|
return self.generate_fallback_caption(prompt) |
|
|
else: |
|
|
print("โ ๏ธ Empty response from SambaNova, using fallback") |
|
|
return self.generate_fallback_caption(prompt) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ SambaNova generation error: {e}") |
|
|
return self.generate_fallback_caption(prompt) |
|
|
|
|
|
def generate_fallback_caption(self, prompt: str) -> str: |
|
|
"""Generate a high-quality fallback caption when AI models fail""" |
|
|
|
|
|
|
|
|
style = "Engaging" |
|
|
audience = "General" |
|
|
|
|
|
if "viral" in prompt.lower(): |
|
|
style = "Viral" |
|
|
elif "professional" in prompt.lower(): |
|
|
style = "Professional" |
|
|
elif "casual" in prompt.lower(): |
|
|
style = "Casual" |
|
|
elif "motivational" in prompt.lower(): |
|
|
style = "Motivational" |
|
|
elif "humor" in prompt.lower(): |
|
|
style = "Humorous" |
|
|
|
|
|
if "business" in prompt.lower(): |
|
|
audience = "Business" |
|
|
elif "tech" in prompt.lower(): |
|
|
audience = "Tech" |
|
|
elif "food" in prompt.lower(): |
|
|
audience = "Food" |
|
|
elif "travel" in prompt.lower(): |
|
|
audience = "Travel" |
|
|
elif "fitness" in prompt.lower(): |
|
|
audience = "Fitness" |
|
|
|
|
|
|
|
|
caption_templates = { |
|
|
"Viral": { |
|
|
"opening": "๐ฅ This is exactly what everyone needs to see! ", |
|
|
"middle": "The energy here is absolutely incredible and I can't get enough of it. ", |
|
|
"cta": "๐ฌ TAG someone who needs to see this!", |
|
|
"hashtags": ["#Viral", "#Trending", "#MustSee", "#Incredible", "#ShareThis"] |
|
|
}, |
|
|
"Professional": { |
|
|
"opening": "๐ผ Excellence in action. ", |
|
|
"middle": "This represents the quality and dedication we bring to everything we do. ", |
|
|
"cta": "๐ Let's connect and discuss opportunities.", |
|
|
"hashtags": ["#Professional", "#Excellence", "#Quality", "#Business", "#Success"] |
|
|
}, |
|
|
"Casual": { |
|
|
"opening": "๐ Just sharing some good vibes! ", |
|
|
"middle": "Sometimes it's the simple moments that make the biggest difference. ", |
|
|
"cta": "๐ญ What's making you smile today?", |
|
|
"hashtags": ["#GoodVibes", "#SimpleJoys", "#Lifestyle", "#Mood", "#Happiness"] |
|
|
}, |
|
|
"Motivational": { |
|
|
"opening": "๐ช Every step forward is progress! ", |
|
|
"middle": "Remember that growth happens outside your comfort zone. Keep pushing boundaries! ", |
|
|
"cta": "๐ What's your next big goal?", |
|
|
"hashtags": ["#Motivation", "#Growth", "#Progress", "#Goals", "#Success"] |
|
|
}, |
|
|
"Humorous": { |
|
|
"opening": "๐ When life gives you moments like this... ", |
|
|
"middle": "You just have to laugh and enjoy the ride! ", |
|
|
"cta": "๐คฃ Can you relate to this?", |
|
|
"hashtags": ["#Funny", "#Humor", "#Relatable", "#Laughs", "#GoodTimes"] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
audience_hashtags = { |
|
|
"Business": ["#BusinessLife", "#Entrepreneur", "#Leadership", "#Innovation"], |
|
|
"Tech": ["#Technology", "#Innovation", "#DigitalLife", "#TechTrends"], |
|
|
"Food": ["#Foodie", "#Delicious", "#Yummy", "#FoodLover"], |
|
|
"Travel": ["#Travel", "#Adventure", "#Wanderlust", "#Explore"], |
|
|
"Fitness": ["#Fitness", "#Health", "#Workout", "#Strong"], |
|
|
"General": ["#Life", "#Inspiration", "#Community", "#Content"] |
|
|
} |
|
|
|
|
|
|
|
|
template = caption_templates.get(style, caption_templates["Viral"]) |
|
|
|
|
|
caption_parts = [] |
|
|
caption_parts.append(template["opening"]) |
|
|
caption_parts.append(template["middle"]) |
|
|
caption_parts.append(f"\n\n{template['cta']}") |
|
|
|
|
|
|
|
|
all_hashtags = template["hashtags"] + audience_hashtags.get(audience, audience_hashtags["General"]) |
|
|
all_hashtags.extend(["#ContentCreation", "#SocialMedia", "#Engagement", "#Community", "#Inspiration"]) |
|
|
|
|
|
|
|
|
hashtag_text = " ".join(all_hashtags[:25]) |
|
|
caption_parts.append(f"\n\n{hashtag_text}") |
|
|
|
|
|
|
|
|
caption_parts.append("\n\nโจ Created with AI-powered optimization") |
|
|
|
|
|
return ''.join(caption_parts) |
|
|
|
|
|
async def generate_mistral_variations(self, base_caption: str, count: int = 3) -> List[str]: |
|
|
"""Generate caption variations using Meta-Llama-3.2-3B-Instruct""" |
|
|
variations = [] |
|
|
|
|
|
|
|
|
if not self.sambanova_client: |
|
|
print("โ ๏ธ SambaNova client not available for Llama variations, using fallback") |
|
|
for i in range(count): |
|
|
fallback_variation = self.create_simple_variation(base_caption, i+1) |
|
|
variations.append(f"{fallback_variation}\n\nโจ Generated by Fallback Method (SambaNova unavailable)") |
|
|
return variations |
|
|
|
|
|
|
|
|
variation_styles = [ |
|
|
"Make this caption more energetic and exciting with different emojis", |
|
|
"Create a more casual and friendly version of this caption", |
|
|
"Write a shorter, punchier version that's more direct" |
|
|
] |
|
|
|
|
|
for i in range(count): |
|
|
try: |
|
|
|
|
|
variation_prompt = f"""You are creating Instagram caption variations. {variation_styles[i]}. |
|
|
|
|
|
Original caption: |
|
|
{base_caption} |
|
|
|
|
|
Instructions: |
|
|
- Keep the same hashtags but rearrange them |
|
|
- Change the wording while keeping the same message |
|
|
- Use different emojis and expressions |
|
|
- Don't explain your changes |
|
|
- Only output the new caption, nothing else |
|
|
|
|
|
New caption:""" |
|
|
|
|
|
print(f"๐ Generating Llama-3.2 variation {i+1}...") |
|
|
|
|
|
|
|
|
response = self.sambanova_client.chat.completions.create( |
|
|
model=self.variation_model, |
|
|
messages=[ |
|
|
{"role": "system", "content": "You are a helpful Instagram caption writer. Only output the caption, no explanations."}, |
|
|
{"role": "user", "content": variation_prompt} |
|
|
], |
|
|
temperature=0.9, |
|
|
top_p=0.95, |
|
|
max_tokens=200 |
|
|
) |
|
|
|
|
|
if response and response.choices and len(response.choices) > 0: |
|
|
result = response.choices[0].message.content.strip() |
|
|
|
|
|
|
|
|
lines = result.split('\n') |
|
|
clean_result = [] |
|
|
|
|
|
for line in lines: |
|
|
line = line.strip() |
|
|
|
|
|
if (line and |
|
|
not line.startswith('This variation') and |
|
|
not line.startswith('- ') and |
|
|
not line.startswith('The ') and |
|
|
not 'maintains the same' in line.lower() and |
|
|
not 'variation' in line.lower()): |
|
|
clean_result.append(line) |
|
|
|
|
|
final_result = '\n'.join(clean_result).strip() |
|
|
|
|
|
if final_result and len(final_result.strip()) > 20: |
|
|
variations.append(f"{final_result}\n\nโจ Generated by Meta-Llama-3.2-3B-Instruct") |
|
|
print(f"โ
Llama-3.2 variation {i+1} generated successfully") |
|
|
else: |
|
|
print(f"โ ๏ธ Poor response from Llama-3.2 for variation {i+1}, using fallback") |
|
|
fallback_variation = self.create_simple_variation(base_caption, i+1) |
|
|
variations.append(f"{fallback_variation}\n\nโจ Generated by Fallback Method (Poor response)") |
|
|
else: |
|
|
print(f"โ ๏ธ Empty response from Llama-3.2 for variation {i+1}, using fallback") |
|
|
fallback_variation = self.create_simple_variation(base_caption, i+1) |
|
|
variations.append(f"{fallback_variation}\n\nโจ Generated by Fallback Method (Empty response)") |
|
|
|
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Error generating Llama-3.2 variation {i+1}: {e}") |
|
|
|
|
|
fallback_variation = self.create_simple_variation(base_caption, i+1) |
|
|
variations.append(f"{fallback_variation}\n\nโจ Generated by Fallback Method (Error: {str(e)[:50]})") |
|
|
|
|
|
return variations |
|
|
|
|
|
def create_simple_variation(self, base_caption: str, variation_num: int) -> str: |
|
|
"""Create a simple variation when Mistral fails""" |
|
|
|
|
|
|
|
|
if variation_num == 1: |
|
|
|
|
|
modified = base_caption.replace("This is", "Here's").replace("Check out", "Take a look at") |
|
|
modified = modified.replace("Amazing", "Incredible").replace("Love", "Absolutely adore") |
|
|
modified = modified.replace("Can't wait", "So excited").replace("Let me know", "Tell me") |
|
|
return modified |
|
|
|
|
|
elif variation_num == 2: |
|
|
|
|
|
modified = base_caption.replace("!", " โจ").replace(".", "! ") |
|
|
modified = modified.replace("Great", "Fantastic").replace("Beautiful", "Stunning") |
|
|
modified = modified.replace("Perfect", "Absolutely perfect").replace("Share", "Don't forget to share") |
|
|
return modified |
|
|
|
|
|
else: |
|
|
|
|
|
modified = base_caption.replace("๐ฅ", "๐ซ").replace("Follow", "Join me") |
|
|
modified = modified.replace("Comment", "Share your thoughts").replace("Tag", "Make sure to tag") |
|
|
modified = modified.replace("What do you think", "I'd love to hear your thoughts") |
|
|
return modified |
|
|
|
|
|
async def generate_advanced_caption(self, images: List[Image.Image], style: str, |
|
|
audience: str, custom_prompt: str = "") -> str: |
|
|
"""Generate advanced caption with SambaNova integration""" |
|
|
if not images: |
|
|
return "โ Please upload at least one image for analysis." |
|
|
|
|
|
try: |
|
|
|
|
|
image_analyses = [] |
|
|
for i, image in enumerate(images[:3]): |
|
|
analysis = self.analyze_image_advanced(image) |
|
|
image_analyses.append(analysis) |
|
|
|
|
|
|
|
|
enhanced_prompt = self.build_enhanced_prompt( |
|
|
image_analyses, style, audience, custom_prompt |
|
|
) |
|
|
|
|
|
|
|
|
image_url = None |
|
|
if images and len(images) > 0: |
|
|
try: |
|
|
buffer = io.BytesIO() |
|
|
images[0].save(buffer, format="JPEG", quality=85) |
|
|
image_base64 = base64.b64encode(buffer.getvalue()).decode() |
|
|
image_url = f"data:image/jpeg;base64,{image_base64}" |
|
|
except Exception as e: |
|
|
print(f"โ ๏ธ Error converting image: {e}") |
|
|
image_url = None |
|
|
|
|
|
|
|
|
base_caption = await self.generate_text_with_sambanova(enhanced_prompt, image_url) |
|
|
|
|
|
|
|
|
gc.collect() |
|
|
|
|
|
|
|
|
result = f"""โจ AI-GENERATED INSTAGRAM CONTENT: |
|
|
|
|
|
{base_caption} |
|
|
|
|
|
๐ค Powered by SambaNova Llama-4-Maverick |
|
|
""" |
|
|
|
|
|
|
|
|
self.performance_cache[datetime.now().isoformat()] = { |
|
|
"caption": base_caption, |
|
|
"images_analyzed": len(images) |
|
|
} |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
return f"โ Advanced generation error: {str(e)}" |
|
|
|
|
|
def build_enhanced_prompt(self, image_analyses: List[Dict], style: str, |
|
|
audience: str, custom_prompt: str) -> str: |
|
|
"""Build enhanced prompt with image analysis data""" |
|
|
|
|
|
|
|
|
image_summary = "\n".join([ |
|
|
f"Image {i+1}: Visual content detected, " |
|
|
f"Quality: {analysis.get('quality_score', 0.5):.1f}/1.0, " |
|
|
f"Colors: {', '.join(analysis.get('colors', [])[:3])}" |
|
|
for i, analysis in enumerate(image_analyses) |
|
|
]) |
|
|
|
|
|
return f"""Create an engaging Instagram caption for the following content: |
|
|
|
|
|
STYLE: {style} |
|
|
AUDIENCE: {audience} |
|
|
{f"SPECIAL REQUIREMENTS: {custom_prompt}" if custom_prompt else ""} |
|
|
|
|
|
IMAGE CONTENT: |
|
|
{image_summary} |
|
|
|
|
|
Create a {style.lower()} caption that: |
|
|
1. Captures attention in the first line |
|
|
2. Tells a compelling story |
|
|
3. Includes 15-25 relevant hashtags |
|
|
4. Has a clear call-to-action |
|
|
5. Uses appropriate emojis |
|
|
6. Is optimized for {audience.lower()} audience |
|
|
|
|
|
Format: |
|
|
[Main caption with emojis and storytelling] |
|
|
|
|
|
[Call-to-action] |
|
|
|
|
|
[Hashtags]""" |
|
|
|
|
|
|
|
|
|
|
|
@functools.lru_cache(maxsize=1) |
|
|
def get_generator(): |
|
|
"""Get cached generator instance""" |
|
|
return AdvancedInstagramGenerator() |
|
|
|
|
|
try: |
|
|
generator = get_generator() |
|
|
setup_success = True |
|
|
setup_error = "" |
|
|
except Exception as e: |
|
|
generator = None |
|
|
setup_success = False |
|
|
setup_error = str(e) |
|
|
print(f"โ Setup failed: {e}") |
|
|
|
|
|
|
|
|
|
|
|
async def generate_advanced_caption_interface(uploaded_files, style, audience, |
|
|
custom_prompt): |
|
|
"""Advanced interface function for caption generation""" |
|
|
if not setup_success: |
|
|
return f"โ Setup Error: {setup_error}", "" |
|
|
|
|
|
images = [] |
|
|
if uploaded_files: |
|
|
for file in uploaded_files[:3]: |
|
|
try: |
|
|
image = Image.open(file.name) |
|
|
images.append(image) |
|
|
except Exception as e: |
|
|
return f"โ Error processing file: {e}", "" |
|
|
|
|
|
result = await generator.generate_advanced_caption( |
|
|
images, style, audience, custom_prompt |
|
|
) |
|
|
|
|
|
|
|
|
caption_only = "" |
|
|
if "โจ AI-GENERATED INSTAGRAM CONTENT:" in result: |
|
|
lines = result.split('\n') |
|
|
caption_lines = [] |
|
|
start_capturing = False |
|
|
|
|
|
for line in lines: |
|
|
if "โจ AI-GENERATED INSTAGRAM CONTENT:" in line: |
|
|
start_capturing = True |
|
|
continue |
|
|
elif "๐ค Powered by SambaNova" in line: |
|
|
break |
|
|
elif start_capturing and line.strip(): |
|
|
caption_lines.append(line) |
|
|
|
|
|
caption_only = '\n'.join(caption_lines).strip() |
|
|
|
|
|
if not caption_only: |
|
|
caption_only = result |
|
|
|
|
|
return result, caption_only |
|
|
|
|
|
|
|
|
async def generate_multiple_captions_interface(uploaded_files, style, audience, |
|
|
custom_prompt): |
|
|
"""Generate multiple caption variations using Meta-Llama-3.2-3B-Instruct""" |
|
|
if not setup_success: |
|
|
return f"โ Setup Error: {setup_error}" |
|
|
|
|
|
images = [] |
|
|
if uploaded_files: |
|
|
for file in uploaded_files[:3]: |
|
|
try: |
|
|
image = Image.open(file.name) |
|
|
images.append(image) |
|
|
except Exception as e: |
|
|
return f"โ Error processing file: {e}" |
|
|
|
|
|
if not images: |
|
|
return "โ Please upload at least one image to generate caption variations." |
|
|
|
|
|
|
|
|
main_result = await generator.generate_advanced_caption( |
|
|
images, style, audience, custom_prompt |
|
|
) |
|
|
|
|
|
|
|
|
base_caption = "" |
|
|
if "โจ AI-GENERATED INSTAGRAM CONTENT:" in main_result: |
|
|
lines = main_result.split('\n') |
|
|
caption_lines = [] |
|
|
start_capturing = False |
|
|
|
|
|
for line in lines: |
|
|
if "โจ AI-GENERATED INSTAGRAM CONTENT:" in line: |
|
|
start_capturing = True |
|
|
continue |
|
|
elif "๐ค Powered by SambaNova" in line: |
|
|
break |
|
|
elif start_capturing and line.strip(): |
|
|
caption_lines.append(line) |
|
|
|
|
|
base_caption = '\n'.join(caption_lines).strip() |
|
|
|
|
|
if not base_caption: |
|
|
return "โ Failed to generate base caption for variations" |
|
|
|
|
|
|
|
|
variations = await generator.generate_mistral_variations(base_caption, count=3) |
|
|
|
|
|
|
|
|
formatted_result = "โจ ALTERNATIVE CAPTIONS:\n\n" |
|
|
formatted_result += "=" * 60 + "\n\n" |
|
|
|
|
|
for i, variation in enumerate(variations, 1): |
|
|
formatted_result += f"๐ ALTERNATIVE {i}:\n" |
|
|
formatted_result += f"{variation}\n" |
|
|
formatted_result += "=" * 60 + "\n\n" |
|
|
|
|
|
return formatted_result |
|
|
|
|
|
|
|
|
async def translate_caption_interface(base_caption, selected_languages): |
|
|
"""Generate multi-language versions of captions""" |
|
|
if not base_caption.strip(): |
|
|
return "โ Please provide a caption to translate" |
|
|
|
|
|
if not selected_languages: |
|
|
return "โ Please select at least one language" |
|
|
|
|
|
result = "๐ MULTI-LANGUAGE CAPTION VERSIONS:\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
|
|
|
for language in selected_languages: |
|
|
if language == "๐ฉ๐ช German": |
|
|
|
|
|
if generator and generator.hf_client_working: |
|
|
try: |
|
|
german_translation = await generator.translate_to_german(base_caption) |
|
|
result += "๐ฉ๐ช GERMAN VERSION (Hugging Face T5):\n" |
|
|
result += f"{german_translation}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
except Exception as e: |
|
|
fallback_german = generator.get_fallback_german_translation(base_caption) |
|
|
result += f"{fallback_german}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
else: |
|
|
fallback_german = generator.get_fallback_german_translation(base_caption) |
|
|
result += f"{fallback_german}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
|
|
|
elif language == "๐จ๐ณ Chinese": |
|
|
|
|
|
if generator and generator.hf_client_working: |
|
|
try: |
|
|
chinese_translation = await generator.translate_to_chinese(base_caption) |
|
|
result += "๐จ๐ณ CHINESE VERSION (Hugging Face MT5):\n" |
|
|
result += f"{chinese_translation}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
except Exception as e: |
|
|
fallback_chinese = generator.get_fallback_chinese_translation(base_caption) |
|
|
result += f"{fallback_chinese}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
else: |
|
|
fallback_chinese = generator.get_fallback_chinese_translation(base_caption) |
|
|
result += f"{fallback_chinese}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
|
|
|
elif language == "๐ฎ๐ณ Hindi": |
|
|
|
|
|
if generator and generator.hf_client_working: |
|
|
try: |
|
|
hindi_translation = await generator.translate_to_hindi(base_caption) |
|
|
result += "๐ฎ๐ณ HINDI VERSION (Hugging Face Helsinki-NLP):\n" |
|
|
result += f"{hindi_translation}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
except Exception as e: |
|
|
fallback_hindi = generator.get_fallback_hindi_translation(base_caption) |
|
|
result += f"{fallback_hindi}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
else: |
|
|
fallback_hindi = generator.get_fallback_hindi_translation(base_caption) |
|
|
result += f"{fallback_hindi}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
|
|
|
elif language == "๐ธ๐ฆ Arabic": |
|
|
|
|
|
if generator and generator.hf_client_working: |
|
|
try: |
|
|
arabic_translation = await generator.translate_to_arabic(base_caption) |
|
|
result += "๐ธ๐ฆ ARABIC VERSION (Hugging Face Marefa):\n" |
|
|
result += f"{arabic_translation}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
except Exception as e: |
|
|
fallback_arabic = generator.get_fallback_arabic_translation(base_caption) |
|
|
result += f"{fallback_arabic}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
else: |
|
|
fallback_arabic = generator.get_fallback_arabic_translation(base_caption) |
|
|
result += f"{fallback_arabic}\n\n" |
|
|
result += "=" * 60 + "\n\n" |
|
|
|
|
|
if any(lang in selected_languages for lang in ["๐ฉ๐ช German", "๐จ๐ณ Chinese", "๐ฎ๐ณ Hindi", "๐ธ๐ฆ Arabic"]): |
|
|
hf_langs = [] |
|
|
if "๐ฉ๐ช German" in selected_languages: |
|
|
hf_langs.append("German (T5)") |
|
|
if "๐จ๐ณ Chinese" in selected_languages: |
|
|
hf_langs.append("Chinese (MT5)") |
|
|
if "๐ฎ๐ณ Hindi" in selected_languages: |
|
|
hf_langs.append("Hindi (Helsinki-NLP)") |
|
|
if "๐ธ๐ฆ Arabic" in selected_languages: |
|
|
hf_langs.append("Arabic (Marefa)") |
|
|
|
|
|
result += f"๐ Note: {', '.join(hf_langs)} powered by Hugging Face models. Other languages use sample translations." |
|
|
else: |
|
|
result += "๐ Note: These are sample translations. Select German/Chinese/Hindi/Arabic to use Hugging Face translation models." |
|
|
|
|
|
return result |
|
|
|
|
|
|
|
|
def create_gradio_app(): |
|
|
"""Create the Gradio app with SambaNova and Hugging Face integration""" |
|
|
|
|
|
|
|
|
hf_status = "โ
Connected" if generator and generator.hf_client_working else "โ ๏ธ Fallback Mode" |
|
|
sambanova_status = "โ
Connected" if generator and generator.sambanova_client_working else "โ ๏ธ Fallback Mode" |
|
|
|
|
|
|
|
|
css = """ |
|
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap'); |
|
|
|
|
|
.gradio-container { |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #4facfe 100%); |
|
|
font-family: 'Space Grotesk', 'Inter', system-ui, sans-serif; |
|
|
min-height: 100vh; |
|
|
position: relative; |
|
|
overflow-x: hidden; |
|
|
} |
|
|
|
|
|
.gradio-container::before { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
top: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
bottom: 0; |
|
|
background: radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%), |
|
|
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%); |
|
|
pointer-events: none; |
|
|
z-index: 1; |
|
|
} |
|
|
|
|
|
.main-header { |
|
|
text-align: center; |
|
|
color: white; |
|
|
margin-bottom: 40px; |
|
|
padding: 40px; |
|
|
background: rgba(255,255,255,0.1); |
|
|
border-radius: 30px; |
|
|
backdrop-filter: blur(30px); |
|
|
border: 2px solid rgba(255,255,255,0.2); |
|
|
box-shadow: 0 25px 50px rgba(0,0,0,0.1); |
|
|
position: relative; |
|
|
z-index: 2; |
|
|
animation: float 6s ease-in-out infinite; |
|
|
} |
|
|
|
|
|
@keyframes float { |
|
|
0%, 100% { transform: translateY(0px); } |
|
|
50% { transform: translateY(-10px); } |
|
|
} |
|
|
|
|
|
.feature-card { |
|
|
background: rgba(255,255,255,0.15); |
|
|
border-radius: 25px; |
|
|
padding: 30px; |
|
|
backdrop-filter: blur(20px); |
|
|
border: 1px solid rgba(255,255,255,0.3); |
|
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1); |
|
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); |
|
|
position: relative; |
|
|
z-index: 2; |
|
|
} |
|
|
|
|
|
.gradio-button-primary { |
|
|
background: linear-gradient(45deg, #ff6b6b, #ee5a24, #ff9ff3, #54a0ff) !important; |
|
|
background-size: 300% 300% !important; |
|
|
animation: gradient-shift 4s ease infinite !important; |
|
|
border: none !important; |
|
|
border-radius: 20px !important; |
|
|
padding: 18px 35px !important; |
|
|
font-weight: 700 !important; |
|
|
text-transform: uppercase !important; |
|
|
letter-spacing: 2px !important; |
|
|
box-shadow: 0 15px 35px rgba(255, 107, 107, 0.4) !important; |
|
|
transition: all 0.3s ease !important; |
|
|
position: relative !important; |
|
|
overflow: hidden !important; |
|
|
} |
|
|
|
|
|
@keyframes gradient-shift { |
|
|
0% { background-position: 0% 50%; } |
|
|
50% { background-position: 100% 50%; } |
|
|
100% { background-position: 0% 50%; } |
|
|
} |
|
|
|
|
|
.sambanova-status { |
|
|
background: linear-gradient(90deg, #2ecc71, #27ae60); |
|
|
color: white; |
|
|
padding: 15px 25px; |
|
|
border-radius: 15px; |
|
|
text-align: center; |
|
|
font-weight: 600; |
|
|
box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3); |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
|
|
|
@keyframes pulse { |
|
|
0% { box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3); } |
|
|
50% { box-shadow: 0 15px 30px rgba(46, 204, 113, 0.5); } |
|
|
100% { box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3); } |
|
|
} |
|
|
""" |
|
|
|
|
|
with gr.Blocks(css=css, title="๐ฑ Instagram Generator - GRADIO AGENTS & MCP HACKATHON 2025", theme=gr.themes.Glass()) as app: |
|
|
|
|
|
|
|
|
gr.HTML(""" |
|
|
<div class="main-header"> |
|
|
<h1 style="font-size: 3rem; margin-bottom: 15px; font-weight: 800; background: linear-gradient(45deg, #ff6b6b, #feca57, #ff9ff3, #54a0ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent;"> |
|
|
๐ฑ INSTAGRAM CAPTION GENERATOR |
|
|
</h1> |
|
|
<h2 style="font-size: 1.4rem; margin-bottom: 20px; opacity: 0.9; font-weight: 500;"> |
|
|
๐ GRADIO AGENTS & MCP HACKATHON 2025 Submission โข SambaNova + Hugging Face Edition |
|
|
</h2> |
|
|
<div style="display: flex; justify-content: center; gap: 20px; margin-top: 25px;"> |
|
|
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; font-size: 0.9rem;">๐ค SambaNova AI</span> |
|
|
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; font-size: 0.9rem;">๐ Multi-Language</span> |
|
|
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; font-size: 0.9rem;">๐ MCP Server</span> |
|
|
</div> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
|
|
|
gr.HTML(f""" |
|
|
<div class="sambanova-status"> |
|
|
๐ SambaNova: {sambanova_status} โข ๐ค Hugging Face: {hf_status} โข |
|
|
</div> |
|
|
""") |
|
|
|
|
|
|
|
|
with gr.Tab("๐ฏ Advanced Caption Generator"): |
|
|
with gr.Row(): |
|
|
|
|
|
with gr.Column(scale=2, elem_classes=["feature-card"]): |
|
|
gr.Markdown("### ๐ผ๏ธ Multi-Image Upload & Analysis") |
|
|
gr.Markdown("*SambaNova AI vision analysis with quality scoring*") |
|
|
|
|
|
images = gr.File( |
|
|
label="๐ธ Upload Images (Max 3)", |
|
|
file_count="multiple", |
|
|
file_types=["image"] |
|
|
) |
|
|
|
|
|
gr.Markdown("### โ๏ธ AI Configuration") |
|
|
|
|
|
caption_style = gr.Radio( |
|
|
choices=[ |
|
|
"๐ฏ Viral Engagement", |
|
|
"๐ผ Professional Brand", |
|
|
"๐ Casual Fun", |
|
|
"๐ Humor & Memes", |
|
|
"๐ช Motivational", |
|
|
"๐ Storytelling", |
|
|
"๐ Luxury Lifestyle", |
|
|
"๐ฅ Trending Culture" |
|
|
], |
|
|
value="๐ฏ Viral Engagement", |
|
|
label="๐จ Caption Style" |
|
|
) |
|
|
|
|
|
target_audience = gr.Radio( |
|
|
choices=[ |
|
|
"๐ General Audience", |
|
|
"๐ผ Business Professionals", |
|
|
"โ๏ธ Travel Enthusiasts", |
|
|
"๐ Food Lovers", |
|
|
"๐ช Fitness Community", |
|
|
"๐ Fashion Forward", |
|
|
"๐ป Tech Innovators", |
|
|
"๐จ Creative Artists", |
|
|
"๐ฑ Sustainability Advocates", |
|
|
"๐ต Music Fans" |
|
|
], |
|
|
value="๐ General Audience", |
|
|
label="๐ฅ Target Audience" |
|
|
) |
|
|
|
|
|
custom_prompt = gr.Textbox( |
|
|
label="๐ฌ Advanced Instructions", |
|
|
placeholder="e.g., 'Focus on sustainability messaging', 'Include product launch details', 'Emphasize community building'...", |
|
|
lines=3 |
|
|
) |
|
|
|
|
|
generate_btn = gr.Button( |
|
|
"๐ Generate Caption", |
|
|
variant="primary" |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Column(scale=3, elem_classes=["feature-card"]): |
|
|
gr.Markdown("### ๐ AI-Generated Content") |
|
|
|
|
|
output = gr.Textbox( |
|
|
label="๐ฏ Generated Caption", |
|
|
lines=15, |
|
|
show_copy_button=True, |
|
|
placeholder="Upload images and generate your Instagram content with AI..." |
|
|
) |
|
|
|
|
|
alternatives_btn = gr.Button( |
|
|
"โจ Generate 3 Alternative Captions", |
|
|
variant="secondary" |
|
|
) |
|
|
|
|
|
alternatives_output = gr.Textbox( |
|
|
label="โจ Alternative Captions", |
|
|
lines=15, |
|
|
show_copy_button=True, |
|
|
placeholder="Generate 3 different caption alternatives..." |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Tab("๐ Multi-Language Generator"): |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Markdown("### ๐ฃ๏ธ Global Content Creation") |
|
|
gr.Markdown("*Featuring Hugging Face Helsinki-NLP Translation Models*") |
|
|
|
|
|
base_caption_input = gr.Textbox( |
|
|
label="๐ Base Caption", |
|
|
placeholder="Paste your generated caption here...", |
|
|
lines=5 |
|
|
) |
|
|
|
|
|
language_selector = gr.CheckboxGroup( |
|
|
choices=[ |
|
|
"๐ฉ๐ช German", |
|
|
"๐จ๐ณ Chinese", |
|
|
"๐ฎ๐ณ Hindi", |
|
|
"๐ธ๐ฆ Arabic" |
|
|
], |
|
|
label="๐ Select Languages", |
|
|
value=["๐ฉ๐ช German", "๐ฎ๐ณ Hindi"] |
|
|
) |
|
|
|
|
|
translate_btn = gr.Button( |
|
|
"๐ Generate Multi-Language Versions", |
|
|
variant="primary" |
|
|
) |
|
|
|
|
|
with gr.Column(): |
|
|
multilingual_output = gr.Textbox( |
|
|
label="๐บ๏ธ Multi-Language Captions", |
|
|
lines=20, |
|
|
show_copy_button=True, |
|
|
placeholder="Culturally adapted captions for global audiences..." |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Tab("๐ค SambaNova Features"): |
|
|
gr.HTML(f""" |
|
|
<div class="sambanova-status"> |
|
|
๐ SambaNova Status: {sambanova_status} โข ๐ฆ Llama-4-Maverick + Llama-3.2-3B |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(elem_classes=["feature-card"]): |
|
|
gr.HTML(""" |
|
|
<div style="text-align: center; padding: 20px;"> |
|
|
<h3>โก SambaNova AI Capabilities</h3> |
|
|
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 20px;"> |
|
|
<div style="padding: 15px; background: rgba(46, 204, 113, 0.2); border-radius: 10px; border: 2px solid #2ecc71;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #2ecc71;">Llama-4-Maverick</h4> |
|
|
<p style="margin: 5px 0; color: #e8f8f5; font-weight: 500;">Main Caption Generation</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(52, 152, 219, 0.2); border-radius: 10px; border: 2px solid #3498db;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #3498db;">Llama-3.2-3B</h4> |
|
|
<p style="margin: 5px 0; color: #ebf3fd; font-weight: 500;">Caption Variations</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(231, 76, 60, 0.2); border-radius: 10px; border: 2px solid #e74c3c;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #e74c3c;">Multi-Modal</h4> |
|
|
<p style="margin: 5px 0; color: #fdedec; font-weight: 500;">Vision + Text Analysis</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(155, 89, 182, 0.2); border-radius: 10px; border: 2px solid #9b59b6;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #9b59b6;">Advanced</h4> |
|
|
<p style="margin: 5px 0; color: #f4ecf7; font-weight: 500;">Style & Audience Targeting</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Column(elem_classes=["feature-card"]): |
|
|
gr.Code( |
|
|
value=""" |
|
|
# SambaNova API Integration: |
|
|
|
|
|
from openai import OpenAI |
|
|
|
|
|
client = OpenAI( |
|
|
api_key=os.environ["SAMBANOVA_API_KEY"], |
|
|
base_url="https://api.sambanova.ai/v1", |
|
|
) |
|
|
|
|
|
# Main caption generation |
|
|
response = client.chat.completions.create( |
|
|
model="Llama-4-Maverick-17B-128E-Instruct", |
|
|
messages=[{ |
|
|
"role": "user", |
|
|
"content": [ |
|
|
{"type": "text", "text": "Create Instagram caption"}, |
|
|
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}} |
|
|
] |
|
|
}], |
|
|
temperature=0.1, |
|
|
top_p=0.1 |
|
|
) |
|
|
|
|
|
# Caption variations |
|
|
variations = client.chat.completions.create( |
|
|
model="Meta-Llama-3.2-3B-Instruct", |
|
|
messages=[{ |
|
|
"role": "user", |
|
|
"content": "Create different version of this caption..." |
|
|
}], |
|
|
temperature=0.9, |
|
|
top_p=0.95 |
|
|
) |
|
|
""", |
|
|
language="python", |
|
|
label="๐ง SambaNova Integration Code" |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Tab("๐ค Hugging Face Features"): |
|
|
gr.HTML(f""" |
|
|
<div class="sambanova-status"> |
|
|
๐ค Hugging Face Status: {hf_status} โข ๐ Multi-Language Translation |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(elem_classes=["feature-card"]): |
|
|
gr.HTML(""" |
|
|
<div style="text-align: center; padding: 20px;"> |
|
|
<h3>๐ Translation Models</h3> |
|
|
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 20px;"> |
|
|
<div style="padding: 15px; background: rgba(46, 204, 113, 0.2); border-radius: 10px; border: 2px solid #2ecc71;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #2ecc71;">๐ฉ๐ช German</h4> |
|
|
<p style="margin: 5px 0; color: #e8f8f5; font-weight: 500;">google-t5/t5-small</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(52, 152, 219, 0.2); border-radius: 10px; border: 2px solid #3498db;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #3498db;">๐จ๐ณ Chinese</h4> |
|
|
<p style="margin: 5px 0; color: #ebf3fd; font-weight: 500;">chence08/mt5-small-iwslt2017-zh-en</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(231, 76, 60, 0.2); border-radius: 10px; border: 2px solid #e74c3c;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #e74c3c;">๐ฎ๐ณ Hindi</h4> |
|
|
<p style="margin: 5px 0; color: #fdedec; font-weight: 500;">Helsinki-NLP/opus-mt-en-hi</p> |
|
|
</div> |
|
|
<div style="padding: 15px; background: rgba(155, 89, 182, 0.2); border-radius: 10px; border: 2px solid #9b59b6;"> |
|
|
<h4 style="color: #ffffff; margin: 0; text-shadow: 0 0 10px #9b59b6;">๐ธ๐ฆ Arabic</h4> |
|
|
<p style="margin: 5px 0; color: #f4ecf7; font-weight: 500;">marefa-nlp/marefa-mt-en-ar</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Column(elem_classes=["feature-card"]): |
|
|
gr.Code( |
|
|
value=""" |
|
|
# Hugging Face Translation Integration: |
|
|
|
|
|
from huggingface_hub import InferenceClient |
|
|
|
|
|
client = InferenceClient( |
|
|
provider="hf-inference", |
|
|
api_key=os.environ["HF_TOKEN"], |
|
|
) |
|
|
|
|
|
# German translation |
|
|
german_result = client.translation( |
|
|
"This is an amazing moment! โจ", |
|
|
model="google-t5/t5-small", |
|
|
) |
|
|
|
|
|
# Chinese translation |
|
|
chinese_result = client.translation( |
|
|
"Amazing content for Instagram", |
|
|
model="chence08/mt5-small-iwslt2017-zh-en", |
|
|
) |
|
|
|
|
|
# Hindi translation |
|
|
hindi_result = client.translation( |
|
|
"Beautiful content creation", |
|
|
model="Helsinki-NLP/opus-mt-en-hi", |
|
|
) |
|
|
|
|
|
# Arabic translation |
|
|
arabic_result = client.translation( |
|
|
"Social media content", |
|
|
model="marefa-nlp/marefa-mt-en-ar", |
|
|
) |
|
|
|
|
|
# Features: |
|
|
# โ
4 language models |
|
|
# โ
Fallback support |
|
|
# โ
Instagram-optimized output |
|
|
# โ
Cultural adaptation |
|
|
""", |
|
|
language="python", |
|
|
label="๐ง Hugging Face Translation Code" |
|
|
) |
|
|
|
|
|
|
|
|
generate_btn.click( |
|
|
fn=generate_advanced_caption_interface, |
|
|
inputs=[images, caption_style, target_audience, custom_prompt], |
|
|
outputs=[output, base_caption_input] |
|
|
) |
|
|
|
|
|
alternatives_btn.click( |
|
|
fn=generate_multiple_captions_interface, |
|
|
inputs=[images, caption_style, target_audience, custom_prompt], |
|
|
outputs=alternatives_output |
|
|
) |
|
|
|
|
|
translate_btn.click( |
|
|
fn=translate_caption_interface, |
|
|
inputs=[base_caption_input, language_selector], |
|
|
outputs=multilingual_output |
|
|
) |
|
|
|
|
|
return app |
|
|
|
|
|
|
|
|
def main(): |
|
|
"""Main function to launch the Instagram Caption Generator""" |
|
|
print("๐ Starting Instagram Caption Generator...") |
|
|
print("๐ฑ AI-Powered Content Creation Suite!") |
|
|
print("=" * 50) |
|
|
|
|
|
if not setup_success: |
|
|
print(f"โ Setup failed: {setup_error}") |
|
|
print("๐ก Please check your API configuration") |
|
|
|
|
|
|
|
|
sambanova_msg = "โ
SambaNova ready!" if generator and generator.sambanova_client_working else "โ ๏ธ SambaNova fallback mode" |
|
|
hf_msg = "โ
Hugging Face ready!" if generator and generator.hf_client_working else "โ ๏ธ Hugging Face fallback mode" |
|
|
|
|
|
print(sambanova_msg) |
|
|
print(hf_msg) |
|
|
print("๐ Multi-language support active!") |
|
|
print("=" * 50) |
|
|
|
|
|
|
|
|
app = create_gradio_app() |
|
|
app.launch(mcp_server=True) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |