|
""" |
|
๐ฑ 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.1-8B-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*") |
|
gr.HTML(""" |
|
<div style="background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107; padding: 15px; border-radius: 8px; margin: 15px 0;"> |
|
<div style="display: flex; align-items: center; gap: 10px;"> |
|
<span style="font-size: 1.2em;">โ ๏ธ</span> |
|
<div> |
|
<strong style="color: #ff8800;">Translation Notice:</strong> |
|
<p style="margin: 5px 0 0 0; font-size: 0.9em; opacity: 0.8;"> |
|
Emojis may be ignored or lost in translation output. Translation models focus on text content and may not preserve emojis. Try with shorter captions if you experience any problems in output. |
|
</p> |
|
</div> |
|
</div> |
|
</div> |
|
""") |
|
|
|
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() |