rusticluftig commited on
Commit
17bb6e0
1 Parent(s): f2a2662

First pass at finetuning api

Browse files
Files changed (3) hide show
  1. README.md +2 -2
  2. app.py +23 -13
  3. utils.py +8 -10
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: Sn9
3
- emoji: 👁
4
  colorFrom: purple
5
  colorTo: pink
6
  sdk: gradio
 
1
  ---
2
+ title: Finetuning subnet
3
+ emoji: :em
4
  colorFrom: purple
5
  colorTo: pink
6
  sdk: gradio
app.py CHANGED
@@ -2,6 +2,7 @@
2
 
3
  import os
4
  import datetime
 
5
  import gradio as gr
6
 
7
  from dotenv import load_dotenv
@@ -13,14 +14,18 @@ import utils
13
  FONT = (
14
  """<link href="https://fonts.cdnfonts.com/css/jmh-typewriter" rel="stylesheet">"""
15
  )
16
- TITLE = """<h1 align="center" id="space-title" class="typewriter">Subnet 9 Leaderboard</h1>"""
17
- HEADER = """<h2 align="center" class="typewriter"><a href="https://github.com/macrocosm-os/pretraining" target="_blank">Subnet 9</a> is a <a href="https://bittensor.com/" target="_blank">Bittensor</a> subnet that rewards miners for producing pretrained Foundation-Models on the <a href="https://huggingface.co/datasets/tiiuae/falcon-refinedweb" target="_blank">Falcon Refined Web dataset</a>. It acts like a continuous benchmark whereby miners are rewarded for attaining the best losses on randomly sampled pages of Falcon.<br/>The models with the best head-to-head loss on the evaluation data receive a steady emission of TAO.</h3>"""
18
-
19
  EVALUATION_DETAILS = """<ul><li><b>Name:</b> the 🤗 Hugging Face model name (click to go to the model card)</li><li><b>Rewards / Day:</b> the expected rewards per day based on current ranking.</li><li><b>Last Average Loss:</b> the last loss value on the evaluation data for the model as calculated by a validator (lower is better)</li><li><b>UID:</b> the Bittensor UID of the miner</li><li><b>Block:</b> the Bittensor block that the model was submitted in</li></ul><br/>More stats on <a href="https://taostats.io/subnets/netuid-9/" target="_blank">taostats</a>."""
20
  EVALUATION_HEADER = """<h3 align="center">Shows the latest internal evaluation statistics as calculated by the Opentensor validator</h3>"""
21
 
 
 
 
 
22
 
23
- HF_REPO_ID = "macrocosm-os/pretraining-leaderboard"
24
  SECONDS_PER_BLOCK = 12
25
 
26
  load_dotenv()
@@ -68,6 +73,7 @@ def main():
68
  # TODO: Re-enable once ""SubtensorModule.BlocksSinceEpoch" not found" issue is resolved.
69
  # gr.HTML(value=get_next_update_div(current_block, next_epoch_block))
