Spaces:
Running
Running
File size: 5,803 Bytes
af86b7d 4831588 5dd5427 af86b7d 3c9c1d8 a918c3e af86b7d a918c3e 53d138c af86b7d 53d138c af86b7d 5beb699 e4e854a 5beb699 e4e854a af86b7d 5dd5427 4831588 53d138c 3c9c1d8 0787f2d 3c9c1d8 0787f2d 793a92d 3c9c1d8 53d138c af86b7d e4e854a af86b7d e4e854a af86b7d e4e854a af86b7d e4e854a af86b7d 53d138c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import os
from dotenv import load_dotenv
import logging
# Load environment variables from .env file
load_dotenv()
# Import HF Leaderboard Service
from hf_leaderboard import HFLeaderboardService
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
# Add CORS middleware for local development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize HF Leaderboard Service
# Using dedicated leaderboard Space: milwright/cloze-leaderboard
hf_token = os.getenv("HF_TOKEN")
try:
hf_leaderboard = HFLeaderboardService(
repo_id="milwright/cloze-leaderboard", # Dedicated leaderboard Space
token=hf_token
)
except ValueError as e:
logger.warning(f"Could not initialize HF Leaderboard Service: {e}")
logger.warning("Leaderboard will use localStorage fallback only")
hf_leaderboard = None
# Pydantic models for API
class LeaderboardEntry(BaseModel):
initials: str
level: int
round: int
passagesPassed: int
date: str
class LeaderboardResponse(BaseModel):
success: bool
leaderboard: List[LeaderboardEntry]
message: Optional[str] = None
# Mount static files
app.mount("/src", StaticFiles(directory="src"), name="src")
@app.get("/icon.png")
async def get_icon():
# Redirect to GitHub-hosted icon
return RedirectResponse(url="https://raw.githubusercontent.com/zmuhls/cloze-reader/main/icon.png")
@app.get("/")
async def read_root():
# Read the HTML file and inject environment variables
with open("index.html", "r") as f:
html_content = f.read()
# Inject environment variables as a script
openrouter_key = os.getenv("OPENROUTER_API_KEY", "")
hf_key = os.getenv("HF_API_KEY", "")
# Create a CSP-compliant way to inject the keys
env_script = f"""
<meta name="openrouter-key" content="{openrouter_key}">
<meta name="hf-key" content="{hf_key}">
<script src="./src/init-env.js"></script>
"""
# Insert the script before closing head tag
html_content = html_content.replace("</head>", env_script + "</head>")
return HTMLResponse(content=html_content)
# ===== LEADERBOARD API ENDPOINTS =====
@app.get("/api/leaderboard", response_model=LeaderboardResponse)
async def get_leaderboard():
"""
Get current leaderboard data from HF Hub
"""
if not hf_leaderboard:
return {
"success": True,
"leaderboard": [],
"message": "HF leaderboard not available (using localStorage only)"
}
try:
leaderboard = hf_leaderboard.get_leaderboard()
return {
"success": True,
"leaderboard": leaderboard,
"message": f"Retrieved {len(leaderboard)} entries"
}
except Exception as e:
logger.error(f"Error fetching leaderboard: {e}")
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/leaderboard/add")
async def add_leaderboard_entry(entry: LeaderboardEntry):
"""
Add new entry to leaderboard
"""
if not hf_leaderboard:
raise HTTPException(status_code=503, detail="HF leaderboard not available")
try:
success = hf_leaderboard.add_entry(entry.dict())
if success:
return {
"success": True,
"message": f"Added {entry.initials} to leaderboard"
}
else:
raise HTTPException(status_code=500, detail="Failed to add entry")
except ValueError as e:
raise HTTPException(status_code=403, detail=str(e))
except Exception as e:
logger.error(f"Error adding entry: {e}")
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/leaderboard/update")
async def update_leaderboard(entries: List[LeaderboardEntry]):
"""
Update entire leaderboard (replace all data)
"""
if not hf_leaderboard:
raise HTTPException(status_code=503, detail="HF leaderboard not available")
try:
success = hf_leaderboard.update_leaderboard([e.dict() for e in entries])
if success:
return {
"success": True,
"message": "Leaderboard updated successfully"
}
else:
raise HTTPException(status_code=500, detail="Failed to update leaderboard")
except ValueError as e:
raise HTTPException(status_code=403, detail=str(e))
except Exception as e:
logger.error(f"Error updating leaderboard: {e}")
raise HTTPException(status_code=500, detail=str(e))
@app.delete("/api/leaderboard/clear")
async def clear_leaderboard():
"""
Clear all leaderboard data (admin only)
"""
if not hf_leaderboard:
raise HTTPException(status_code=503, detail="HF leaderboard not available")
try:
success = hf_leaderboard.clear_leaderboard()
if success:
return {
"success": True,
"message": "Leaderboard cleared"
}
else:
raise HTTPException(status_code=500, detail="Failed to clear leaderboard")
except ValueError as e:
raise HTTPException(status_code=403, detail=str(e))
except Exception as e:
logger.error(f"Error clearing leaderboard: {e}")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |