Implement Leaderboard Graph

#2
Files changed (2) hide show
  1. app.py +90 -1
  2. requirements.txt +1 -0
app.py CHANGED
@@ -1,8 +1,11 @@
1
  import os
2
  import time
3
  from dataclasses import dataclass
 
 
4
 
5
  import gradio as gr
 
6
  import schedule
7
  import wandb
8
  from substrateinterface import Keypair
@@ -14,6 +17,10 @@ demo = gr.Blocks(css=".typewriter {font-family: 'JMH Typewriter', sans-serif;}")
14
  SOURCE_VALIDATOR_UID = int(os.environ["SOURCE_VALIDATOR_UID"])
15
  WANDB_RUN_PATH = os.environ["WANDB_RUN_PATH"]
16
 
 
 
 
 
17
 
18
  @dataclass
19
  class LeaderboardEntry:
@@ -25,6 +32,14 @@ class LeaderboardEntry:
25
  rank: int
26
 
27
 
 
 
 
 
 
 
 
 
28
  def is_valid_run(run: Run):
29
  required_config_keys = ["hotkey", "uid", "contest", "signature"]
30
 
@@ -44,8 +59,80 @@ def is_valid_run(run: Run):
44
  return False
45
 
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  def refresh_leaderboard():
48
- print("Refreshing Leaderboard")
 
49
 
50
  demo.clear()
51
 
@@ -92,6 +179,8 @@ def refresh_leaderboard():
92
  for entry in sorted(entries.values(), key=lambda entry: (entry.score, entry.rank), reverse=True)
93
  ]
94
 
 
 
95
  gr.components.Dataframe(
96
  value=leaderboard,
97
  headers=["Rank", "Uid", "Model", "Score", "Hotkey", "Previous day winner"],
 
1
  import os
2
  import time
3
  from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from zoneinfo import ZoneInfo
6
 
7
  import gradio as gr
8
+ import plotly.graph_objects as go
9
  import schedule
10
  import wandb
11
  from substrateinterface import Keypair
 
17
  SOURCE_VALIDATOR_UID = int(os.environ["SOURCE_VALIDATOR_UID"])
18
  WANDB_RUN_PATH = os.environ["WANDB_RUN_PATH"]
19
 
20
+ BASELINE = 0.0
21
+ GRAPH_HISTORY_DAYS = 30
22
+ MAX_GRAPH_ENTRIES = 5
23
+
24
 
25
  @dataclass
26
  class LeaderboardEntry:
 
32
  rank: int
33
 
34
 
35
+ @dataclass
36
+ class GraphEntry:
37
+ dates: list[datetime]
38
+ scores: list[float]
39
+ models: list[str]
40
+ max_score: float
41
+
42
+
43
  def is_valid_run(run: Run):
44
  required_config_keys = ["hotkey", "uid", "contest", "signature"]
45
 
 
59
  return False
60
 
61
 
62
+ def get_graph_entries(runs: Runs) -> dict[int, GraphEntry]:
63
+ graph_entries: dict[int, GraphEntry] = {}
64
+
65
+ for run in reversed(runs[:GRAPH_HISTORY_DAYS]):
66
+ if not is_valid_run(run):
67
+ continue
68
+
69
+ date = datetime.strptime(run.created_at, "%Y-%m-%dT%H:%M:%S")
70
+
71
+ for key, value in run.summary.items():
72
+ if key.startswith("_"):
73
+ continue
74
+
75
+ uid = int(key)
76
+ score = value["score"]
77
+ model = value["model"]
78
+
79
+ if uid not in graph_entries:
80
+ graph_entries[uid] = GraphEntry([date], [score], [model], score)
81
+ else:
82
+ if score > graph_entries[uid].max_score:
83
+ graph_entries[uid].max_score = score
84
+
85
+ data = graph_entries[uid]
86
+ data.dates.append(date)
87
+ data.scores.append(data.max_score)
88
+ data.models.append(model)
89
+
90
+ return dict(sorted(graph_entries.items(), key=lambda entry: entry[1].max_score, reverse=True)[:MAX_GRAPH_ENTRIES])
91
+
92
+
93
+ def create_graph(graph_entries: dict[int, GraphEntry]):
94
+ fig = go.Figure()
95
+
96
+ for uid, data in graph_entries.items():
97
+ fig.add_trace(go.Scatter(
98
+ x=data.dates,
99
+ y=data.scores,
100
+ customdata=data.models,
101
+ mode="lines+markers",
102
+ name=uid,
103
+ hovertemplate=(
104
+ "<b>Date:</b> %{x|%Y-%m-%d}<br>" +
105
+ "<b>Score:</b> %{y}<br>" +
106
+ "<b>Model:</b> %{customdata}<br>"
107
+ ),
108
+ ))
109
+
110
+ date_range = max(graph_entries.values(), key=lambda entry: len(entry.dates)).dates
111
+
112
+ fig.add_trace(go.Scatter(
113
+ x=date_range,
114
+ y=[BASELINE] * len(date_range),
115
+ line=dict(color="#ff0000", width=3),
116
+ mode="lines",
117
+ name="Baseline",
118
+ ))
119
+
120
+ background_color = gr.themes.default.colors.slate.c800
121
+
122
+ fig.update_layout(
123
+ title="Score Improvements",
124
+ yaxis_title="Score",
125
+ plot_bgcolor=background_color,
126
+ paper_bgcolor=background_color,
127
+ template="plotly_dark"
128
+ )
129
+
130
+ gr.Plot(fig)
131
+
132
+
133
  def refresh_leaderboard():
134
+ now = datetime.now(tz=ZoneInfo("America/New_York"))
135
+ print(f"Refreshing Leaderboard at {now.strftime('%Y-%m-%d %H:%M:%S')}")
136
 
137
  demo.clear()
138
 
 
179
  for entry in sorted(entries.values(), key=lambda entry: (entry.score, entry.rank), reverse=True)
180
  ]
181
 
182
+ create_graph(get_graph_entries(runs))
183
+
184
  gr.components.Dataframe(
185
  value=leaderboard,
186
  headers=["Rank", "Uid", "Model", "Score", "Hotkey", "Previous day winner"],
requirements.txt CHANGED
@@ -3,3 +3,4 @@ gradio
3
  wandb
4
  substrate-interface
5
  schedule
 
 
3
  wandb
4
  substrate-interface
5
  schedule
6
+ plotly