emozilla commited on
Commit
7b8017a
1 Parent(s): ad6bebd

initial commit

Browse files
Files changed (5) hide show
  1. .gitignore +7 -0
  2. README.md +2 -2
  3. app.py +155 -0
  4. nousgirl.png +0 -0
  5. requirements.txt +6 -0
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ env/
2
+ bin/
3
+ cd/
4
+ lib
5
+ lib64
6
+ pyvenv.cfg
7
+ .env
README.md CHANGED
@@ -1,10 +1,10 @@
1
  ---
2
  title: Finetuning Subnet Leaderboard
3
- emoji: 🚀
4
  colorFrom: indigo
5
  colorTo: blue
6
  sdk: gradio
7
- sdk_version: 4.16.0
8
  app_file: app.py
9
  pinned: false
10
  ---
 
1
  ---
2
  title: Finetuning Subnet Leaderboard
3
+ emoji: ⚒️
4
  colorFrom: indigo
5
  colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 3.41.0
8
  app_file: app.py
9
  pinned: false
10
  ---
app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import bittensor as bt
3
+ import typing
4
+ from bittensor.extrinsics.serving import get_metadata
5
+ from dataclasses import dataclass
6
+ import requests
7
+ import wandb
8
+ import math
9
+ import os
10
+ import statistics
11
+ from dotenv import load_dotenv
12
+ from huggingface_hub import HfApi
13
+ from apscheduler.schedulers.background import BackgroundScheduler
14
+
15
+ load_dotenv()
16
+
17
+ TITLE = """<h1 align="center" id="space-title">Subnet 6 Leaderboard</h1>"""
18
+ IMAGE = """<a href="https://discord.gg/jqVphNsB4H" target="_blank"><img src="https://i.ibb.co/88wyVQ7/nousgirl.png" alt="nousgirl" style="margin: auto; width: 20%; border: 0;" /></a>"""
19
+ HEADER = """<h2 align="center"><a href="https://github.com/NousResearch/finetuning-subnet" target="_blank">Subnet 6</a> is a <a href="https://bittensor.com/" target="_blank">Bittensor</a> subnet that incentivizes the creation of the best open models by evaluating submissions on a constant stream of newly generated syntheic GPT-4 data. The models with the best head-to-head loss on the evaluation data receive a steady emission of TAO.</h3>"""
20
+ DETAILS = """<b>Name</b> is the 🤗 Hugging Face model name (click to go to the model card). <b>Rewards / Day</b> are the expected rewards per day for each model. <b>Last Average Loss</b> is the last loss value on the evaluation data for the model as calculated by a validator (lower is better). <b>UID</b> is the Bittensor user id of the submitter. More stats on <a href="https://taostats.io/subnets/netuid-6/" target="_blank">taostats</a>."""
21
+ VALIDATOR_WANDB_PROJECT = os.environ["VALIDATOR_WANDB_PROJECT"]
22
+ H4_TOKEN = os.environ.get("H4_TOKEN", None)
23
+ API = HfApi(token=H4_TOKEN)
24
+ REPO_ID = "NousResearch/finetuning_subnet_leaderboard"
25
+ MAX_AVG_LOSS_POINTS = 5
26
+
27
+ subtensor = bt.subtensor("finney")
28
+ metagraph: bt.metagraph = subtensor.metagraph(6, lite=False)
29
+
30
+ @dataclass
31
+ class ModelData:
32
+ uid: int
33
+ hotkey: str
34
+ namespace: str
35
+ name: str
36
+ commit: str
37
+ hash: str
38
+ block: int
39
+ incentive: float
40
+ emission: float
41
+
42
+ @classmethod
43
+ def from_compressed_str(cls, uid: int, hotkey: str, cs: str, block: int, incentive: float, emission: float):
44
+ """Returns an instance of this class from a compressed string representation"""
45
+ tokens = cs.split(":")
46
+ return ModelData(
47
+ uid=uid,
48
+ hotkey=hotkey,
49
+ namespace=tokens[0],
50
+ name=tokens[1],
51
+ commit=tokens[2] if tokens[2] != "None" else None,
52
+ hash=tokens[3] if tokens[3] != "None" else None,
53
+ block=block,
54
+ incentive=incentive,
55
+ emission=emission
56
+ )
57
+
58
+ def get_tao_price():
59
+ return float(requests.get("https://api.kucoin.com/api/v1/market/stats?symbol=TAO-USDT").json()["data"]["last"])
60
+
61
+ def print_validator_weights(metagraph: bt.metagraph):
62
+ for uid in metagraph.uids.tolist():
63
+ if metagraph.validator_trust[uid].item() > 0:
64
+ print(f"uid: {uid}")
65
+ for ouid in metagraph.uids.tolist():
66
+ if ouid == uid:
67
+ continue
68
+ weight = round(metagraph.weights[uid][ouid].item(), 4)
69
+ if weight > 0:
70
+ print(f" {ouid} = {weight}")
71
+
72
+ def get_subnet_data(metagraph: bt.metagraph) -> typing.List[ModelData]:
73
+ result = []
74
+ for uid in metagraph.uids.tolist():
75
+ hotkey = metagraph.hotkeys[uid]
76
+ metadata = get_metadata(subtensor, metagraph.netuid, hotkey)
77
+ if not metadata:
78
+ continue
79
+
80
+ commitment = metadata["info"]["fields"][0]
81
+ hex_data = commitment[list(commitment.keys())[0]][2:]
82
+ chain_str = bytes.fromhex(hex_data).decode()
83
+ block = metadata["block"]
84
+ incentive = metagraph.incentive[uid].nan_to_num().item()
85
+ emission = metagraph.emission[uid].nan_to_num().item() * 20 # convert to daily TAO
86
+
87
+ model_data = None
88
+ try:
89
+ model_data = ModelData.from_compressed_str(uid, hotkey, chain_str, block, incentive, emission)
90
+ except:
91
+ continue
92
+
93
+ result.append(model_data)
94
+ return result
95
+
96
+ def get_avg_loss(uids: typing.List[int]) -> typing.Dict[int, float]:
97
+ api = wandb.Api()
98
+ runs = list(api.runs(VALIDATOR_WANDB_PROJECT))
99
+ runs.reverse()
100
+
101
+ result = {}
102
+ for run in runs:
103
+ history = run.history()
104
+ for uid in uids:
105
+ if uid in result.keys():
106
+ continue
107
+ key = f"uid_data.{uid}"
108
+ if key in history:
109
+ data = [x for x in list(history[key]) if not math.isnan(x)][-MAX_AVG_LOSS_POINTS:]
110
+ if len(data) > 0:
111
+ result[uid] = statistics.fmean(data)
112
+ if len(result.keys()) == len(uids):
113
+ break
114
+ return result
115
+
116
+
117
+ tao_price = get_tao_price()
118
+
119
+ leaderboard_df = get_subnet_data(metagraph)
120
+ leaderboard_df.sort(key=lambda x: x.incentive, reverse=True)
121
+
122
+ losses = get_avg_loss([x.uid for x in leaderboard_df])
123
+
124
+ demo = gr.Blocks()
125
+ with demo:
126
+ gr.HTML(TITLE)
127
+ gr.HTML(IMAGE)
128
+ gr.HTML(HEADER)
129
+ gr.HTML(DETAILS)
130
+
131
+ value = [
132
+ [
133
+ f'[{c.namespace}/{c.name}](https://huggingface.co/{c.namespace}/{c.name})',
134
+ f'${round(c.emission * tao_price, 2):,} (τ{round(c.emission, 2):,})',
135
+ f'{round(losses[c.uid], 4) if c.uid in losses.keys() else ""}',
136
+ c.uid
137
+ ] for c in leaderboard_df
138
+ ]
139
+ leaderboard_table = gr.components.Dataframe(
140
+ value=value,
141
+ headers=["Name", "Rewards / Day", "Last Average Loss", "UID",],
142
+ datatype=["markdown", "number", "number", "number"],
143
+ elem_id="leaderboard-table",
144
+ interactive=False,
145
+ visible=True,
146
+ )
147
+
148
+ def restart_space():
149
+ API.restart_space(repo_id=REPO_ID, token=H4_TOKEN)
150
+
151
+ scheduler = BackgroundScheduler()
152
+ scheduler.add_job(restart_space, "interval", seconds=60 * 15) # restart every 15 minutes
153
+ scheduler.start()
154
+
155
+ demo.launch()
nousgirl.png ADDED
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ bittensor==6.7.0
2
+ requests==2.31.0
3
+ wandb==0.16.2
4
+ python-dotenv==1.0.1
5
+ APScheduler==3.10.1
6
+ huggingface-hub>=0.18.0