Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
"""
|
| 2 |
-
📱 Instagram Caption Generator - Simplified Version
|
| 3 |
==================================================
|
| 4 |
|
| 5 |
AI-Powered Instagram Content Creation Suite with SambaNova Integration
|
|
@@ -8,7 +8,7 @@ Multi-Modal AI Analysis (Vision + Text) + Multi-Language Support
|
|
| 8 |
🚀 Key Features:
|
| 9 |
- SambaNova Llama-4-Maverick Integration
|
| 10 |
- Multi-Language Support (German, Chinese, French, Arabic via Hugging Face)
|
| 11 |
-
- Advanced Gradio Interface
|
| 12 |
- Advanced Error Handling & Security
|
| 13 |
|
| 14 |
Author: MCP Hackathon 2025 Participant
|
|
@@ -133,14 +133,14 @@ class AdvancedInstagramGenerator:
|
|
| 133 |
print("✅ AI models setup completed!")
|
| 134 |
|
| 135 |
def setup_huggingface_client(self):
|
| 136 |
-
"""Initialize Hugging Face client for translations
|
| 137 |
try:
|
| 138 |
-
# Initialize Hugging Face client
|
| 139 |
hf_token = os.environ.get("HF_TOKEN")
|
| 140 |
if hf_token:
|
| 141 |
-
# FIXED: Use correct initialization method
|
| 142 |
self.hf_client = InferenceClient(
|
| 143 |
-
|
|
|
|
| 144 |
)
|
| 145 |
print("✅ Hugging Face client initialized successfully!")
|
| 146 |
self.hf_client_working = True
|
|
@@ -418,41 +418,6 @@ class AdvancedInstagramGenerator:
|
|
| 418 |
|
| 419 |
return f"🇸🇦 ARABIC VERSION (Fallback):\n{translated}"
|
| 420 |
|
| 421 |
-
def get_fallback_hindi_translation(self, text: str) -> str:
|
| 422 |
-
"""Fallback Hindi translation when HF API fails"""
|
| 423 |
-
# Simple keyword-based translation for common Instagram terms
|
| 424 |
-
hindi_translations = {
|
| 425 |
-
"amazing": "अद्भुत",
|
| 426 |
-
"beautiful": "सुंदर",
|
| 427 |
-
"love": "प्रेम",
|
| 428 |
-
"perfect": "परफेक्ट",
|
| 429 |
-
"awesome": "शानदार",
|
| 430 |
-
"incredible": "अविश्वसनीय",
|
| 431 |
-
"follow": "फॉलो",
|
| 432 |
-
"like": "लाइक",
|
| 433 |
-
"share": "शेयर",
|
| 434 |
-
"comment": "कमेंट",
|
| 435 |
-
"today": "आज",
|
| 436 |
-
"moment": "पल",
|
| 437 |
-
"life": "जीवन",
|
| 438 |
-
"inspiration": "प्रेरणा",
|
| 439 |
-
"community": "समुदाय",
|
| 440 |
-
"content": "कंटेंट",
|
| 441 |
-
"check out": "देखें",
|
| 442 |
-
"what do you think": "आप क्या सोचते हैं"
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
# Basic word replacement (not perfect but functional fallback)
|
| 446 |
-
translated = text.lower()
|
| 447 |
-
for english, hindi in hindi_translations.items():
|
| 448 |
-
translated = translated.replace(english, hindi)
|
| 449 |
-
|
| 450 |
-
# Add Hindi hashtags
|
| 451 |
-
if "#" in translated:
|
| 452 |
-
translated += " #हिंदी #भारत #सोशलमीडिया #कंटेंट"
|
| 453 |
-
|
| 454 |
-
return f"🇮🇳 HINDI VERSION (Fallback):\n{translated}"
|
| 455 |
-
|
| 456 |
def setup_trend_analysis(self):
|
| 457 |
"""Initialize basic trend analysis"""
|
| 458 |
self.trending_cache = {}
|
|
@@ -1026,18 +991,16 @@ Format:
|
|
| 1026 |
[Hashtags]"""
|
| 1027 |
|
| 1028 |
|
| 1029 |
-
# Global generator instance with caching
|
| 1030 |
@functools.lru_cache(maxsize=1)
|
| 1031 |
def get_generator():
|
| 1032 |
"""Get cached generator instance"""
|
| 1033 |
return AdvancedInstagramGenerator()
|
| 1034 |
|
| 1035 |
-
# FIXED: Initialize generator with proper error handling
|
| 1036 |
try:
|
| 1037 |
generator = get_generator()
|
| 1038 |
setup_success = True
|
| 1039 |
setup_error = ""
|
| 1040 |
-
print("✅ Generator initialized successfully!")
|
| 1041 |
except Exception as e:
|
| 1042 |
generator = None
|
| 1043 |
setup_success = False
|
|
@@ -1045,35 +1008,25 @@ except Exception as e:
|
|
| 1045 |
print(f"❌ Setup failed: {e}")
|
| 1046 |
|
| 1047 |
|
| 1048 |
-
#
|
| 1049 |
-
def generate_advanced_caption_interface(uploaded_files, style, audience,
|
| 1050 |
-
|
|
|
|
| 1051 |
if not setup_success:
|
| 1052 |
return f"❌ Setup Error: {setup_error}", ""
|
| 1053 |
|
| 1054 |
-
# FIXED: Debug dropdown values
|
| 1055 |
-
print(f"🔍 DEBUG - Style received: {style}")
|
| 1056 |
-
print(f"🔍 DEBUG - Audience received: {audience}")
|
| 1057 |
-
print(f"🔍 DEBUG - Custom prompt: {custom_prompt}")
|
| 1058 |
-
|
| 1059 |
images = []
|
| 1060 |
if uploaded_files:
|
| 1061 |
for file in uploaded_files[:3]:
|
| 1062 |
try:
|
| 1063 |
image = Image.open(file.name)
|
| 1064 |
images.append(image)
|
| 1065 |
-
print(f"✅ Loaded image: {file.name}")
|
| 1066 |
except Exception as e:
|
| 1067 |
return f"❌ Error processing file: {e}", ""
|
| 1068 |
|
| 1069 |
-
|
| 1070 |
-
|
| 1071 |
-
|
| 1072 |
-
result = asyncio.run(generator.generate_advanced_caption(
|
| 1073 |
-
images, style, audience, custom_prompt
|
| 1074 |
-
))
|
| 1075 |
-
except Exception as e:
|
| 1076 |
-
return f"❌ Generation error: {str(e)}", ""
|
| 1077 |
|
| 1078 |
# Extract clean caption for multi-language processing
|
| 1079 |
caption_only = ""
|
|
@@ -1099,14 +1052,12 @@ def generate_advanced_caption_interface(uploaded_files, style, audience, custom_
|
|
| 1099 |
return result, caption_only
|
| 1100 |
|
| 1101 |
|
| 1102 |
-
def generate_multiple_captions_interface(uploaded_files, style, audience,
|
| 1103 |
-
|
|
|
|
| 1104 |
if not setup_success:
|
| 1105 |
return f"❌ Setup Error: {setup_error}"
|
| 1106 |
|
| 1107 |
-
# FIXED: Debug dropdown values
|
| 1108 |
-
print(f"🔍 DEBUG VARIATIONS - Style: {style}, Audience: {audience}")
|
| 1109 |
-
|
| 1110 |
images = []
|
| 1111 |
if uploaded_files:
|
| 1112 |
for file in uploaded_files[:3]:
|
|
@@ -1119,141 +1070,126 @@ def generate_multiple_captions_interface(uploaded_files, style, audience, custom
|
|
| 1119 |
if not images:
|
| 1120 |
return "❌ Please upload at least one image to generate caption variations."
|
| 1121 |
|
| 1122 |
-
#
|
| 1123 |
-
|
| 1124 |
-
|
| 1125 |
-
|
| 1126 |
-
|
| 1127 |
-
|
| 1128 |
-
|
| 1129 |
-
|
| 1130 |
-
|
| 1131 |
-
|
| 1132 |
-
|
| 1133 |
-
if "✨ AI-GENERATED INSTAGRAM CONTENT:" in main_result:
|
| 1134 |
-
lines = main_result.split('\n')
|
| 1135 |
-
caption_lines = []
|
| 1136 |
-
start_capturing = False
|
| 1137 |
-
|
| 1138 |
-
for line in lines:
|
| 1139 |
-
if "✨ AI-GENERATED INSTAGRAM CONTENT:" in line:
|
| 1140 |
-
start_capturing = True
|
| 1141 |
-
continue
|
| 1142 |
-
elif "🤖 Powered by SambaNova" in line:
|
| 1143 |
-
break
|
| 1144 |
-
elif start_capturing and line.strip():
|
| 1145 |
-
caption_lines.append(line)
|
| 1146 |
-
|
| 1147 |
-
base_caption = '\n'.join(caption_lines).strip()
|
| 1148 |
-
|
| 1149 |
-
if not base_caption:
|
| 1150 |
-
return "❌ Failed to generate base caption for variations"
|
| 1151 |
|
| 1152 |
-
|
| 1153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1154 |
|
| 1155 |
-
|
| 1156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1157 |
formatted_result += "=" * 60 + "\n\n"
|
| 1158 |
-
|
| 1159 |
-
|
| 1160 |
-
formatted_result += f"📝 ALTERNATIVE {i}:\n"
|
| 1161 |
-
formatted_result += f"{variation}\n"
|
| 1162 |
-
formatted_result += "=" * 60 + "\n\n"
|
| 1163 |
-
|
| 1164 |
-
return formatted_result
|
| 1165 |
-
except Exception as e:
|
| 1166 |
-
return f"❌ Variation generation error: {str(e)}"
|
| 1167 |
|
| 1168 |
|
| 1169 |
-
def translate_caption_interface(base_caption, selected_languages):
|
| 1170 |
-
"""Generate multi-language versions of captions
|
| 1171 |
if not base_caption.strip():
|
| 1172 |
return "❌ Please provide a caption to translate"
|
| 1173 |
|
| 1174 |
if not selected_languages:
|
| 1175 |
return "❌ Please select at least one language"
|
| 1176 |
|
| 1177 |
-
# FIXED: Debug language selection
|
| 1178 |
-
print(f"🔍 DEBUG TRANSLATION - Languages: {selected_languages}")
|
| 1179 |
-
|
| 1180 |
result = "🌍 MULTI-LANGUAGE CAPTION VERSIONS:\n\n"
|
| 1181 |
result += "=" * 60 + "\n\n"
|
| 1182 |
|
| 1183 |
-
# FIXED: Use asyncio.run for async translation functions
|
| 1184 |
-
import asyncio
|
| 1185 |
-
|
| 1186 |
for language in selected_languages:
|
| 1187 |
-
|
| 1188 |
-
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
-
|
| 1195 |
-
|
| 1196 |
-
except Exception as e:
|
| 1197 |
-
fallback_german = generator.get_fallback_german_translation(base_caption)
|
| 1198 |
-
result += f"{fallback_german}\n\n"
|
| 1199 |
-
result += "=" * 60 + "\n\n"
|
| 1200 |
-
else:
|
| 1201 |
fallback_german = generator.get_fallback_german_translation(base_caption)
|
| 1202 |
result += f"{fallback_german}\n\n"
|
| 1203 |
result += "=" * 60 + "\n\n"
|
| 1204 |
-
|
| 1205 |
-
|
| 1206 |
-
|
| 1207 |
-
|
| 1208 |
-
|
| 1209 |
-
|
| 1210 |
-
|
| 1211 |
-
|
| 1212 |
-
|
| 1213 |
-
|
| 1214 |
-
|
| 1215 |
-
|
| 1216 |
-
|
| 1217 |
-
|
| 1218 |
fallback_chinese = generator.get_fallback_chinese_translation(base_caption)
|
| 1219 |
result += f"{fallback_chinese}\n\n"
|
| 1220 |
result += "=" * 60 + "\n\n"
|
| 1221 |
-
|
| 1222 |
-
|
| 1223 |
-
|
| 1224 |
-
|
| 1225 |
-
|
| 1226 |
-
|
| 1227 |
-
|
| 1228 |
-
|
| 1229 |
-
|
| 1230 |
-
|
| 1231 |
-
|
| 1232 |
-
|
| 1233 |
-
|
| 1234 |
-
|
| 1235 |
fallback_hindi = generator.get_fallback_hindi_translation(base_caption)
|
| 1236 |
result += f"{fallback_hindi}\n\n"
|
| 1237 |
result += "=" * 60 + "\n\n"
|
| 1238 |
-
|
| 1239 |
-
|
| 1240 |
-
|
| 1241 |
-
|
| 1242 |
-
|
| 1243 |
-
|
| 1244 |
-
|
| 1245 |
-
|
| 1246 |
-
|
| 1247 |
-
|
| 1248 |
-
|
| 1249 |
-
|
| 1250 |
-
|
| 1251 |
-
|
| 1252 |
fallback_arabic = generator.get_fallback_arabic_translation(base_caption)
|
| 1253 |
result += f"{fallback_arabic}\n\n"
|
| 1254 |
result += "=" * 60 + "\n\n"
|
| 1255 |
-
|
| 1256 |
-
|
|
|
|
|
|
|
| 1257 |
|
| 1258 |
if any(lang in selected_languages for lang in ["🇩🇪 German", "🇨🇳 Chinese", "🇮🇳 Hindi", "🇸🇦 Arabic"]):
|
| 1259 |
hf_langs = []
|
|
@@ -1274,9 +1210,13 @@ def translate_caption_interface(base_caption, selected_languages):
|
|
| 1274 |
|
| 1275 |
|
| 1276 |
def create_gradio_app():
|
| 1277 |
-
"""Create the Gradio app with
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1278 |
|
| 1279 |
-
#
|
| 1280 |
css = """
|
| 1281 |
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
| 1282 |
|
|
@@ -1284,258 +1224,146 @@ def create_gradio_app():
|
|
| 1284 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #4facfe 100%);
|
| 1285 |
font-family: 'Space Grotesk', 'Inter', system-ui, sans-serif;
|
| 1286 |
min-height: 100vh;
|
| 1287 |
-
position: relative;
|
| 1288 |
-
overflow-x: hidden;
|
| 1289 |
-
}
|
| 1290 |
-
|
| 1291 |
-
.gradio-container::before {
|
| 1292 |
-
content: '';
|
| 1293 |
-
position: absolute;
|
| 1294 |
-
top: 0;
|
| 1295 |
-
left: 0;
|
| 1296 |
-
right: 0;
|
| 1297 |
-
bottom: 0;
|
| 1298 |
-
background: radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
| 1299 |
-
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%);
|
| 1300 |
-
pointer-events: none;
|
| 1301 |
-
z-index: 1;
|
| 1302 |
}
|
| 1303 |
|
| 1304 |
.main-header {
|
| 1305 |
text-align: center;
|
| 1306 |
color: white;
|
| 1307 |
-
margin-bottom:
|
| 1308 |
-
padding: 40px;
|
| 1309 |
-
background: rgba(255,255,255,0.1);
|
| 1310 |
-
border-radius: 30px;
|
| 1311 |
-
backdrop-filter: blur(30px);
|
| 1312 |
-
border: 2px solid rgba(255,255,255,0.2);
|
| 1313 |
-
box-shadow: 0 25px 50px rgba(0,0,0,0.1);
|
| 1314 |
-
position: relative;
|
| 1315 |
-
z-index: 2;
|
| 1316 |
-
animation: float 6s ease-in-out infinite;
|
| 1317 |
-
}
|
| 1318 |
-
|
| 1319 |
-
@keyframes float {
|
| 1320 |
-
0%, 100% { transform: translateY(0px); }
|
| 1321 |
-
50% { transform: translateY(-10px); }
|
| 1322 |
-
}
|
| 1323 |
-
|
| 1324 |
-
.feature-card {
|
| 1325 |
-
background: rgba(255,255,255,0.15);
|
| 1326 |
-
border-radius: 25px;
|
| 1327 |
padding: 30px;
|
|
|
|
|
|
|
| 1328 |
backdrop-filter: blur(20px);
|
| 1329 |
-
border: 1px solid rgba(255,255,255,0.
|
| 1330 |
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
| 1331 |
-
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 1332 |
-
position: relative;
|
| 1333 |
-
z-index: 2;
|
| 1334 |
}
|
| 1335 |
|
| 1336 |
-
.feature-card
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1340 |
}
|
| 1341 |
|
| 1342 |
.gradio-button-primary {
|
| 1343 |
background: linear-gradient(45deg, #ff6b6b, #ee5a24, #ff9ff3, #54a0ff) !important;
|
| 1344 |
-
background-size: 300% 300% !important;
|
| 1345 |
-
animation: gradient-shift 4s ease infinite !important;
|
| 1346 |
border: none !important;
|
| 1347 |
-
border-radius:
|
| 1348 |
-
padding:
|
| 1349 |
-
font-weight:
|
| 1350 |
-
|
| 1351 |
-
|
| 1352 |
-
box-shadow: 0 15px 35px rgba(255, 107, 107, 0.4) !important;
|
| 1353 |
transition: all 0.3s ease !important;
|
| 1354 |
-
position: relative !important;
|
| 1355 |
-
overflow: hidden !important;
|
| 1356 |
-
}
|
| 1357 |
-
|
| 1358 |
-
@keyframes gradient-shift {
|
| 1359 |
-
0% { background-position: 0% 50%; }
|
| 1360 |
-
50% { background-position: 100% 50%; }
|
| 1361 |
-
100% { background-position: 0% 50%; }
|
| 1362 |
}
|
| 1363 |
|
| 1364 |
.gradio-button-primary:hover {
|
| 1365 |
-
transform: translateY(-
|
| 1366 |
-
box-shadow: 0
|
| 1367 |
}
|
| 1368 |
|
| 1369 |
.gradio-button-secondary {
|
| 1370 |
background: linear-gradient(45deg, #feca57, #ff9ff3, #54a0ff, #5f27cd) !important;
|
| 1371 |
-
background-size: 300% 300% !important;
|
| 1372 |
-
animation: gradient-shift 4s ease infinite !important;
|
| 1373 |
border: none !important;
|
| 1374 |
-
border-radius:
|
| 1375 |
-
padding:
|
| 1376 |
font-weight: 600 !important;
|
| 1377 |
-
text-transform: uppercase !important;
|
| 1378 |
-
letter-spacing: 1.5px !important;
|
| 1379 |
-
box-shadow: 0 12px 25px rgba(254, 202, 87, 0.4) !important;
|
| 1380 |
-
transition: all 0.3s ease !important;
|
| 1381 |
color: white !important;
|
|
|
|
| 1382 |
}
|
| 1383 |
|
| 1384 |
-
.
|
| 1385 |
-
transform: translateY(-2px) scale(1.03) !important;
|
| 1386 |
-
box-shadow: 0 15px 30px rgba(254, 202, 87, 0.6) !important;
|
| 1387 |
-
}
|
| 1388 |
-
|
| 1389 |
-
.advanced-controls {
|
| 1390 |
-
background: rgba(255,255,255,0.1);
|
| 1391 |
-
border-radius: 20px;
|
| 1392 |
-
padding: 25px;
|
| 1393 |
-
backdrop-filter: blur(15px);
|
| 1394 |
-
border: 1px solid rgba(255,255,255,0.2);
|
| 1395 |
-
margin: 20px 0;
|
| 1396 |
-
}
|
| 1397 |
-
|
| 1398 |
-
.sambanova-status {
|
| 1399 |
background: linear-gradient(90deg, #2ecc71, #27ae60);
|
| 1400 |
color: white;
|
| 1401 |
-
padding:
|
| 1402 |
-
border-radius:
|
| 1403 |
text-align: center;
|
| 1404 |
font-weight: 600;
|
| 1405 |
-
box-shadow: 0
|
| 1406 |
-
|
| 1407 |
-
}
|
| 1408 |
-
|
| 1409 |
-
@keyframes pulse {
|
| 1410 |
-
0% { box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3); }
|
| 1411 |
-
50% { box-shadow: 0 15px 30px rgba(46, 204, 113, 0.5); }
|
| 1412 |
-
100% { box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3); }
|
| 1413 |
-
}
|
| 1414 |
-
|
| 1415 |
-
.trending-indicator {
|
| 1416 |
-
display: inline-block;
|
| 1417 |
-
width: 8px;
|
| 1418 |
-
height: 8px;
|
| 1419 |
-
background: #ff6b6b;
|
| 1420 |
-
border-radius: 50%;
|
| 1421 |
-
animation: blink 1s infinite;
|
| 1422 |
-
margin-right: 8px;
|
| 1423 |
-
}
|
| 1424 |
-
|
| 1425 |
-
@keyframes blink {
|
| 1426 |
-
0%, 50% { opacity: 1; }
|
| 1427 |
-
51%, 100% { opacity: 0.3; }
|
| 1428 |
}
|
| 1429 |
"""
|
| 1430 |
|
| 1431 |
-
|
| 1432 |
-
with gr.Blocks(
|
| 1433 |
-
css=css,
|
| 1434 |
-
title="📱 Instagram Generator - MCP Hackathon 2025",
|
| 1435 |
-
theme=gr.themes.Soft() # Changed from Glass to Soft for better dropdown compatibility
|
| 1436 |
-
) as app:
|
| 1437 |
|
| 1438 |
# Main Header
|
| 1439 |
-
gr.HTML("""
|
| 1440 |
<div class="main-header">
|
| 1441 |
-
<h1 style="font-size:
|
| 1442 |
📱 INSTAGRAM CAPTION GENERATOR
|
| 1443 |
</h1>
|
| 1444 |
-
<h2 style="font-size: 1.
|
| 1445 |
-
🚀
|
| 1446 |
</h2>
|
| 1447 |
-
<div style="display: flex; justify-content: center; gap: 20px; margin-top:
|
| 1448 |
-
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius:
|
| 1449 |
-
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius:
|
| 1450 |
-
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; font-size: 0.9rem;">🔗 MCP Server</span>
|
| 1451 |
</div>
|
| 1452 |
</div>
|
| 1453 |
""")
|
| 1454 |
|
| 1455 |
-
# Status Indicators
|
| 1456 |
-
hf_status = "✅ Connected" if generator and generator.hf_client_working else "⚠️ Fallback Mode"
|
| 1457 |
-
sambanova_status = "✅ Connected" if generator and generator.sambanova_client_working else "⚠️ Fallback Mode"
|
| 1458 |
-
|
| 1459 |
-
gr.HTML(f"""
|
| 1460 |
-
<div class="sambanova-status">
|
| 1461 |
-
<span class="trending-indicator"></span>
|
| 1462 |
-
🚀 SambaNova: {sambanova_status} • 🤗 Hugging Face: {hf_status} • 🦙 Llama-3.2 • MCP Server Ready
|
| 1463 |
-
</div>
|
| 1464 |
-
""")
|
| 1465 |
-
|
| 1466 |
# Main Interface
|
| 1467 |
-
with gr.Tab("🎯
|
| 1468 |
with gr.Row():
|
| 1469 |
-
# Left Column -
|
| 1470 |
with gr.Column(scale=2, elem_classes=["feature-card"]):
|
| 1471 |
-
gr.Markdown("### 🖼️
|
| 1472 |
gr.Markdown("*SambaNova AI vision analysis with quality scoring*")
|
| 1473 |
|
| 1474 |
images = gr.File(
|
| 1475 |
label="📸 Upload Images (Max 3)",
|
| 1476 |
file_count="multiple",
|
| 1477 |
file_types=["image"],
|
| 1478 |
-
height=
|
| 1479 |
)
|
| 1480 |
|
| 1481 |
-
|
| 1482 |
-
|
| 1483 |
-
|
| 1484 |
-
|
| 1485 |
-
|
| 1486 |
-
|
| 1487 |
-
|
| 1488 |
-
|
| 1489 |
-
|
| 1490 |
-
|
| 1491 |
-
|
| 1492 |
-
|
| 1493 |
-
|
| 1494 |
-
|
| 1495 |
-
|
| 1496 |
-
|
| 1497 |
-
|
| 1498 |
-
value="🎯 Viral Engagement",
|
| 1499 |
-
interactive=True, # FIXED: Explicitly set interactive
|
| 1500 |
-
allow_custom_value=False, # FIXED: Prevent custom values
|
| 1501 |
-
multiselect=False # FIXED: Single selection only
|
| 1502 |
-
)
|
| 1503 |
-
|
| 1504 |
-
target_audience = gr.Dropdown(
|
| 1505 |
-
label="👥 Target Audience",
|
| 1506 |
-
choices=[
|
| 1507 |
-
"🌟 General Audience",
|
| 1508 |
-
"💼 Business Professionals",
|
| 1509 |
-
"✈️ Travel Enthusiasts",
|
| 1510 |
-
"🍕 Food Lovers",
|
| 1511 |
-
"💪 Fitness Community",
|
| 1512 |
-
"👗 Fashion Forward",
|
| 1513 |
-
"💻 Tech Innovators",
|
| 1514 |
-
"🎨 Creative Artists",
|
| 1515 |
-
"🌱 Sustainability Advocates",
|
| 1516 |
-
"🎵 Music Fans"
|
| 1517 |
-
],
|
| 1518 |
-
value="🌟 General Audience",
|
| 1519 |
-
interactive=True, # FIXED: Explicitly set interactive
|
| 1520 |
-
allow_custom_value=False, # FIXED: Prevent custom values
|
| 1521 |
-
multiselect=False # FIXED: Single selection only
|
| 1522 |
-
)
|
| 1523 |
|
| 1524 |
-
|
| 1525 |
-
|
| 1526 |
-
|
| 1527 |
-
|
| 1528 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1529 |
)
|
| 1530 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1531 |
generate_btn = gr.Button(
|
| 1532 |
"🚀 Generate Caption",
|
| 1533 |
variant="primary",
|
| 1534 |
-
size="lg"
|
| 1535 |
-
scale=2
|
| 1536 |
)
|
| 1537 |
|
| 1538 |
-
|
| 1539 |
# Right Column - Results
|
| 1540 |
with gr.Column(scale=3, elem_classes=["feature-card"]):
|
| 1541 |
gr.Markdown("### 📊 Generated Content")
|
|
@@ -1545,8 +1373,7 @@ def create_gradio_app():
|
|
| 1545 |
lines=15,
|
| 1546 |
max_lines=20,
|
| 1547 |
show_copy_button=True,
|
| 1548 |
-
placeholder="Upload images and generate your Instagram content..."
|
| 1549 |
-
interactive=False # FIXED: Output should not be interactive
|
| 1550 |
)
|
| 1551 |
|
| 1552 |
with gr.Row():
|
|
@@ -1560,8 +1387,7 @@ def create_gradio_app():
|
|
| 1560 |
label="✨ Alternative Captions",
|
| 1561 |
lines=15,
|
| 1562 |
show_copy_button=True,
|
| 1563 |
-
placeholder="Generate 3 different caption alternatives using Meta-Llama-3.2-3B-Instruct..."
|
| 1564 |
-
interactive=False # FIXED: Output should not be interactive
|
| 1565 |
)
|
| 1566 |
|
| 1567 |
# Multi-Language Tab
|
|
@@ -1574,21 +1400,18 @@ def create_gradio_app():
|
|
| 1574 |
base_caption_input = gr.Textbox(
|
| 1575 |
label="📝 Base Caption",
|
| 1576 |
placeholder="Paste your generated caption here...",
|
| 1577 |
-
lines=5
|
| 1578 |
-
interactive=True # FIXED: Input should be interactive
|
| 1579 |
)
|
| 1580 |
|
| 1581 |
-
# FIXED: Improved checkbox group definition
|
| 1582 |
language_selector = gr.CheckboxGroup(
|
| 1583 |
-
label="🌐 Select Languages",
|
| 1584 |
choices=[
|
| 1585 |
"🇩🇪 German",
|
| 1586 |
"🇨🇳 Chinese",
|
| 1587 |
"🇮🇳 Hindi",
|
| 1588 |
"🇸🇦 Arabic"
|
| 1589 |
],
|
| 1590 |
-
|
| 1591 |
-
|
| 1592 |
)
|
| 1593 |
|
| 1594 |
translate_btn = gr.Button(
|
|
@@ -1601,8 +1424,7 @@ def create_gradio_app():
|
|
| 1601 |
label="🗺️ Multi-Language Captions",
|
| 1602 |
lines=20,
|
| 1603 |
show_copy_button=True,
|
| 1604 |
-
placeholder="Culturally adapted captions for global audiences..."
|
| 1605 |
-
interactive=False # FIXED: Output should not be interactive
|
| 1606 |
)
|
| 1607 |
|
| 1608 |
# SambaNova Features Tab
|
|
@@ -1722,7 +1544,8 @@ variations = client.chat.completions.create(
|
|
| 1722 |
from huggingface_hub import InferenceClient
|
| 1723 |
|
| 1724 |
client = InferenceClient(
|
| 1725 |
-
|
|
|
|
| 1726 |
)
|
| 1727 |
|
| 1728 |
# German translation
|
|
@@ -1759,34 +1582,26 @@ arabic_result = client.translation(
|
|
| 1759 |
label="🔧 Hugging Face Translation Code"
|
| 1760 |
)
|
| 1761 |
|
| 1762 |
-
#
|
| 1763 |
-
print("🔗 Setting up event handlers...")
|
| 1764 |
-
|
| 1765 |
-
# Main caption generation
|
| 1766 |
generate_btn.click(
|
| 1767 |
fn=generate_advanced_caption_interface,
|
| 1768 |
inputs=[images, caption_style, target_audience, custom_prompt],
|
| 1769 |
-
outputs=[output, base_caption_input]
|
| 1770 |
-
show_progress=True # FIXED: Show progress indicator
|
| 1771 |
)
|
| 1772 |
|
| 1773 |
# Generate multiple alternatives
|
| 1774 |
alternatives_btn.click(
|
| 1775 |
fn=generate_multiple_captions_interface,
|
| 1776 |
inputs=[images, caption_style, target_audience, custom_prompt],
|
| 1777 |
-
outputs=alternatives_output
|
| 1778 |
-
show_progress=True # FIXED: Show progress indicator
|
| 1779 |
)
|
| 1780 |
|
| 1781 |
# Multi-language translation
|
| 1782 |
translate_btn.click(
|
| 1783 |
fn=translate_caption_interface,
|
| 1784 |
inputs=[base_caption_input, language_selector],
|
| 1785 |
-
outputs=multilingual_output
|
| 1786 |
-
show_progress=True # FIXED: Show progress indicator
|
| 1787 |
)
|
| 1788 |
-
|
| 1789 |
-
print("✅ Event handlers configured successfully!")
|
| 1790 |
|
| 1791 |
return app
|
| 1792 |
|
|
@@ -1800,7 +1615,6 @@ def main():
|
|
| 1800 |
if not setup_success:
|
| 1801 |
print(f"❌ Setup failed: {setup_error}")
|
| 1802 |
print("💡 Please check your API configuration")
|
| 1803 |
-
return
|
| 1804 |
|
| 1805 |
# Status messages
|
| 1806 |
sambanova_msg = "✅ SambaNova ready!" if generator and generator.sambanova_client_working else "⚠️ SambaNova fallback mode"
|
|
@@ -1813,20 +1627,7 @@ def main():
|
|
| 1813 |
|
| 1814 |
# Create and launch the app
|
| 1815 |
app = create_gradio_app()
|
| 1816 |
-
|
| 1817 |
-
# FIXED: Launch configuration for better compatibility
|
| 1818 |
-
app.launch(
|
| 1819 |
-
server_name="0.0.0.0",
|
| 1820 |
-
server_port=7860,
|
| 1821 |
-
share=False,
|
| 1822 |
-
show_error=True,
|
| 1823 |
-
debug=True, # FIXED: Enable debug mode for troubleshooting
|
| 1824 |
-
show_api=True, # FIXED: Show API for debugging
|
| 1825 |
-
inbrowser=False,
|
| 1826 |
-
favicon_path=None,
|
| 1827 |
-
ssl_verify=False,
|
| 1828 |
-
quiet=False
|
| 1829 |
-
)
|
| 1830 |
|
| 1831 |
|
| 1832 |
if __name__ == "__main__":
|
|
|
|
| 1 |
"""
|
| 2 |
+
📱 Instagram Caption Generator - Simplified Version
|
| 3 |
==================================================
|
| 4 |
|
| 5 |
AI-Powered Instagram Content Creation Suite with SambaNova Integration
|
|
|
|
| 8 |
🚀 Key Features:
|
| 9 |
- SambaNova Llama-4-Maverick Integration
|
| 10 |
- Multi-Language Support (German, Chinese, French, Arabic via Hugging Face)
|
| 11 |
+
- Advanced Gradio Interface
|
| 12 |
- Advanced Error Handling & Security
|
| 13 |
|
| 14 |
Author: MCP Hackathon 2025 Participant
|
|
|
|
| 133 |
print("✅ AI models setup completed!")
|
| 134 |
|
| 135 |
def setup_huggingface_client(self):
|
| 136 |
+
"""Initialize Hugging Face client for translations"""
|
| 137 |
try:
|
| 138 |
+
# Initialize Hugging Face client
|
| 139 |
hf_token = os.environ.get("HF_TOKEN")
|
| 140 |
if hf_token:
|
|
|
|
| 141 |
self.hf_client = InferenceClient(
|
| 142 |
+
provider="hf-inference",
|
| 143 |
+
api_key=hf_token,
|
| 144 |
)
|
| 145 |
print("✅ Hugging Face client initialized successfully!")
|
| 146 |
self.hf_client_working = True
|
|
|
|
| 418 |
|
| 419 |
return f"🇸🇦 ARABIC VERSION (Fallback):\n{translated}"
|
| 420 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
def setup_trend_analysis(self):
|
| 422 |
"""Initialize basic trend analysis"""
|
| 423 |
self.trending_cache = {}
|
|
|
|
| 991 |
[Hashtags]"""
|
| 992 |
|
| 993 |
|
| 994 |
+
# Global generator instance with caching
|
| 995 |
@functools.lru_cache(maxsize=1)
|
| 996 |
def get_generator():
|
| 997 |
"""Get cached generator instance"""
|
| 998 |
return AdvancedInstagramGenerator()
|
| 999 |
|
|
|
|
| 1000 |
try:
|
| 1001 |
generator = get_generator()
|
| 1002 |
setup_success = True
|
| 1003 |
setup_error = ""
|
|
|
|
| 1004 |
except Exception as e:
|
| 1005 |
generator = None
|
| 1006 |
setup_success = False
|
|
|
|
| 1008 |
print(f"❌ Setup failed: {e}")
|
| 1009 |
|
| 1010 |
|
| 1011 |
+
# Gradio Interface Functions
|
| 1012 |
+
async def generate_advanced_caption_interface(uploaded_files, style, audience,
|
| 1013 |
+
custom_prompt):
|
| 1014 |
+
"""Advanced interface function for caption generation"""
|
| 1015 |
if not setup_success:
|
| 1016 |
return f"❌ Setup Error: {setup_error}", ""
|
| 1017 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1018 |
images = []
|
| 1019 |
if uploaded_files:
|
| 1020 |
for file in uploaded_files[:3]:
|
| 1021 |
try:
|
| 1022 |
image = Image.open(file.name)
|
| 1023 |
images.append(image)
|
|
|
|
| 1024 |
except Exception as e:
|
| 1025 |
return f"❌ Error processing file: {e}", ""
|
| 1026 |
|
| 1027 |
+
result = await generator.generate_advanced_caption(
|
| 1028 |
+
images, style, audience, custom_prompt
|
| 1029 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1030 |
|
| 1031 |
# Extract clean caption for multi-language processing
|
| 1032 |
caption_only = ""
|
|
|
|
| 1052 |
return result, caption_only
|
| 1053 |
|
| 1054 |
|
| 1055 |
+
async def generate_multiple_captions_interface(uploaded_files, style, audience,
|
| 1056 |
+
custom_prompt):
|
| 1057 |
+
"""Generate multiple caption variations using Meta-Llama-3.2-3B-Instruct"""
|
| 1058 |
if not setup_success:
|
| 1059 |
return f"❌ Setup Error: {setup_error}"
|
| 1060 |
|
|
|
|
|
|
|
|
|
|
| 1061 |
images = []
|
| 1062 |
if uploaded_files:
|
| 1063 |
for file in uploaded_files[:3]:
|
|
|
|
| 1070 |
if not images:
|
| 1071 |
return "❌ Please upload at least one image to generate caption variations."
|
| 1072 |
|
| 1073 |
+
# First generate the main caption using Llama-4-Maverick
|
| 1074 |
+
main_result = await generator.generate_advanced_caption(
|
| 1075 |
+
images, style, audience, custom_prompt
|
| 1076 |
+
)
|
| 1077 |
+
|
| 1078 |
+
# Extract just the caption text (without the header and footer)
|
| 1079 |
+
base_caption = ""
|
| 1080 |
+
if "✨ AI-GENERATED INSTAGRAM CONTENT:" in main_result:
|
| 1081 |
+
lines = main_result.split('\n')
|
| 1082 |
+
caption_lines = []
|
| 1083 |
+
start_capturing = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1084 |
|
| 1085 |
+
for line in lines:
|
| 1086 |
+
if "✨ AI-GENERATED INSTAGRAM CONTENT:" in line:
|
| 1087 |
+
start_capturing = True
|
| 1088 |
+
continue
|
| 1089 |
+
elif "🤖 Powered by SambaNova" in line:
|
| 1090 |
+
break
|
| 1091 |
+
elif start_capturing and line.strip():
|
| 1092 |
+
caption_lines.append(line)
|
| 1093 |
|
| 1094 |
+
base_caption = '\n'.join(caption_lines).strip()
|
| 1095 |
+
|
| 1096 |
+
if not base_caption:
|
| 1097 |
+
return "❌ Failed to generate base caption for variations"
|
| 1098 |
+
|
| 1099 |
+
# Generate 3 variations using Meta-Llama-3.2-3B-Instruct
|
| 1100 |
+
variations = await generator.generate_mistral_variations(base_caption, count=3)
|
| 1101 |
+
|
| 1102 |
+
# Format the results
|
| 1103 |
+
formatted_result = "✨ ALTERNATIVE CAPTIONS:\n\n"
|
| 1104 |
+
formatted_result += "=" * 60 + "\n\n"
|
| 1105 |
+
|
| 1106 |
+
for i, variation in enumerate(variations, 1):
|
| 1107 |
+
formatted_result += f"📝 ALTERNATIVE {i}:\n"
|
| 1108 |
+
formatted_result += f"{variation}\n"
|
| 1109 |
formatted_result += "=" * 60 + "\n\n"
|
| 1110 |
+
|
| 1111 |
+
return formatted_result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1112 |
|
| 1113 |
|
| 1114 |
+
async def translate_caption_interface(base_caption, selected_languages):
|
| 1115 |
+
"""Generate multi-language versions of captions"""
|
| 1116 |
if not base_caption.strip():
|
| 1117 |
return "❌ Please provide a caption to translate"
|
| 1118 |
|
| 1119 |
if not selected_languages:
|
| 1120 |
return "❌ Please select at least one language"
|
| 1121 |
|
|
|
|
|
|
|
|
|
|
| 1122 |
result = "🌍 MULTI-LANGUAGE CAPTION VERSIONS:\n\n"
|
| 1123 |
result += "=" * 60 + "\n\n"
|
| 1124 |
|
|
|
|
|
|
|
|
|
|
| 1125 |
for language in selected_languages:
|
| 1126 |
+
if language == "🇩🇪 German":
|
| 1127 |
+
# Use Hugging Face for German translation
|
| 1128 |
+
if generator and generator.hf_client_working:
|
| 1129 |
+
try:
|
| 1130 |
+
german_translation = await generator.translate_to_german(base_caption)
|
| 1131 |
+
result += "🇩🇪 GERMAN VERSION (Hugging Face T5):\n"
|
| 1132 |
+
result += f"{german_translation}\n\n"
|
| 1133 |
+
result += "=" * 60 + "\n\n"
|
| 1134 |
+
except Exception as e:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1135 |
fallback_german = generator.get_fallback_german_translation(base_caption)
|
| 1136 |
result += f"{fallback_german}\n\n"
|
| 1137 |
result += "=" * 60 + "\n\n"
|
| 1138 |
+
else:
|
| 1139 |
+
fallback_german = generator.get_fallback_german_translation(base_caption)
|
| 1140 |
+
result += f"{fallback_german}\n\n"
|
| 1141 |
+
result += "=" * 60 + "\n\n"
|
| 1142 |
+
|
| 1143 |
+
elif language == "🇨🇳 Chinese":
|
| 1144 |
+
# Use Hugging Face for Chinese translation
|
| 1145 |
+
if generator and generator.hf_client_working:
|
| 1146 |
+
try:
|
| 1147 |
+
chinese_translation = await generator.translate_to_chinese(base_caption)
|
| 1148 |
+
result += "🇨🇳 CHINESE VERSION (Hugging Face MT5):\n"
|
| 1149 |
+
result += f"{chinese_translation}\n\n"
|
| 1150 |
+
result += "=" * 60 + "\n\n"
|
| 1151 |
+
except Exception as e:
|
| 1152 |
fallback_chinese = generator.get_fallback_chinese_translation(base_caption)
|
| 1153 |
result += f"{fallback_chinese}\n\n"
|
| 1154 |
result += "=" * 60 + "\n\n"
|
| 1155 |
+
else:
|
| 1156 |
+
fallback_chinese = generator.get_fallback_chinese_translation(base_caption)
|
| 1157 |
+
result += f"{fallback_chinese}\n\n"
|
| 1158 |
+
result += "=" * 60 + "\n\n"
|
| 1159 |
+
|
| 1160 |
+
elif language == "🇮🇳 Hindi":
|
| 1161 |
+
# Use Hugging Face for Hindi translation
|
| 1162 |
+
if generator and generator.hf_client_working:
|
| 1163 |
+
try:
|
| 1164 |
+
hindi_translation = await generator.translate_to_hindi(base_caption)
|
| 1165 |
+
result += "🇮🇳 HINDI VERSION (Hugging Face Helsinki-NLP):\n"
|
| 1166 |
+
result += f"{hindi_translation}\n\n"
|
| 1167 |
+
result += "=" * 60 + "\n\n"
|
| 1168 |
+
except Exception as e:
|
| 1169 |
fallback_hindi = generator.get_fallback_hindi_translation(base_caption)
|
| 1170 |
result += f"{fallback_hindi}\n\n"
|
| 1171 |
result += "=" * 60 + "\n\n"
|
| 1172 |
+
else:
|
| 1173 |
+
fallback_hindi = generator.get_fallback_hindi_translation(base_caption)
|
| 1174 |
+
result += f"{fallback_hindi}\n\n"
|
| 1175 |
+
result += "=" * 60 + "\n\n"
|
| 1176 |
+
|
| 1177 |
+
elif language == "🇸🇦 Arabic":
|
| 1178 |
+
# Use Hugging Face for Arabic translation
|
| 1179 |
+
if generator and generator.hf_client_working:
|
| 1180 |
+
try:
|
| 1181 |
+
arabic_translation = await generator.translate_to_arabic(base_caption)
|
| 1182 |
+
result += "🇸🇦 ARABIC VERSION (Hugging Face Marefa):\n"
|
| 1183 |
+
result += f"{arabic_translation}\n\n"
|
| 1184 |
+
result += "=" * 60 + "\n\n"
|
| 1185 |
+
except Exception as e:
|
| 1186 |
fallback_arabic = generator.get_fallback_arabic_translation(base_caption)
|
| 1187 |
result += f"{fallback_arabic}\n\n"
|
| 1188 |
result += "=" * 60 + "\n\n"
|
| 1189 |
+
else:
|
| 1190 |
+
fallback_arabic = generator.get_fallback_arabic_translation(base_caption)
|
| 1191 |
+
result += f"{fallback_arabic}\n\n"
|
| 1192 |
+
result += "=" * 60 + "\n\n"
|
| 1193 |
|
| 1194 |
if any(lang in selected_languages for lang in ["🇩🇪 German", "🇨🇳 Chinese", "🇮🇳 Hindi", "🇸🇦 Arabic"]):
|
| 1195 |
hf_langs = []
|
|
|
|
| 1210 |
|
| 1211 |
|
| 1212 |
def create_gradio_app():
|
| 1213 |
+
"""Create the Gradio app with good UI styling"""
|
| 1214 |
+
|
| 1215 |
+
# Status indicators
|
| 1216 |
+
hf_status = "✅ Connected" if generator and generator.hf_client_working else "⚠️ Fallback Mode"
|
| 1217 |
+
sambanova_status = "✅ Connected" if generator and generator.sambanova_client_working else "⚠️ Fallback Mode"
|
| 1218 |
|
| 1219 |
+
# Enhanced CSS for better UI
|
| 1220 |
css = """
|
| 1221 |
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
| 1222 |
|
|
|
|
| 1224 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #4facfe 100%);
|
| 1225 |
font-family: 'Space Grotesk', 'Inter', system-ui, sans-serif;
|
| 1226 |
min-height: 100vh;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1227 |
}
|
| 1228 |
|
| 1229 |
.main-header {
|
| 1230 |
text-align: center;
|
| 1231 |
color: white;
|
| 1232 |
+
margin-bottom: 30px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1233 |
padding: 30px;
|
| 1234 |
+
background: rgba(255,255,255,0.1);
|
| 1235 |
+
border-radius: 20px;
|
| 1236 |
backdrop-filter: blur(20px);
|
| 1237 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 1238 |
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
|
|
| 1239 |
}
|
| 1240 |
|
| 1241 |
+
.feature-card {
|
| 1242 |
+
background: rgba(255,255,255,0.1);
|
| 1243 |
+
border-radius: 15px;
|
| 1244 |
+
padding: 20px;
|
| 1245 |
+
backdrop-filter: blur(15px);
|
| 1246 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 1247 |
+
box-shadow: 0 15px 30px rgba(0,0,0,0.1);
|
| 1248 |
+
margin: 10px 0;
|
| 1249 |
}
|
| 1250 |
|
| 1251 |
.gradio-button-primary {
|
| 1252 |
background: linear-gradient(45deg, #ff6b6b, #ee5a24, #ff9ff3, #54a0ff) !important;
|
|
|
|
|
|
|
| 1253 |
border: none !important;
|
| 1254 |
+
border-radius: 15px !important;
|
| 1255 |
+
padding: 15px 25px !important;
|
| 1256 |
+
font-weight: 600 !important;
|
| 1257 |
+
color: white !important;
|
| 1258 |
+
box-shadow: 0 10px 20px rgba(255, 107, 107, 0.3) !important;
|
|
|
|
| 1259 |
transition: all 0.3s ease !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1260 |
}
|
| 1261 |
|
| 1262 |
.gradio-button-primary:hover {
|
| 1263 |
+
transform: translateY(-2px) !important;
|
| 1264 |
+
box-shadow: 0 15px 30px rgba(255, 107, 107, 0.5) !important;
|
| 1265 |
}
|
| 1266 |
|
| 1267 |
.gradio-button-secondary {
|
| 1268 |
background: linear-gradient(45deg, #feca57, #ff9ff3, #54a0ff, #5f27cd) !important;
|
|
|
|
|
|
|
| 1269 |
border: none !important;
|
| 1270 |
+
border-radius: 12px !important;
|
| 1271 |
+
padding: 12px 20px !important;
|
| 1272 |
font-weight: 600 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1273 |
color: white !important;
|
| 1274 |
+
box-shadow: 0 8px 16px rgba(254, 202, 87, 0.3) !important;
|
| 1275 |
}
|
| 1276 |
|
| 1277 |
+
.status-badge {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1278 |
background: linear-gradient(90deg, #2ecc71, #27ae60);
|
| 1279 |
color: white;
|
| 1280 |
+
padding: 10px 20px;
|
| 1281 |
+
border-radius: 10px;
|
| 1282 |
text-align: center;
|
| 1283 |
font-weight: 600;
|
| 1284 |
+
box-shadow: 0 8px 16px rgba(46, 204, 113, 0.3);
|
| 1285 |
+
margin: 10px 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1286 |
}
|
| 1287 |
"""
|
| 1288 |
|
| 1289 |
+
with gr.Blocks(css=css, title="📱 Instagram Generator", theme=gr.themes.Glass()) as app:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1290 |
|
| 1291 |
# Main Header
|
| 1292 |
+
gr.HTML(f"""
|
| 1293 |
<div class="main-header">
|
| 1294 |
+
<h1 style="font-size: 2.5rem; margin-bottom: 15px; font-weight: 800; background: linear-gradient(45deg, #ff6b6b, #feca57, #ff9ff3, #54a0ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
|
| 1295 |
📱 INSTAGRAM CAPTION GENERATOR
|
| 1296 |
</h1>
|
| 1297 |
+
<h2 style="font-size: 1.2rem; margin-bottom: 20px; opacity: 0.9;">
|
| 1298 |
+
🚀 AI-Powered Content Creation • SambaNova + Hugging Face
|
| 1299 |
</h2>
|
| 1300 |
+
<div style="display: flex; justify-content: center; gap: 20px; margin-top: 15px;">
|
| 1301 |
+
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 15px;">🤖 SambaNova: {sambanova_status}</span>
|
| 1302 |
+
<span style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 15px;">🤗 Hugging Face: {hf_status}</span>
|
|
|
|
| 1303 |
</div>
|
| 1304 |
</div>
|
| 1305 |
""")
|
| 1306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1307 |
# Main Interface
|
| 1308 |
+
with gr.Tab("🎯 Caption Generator"):
|
| 1309 |
with gr.Row():
|
| 1310 |
+
# Left Column - Controls
|
| 1311 |
with gr.Column(scale=2, elem_classes=["feature-card"]):
|
| 1312 |
+
gr.Markdown("### 🖼️ Upload Images")
|
| 1313 |
gr.Markdown("*SambaNova AI vision analysis with quality scoring*")
|
| 1314 |
|
| 1315 |
images = gr.File(
|
| 1316 |
label="📸 Upload Images (Max 3)",
|
| 1317 |
file_count="multiple",
|
| 1318 |
file_types=["image"],
|
| 1319 |
+
height=200
|
| 1320 |
)
|
| 1321 |
|
| 1322 |
+
gr.Markdown("### ⚙️ Configuration")
|
| 1323 |
+
|
| 1324 |
+
with gr.Row():
|
| 1325 |
+
caption_style = gr.Dropdown(
|
| 1326 |
+
choices=[
|
| 1327 |
+
"🎯 Viral Engagement",
|
| 1328 |
+
"💼 Professional Brand",
|
| 1329 |
+
"😄 Casual Fun",
|
| 1330 |
+
"😂 Humor & Memes",
|
| 1331 |
+
"💪 Motivational",
|
| 1332 |
+
"📖 Storytelling",
|
| 1333 |
+
"🌟 Luxury Lifestyle",
|
| 1334 |
+
"🔥 Trending Culture"
|
| 1335 |
+
],
|
| 1336 |
+
value="🎯 Viral Engagement",
|
| 1337 |
+
label="🎨 Caption Style"
|
| 1338 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1339 |
|
| 1340 |
+
target_audience = gr.Dropdown(
|
| 1341 |
+
choices=[
|
| 1342 |
+
"🌟 General Audience",
|
| 1343 |
+
"💼 Business Professionals",
|
| 1344 |
+
"✈️ Travel Enthusiasts",
|
| 1345 |
+
"🍕 Food Lovers",
|
| 1346 |
+
"💪 Fitness Community",
|
| 1347 |
+
"👗 Fashion Forward",
|
| 1348 |
+
"💻 Tech Innovators",
|
| 1349 |
+
"🎨 Creative Artists"
|
| 1350 |
+
],
|
| 1351 |
+
value="🌟 General Audience",
|
| 1352 |
+
label="👥 Target Audience"
|
| 1353 |
)
|
| 1354 |
|
| 1355 |
+
custom_prompt = gr.Textbox(
|
| 1356 |
+
label="💬 Additional Instructions",
|
| 1357 |
+
placeholder="e.g., 'Focus on sustainability', 'Include product details'...",
|
| 1358 |
+
lines=2
|
| 1359 |
+
)
|
| 1360 |
+
|
| 1361 |
generate_btn = gr.Button(
|
| 1362 |
"🚀 Generate Caption",
|
| 1363 |
variant="primary",
|
| 1364 |
+
size="lg"
|
|
|
|
| 1365 |
)
|
| 1366 |
|
|
|
|
| 1367 |
# Right Column - Results
|
| 1368 |
with gr.Column(scale=3, elem_classes=["feature-card"]):
|
| 1369 |
gr.Markdown("### 📊 Generated Content")
|
|
|
|
| 1373 |
lines=15,
|
| 1374 |
max_lines=20,
|
| 1375 |
show_copy_button=True,
|
| 1376 |
+
placeholder="Upload images and generate your Instagram content..."
|
|
|
|
| 1377 |
)
|
| 1378 |
|
| 1379 |
with gr.Row():
|
|
|
|
| 1387 |
label="✨ Alternative Captions",
|
| 1388 |
lines=15,
|
| 1389 |
show_copy_button=True,
|
| 1390 |
+
placeholder="Generate 3 different caption alternatives using Meta-Llama-3.2-3B-Instruct..."
|
|
|
|
| 1391 |
)
|
| 1392 |
|
| 1393 |
# Multi-Language Tab
|
|
|
|
| 1400 |
base_caption_input = gr.Textbox(
|
| 1401 |
label="📝 Base Caption",
|
| 1402 |
placeholder="Paste your generated caption here...",
|
| 1403 |
+
lines=5
|
|
|
|
| 1404 |
)
|
| 1405 |
|
|
|
|
| 1406 |
language_selector = gr.CheckboxGroup(
|
|
|
|
| 1407 |
choices=[
|
| 1408 |
"🇩🇪 German",
|
| 1409 |
"🇨🇳 Chinese",
|
| 1410 |
"🇮🇳 Hindi",
|
| 1411 |
"🇸🇦 Arabic"
|
| 1412 |
],
|
| 1413 |
+
label="🌐 Select Languages",
|
| 1414 |
+
value=["🇩🇪 German", "🇮🇳 Hindi"]
|
| 1415 |
)
|
| 1416 |
|
| 1417 |
translate_btn = gr.Button(
|
|
|
|
| 1424 |
label="🗺️ Multi-Language Captions",
|
| 1425 |
lines=20,
|
| 1426 |
show_copy_button=True,
|
| 1427 |
+
placeholder="Culturally adapted captions for global audiences..."
|
|
|
|
| 1428 |
)
|
| 1429 |
|
| 1430 |
# SambaNova Features Tab
|
|
|
|
| 1544 |
from huggingface_hub import InferenceClient
|
| 1545 |
|
| 1546 |
client = InferenceClient(
|
| 1547 |
+
provider="hf-inference",
|
| 1548 |
+
api_key=os.environ["HF_TOKEN"],
|
| 1549 |
)
|
| 1550 |
|
| 1551 |
# German translation
|
|
|
|
| 1582 |
label="🔧 Hugging Face Translation Code"
|
| 1583 |
)
|
| 1584 |
|
| 1585 |
+
# Event Handlers
|
|
|
|
|
|
|
|
|
|
| 1586 |
generate_btn.click(
|
| 1587 |
fn=generate_advanced_caption_interface,
|
| 1588 |
inputs=[images, caption_style, target_audience, custom_prompt],
|
| 1589 |
+
outputs=[output, base_caption_input]
|
|
|
|
| 1590 |
)
|
| 1591 |
|
| 1592 |
# Generate multiple alternatives
|
| 1593 |
alternatives_btn.click(
|
| 1594 |
fn=generate_multiple_captions_interface,
|
| 1595 |
inputs=[images, caption_style, target_audience, custom_prompt],
|
| 1596 |
+
outputs=alternatives_output
|
|
|
|
| 1597 |
)
|
| 1598 |
|
| 1599 |
# Multi-language translation
|
| 1600 |
translate_btn.click(
|
| 1601 |
fn=translate_caption_interface,
|
| 1602 |
inputs=[base_caption_input, language_selector],
|
| 1603 |
+
outputs=multilingual_output
|
|
|
|
| 1604 |
)
|
|
|
|
|
|
|
| 1605 |
|
| 1606 |
return app
|
| 1607 |
|
|
|
|
| 1615 |
if not setup_success:
|
| 1616 |
print(f"❌ Setup failed: {setup_error}")
|
| 1617 |
print("💡 Please check your API configuration")
|
|
|
|
| 1618 |
|
| 1619 |
# Status messages
|
| 1620 |
sambanova_msg = "✅ SambaNova ready!" if generator and generator.sambanova_client_working else "⚠️ SambaNova fallback mode"
|
|
|
|
| 1627 |
|
| 1628 |
# Create and launch the app
|
| 1629 |
app = create_gradio_app()
|
| 1630 |
+
app.launch(mcp_server=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1631 |
|
| 1632 |
|
| 1633 |
if __name__ == "__main__":
|