Upload 3 files
Browse files- app.py +85 -17
- auth.py +46 -1
- model_config.py +28 -27
app.py
CHANGED
@@ -13,14 +13,16 @@ from auth import HuggingFaceAuth
|
|
13 |
from benchmark_selection import BenchmarkSelector, create_benchmark_selection_ui
|
14 |
from evaluation_queue import EvaluationQueue, create_model_submission_ui
|
15 |
from leaderboard import Leaderboard, create_leaderboard_ui
|
|
|
16 |
from sample_benchmarks import add_sample_benchmarks
|
17 |
|
18 |
# Initialize components in main thread
|
19 |
db = DynamicHighscoresDB()
|
20 |
auth_manager = HuggingFaceAuth(db)
|
21 |
benchmark_selector = BenchmarkSelector(db, auth_manager)
|
22 |
-
evaluation_queue = EvaluationQueue(db, auth_manager)
|
23 |
leaderboard = Leaderboard(db)
|
|
|
24 |
|
25 |
# Initialize sample benchmarks if none exist
|
26 |
print("Checking for existing benchmarks...")
|
@@ -134,6 +136,7 @@ input[type="text"], input[type="password"], textarea {
|
|
134 |
def js_login_script():
|
135 |
space_host = os.environ.get("SPACE_HOST", "localhost:7860")
|
136 |
redirect_uri = f"https://{space_host}"
|
|
|
137 |
|
138 |
return f"""
|
139 |
<script src="https://unpkg.com/@huggingface/[email protected]/dist/index.umd.min.js"></script>
|
@@ -155,6 +158,19 @@ def js_login_script():
|
|
155 |
document.getElementById("login-status").textContent = "Logged in as: " + oauthResult.userInfo.name;
|
156 |
document.getElementById("login-button").style.display = "none";
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
// Refresh the page to update server-side state
|
159 |
setTimeout(() => window.location.reload(), 1000);
|
160 |
}}
|
@@ -164,29 +180,62 @@ def js_login_script():
|
|
164 |
|
165 |
// Check if user is already logged in from localStorage
|
166 |
const storedUser = localStorage.getItem("hf_user");
|
167 |
-
|
|
|
|
|
168 |
try {{
|
169 |
const userInfo = JSON.parse(storedUser);
|
170 |
document.getElementById("login-status").textContent = "Logged in as: " + userInfo.name;
|
171 |
document.getElementById("login-button").style.display = "none";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}} catch (e) {{
|
173 |
console.error("Error parsing stored user:", e);
|
174 |
}}
|
175 |
}}
|
176 |
|
177 |
// Setup login button
|
178 |
-
document.getElementById("login-button")
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
}})();
|
191 |
</script>
|
192 |
"""
|
@@ -194,10 +243,11 @@ def js_login_script():
|
|
194 |
# Simple manual authentication check
|
195 |
def check_user(request: gr.Request):
|
196 |
if request:
|
|
|
197 |
username = request.headers.get("HF-User")
|
198 |
if username:
|
199 |
# User is logged in via HF Spaces
|
200 |
-
print(f"User logged in: {username}")
|
201 |
user = db.get_user_by_username(username)
|
202 |
if not user:
|
203 |
# Create user if they don't exist
|
@@ -206,6 +256,20 @@ def check_user(request: gr.Request):
|
|
206 |
db.add_user(username, username, is_admin)
|
207 |
user = db.get_user_by_username(username)
|
208 |
return username
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
return None
|
210 |
|
211 |
# Start evaluation queue worker
|
@@ -238,7 +302,7 @@ with gr.Blocks(css=css, title="Dynamic Highscores") as app:
|
|
238 |
|
239 |
gr.Markdown("# 🏆 Dynamic Highscores", elem_classes=["header"])
|
240 |
gr.Markdown("""
|
241 |
-
|
242 |
|
243 |
- **Add your own benchmarks** from HuggingFace datasets
|
244 |
- **Submit your models** for CPU-only evaluation
|
@@ -256,6 +320,9 @@ with gr.Blocks(css=css, title="Dynamic Highscores") as app:
|
|
256 |
|
257 |
with gr.TabItem("🔍 Benchmarks", id=2):
|
258 |
benchmark_ui = create_benchmark_selection_ui(benchmark_selector, auth_manager)
|
|
|
|
|
|
|
259 |
|
260 |
gr.Markdown("""
|
261 |
### About Dynamic Highscores
|
@@ -281,4 +348,5 @@ if __name__ == "__main__":
|
|
281 |
queue_thread.daemon = True
|
282 |
queue_thread.start()
|
283 |
|
284 |
-
app
|
|
|
|
13 |
from benchmark_selection import BenchmarkSelector, create_benchmark_selection_ui
|
14 |
from evaluation_queue import EvaluationQueue, create_model_submission_ui
|
15 |
from leaderboard import Leaderboard, create_leaderboard_ui
|
16 |
+
from model_config import ModelConfigManager, create_community_framework_ui
|
17 |
from sample_benchmarks import add_sample_benchmarks
|
18 |
|
19 |
# Initialize components in main thread
|
20 |
db = DynamicHighscoresDB()
|
21 |
auth_manager = HuggingFaceAuth(db)
|
22 |
benchmark_selector = BenchmarkSelector(db, auth_manager)
|
23 |
+
evaluation_queue = EvaluationQueue(db, auth_manager, ModelConfigManager(db))
|
24 |
leaderboard = Leaderboard(db)
|
25 |
+
model_config_manager = ModelConfigManager(db)
|
26 |
|
27 |
# Initialize sample benchmarks if none exist
|
28 |
print("Checking for existing benchmarks...")
|
|
|
136 |
def js_login_script():
|
137 |
space_host = os.environ.get("SPACE_HOST", "localhost:7860")
|
138 |
redirect_uri = f"https://{space_host}"
|
139 |
+
client_id = os.environ.get("OAUTH_CLIENT_ID", "")
|
140 |
|
141 |
return f"""
|
142 |
<script src="https://unpkg.com/@huggingface/[email protected]/dist/index.umd.min.js"></script>
|
|
|
158 |
document.getElementById("login-status").textContent = "Logged in as: " + oauthResult.userInfo.name;
|
159 |
document.getElementById("login-button").style.display = "none";
|
160 |
|
161 |
+
// Add token to headers for future requests
|
162 |
+
const originalFetch = window.fetch;
|
163 |
+
window.fetch = function(url, options = {{}}) {{
|
164 |
+
if (!options.headers) {{
|
165 |
+
options.headers = {{}};
|
166 |
+
}}
|
167 |
+
|
168 |
+
// Add the token to the headers
|
169 |
+
options.headers["HF-Token"] = oauthResult.accessToken;
|
170 |
+
|
171 |
+
return originalFetch(url, options);
|
172 |
+
}};
|
173 |
+
|
174 |
// Refresh the page to update server-side state
|
175 |
setTimeout(() => window.location.reload(), 1000);
|
176 |
}}
|
|
|
180 |
|
181 |
// Check if user is already logged in from localStorage
|
182 |
const storedUser = localStorage.getItem("hf_user");
|
183 |
+
const storedToken = localStorage.getItem("hf_token");
|
184 |
+
|
185 |
+
if (storedUser && storedToken) {{
|
186 |
try {{
|
187 |
const userInfo = JSON.parse(storedUser);
|
188 |
document.getElementById("login-status").textContent = "Logged in as: " + userInfo.name;
|
189 |
document.getElementById("login-button").style.display = "none";
|
190 |
+
|
191 |
+
// Add token to headers for future requests
|
192 |
+
const originalFetch = window.fetch;
|
193 |
+
window.fetch = function(url, options = {{}}) {{
|
194 |
+
if (!options.headers) {{
|
195 |
+
options.headers = {{}};
|
196 |
+
}}
|
197 |
+
|
198 |
+
// Add the token to the headers
|
199 |
+
options.headers["HF-Token"] = storedToken;
|
200 |
+
|
201 |
+
return originalFetch(url, options);
|
202 |
+
}};
|
203 |
}} catch (e) {{
|
204 |
console.error("Error parsing stored user:", e);
|
205 |
}}
|
206 |
}}
|
207 |
|
208 |
// Setup login button
|
209 |
+
const loginButton = document.getElementById("login-button");
|
210 |
+
if (loginButton) {{
|
211 |
+
loginButton.addEventListener("click", async function() {{
|
212 |
+
try {{
|
213 |
+
const clientId = "{client_id}";
|
214 |
+
if (clientId) {{
|
215 |
+
// Use HuggingFace OAuth
|
216 |
+
const loginUrl = await HfHub.oauthLoginUrl({{
|
217 |
+
clientId: clientId,
|
218 |
+
redirectUrl: "{redirect_uri}",
|
219 |
+
scopes: ["openid", "profile"]
|
220 |
+
}});
|
221 |
+
console.log("Redirecting to:", loginUrl);
|
222 |
+
window.location.href = loginUrl;
|
223 |
+
}} else {{
|
224 |
+
// Fallback to token-based login
|
225 |
+
const token = prompt("Enter your HuggingFace token:");
|
226 |
+
if (token) {{
|
227 |
+
// Set the token as a cookie
|
228 |
+
document.cookie = "hf_token=" + token + "; path=/; SameSite=Strict";
|
229 |
+
// Reload the page to apply the token
|
230 |
+
window.location.reload();
|
231 |
+
}}
|
232 |
+
}}
|
233 |
+
}} catch (error) {{
|
234 |
+
console.error("Error starting login process:", error);
|
235 |
+
alert("Error starting login process. Please try again.");
|
236 |
+
}}
|
237 |
+
}});
|
238 |
+
}}
|
239 |
}})();
|
240 |
</script>
|
241 |
"""
|
|
|
243 |
# Simple manual authentication check
|
244 |
def check_user(request: gr.Request):
|
245 |
if request:
|
246 |
+
# Check for HF-User header from Space OAuth
|
247 |
username = request.headers.get("HF-User")
|
248 |
if username:
|
249 |
# User is logged in via HF Spaces
|
250 |
+
print(f"User logged in via HF-User header: {username}")
|
251 |
user = db.get_user_by_username(username)
|
252 |
if not user:
|
253 |
# Create user if they don't exist
|
|
|
256 |
db.add_user(username, username, is_admin)
|
257 |
user = db.get_user_by_username(username)
|
258 |
return username
|
259 |
+
|
260 |
+
# Check for token in headers (from our custom JS)
|
261 |
+
token = request.headers.get("HF-Token")
|
262 |
+
if token:
|
263 |
+
try:
|
264 |
+
# Validate token with HuggingFace
|
265 |
+
user_info = auth_manager.hf_api.whoami(token=token)
|
266 |
+
if user_info:
|
267 |
+
username = user_info.get("name", "")
|
268 |
+
print(f"User logged in via token: {username}")
|
269 |
+
return username
|
270 |
+
except Exception as e:
|
271 |
+
print(f"Token validation error: {e}")
|
272 |
+
|
273 |
return None
|
274 |
|
275 |
# Start evaluation queue worker
|
|
|
302 |
|
303 |
gr.Markdown("# 🏆 Dynamic Highscores", elem_classes=["header"])
|
304 |
gr.Markdown("""
|
305 |
+
Welcome to Dynamic Highscores - a community benchmark platform for evaluating and comparing language models.
|
306 |
|
307 |
- **Add your own benchmarks** from HuggingFace datasets
|
308 |
- **Submit your models** for CPU-only evaluation
|
|
|
320 |
|
321 |
with gr.TabItem("🔍 Benchmarks", id=2):
|
322 |
benchmark_ui = create_benchmark_selection_ui(benchmark_selector, auth_manager)
|
323 |
+
|
324 |
+
with gr.TabItem("🌐 Community Framework", id=3):
|
325 |
+
community_ui = create_community_framework_ui(model_config_manager)
|
326 |
|
327 |
gr.Markdown("""
|
328 |
### About Dynamic Highscores
|
|
|
348 |
queue_thread.daemon = True
|
349 |
queue_thread.start()
|
350 |
|
351 |
+
# Launch the app
|
352 |
+
app.launch()
|
auth.py
CHANGED
@@ -26,6 +26,18 @@ class HuggingFaceAuth:
|
|
26 |
self.hf_api = HfApi()
|
27 |
self.admin_username = os.environ.get("ADMIN_USERNAME", "Quazim0t0")
|
28 |
self.running_in_space = 'SPACE_ID' in os.environ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
def login_user(self, token):
|
31 |
"""Log in a user with their HuggingFace token.
|
@@ -89,6 +101,7 @@ class HuggingFaceAuth:
|
|
89 |
# Check for HF-User header from Space OAuth
|
90 |
username = request.headers.get("HF-User")
|
91 |
if username:
|
|
|
92 |
# Check if user exists in our database, create if not
|
93 |
user = self.db_manager.get_user_by_username(username)
|
94 |
if not user:
|
@@ -101,6 +114,10 @@ class HuggingFaceAuth:
|
|
101 |
# Fallback to token-based auth for local development
|
102 |
token = request.cookies.get("hf_token")
|
103 |
|
|
|
|
|
|
|
|
|
104 |
if not token:
|
105 |
return None
|
106 |
|
@@ -223,6 +240,31 @@ class HuggingFaceAuth:
|
|
223 |
user_id: User ID to update
|
224 |
"""
|
225 |
self.db_manager.update_submission_date(user_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
|
227 |
# Authentication UI components
|
228 |
def create_login_ui():
|
@@ -296,6 +338,9 @@ def logout_handler():
|
|
296 |
<script>
|
297 |
// Clear the token cookie
|
298 |
document.cookie = "hf_token=; path=/; max-age=0; SameSite=Strict";
|
|
|
|
|
|
|
299 |
// Reload the page
|
300 |
window.location.reload();
|
301 |
</script>
|
@@ -323,4 +368,4 @@ def setup_auth_handlers(login_button, logout_button, user_info, auth_manager):
|
|
323 |
fn=logout_handler,
|
324 |
inputs=[],
|
325 |
outputs=[login_button, logout_button, user_info, gr.HTML()]
|
326 |
-
)
|
|
|
26 |
self.hf_api = HfApi()
|
27 |
self.admin_username = os.environ.get("ADMIN_USERNAME", "Quazim0t0")
|
28 |
self.running_in_space = 'SPACE_ID' in os.environ
|
29 |
+
|
30 |
+
# OAuth configuration
|
31 |
+
self.client_id = os.environ.get("OAUTH_CLIENT_ID", "")
|
32 |
+
self.client_secret = os.environ.get("OAUTH_CLIENT_SECRET", "")
|
33 |
+
self.oauth_scopes = os.environ.get("OAUTH_SCOPES", "openid profile")
|
34 |
+
self.openid_provider_url = os.environ.get("OPENID_PROVIDER_URL", "https://huggingface.co")
|
35 |
+
|
36 |
+
print(f"Running in Space: {self.running_in_space}")
|
37 |
+
if self.running_in_space:
|
38 |
+
print(f"OAuth Client ID: {self.client_id}")
|
39 |
+
print(f"OAuth Scopes: {self.oauth_scopes}")
|
40 |
+
print(f"OpenID Provider URL: {self.openid_provider_url}")
|
41 |
|
42 |
def login_user(self, token):
|
43 |
"""Log in a user with their HuggingFace token.
|
|
|
101 |
# Check for HF-User header from Space OAuth
|
102 |
username = request.headers.get("HF-User")
|
103 |
if username:
|
104 |
+
print(f"Found HF-User header: {username}")
|
105 |
# Check if user exists in our database, create if not
|
106 |
user = self.db_manager.get_user_by_username(username)
|
107 |
if not user:
|
|
|
114 |
# Fallback to token-based auth for local development
|
115 |
token = request.cookies.get("hf_token")
|
116 |
|
117 |
+
if not token:
|
118 |
+
# Try to get token from localStorage via headers
|
119 |
+
token = request.headers.get("HF-Token")
|
120 |
+
|
121 |
if not token:
|
122 |
return None
|
123 |
|
|
|
240 |
user_id: User ID to update
|
241 |
"""
|
242 |
self.db_manager.update_submission_date(user_id)
|
243 |
+
|
244 |
+
def get_oauth_login_url(self, redirect_uri=None):
|
245 |
+
"""Get the OAuth login URL for HuggingFace.
|
246 |
+
|
247 |
+
Args:
|
248 |
+
redirect_uri: Redirect URI after login (optional)
|
249 |
+
|
250 |
+
Returns:
|
251 |
+
str: OAuth login URL
|
252 |
+
"""
|
253 |
+
if not self.client_id:
|
254 |
+
return None
|
255 |
+
|
256 |
+
if not redirect_uri:
|
257 |
+
space_host = os.environ.get("SPACE_HOST", "localhost:7860")
|
258 |
+
redirect_uri = f"https://{space_host}"
|
259 |
+
|
260 |
+
# Create a random state for security
|
261 |
+
state = os.urandom(16).hex()
|
262 |
+
|
263 |
+
# Build the OAuth URL
|
264 |
+
scopes = self.oauth_scopes.replace(" ", "%20")
|
265 |
+
auth_url = f"{self.openid_provider_url}/oauth/authorize?client_id={self.client_id}&redirect_uri={redirect_uri}&scope={scopes}&state={state}&response_type=code"
|
266 |
+
|
267 |
+
return auth_url
|
268 |
|
269 |
# Authentication UI components
|
270 |
def create_login_ui():
|
|
|
338 |
<script>
|
339 |
// Clear the token cookie
|
340 |
document.cookie = "hf_token=; path=/; max-age=0; SameSite=Strict";
|
341 |
+
// Clear localStorage
|
342 |
+
localStorage.removeItem("hf_user");
|
343 |
+
localStorage.removeItem("hf_token");
|
344 |
// Reload the page
|
345 |
window.location.reload();
|
346 |
</script>
|
|
|
368 |
fn=logout_handler,
|
369 |
inputs=[],
|
370 |
outputs=[login_button, logout_button, user_info, gr.HTML()]
|
371 |
+
)
|
model_config.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
"""
|
2 |
-
|
3 |
|
4 |
-
This module provides
|
5 |
-
system for model configurations.
|
6 |
"""
|
7 |
|
8 |
import os
|
@@ -100,20 +99,21 @@ class ModelConfigManager:
|
|
100 |
configs = []
|
101 |
|
102 |
# Read all JSON files in the config directory
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
117 |
|
118 |
return configs
|
119 |
|
@@ -214,7 +214,7 @@ class ModelConfigManager:
|
|
214 |
|
215 |
return True
|
216 |
except Exception as e:
|
217 |
-
print(f"Error updating config
|
218 |
return False
|
219 |
|
220 |
def delete_config(self, config_id):
|
@@ -227,31 +227,32 @@ class ModelConfigManager:
|
|
227 |
bool: True if successful, False otherwise
|
228 |
"""
|
229 |
try:
|
230 |
-
# Check if config
|
231 |
-
|
232 |
-
|
233 |
-
if not os.path.exists(config_path):
|
234 |
return False
|
235 |
|
236 |
# Delete file
|
237 |
-
os.
|
|
|
|
|
|
|
238 |
|
239 |
-
return
|
240 |
except Exception as e:
|
241 |
-
print(f"Error deleting config
|
242 |
return False
|
243 |
|
244 |
def apply_config_to_model_params(self, model_params, config_id):
|
245 |
"""Apply a configuration to model parameters.
|
246 |
|
247 |
Args:
|
248 |
-
model_params: Dictionary of model parameters
|
249 |
config_id: Configuration ID to apply
|
250 |
|
251 |
Returns:
|
252 |
dict: Updated model parameters
|
253 |
"""
|
254 |
-
# Get the configuration
|
255 |
config = self.get_config(config_id)
|
256 |
|
257 |
if not config or "parameters" not in config:
|
|
|
1 |
"""
|
2 |
+
Model configuration system for Dynamic Highscores.
|
3 |
|
4 |
+
This module provides a modular system for model configurations.
|
|
|
5 |
"""
|
6 |
|
7 |
import os
|
|
|
99 |
configs = []
|
100 |
|
101 |
# Read all JSON files in the config directory
|
102 |
+
if os.path.exists(self.config_dir):
|
103 |
+
for filename in os.listdir(self.config_dir):
|
104 |
+
if filename.endswith(".json"):
|
105 |
+
config_path = os.path.join(self.config_dir, filename)
|
106 |
+
try:
|
107 |
+
with open(config_path, "r") as f:
|
108 |
+
config = json.load(f)
|
109 |
+
|
110 |
+
# Add filename (without extension) as ID
|
111 |
+
config_id = os.path.splitext(filename)[0]
|
112 |
+
config["id"] = config_id
|
113 |
+
|
114 |
+
configs.append(config)
|
115 |
+
except Exception as e:
|
116 |
+
print(f"Error loading config {filename}: {e}")
|
117 |
|
118 |
return configs
|
119 |
|
|
|
214 |
|
215 |
return True
|
216 |
except Exception as e:
|
217 |
+
print(f"Error updating config: {e}")
|
218 |
return False
|
219 |
|
220 |
def delete_config(self, config_id):
|
|
|
227 |
bool: True if successful, False otherwise
|
228 |
"""
|
229 |
try:
|
230 |
+
# Check if this is a default config
|
231 |
+
if config_id in self.default_configs:
|
232 |
+
print(f"Cannot delete default config: {config_id}")
|
|
|
233 |
return False
|
234 |
|
235 |
# Delete file
|
236 |
+
config_path = os.path.join(self.config_dir, f"{config_id}.json")
|
237 |
+
if os.path.exists(config_path):
|
238 |
+
os.remove(config_path)
|
239 |
+
return True
|
240 |
|
241 |
+
return False
|
242 |
except Exception as e:
|
243 |
+
print(f"Error deleting config: {e}")
|
244 |
return False
|
245 |
|
246 |
def apply_config_to_model_params(self, model_params, config_id):
|
247 |
"""Apply a configuration to model parameters.
|
248 |
|
249 |
Args:
|
250 |
+
model_params: Dictionary of model parameters to update
|
251 |
config_id: Configuration ID to apply
|
252 |
|
253 |
Returns:
|
254 |
dict: Updated model parameters
|
255 |
"""
|
|
|
256 |
config = self.get_config(config_id)
|
257 |
|
258 |
if not config or "parameters" not in config:
|