tytsui commited on
Commit
f797866
·
1 Parent(s): 0526e23
Files changed (2) hide show
  1. app.py +19 -2
  2. src/leaderboard/student_results.py +86 -47
app.py CHANGED
@@ -10,7 +10,7 @@ from src.leaderboard.student_results import (
10
  )
11
  import time
12
  from src.submission.student_queue import queue_student_submission
13
- from src.envs import EVAL_RESULTS_PATH, RESULTS_REPO, TOKEN
14
 
15
 
16
  demo = gr.Blocks(css=custom_css)
@@ -69,6 +69,7 @@ with demo:
69
  return f"Timed out waiting for results. Please check back later. Submission ID: {ts}"
70
 
71
  try:
 
72
  snapshot_download(
73
  repo_id=RESULTS_REPO,
74
  local_dir=EVAL_RESULTS_PATH,
@@ -77,6 +78,14 @@ with demo:
77
  etag_timeout=30,
78
  token=TOKEN,
79
  )
 
 
 
 
 
 
 
 
80
  except Exception:
81
  pass # Ignore network errors during polling
82
 
@@ -183,7 +192,7 @@ with demo:
183
  if not group_id:
184
  return "Please enter a valid Group ID.", pd.DataFrame()
185
 
186
- # Ensure we have the latest evaluation results locally
187
  try:
188
  snapshot_download(
189
  repo_id=RESULTS_REPO,
@@ -193,6 +202,14 @@ with demo:
193
  etag_timeout=30,
194
  token=TOKEN,
195
  )
 
 
 
 
 
 
 
 
196
  except Exception:
197
  # Network/cache errors shouldn't break the UI; we'll just use whatever is cached locally.
198
  pass
 
10
  )
11
  import time
12
  from src.submission.student_queue import queue_student_submission
13
+ from src.envs import EVAL_REQUESTS_PATH, EVAL_RESULTS_PATH, QUEUE_REPO, RESULTS_REPO, TOKEN
14
 
15
 
16
  demo = gr.Blocks(css=custom_css)
 
69
  return f"Timed out waiting for results. Please check back later. Submission ID: {ts}"
70
 
71
  try:
72
+ # Refresh both results and requests so status/error and metrics stay in sync
73
  snapshot_download(
74
  repo_id=RESULTS_REPO,
75
  local_dir=EVAL_RESULTS_PATH,
 
78
  etag_timeout=30,
79
  token=TOKEN,
80
  )
81
+ snapshot_download(
82
+ repo_id=QUEUE_REPO,
83
+ local_dir=EVAL_REQUESTS_PATH,
84
+ repo_type="dataset",
85
+ tqdm_class=None,
86
+ etag_timeout=30,
87
+ token=TOKEN,
88
+ )
89
  except Exception:
90
  pass # Ignore network errors during polling
91
 
 
192
  if not group_id:
193
  return "Please enter a valid Group ID.", pd.DataFrame()
194
 
195
+ # Ensure we have the latest evaluation results and request metadata locally
196
  try:
197
  snapshot_download(
198
  repo_id=RESULTS_REPO,
 
202
  etag_timeout=30,
203
  token=TOKEN,
204
  )
205
+ snapshot_download(
206
+ repo_id=QUEUE_REPO,
207
+ local_dir=EVAL_REQUESTS_PATH,
208
+ repo_type="dataset",
209
+ tqdm_class=None,
210
+ etag_timeout=30,
211
+ token=TOKEN,
212
+ )
213
  except Exception:
214
  # Network/cache errors shouldn't break the UI; we'll just use whatever is cached locally.
215
  pass
src/leaderboard/student_results.py CHANGED
@@ -5,7 +5,7 @@ from typing import Dict, Optional, Tuple
5
  import numpy as np
6
  import pandas as pd
7
 
8
- from src.envs import EVAL_RESULTS_PATH, PROJ_DIR
9
 
10
 
11
  def _load_all_attempts() -> pd.DataFrame:
