Update app-backup.py
Browse files- app-backup.py +192 -67
app-backup.py
CHANGED
|
@@ -418,31 +418,61 @@ class ArenaDatabase:
|
|
| 418 |
cursor.execute('UPDATE model_stats SET elo_rating = ? WHERE model_name = ?', (new_elo_b, model_b))
|
| 419 |
|
| 420 |
def _sync_to_hf(self):
|
| 421 |
-
"""Sync local database to Hugging Face
|
| 422 |
if not self.use_hf:
|
|
|
|
| 423 |
return
|
| 424 |
|
| 425 |
try:
|
| 426 |
conn = sqlite3.connect(self.db_path)
|
| 427 |
|
| 428 |
-
# Export battles
|
| 429 |
battles_df = pd.read_sql_query("SELECT * FROM battles", conn)
|
|
|
|
| 430 |
if len(battles_df) > 0:
|
|
|
|
|
|
|
|
|
|
| 431 |
battles_dataset = Dataset.from_pandas(battles_df)
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
|
| 440 |
conn.close()
|
| 441 |
|
| 442 |
except Exception as e:
|
| 443 |
-
print(f"
|
| 444 |
-
|
| 445 |
-
|
| 446 |
|
| 447 |
def init_database(self):
|
| 448 |
"""Initialize SQLite database - ONLY called when no existing data"""
|
|
@@ -502,11 +532,21 @@ class ArenaDatabase:
|
|
| 502 |
conn.close()
|
| 503 |
|
| 504 |
def save_battle(self, battle: Battle):
|
| 505 |
-
"""Save battle result
|
| 506 |
conn = sqlite3.connect(self.db_path)
|
| 507 |
cursor = conn.cursor()
|
| 508 |
|
| 509 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
cursor.execute('''
|
| 511 |
INSERT OR REPLACE INTO battles VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
| 512 |
''', (
|
|
@@ -529,21 +569,23 @@ class ArenaDatabase:
|
|
| 529 |
winner = battle.winner
|
| 530 |
loser = battle.model_b if winner == battle.model_a else battle.model_a
|
| 531 |
|
| 532 |
-
#
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
# 새 투표이거나 변경된 경우만 업데이트
|
| 538 |
cursor.execute('''
|
| 539 |
UPDATE model_stats
|
| 540 |
-
SET total_battles = total_battles + 1,
|
|
|
|
| 541 |
WHERE model_name = ?
|
| 542 |
''', (winner,))
|
| 543 |
-
|
|
|
|
| 544 |
cursor.execute('''
|
| 545 |
UPDATE model_stats
|
| 546 |
-
SET total_battles = total_battles + 1,
|
|
|
|
| 547 |
WHERE model_name = ?
|
| 548 |
''', (loser,))
|
| 549 |
|
|
@@ -551,20 +593,22 @@ class ArenaDatabase:
|
|
| 551 |
self._update_category_scores(cursor, winner, battle.category, True)
|
| 552 |
self._update_category_scores(cursor, loser, battle.category, False)
|
| 553 |
|
| 554 |
-
# Update ELO
|
| 555 |
self._update_elo_ratings(cursor, winner, loser)
|
|
|
|
|
|
|
| 556 |
|
| 557 |
conn.commit()
|
|
|
|
|
|
|
| 558 |
except Exception as e:
|
| 559 |
-
print(f"Error saving battle: {e}")
|
| 560 |
conn.rollback()
|
| 561 |
finally:
|
| 562 |
conn.close()
|
| 563 |
|
| 564 |
# Sync to Hugging Face after saving
|
| 565 |
self._sync_to_hf()
|
| 566 |
-
|
| 567 |
-
|
| 568 |
|
| 569 |
def _update_category_scores(self, cursor, model, category, is_winner):
|
| 570 |
"""Update category-specific scores"""
|
|
@@ -658,6 +702,41 @@ class ArenaDatabase:
|
|
| 658 |
|
| 659 |
df.insert(0, 'rank', range(1, len(df) + 1))
|
| 660 |
return df
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 661 |
|
| 662 |
# ==================== Fixed LLM Interface with 4 Models ====================
|
| 663 |
class LLMInterface:
|
|
@@ -851,7 +930,7 @@ class LLMInterface:
|
|
| 851 |
top_k=40,
|
| 852 |
)
|
| 853 |
|
| 854 |
-
|
| 855 |
full_response = ""
|
| 856 |
|
| 857 |
for chunk in self.gemini_client.models.generate_content_stream(
|
|
@@ -874,8 +953,6 @@ class LLMInterface:
|
|
| 874 |
fallback = self._generate_fallback("Gemini-2.5-Pro", prompt, "en")
|
| 875 |
yield fallback
|
| 876 |
|
| 877 |
-
|
| 878 |
-
|
| 879 |
def _stream_claude(self, prompt: str) -> Generator[str, None, None]:
|
| 880 |
"""Stream Claude Opus 4.1 response"""
|
| 881 |
if not self.claude_client:
|
|
@@ -1283,15 +1360,28 @@ class CreativityArena:
|
|
| 1283 |
}
|
| 1284 |
|
| 1285 |
def vote(self, choice: str, voter_id: str = None):
|
| 1286 |
-
"""Process vote"""
|
| 1287 |
if not self.current_battle:
|
|
|
|
| 1288 |
return {"error": "No active battle"}
|
| 1289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1290 |
self.current_battle.winner = self.current_battle.model_a if choice == "A" else self.current_battle.model_b
|
| 1291 |
-
self.current_battle.voter_id = voter_id or "
|
|
|
|
|
|
|
| 1292 |
|
|
|
|
| 1293 |
self.db.save_battle(self.current_battle)
|
| 1294 |
|
|
|
|
|
|
|
|
|
|
| 1295 |
return {
|
| 1296 |
"model_a": self.current_battle.model_a,
|
| 1297 |
"model_b": self.current_battle.model_b,
|
|
@@ -1302,7 +1392,17 @@ class CreativityArena:
|
|
| 1302 |
"""Get leaderboard from database"""
|
| 1303 |
return self.db.get_leaderboard(category)
|
| 1304 |
|
| 1305 |
-
# ====================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1306 |
# ==================== Gradio Interface ====================
|
| 1307 |
def create_app():
|
| 1308 |
arena = CreativityArena()
|
|
@@ -1679,16 +1779,29 @@ def create_app():
|
|
| 1679 |
|
| 1680 |
def process_vote(choice, state, lang):
|
| 1681 |
if not state or 'battle' not in state:
|
|
|
|
| 1682 |
return (
|
| 1683 |
gr.update(),
|
| 1684 |
gr.update(),
|
| 1685 |
"Error: No active battle"
|
| 1686 |
)
|
| 1687 |
|
| 1688 |
-
#
|
| 1689 |
-
|
|
|
|
|
|
|
|
|
|
| 1690 |
|
|
|
|
| 1691 |
result = arena.vote(choice)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1692 |
ui = UI_TEXT[lang]
|
| 1693 |
|
| 1694 |
winner_emoji = "🏆" if result['winner'] == result['model_a'] else "🥈"
|
|
@@ -1705,6 +1818,9 @@ def create_app():
|
|
| 1705 |
{ui['elo_updated']}
|
| 1706 |
"""
|
| 1707 |
|
|
|
|
|
|
|
|
|
|
| 1708 |
return (
|
| 1709 |
gr.update(value=result['model_a'], visible=True),
|
| 1710 |
gr.update(value=result['model_b'], visible=True),
|
|
@@ -1785,36 +1901,45 @@ def create_app():
|
|
| 1785 |
|
| 1786 |
# ==================== Main ====================
|
| 1787 |
if __name__ == "__main__":
|
| 1788 |
-
|
| 1789 |
-
|
| 1790 |
-
|
| 1791 |
-
|
| 1792 |
-
|
| 1793 |
-
|
| 1794 |
-
|
| 1795 |
-
|
| 1796 |
-
|
| 1797 |
-
|
| 1798 |
-
|
| 1799 |
-
|
| 1800 |
-
|
| 1801 |
-
|
| 1802 |
-
|
| 1803 |
-
|
| 1804 |
-
|
| 1805 |
-
|
| 1806 |
-
|
| 1807 |
-
|
| 1808 |
-
|
| 1809 |
-
|
| 1810 |
-
|
| 1811 |
-
|
| 1812 |
-
|
| 1813 |
-
|
| 1814 |
-
|
| 1815 |
-
|
| 1816 |
-
|
| 1817 |
-
|
| 1818 |
-
|
| 1819 |
-
|
| 1820 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
cursor.execute('UPDATE model_stats SET elo_rating = ? WHERE model_name = ?', (new_elo_b, model_b))
|
| 419 |
|
| 420 |
def _sync_to_hf(self):
|
| 421 |
+
"""Sync local database to Hugging Face with improved error handling"""
|
| 422 |
if not self.use_hf:
|
| 423 |
+
print("HF sync disabled")
|
| 424 |
return
|
| 425 |
|
| 426 |
try:
|
| 427 |
conn = sqlite3.connect(self.db_path)
|
| 428 |
|
| 429 |
+
# Export battles
|
| 430 |
battles_df = pd.read_sql_query("SELECT * FROM battles", conn)
|
| 431 |
+
|
| 432 |
if len(battles_df) > 0:
|
| 433 |
+
print(f"📤 Syncing {len(battles_df)} battles to HF...")
|
| 434 |
+
|
| 435 |
+
# Convert to Dataset
|
| 436 |
battles_dataset = Dataset.from_pandas(battles_df)
|
| 437 |
+
|
| 438 |
+
# Push to hub with retry logic
|
| 439 |
+
max_retries = 3
|
| 440 |
+
for attempt in range(max_retries):
|
| 441 |
+
try:
|
| 442 |
+
battles_dataset.push_to_hub(
|
| 443 |
+
self.hf_repo_id,
|
| 444 |
+
split="train",
|
| 445 |
+
token=self.hf_token,
|
| 446 |
+
private=True
|
| 447 |
+
)
|
| 448 |
+
print(f"✅ Successfully pushed {len(battles_df)} battles to HF")
|
| 449 |
+
break
|
| 450 |
+
except Exception as push_error:
|
| 451 |
+
if attempt < max_retries - 1:
|
| 452 |
+
print(f"⚠️ Push attempt {attempt + 1} failed, retrying...")
|
| 453 |
+
time.sleep(2) # Wait before retry
|
| 454 |
+
else:
|
| 455 |
+
print(f"❌ Failed to push to HF after {max_retries} attempts: {push_error}")
|
| 456 |
+
|
| 457 |
+
# Also sync model stats for backup
|
| 458 |
+
stats_df = pd.read_sql_query("SELECT * FROM model_stats", conn)
|
| 459 |
+
if len(stats_df) > 0:
|
| 460 |
+
try:
|
| 461 |
+
stats_dataset = Dataset.from_pandas(stats_df)
|
| 462 |
+
stats_dataset.push_to_hub(
|
| 463 |
+
self.hf_repo_id,
|
| 464 |
+
split="stats",
|
| 465 |
+
token=self.hf_token,
|
| 466 |
+
private=True
|
| 467 |
+
)
|
| 468 |
+
print(f"✅ Model stats synced to HF")
|
| 469 |
+
except Exception as e:
|
| 470 |
+
print(f"⚠️ Could not sync stats: {e}")
|
| 471 |
|
| 472 |
conn.close()
|
| 473 |
|
| 474 |
except Exception as e:
|
| 475 |
+
print(f"❌ Critical error in HF sync: {e}")
|
|
|
|
|
|
|
| 476 |
|
| 477 |
def init_database(self):
|
| 478 |
"""Initialize SQLite database - ONLY called when no existing data"""
|
|
|
|
| 532 |
conn.close()
|
| 533 |
|
| 534 |
def save_battle(self, battle: Battle):
|
| 535 |
+
"""Save battle result with proper duplicate prevention and sync"""
|
| 536 |
conn = sqlite3.connect(self.db_path)
|
| 537 |
cursor = conn.cursor()
|
| 538 |
|
| 539 |
try:
|
| 540 |
+
# First check if this battle already exists
|
| 541 |
+
cursor.execute('SELECT id, winner FROM battles WHERE id = ?', (battle.id,))
|
| 542 |
+
existing = cursor.fetchone()
|
| 543 |
+
|
| 544 |
+
if existing and existing[1]:
|
| 545 |
+
print(f"⚠️ Battle {battle.id} already has a winner: {existing[1]}")
|
| 546 |
+
conn.close()
|
| 547 |
+
return # Don't update if already voted
|
| 548 |
+
|
| 549 |
+
# Insert or update the battle
|
| 550 |
cursor.execute('''
|
| 551 |
INSERT OR REPLACE INTO battles VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
| 552 |
''', (
|
|
|
|
| 569 |
winner = battle.winner
|
| 570 |
loser = battle.model_b if winner == battle.model_a else battle.model_a
|
| 571 |
|
| 572 |
+
# Only update stats if this is a new vote
|
| 573 |
+
if not existing or not existing[1]:
|
| 574 |
+
print(f"📊 Updating stats: {winner} wins, {loser} loses")
|
| 575 |
+
|
| 576 |
+
# Update winner stats
|
|
|
|
| 577 |
cursor.execute('''
|
| 578 |
UPDATE model_stats
|
| 579 |
+
SET total_battles = total_battles + 1,
|
| 580 |
+
wins = wins + 1
|
| 581 |
WHERE model_name = ?
|
| 582 |
''', (winner,))
|
| 583 |
+
|
| 584 |
+
# Update loser stats
|
| 585 |
cursor.execute('''
|
| 586 |
UPDATE model_stats
|
| 587 |
+
SET total_battles = total_battles + 1,
|
| 588 |
+
losses = losses + 1
|
| 589 |
WHERE model_name = ?
|
| 590 |
''', (loser,))
|
| 591 |
|
|
|
|
| 593 |
self._update_category_scores(cursor, winner, battle.category, True)
|
| 594 |
self._update_category_scores(cursor, loser, battle.category, False)
|
| 595 |
|
| 596 |
+
# Update ELO ratings
|
| 597 |
self._update_elo_ratings(cursor, winner, loser)
|
| 598 |
+
|
| 599 |
+
print(f"✅ Stats updated for battle {battle.id}")
|
| 600 |
|
| 601 |
conn.commit()
|
| 602 |
+
print(f"💾 Battle {battle.id} saved to local database")
|
| 603 |
+
|
| 604 |
except Exception as e:
|
| 605 |
+
print(f"❌ Error saving battle: {e}")
|
| 606 |
conn.rollback()
|
| 607 |
finally:
|
| 608 |
conn.close()
|
| 609 |
|
| 610 |
# Sync to Hugging Face after saving
|
| 611 |
self._sync_to_hf()
|
|
|
|
|
|
|
| 612 |
|
| 613 |
def _update_category_scores(self, cursor, model, category, is_winner):
|
| 614 |
"""Update category-specific scores"""
|
|
|
|
| 702 |
|
| 703 |
df.insert(0, 'rank', range(1, len(df) + 1))
|
| 704 |
return df
|
| 705 |
+
|
| 706 |
+
def debug_database_state(self):
|
| 707 |
+
"""Debug method to check current database state"""
|
| 708 |
+
conn = sqlite3.connect(self.db_path)
|
| 709 |
+
cursor = conn.cursor()
|
| 710 |
+
|
| 711 |
+
# Check battles count
|
| 712 |
+
cursor.execute("SELECT COUNT(*) FROM battles")
|
| 713 |
+
total_battles = cursor.fetchone()[0]
|
| 714 |
+
|
| 715 |
+
cursor.execute("SELECT COUNT(*) FROM battles WHERE winner IS NOT NULL")
|
| 716 |
+
voted_battles = cursor.fetchone()[0]
|
| 717 |
+
|
| 718 |
+
# Check model stats
|
| 719 |
+
cursor.execute("SELECT * FROM model_stats ORDER BY elo_rating DESC")
|
| 720 |
+
stats = cursor.fetchall()
|
| 721 |
+
|
| 722 |
+
conn.close()
|
| 723 |
+
|
| 724 |
+
print("\n" + "="*50)
|
| 725 |
+
print("📊 DATABASE STATE DEBUG")
|
| 726 |
+
print("="*50)
|
| 727 |
+
print(f"Total battles: {total_battles}")
|
| 728 |
+
print(f"Voted battles: {voted_battles}")
|
| 729 |
+
print("\nModel Stats:")
|
| 730 |
+
print("-"*50)
|
| 731 |
+
for stat in stats:
|
| 732 |
+
print(f"{stat[0]:20} | Battles: {stat[5]:3} | Wins: {stat[6]:3} | ELO: {stat[8]:4}")
|
| 733 |
+
print("="*50 + "\n")
|
| 734 |
+
|
| 735 |
+
return {
|
| 736 |
+
"total_battles": total_battles,
|
| 737 |
+
"voted_battles": voted_battles,
|
| 738 |
+
"model_stats": stats
|
| 739 |
+
}
|
| 740 |
|
| 741 |
# ==================== Fixed LLM Interface with 4 Models ====================
|
| 742 |
class LLMInterface:
|
|
|
|
| 930 |
top_k=40,
|
| 931 |
)
|
| 932 |
|
| 933 |
+
# 전체 응답을 수집
|
| 934 |
full_response = ""
|
| 935 |
|
| 936 |
for chunk in self.gemini_client.models.generate_content_stream(
|
|
|
|
| 953 |
fallback = self._generate_fallback("Gemini-2.5-Pro", prompt, "en")
|
| 954 |
yield fallback
|
| 955 |
|
|
|
|
|
|
|
| 956 |
def _stream_claude(self, prompt: str) -> Generator[str, None, None]:
|
| 957 |
"""Stream Claude Opus 4.1 response"""
|
| 958 |
if not self.claude_client:
|
|
|
|
| 1360 |
}
|
| 1361 |
|
| 1362 |
def vote(self, choice: str, voter_id: str = None):
|
| 1363 |
+
"""Process vote with better error handling"""
|
| 1364 |
if not self.current_battle:
|
| 1365 |
+
print("❌ No active battle to vote on")
|
| 1366 |
return {"error": "No active battle"}
|
| 1367 |
|
| 1368 |
+
# Ensure we have the complete battle data
|
| 1369 |
+
if not self.current_battle.response_a or not self.current_battle.response_b:
|
| 1370 |
+
print("⚠️ Battle responses not complete")
|
| 1371 |
+
return {"error": "Battle responses not complete"}
|
| 1372 |
+
|
| 1373 |
+
# Set the winner
|
| 1374 |
self.current_battle.winner = self.current_battle.model_a if choice == "A" else self.current_battle.model_b
|
| 1375 |
+
self.current_battle.voter_id = voter_id or f"anonymous_{datetime.now().timestamp()}"
|
| 1376 |
+
|
| 1377 |
+
print(f"🗳️ Vote recorded: {choice} -> {self.current_battle.winner}")
|
| 1378 |
|
| 1379 |
+
# Save to database
|
| 1380 |
self.db.save_battle(self.current_battle)
|
| 1381 |
|
| 1382 |
+
# Force immediate sync to HF
|
| 1383 |
+
self.db._sync_to_hf()
|
| 1384 |
+
|
| 1385 |
return {
|
| 1386 |
"model_a": self.current_battle.model_a,
|
| 1387 |
"model_b": self.current_battle.model_b,
|
|
|
|
| 1392 |
"""Get leaderboard from database"""
|
| 1393 |
return self.db.get_leaderboard(category)
|
| 1394 |
|
| 1395 |
+
# ==================== Periodic Sync Function ====================
|
| 1396 |
+
def periodic_sync(arena):
|
| 1397 |
+
"""Periodically sync to HF every 30 seconds"""
|
| 1398 |
+
while True:
|
| 1399 |
+
time.sleep(30)
|
| 1400 |
+
try:
|
| 1401 |
+
arena.db._sync_to_hf()
|
| 1402 |
+
print(f"⏰ Periodic sync completed at {datetime.now()}")
|
| 1403 |
+
except Exception as e:
|
| 1404 |
+
print(f"⏰ Periodic sync failed: {e}")
|
| 1405 |
+
|
| 1406 |
# ==================== Gradio Interface ====================
|
| 1407 |
def create_app():
|
| 1408 |
arena = CreativityArena()
|
|
|
|
| 1779 |
|
| 1780 |
def process_vote(choice, state, lang):
|
| 1781 |
if not state or 'battle' not in state:
|
| 1782 |
+
print("❌ No battle in state")
|
| 1783 |
return (
|
| 1784 |
gr.update(),
|
| 1785 |
gr.update(),
|
| 1786 |
"Error: No active battle"
|
| 1787 |
)
|
| 1788 |
|
| 1789 |
+
# Ensure the battle object is properly set
|
| 1790 |
+
battle_obj = state['battle']
|
| 1791 |
+
arena.current_battle = battle_obj
|
| 1792 |
+
|
| 1793 |
+
print(f"🎯 Processing vote: Choice={choice}, Battle ID={battle_obj.id}")
|
| 1794 |
|
| 1795 |
+
# Process the vote
|
| 1796 |
result = arena.vote(choice)
|
| 1797 |
+
|
| 1798 |
+
if "error" in result:
|
| 1799 |
+
return (
|
| 1800 |
+
gr.update(),
|
| 1801 |
+
gr.update(),
|
| 1802 |
+
f"Error: {result['error']}"
|
| 1803 |
+
)
|
| 1804 |
+
|
| 1805 |
ui = UI_TEXT[lang]
|
| 1806 |
|
| 1807 |
winner_emoji = "🏆" if result['winner'] == result['model_a'] else "🥈"
|
|
|
|
| 1818 |
{ui['elo_updated']}
|
| 1819 |
"""
|
| 1820 |
|
| 1821 |
+
# Debug: Check database state after vote
|
| 1822 |
+
arena.db.debug_database_state()
|
| 1823 |
+
|
| 1824 |
return (
|
| 1825 |
gr.update(value=result['model_a'], visible=True),
|
| 1826 |
gr.update(value=result['model_b'], visible=True),
|
|
|
|
| 1901 |
|
| 1902 |
# ==================== Main ====================
|
| 1903 |
if __name__ == "__main__":
|
| 1904 |
+
print("="*50)
|
| 1905 |
+
print("🚀 AI Models Creativity Battle Arena")
|
| 1906 |
+
print("="*50)
|
| 1907 |
+
print("\n📋 Environment Setup:")
|
| 1908 |
+
print("1. Set OPENAI_API_KEY for GPT-5")
|
| 1909 |
+
print("2. Set GEMINI_API_KEY for Gemini 2.5 Pro")
|
| 1910 |
+
print("3. Set ANTHROPIC_API_KEY for Claude Opus 4.1")
|
| 1911 |
+
print("4. jetXA will use 'aiqtech/tests' by default")
|
| 1912 |
+
print("5. Set HF_TOKEN for persistent data storage (REQUIRED)")
|
| 1913 |
+
print("6. Optional: Set HF_DATASET_NAME (default: ai_models_arena)")
|
| 1914 |
+
print("\n⚠️ Without HF_TOKEN, data will be lost on server restart!")
|
| 1915 |
+
print("\n" + "="*50 + "\n")
|
| 1916 |
+
|
| 1917 |
+
# Check for required API keys
|
| 1918 |
+
if not os.getenv("HF_TOKEN"):
|
| 1919 |
+
print("⚠️ WARNING: HF_TOKEN not set - data will not persist!")
|
| 1920 |
+
print("Set it with: export HF_TOKEN='your_token_here'")
|
| 1921 |
+
print("")
|
| 1922 |
+
|
| 1923 |
+
if not os.getenv("OPENAI_API_KEY"):
|
| 1924 |
+
print("⚠️ GPT-5: No API key found - will use fallback responses")
|
| 1925 |
+
|
| 1926 |
+
if not os.getenv("GEMINI_API_KEY"):
|
| 1927 |
+
print("⚠️ Gemini: No API key found - will use fallback responses")
|
| 1928 |
+
|
| 1929 |
+
if not os.getenv("ANTHROPIC_API_KEY"):
|
| 1930 |
+
print("⚠️ Claude: No API key found - will use fallback responses")
|
| 1931 |
+
|
| 1932 |
+
print("\n🎯 Starting arena with 4 models: GPT-5, jetXA, Gemini 2.5 Pro, Claude Opus 4.1")
|
| 1933 |
+
print("="*50 + "\n")
|
| 1934 |
+
|
| 1935 |
+
# Create app
|
| 1936 |
+
app = create_app()
|
| 1937 |
+
|
| 1938 |
+
# Start periodic sync in background (optional)
|
| 1939 |
+
arena = CreativityArena()
|
| 1940 |
+
sync_thread = threading.Thread(target=lambda: periodic_sync(arena), daemon=True)
|
| 1941 |
+
sync_thread.start()
|
| 1942 |
+
print("✅ Background sync thread started (every 30 seconds)")
|
| 1943 |
+
|
| 1944 |
+
# Launch app
|
| 1945 |
+
app.launch()
|