70
 
 
71
  gr.Label(
72
  value={
73
  f"{c.namespace}/{c.name} ({c.commit[0:8]}) · (τ{round(c.emission, 2):,})": c.incentive
@@ -85,19 +91,23 @@ def main():
85
  with gr.Accordion("Evaluation Stats"):
86
  gr.HTML(EVALUATION_HEADER)
87
  show_stale = gr.Checkbox(label="Show Stale", interactive=True)
88
- leaderboard_table = gr.components.Dataframe(
89
- value=utils.leaderboard_data(model_data, scores, show_stale.value),
90
- headers=["Name", "Win Rate", "Average Loss", "Weight", "UID", "Block"],
91
- datatype=["markdown", "number", "number", "number", "number", "number"],
92
- elem_id="leaderboard-table",
93
- interactive=False,
94
- visible=True,
95
- )
 
 
 
 
96
  gr.HTML(EVALUATION_DETAILS)
97
  show_stale.change(
98
  lambda stale: utils.leaderboard_data(model_data, scores, stale),
99
  inputs=[show_stale],
100
- outputs=leaderboard_table,
101
  )
102
 
103
  gr.LinePlot(
 
2
 
3
  import os
4
  import datetime
5
+ from typing import Dict
6
  import gradio as gr
7
 
8
  from dotenv import load_dotenv
 
14
  FONT = (
15
  """<link href="https://fonts.cdnfonts.com/css/jmh-typewriter" rel="stylesheet">"""
16
  )
17
+ TITLE = """<h1 align="center" id="space-title" class="typewriter">Finetuning Subnet Leaderboard</h1>"""
18
+ HEADER = """<h2 align="center" class="typewriter"><a href="https://github.com/macrocosm-os/finetuning" target="_blank">Finetuning</a> is a <a href="https://bittensor.com/" target="_blank">Bittensor</a> subnet that rewards miners for producing finetuned models in defined competitions. The model with the best head-to-head score in each competition receive a steady emission of TAO.</h3>"""
19
+ # TODO: Update links once subnet is regged.
20
  EVALUATION_DETAILS = """<ul><li><b>Name:</b> the 🤗 Hugging Face model name (click to go to the model card)</li><li><b>Rewards / Day:</b> the expected rewards per day based on current ranking.</li><li><b>Last Average Loss:</b> the last loss value on the evaluation data for the model as calculated by a validator (lower is better)</li><li><b>UID:</b> the Bittensor UID of the miner</li><li><b>Block:</b> the Bittensor block that the model was submitted in</li></ul><br/>More stats on <a href="https://taostats.io/subnets/netuid-9/" target="_blank">taostats</a>."""
21
  EVALUATION_HEADER = """<h3 align="center">Shows the latest internal evaluation statistics as calculated by the Opentensor validator</h3>"""
22
 
23
+ # A map of competition IDs to HTML descriptions.
24
+ COMPETITION_DETAILS: Dict[int, str] = {
25
+ 1: """<b>Competition ID 1:</b> Produce the best fine-tuned model from a Subnet 9 pretrained model. Models are evaluated using synthetic prompt/response data from Subnet 18."""
26
+ }
27
 
28
+ HF_REPO_ID = "macrocosm-os/finetuning-leaderboard"
29
  SECONDS_PER_BLOCK = 12
30
 
31
  load_dotenv()
 
73
  # TODO: Re-enable once ""SubtensorModule.BlocksSinceEpoch" not found" issue is resolved.
74
  # gr.HTML(value=get_next_update_div(current_block, next_epoch_block))
75
 
76
+ # TODO: Figure out the best approach to showing the per competition rewards.
77
  gr.Label(
78
  value={
79
  f"{c.namespace}/{c.name} ({c.commit[0:8]}) · (τ{round(c.emission, 2):,})": c.incentive
 
91
  with gr.Accordion("Evaluation Stats"):
92
  gr.HTML(EVALUATION_HEADER)
93
  show_stale = gr.Checkbox(label="Show Stale", interactive=True)
94
+ competition_leaderboards = []
95
+ # TODO: Dynamically generate per-competition leaderboards based on model_data.
96
+ with gr.Accordion("Finetuned SN9 competition"):
97
+ gr.HTML(COMPETITION_DETAILS[1])
98
+ competition_leaderboards.append(gr.components.Dataframe(
99
+ value=utils.leaderboard_data(model_data, scores, show_stale.value),
100
+ headers=["Name", "Win Rate", "Average Loss", "Weight", "UID", "Block"],
101
+ datatype=["markdown", "number", "number", "number", "number", "number"],
102
+ elem_id="leaderboard-table",
103
+ interactive=False,
104
+ visible=True,
105
+ ))
106
  gr.HTML(EVALUATION_DETAILS)
107
  show_stale.change(
108
  lambda stale: utils.leaderboard_data(model_data, scores, stale),
109
  inputs=[show_stale],
110
+ outputs=competition_leaderboards,
111
  )
112
 
113
  gr.LinePlot(
utils.py CHANGED
@@ -148,9 +148,10 @@ def get_subnet_data(
148
 
149
  def get_wandb_runs(project: str, filters: Dict[str, Any]) -> List:
150
  """Get the latest runs from Wandb, retrying infinitely until we get them.
151
-
152
  Returns:
153
- List: List of runs matching the provided filters, newest run (by creation time) first."""
 
154
  while True:
155
  api = wandb.Api(api_key=WANDB_TOKEN)
156
  runs = list(
@@ -172,7 +173,7 @@ def get_scores(
172
  wandb_runs: List,
173
  ) -> Dict[int, Dict[str, Optional[float]]]:
174
  """Returns the most recent scores for the provided UIDs.
175
-
176
  Args:
177
  uids (List[int]): List of UIDs to get scores for.
178
  wandb_runs (List): List of validator runs from Wandb. Requires the runs are provided in descending order.
@@ -204,6 +205,7 @@ def get_scores(
204
  "win_rate": uid_data.get("win_rate", None),
205
  "win_total": uid_data.get("win_total", None),
206
  "weight": uid_data.get("weight", None),
 
207
  "fresh": is_fresh,
208
  }
209
  if len(result) == len(uids):
@@ -244,12 +246,7 @@ def get_losses_over_time(wandb_runs: List) -> pd.DataFrame:
244
  best_loss = math.inf
245
  for _, uid_data in all_uid_data.items():
246
  loss = uid_data.get("average_loss", math.inf)
247
- # Filter out the numbers from the exploit and when validators lost the best model.
248
- if (
249
- loss < best_loss
250
- and (loss > 2.5 or timestamp > datetime.datetime(2024, 2, 12))
251
- and (loss < 5 or timestamp > datetime.datetime(2024, 3, 27))
252
- ):
253
  best_loss = uid_data["average_loss"]
254
  if best_loss != math.inf:
255
  timestamps.append(timestamp)
@@ -386,6 +383,7 @@ def load_state_vars() -> dict[Any]:
386
  bt.logging.success(f"Loaded {len(model_data)} models")
387
  vali_runs = get_wandb_runs(
388
  project=VALIDATOR_WANDB_PROJECT,
 
389
  filters={"config.type": "validator", "config.uid": 238},
390
  )
391
 
@@ -427,7 +425,7 @@ def load_state_vars() -> dict[Any]:
427
 
428
 
429
  def test_load_state_vars():
430
-
431
  subtensor = bt.subtensor("finney")
432
  metagraph = subtensor.metagraph(NETUID, lite=True)
433
  model_data = [
 
148
 
149
  def get_wandb_runs(project: str, filters: Dict[str, Any]) -> List:
150
  """Get the latest runs from Wandb, retrying infinitely until we get them.
151
+
152
  Returns:
153
+ List: List of runs matching the provided filters, newest run (by creation time) first.
154
+ """
155
  while True:
156
  api = wandb.Api(api_key=WANDB_TOKEN)
157
  runs = list(
 
173
  wandb_runs: List,
174
  ) -> Dict[int, Dict[str, Optional[float]]]:
175
  """Returns the most recent scores for the provided UIDs.
176
+
177
  Args:
178
  uids (List[int]): List of UIDs to get scores for.
179
  wandb_runs (List): List of validator runs from Wandb. Requires the runs are provided in descending order.
 
205
  "win_rate": uid_data.get("win_rate", None),
206
  "win_total": uid_data.get("win_total", None),
207
  "weight": uid_data.get("weight", None),
208
+ "competition_id": uid_data.get("competition_id", None),
209
  "fresh": is_fresh,
210
  }
211
  if len(result) == len(uids):
 
246
  best_loss = math.inf
247
  for _, uid_data in all_uid_data.items():
248
  loss = uid_data.get("average_loss", math.inf)
249
+ if loss < best_loss:
 
 
 
 
 
250
  best_loss = uid_data["average_loss"]
251
  if best_loss != math.inf:
252
  timestamps.append(timestamp)
 
383
  bt.logging.success(f"Loaded {len(model_data)} models")
384
  vali_runs = get_wandb_runs(
385
  project=VALIDATOR_WANDB_PROJECT,
386
+ # TODO: Update to point to the OTF vali on finetuning
387
  filters={"config.type": "validator", "config.uid": 238},
388
  )
389
 
 
425
 
426
 
427
  def test_load_state_vars():
428
+ # TODO: Change to finetuning data.
429
  subtensor = bt.subtensor("finney")
430
  metagraph = subtensor.metagraph(NETUID, lite=True)
431
  model_data = [