@@ -100,22 +100,23 @@ def get_student_leaderboard_df(dataset_name: Optional[str] = None) -> Tuple[pd.D
100
 
101
 
102
  def get_student_status(group_id: str) -> str:
103
- attempts_dir = os.path.join(EVAL_RESULTS_PATH, PROJ_DIR, "student_attempts")
104
  if not os.path.isdir(attempts_dir):
105
  return "No submissions found."
106
 
107
  rows = []
108
- for fname in os.listdir(attempts_dir):
109
- if not fname.endswith(".json"):
110
- continue
111
- try:
112
- with open(os.path.join(attempts_dir, fname), "r") as f:
113
- data = json.load(f)
114
- # Ensure group_id comparison is robust (string vs int)
115
- if str(data.get("group_id", "")).strip() == str(group_id).strip():
116
- rows.append(data)
117
- except Exception:
118
- continue
 
119
 
120
  if not rows:
121
  return "No submissions found."
@@ -137,22 +138,24 @@ def get_student_status(group_id: str) -> str:
137
 
138
 
139
  def get_latest_submission(group_id: str) -> Optional[Dict]:
140
- attempts_dir = os.path.join(EVAL_RESULTS_PATH, PROJ_DIR, "student_attempts")
141
- if not os.path.isdir(attempts_dir):
 
142
  return None
143
 
144
  rows = []
145
- for fname in os.listdir(attempts_dir):
146
- if not fname.endswith(".json"):
147
- continue
148
- try:
149
- with open(os.path.join(attempts_dir, fname), "r") as f:
150
- data = json.load(f)
151
- # Ensure group_id comparison is robust (string vs int)
152
- if str(data.get("group_id", "")).strip() == str(group_id).strip():
153
- rows.append(data)
154
- except Exception:
155
- continue
 
156
 
157
  if not rows:
158
  return None
@@ -163,28 +166,64 @@ def get_latest_submission(group_id: str) -> Optional[Dict]:
163
 
164
 
165
  def get_group_submission_history(group_id: str) -> pd.DataFrame:
166
- """Return all submissions for a given group_id, sorted by timestamp (latest first)."""
167
- attempts_dir = os.path.join(EVAL_RESULTS_PATH, PROJ_DIR, "student_attempts")
168
- if not os.path.isdir(attempts_dir):
169
- return pd.DataFrame()
170
 
171
- rows = []
172
- for fname in os.listdir(attempts_dir):
173
- if not fname.endswith(".json"):
174
- continue
175
- try:
176
- with open(os.path.join(attempts_dir, fname), "r") as f:
177
- data = json.load(f)
178
- # Ensure group_id comparison is robust (string vs int)
179
- if str(data.get("group_id", "")).strip() == str(group_id).strip():
180
- rows.append(data)
181
- except Exception:
182
- continue
183
 
184
- if not rows:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  return pd.DataFrame()
186
 
187
- df = pd.DataFrame(rows)
188
- if "timestamp" in df.columns:
189
- df = df.sort_values("timestamp", ascending=False)
190
- return df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import numpy as np
6
  import pandas as pd
7
 
8
+ from src.envs import EVAL_REQUESTS_PATH, EVAL_RESULTS_PATH, PROJ_DIR
9
 
10
 
11
  def _load_all_attempts() -> pd.DataFrame:
 
100
 
101
 
102
  def get_student_status(group_id: str) -> str:
103
+ attempts_dir = os.path.join(EVAL_REQUESTS_PATH, PROJ_DIR)
104
  if not os.path.isdir(attempts_dir):
105
  return "No submissions found."
106
 
107
  rows = []
108
+ for root, _, files in os.walk(attempts_dir):
109
+ for fname in files:
110
+ if not fname.endswith(".json"):
111
+ continue
112
+ try:
113
+ with open(os.path.join(root, fname), "r") as f:
114
+ data = json.load(f)
115
+ # Ensure group_id comparison is robust (string vs int)
116
+ if str(data.get("group_id", "")).strip() == str(group_id).strip():
117
+ rows.append(data)
118
+ except Exception:
119
+ continue
120
 
121
  if not rows:
122
  return "No submissions found."
 
138
 
139
 
140
  def get_latest_submission(group_id: str) -> Optional[Dict]:
141
+ """Return the latest request.json entry for a given group_id (used for status + error)."""
142
+ requests_dir = os.path.join(EVAL_REQUESTS_PATH, PROJ_DIR)
143
+ if not os.path.isdir(requests_dir):
144
  return None
145
 
146
  rows = []
147
+ for root, _, files in os.walk(requests_dir):
148
+ for fname in files:
149
+ if not fname.endswith(".json"):
150
+ continue
151
+ try:
152
+ with open(os.path.join(root, fname), "r") as f:
153
+ data = json.load(f)
154
+ # Ensure group_id comparison is robust (string vs int)
155
+ if str(data.get("group_id", "")).strip() == str(group_id).strip():
156
+ rows.append(data)
157
+ except Exception:
158
+ continue
159
 
160
  if not rows:
161
  return None
 
166
 
167
 
168
  def get_group_submission_history(group_id: str) -> pd.DataFrame:
169
+ """
170
+ Return all submissions for a given group_id, sorted by timestamp (latest first).
 
 
171
 
172
+ Status and error are sourced from request.json entries (request dataset),
173
+ while performance metrics are merged in from the results student_attempts
174
+ table when available.
175
+ """
176
+ requests_dir = os.path.join(EVAL_REQUESTS_PATH, PROJ_DIR)
177
+ if not os.path.isdir(requests_dir):
178
+ return pd.DataFrame()
 
 
 
 
 
179
 
180
+ request_rows = []
181
+ for root, _, files in os.walk(requests_dir):
182
+ for fname in files:
183
+ if not fname.endswith(".json"):
184
+ continue
185
+ try:
186
+ with open(os.path.join(root, fname), "r") as f:
187
+ data = json.load(f)
188
+ if str(data.get("group_id", "")).strip() == str(group_id).strip():
189
+ # Normalize fields we care about
190
+ datasets = data.get("datasets") or []
191
+ dataset = datasets[0] if isinstance(datasets, list) and datasets else ""
192
+ request_rows.append(
193
+ {
194
+ "group_id": str(data.get("group_id", "")).strip(),
195
+ "alias": data.get("alias"),
196
+ "timestamp": data.get("timestamp", ""),
197
+ "status": data.get("status", "UNKNOWN"),
198
+ "error": data.get("error", ""),
199
+ "dataset": dataset,
200
+ }
201
+ )
202
+ except Exception:
203
+ continue
204
+
205
+ if not request_rows:
206
  return pd.DataFrame()
207
 
208
+ requests_df = pd.DataFrame(request_rows)
209
+
210
+ # Merge in performance metrics from results student_attempts when possible.
211
+ attempts_df = _load_all_attempts()
212
+ if not attempts_df.empty:
213
+ attempts_df = attempts_df.copy()
214
+ attempts_df["group_id"] = attempts_df["group_id"].astype(str).str.strip()
215
+ requests_df["group_id"] = requests_df["group_id"].astype(str).str.strip()
216
+
217
+ merged = requests_df.merge(
218
+ attempts_df,
219
+ on=["group_id", "timestamp"],
220
+ how="left",
221
+ suffixes=("", "_results"),
222
+ )
223
+ else:
224
+ merged = requests_df
225
+
226
+ if "timestamp" in merged.columns:
227
+ merged = merged.sort_values("timestamp", ascending=False)
228
+
229
+ return merged