root commited on
Commit
81db2be
ยท
0 Parent(s):

add new version

Browse files
Files changed (5) hide show
  1. .gitattributes +35 -0
  2. .gitignore +12 -0
  3. README.md +12 -0
  4. app.py +493 -0
  5. requirements.txt +148 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ scores.json
2
+ main.py
3
+ test.py
4
+ vali_runs.json
5
+ venv/
6
+ venv/*
7
+ __pycache__/
8
+ __pycache__/*
9
+ .env
10
+ wandb/
11
+ wandb/*
12
+ .oldgit/
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Ai Detection Leaderboard
3
+ emoji: ๐Ÿ“ˆ
4
+ colorFrom: red
5
+ colorTo: pink
6
+ sdk: gradio
7
+ sdk_version: 3.50.2
8
+ app_file: app.py
9
+ pinned: false
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import gradio as gr
3
+ import bittensor as bt
4
+ from typing import Dict, List, Any, Optional, Tuple
5
+ from dataclasses import dataclass
6
+ import wandb
7
+ import math
8
+ import os
9
+ import datetime
10
+ import time
11
+ import json
12
+ from dotenv import load_dotenv
13
+ from huggingface_hub import HfApi
14
+ from apscheduler.schedulers.background import BackgroundScheduler
15
+ import pandas as pd
16
+ from tqdm import tqdm
17
+ import numpy as np
18
+
19
+ load_dotenv()
20
+
21
+ FONT = (
22
+ """<link href="https://fonts.cdnfonts.com/css/jmh-typewriter" rel="stylesheet">"""
23
+ )
24
+ TITLE = """<h1 align="center" id="space-title" class="typewriter">Subnet 32 Leaderboard</h1>"""
25
+ HEADER = """<h2 align="center" class="typewriter"><a href="https://github.com/It-s-AI/llm-detection" target="_blank">Subnet 32</a> is a <a href="https://bittensor.com/" target="_blank">Bittensor</a> subnet that incentivizes the development of distributed solutions aimed at identifying LLM-generated content. Reward calculation integrates F1 score, False Positive score, and Average Precision score to accurately evaluate model performance.</h3>"""
26
+ EVALUATION_DETAILS = """<ul><li><b>UID:</b> the Bittensor UID of the miner</li><li><b>Rewards:</b> result number that is average of 3 metrics below.</li><li><b>F1 Score:</b> f-score metric</li><li><b>FP:</b> False Positive metric</li><li><b>AP:</b> average precision metric</li></ul><br/>More stats on <a href="https://x.taostats.io/subnet/32" target="_blank">taostats</a>."""
27
+ EVALUATION_HEADER = """<h3 align="center">Shows the latest internal evaluation statistics as calculated by the "OpenTensor Foundation" validator</h3>"""
28
+ VALIDATOR_WANDB_PROJECT = "itsai-dev/subnet32"
29
+ H4_TOKEN = os.environ.get("H4_TOKEN", None)
30
+ API = HfApi(token=H4_TOKEN)
31
+ WANDB_TOKEN = os.environ.get("WANDB_API_KEY", None)
32
+ SUBTENSOR_ENDPOINT=os.environ.get("SUBTENSOR_ENDPOINT", None)
33
+ REPO_ID = "Infin/ai-detection-leaderboard"
34
+ MAX_AVG_LOSS_POINTS = 1
35
+ RETRIES = 5
36
+ DELAY_SECS = 3
37
+ NETUID = 32
38
+ UID_MAIN_VALIDATOR = 147
39
+ BENCHMARK_TOP_AMOUNT = 3
40
+ EVALUATION_STATS_AMOUNT = 5
41
+
42
+
43
+ @dataclass
44
+ class ModelData:
45
+ uid: int
46
+ coldkey: str
47
+ hotkey: str
48
+ incentive: float
49
+ emission: float
50
+
51
+ @classmethod
52
+ def from_compressed_str(
53
+ cls,
54
+ uid: int,
55
+ coldkey: str,
56
+ hotkey: str,
57
+ incentive: float,
58
+ emission: float,
59
+ ):
60
+ """Returns an instance of this class from a compressed string representation"""
61
+ return ModelData(
62
+ uid=uid,
63
+ coldkey=coldkey,
64
+ hotkey=hotkey,
65
+ incentive=incentive,
66
+ emission=emission,
67
+ )
68
+
69
+
70
+ def run_with_retries(func, *args, **kwargs):
71
+ for i in range(0, RETRIES):
72
+ try:
73
+ return func(*args, **kwargs)
74
+ except (Exception, RuntimeError):
75
+ if i == RETRIES - 1:
76
+ raise
77
+ time.sleep(DELAY_SECS)
78
+ raise RuntimeError("Should never happen")
79
+
80
+
81
+ def get_subtensor_and_metagraph() -> Tuple[bt.subtensor, bt.metagraph]:
82
+ def _internal() -> Tuple[bt.subtensor, bt.metagraph]:
83
+ if SUBTENSOR_ENDPOINT:
84
+ parser = argparse.ArgumentParser()
85
+ bt.subtensor.add_args(parser)
86
+ subtensor = bt.subtensor(config=bt.config(parser=parser, args=["--subtensor.chain_endpoint", SUBTENSOR_ENDPOINT]))
87
+ else:
88
+ subtensor = bt.subtensor("finney")
89
+ metagraph = subtensor.metagraph(NETUID, lite=False)
90
+ return subtensor, metagraph
91
+
92
+ return run_with_retries(_internal)
93
+
94
+
95
+ def get_validator_weights(
96
+ metagraph: bt.metagraph,
97
+ ) -> Dict[int, Tuple[float, int, Dict[int, float]]]:
98
+ """Returns a dictionary of validator UIDs to (vtrust, stake, {uid: weight})."""
99
+ ret = {}
100
+ for uid in metagraph.uids.tolist():
101
+ vtrust = metagraph.validator_trust[uid].item()
102
+ if vtrust > 0:
103
+ ret[uid] = (vtrust, metagraph.S[uid].item(), {})
104
+ for ouid in metagraph.uids.tolist():
105
+ if ouid == uid:
106
+ continue
107
+ weight = round(metagraph.weights[uid][ouid].item(), 6)
108
+ if weight > 0:
109
+ ret[uid][-1][ouid] = weight
110
+ return ret
111
+
112
+
113
+ def get_subnet_data(
114
+ metagraph: bt.metagraph
115
+ ) -> List[ModelData]:
116
+ result = []
117
+ for uid in tqdm(metagraph.uids.tolist()):
118
+ if metagraph.validator_trust[uid] != 0:
119
+ continue
120
+
121
+ coldkey = metagraph.coldkeys[uid]
122
+ hotkey = metagraph.hotkeys[uid]
123
+ incentive = metagraph.incentive[uid].nan_to_num().item()
124
+ emission = (
125
+ metagraph.emission[uid].nan_to_num().item() * 20
126
+ ) # convert to daily TAO
127
+
128
+ model_data = None
129
+ try:
130
+ model_data = ModelData.from_compressed_str(
131
+ uid, coldkey, hotkey, incentive, emission
132
+ )
133
+ except:
134
+ continue
135
+
136
+ result.append(model_data)
137
+ return result
138
+
139
+
140
+ def is_floatable(x) -> bool:
141
+ return (
142
+ isinstance(x, float) and not math.isnan(x) and not math.isinf(x)
143
+ ) or isinstance(x, int)
144
+
145
+
146
+ def get_wandb_runs(project: str, filters: Dict[str, Any]) -> List:
147
+ """Get the latest runs from Wandb, retrying infinitely until we get them."""
148
+ while True:
149
+ api = wandb.Api(api_key=WANDB_TOKEN)
150
+
151
+ runs = list(
152
+ api.runs(
153
+ project,
154
+ order="-created_at",
155
+ filters=filters,
156
+ )
157
+ )
158
+
159
+ print('Runs amount: ', len(runs))
160
+ if len(runs) > 0:
161
+ return runs
162
+ # WandDB API is quite unreliable. Wait another minute and try again.
163
+ print("Failed to get runs from Wandb. Trying again in 60 seconds.")
164
+ time.sleep(10)
165
+
166
+
167
+
168
+ def get_scores(
169
+ wandb_runs: List,
170
+ ) -> Dict[int, Dict[str, Optional[float]]]:
171
+ result = {}
172
+ # result = []
173
+ previous_timestamp = None
174
+ # Iterate through the runs until we've processed all the uids.
175
+
176
+ for i, run in enumerate(wandb_runs):
177
+ config_data = run.config
178
+ vali_uid = config_data['uid']
179
+
180
+ # get only last run of each vali except OTF
181
+ if int(vali_uid) == UID_MAIN_VALIDATOR:
182
+ if len(result.get(vali_uid, [])) >= 5:
183
+ continue
184
+ else:
185
+ if vali_uid in result:
186
+ continue
187
+
188
+ if run.history().empty:
189
+ continue
190
+
191
+ data = json.loads(run.summary["original_format_json"])
192
+
193
+ timestamp = data["timestamp"]
194
+
195
+
196
+ # Make sure runs are indeed in descending time order.
197
+ # assert (
198
+ # previous_timestamp is None or timestamp < previous_timestamp
199
+ # ), f"Timestamps are not in descending order: {timestamp} >= {previous_timestamp}"
200
+ previous_timestamp = timestamp
201
+
202
+ if vali_uid not in result:
203
+ result[vali_uid] = []
204
+ local_vali_uid_iter = {}
205
+ for miner_data in list(data['uid_metrics'].values()):
206
+ local_vali_uid_iter[miner_data['uid']] = {}
207
+ local_vali_uid_iter[miner_data['uid']].update(miner_data)
208
+ result[vali_uid].append(local_vali_uid_iter)
209
+ return result
210
+
211
+
212
+ def average_scores(data: List):
213
+ stats = {}
214
+
215
+ for item in data:
216
+ for key, values in item.items():
217
+ if key not in stats:
218
+ stats[key] = {'sums': {'reward': 0, 'fp_score': 0, 'f1_score': 0, 'ap_score': 0, 'penalty': 0}, 'count': 0}
219
+ stats[key]['uid'] = values['uid']
220
+ stats[key]['weight'] = values['weight']
221
+
222
+ stats[key]['sums']['reward'] += values['reward']
223
+ stats[key]['sums']['fp_score'] += values['fp_score']
224
+ stats[key]['sums']['f1_score'] += values['f1_score']
225
+ stats[key]['sums']['ap_score'] += values['ap_score']
226
+ stats[key]['sums']['penalty'] += values['penalty']
227
+ stats[key]['count'] += 1
228
+
229
+
230
+ averages = {}
231
+ for key, data in stats.items():
232
+ averages[key] = {field: data['sums'][field] / data['count'] for field in data['sums']}
233
+ averages[key] = {**averages[key], 'uid': data['uid'], 'weight': data['weight']}
234
+ return averages
235
+
236
+
237
+ def format_score(uid: int, scores, key) -> Optional[float]:
238
+ if uid in scores:
239
+ if key in scores[uid]:
240
+ point = scores[uid][key]
241
+ if is_floatable(point):
242
+ return round(scores[uid][key], 6)
243
+ return None
244
+
245
+
246
+ def next_epoch(subtensor: bt.subtensor, block: int) -> int:
247
+ return (
248
+ block
249
+ + subtensor.get_subnet_hyperparameters(NETUID).tempo
250
+ - subtensor.blocks_since_epoch(NETUID, block)
251
+ )
252
+
253
+
254
+ def get_last_updated_div() -> str:
255
+ return f"""<div>Last Updated: {datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")} (UTC)</div>"""
256
+
257
+
258
+ def leaderboard_data(
259
+ leaderboard: List[ModelData],
260
+ scores: Dict[int, Dict[str, Optional[float]]],
261
+ show_stale: bool,
262
+ ) -> List[List[Any]]:
263
+ """Returns the leaderboard data, based on models data and UID scores."""
264
+ # headers=["Top", "UID", "Reward", "F1 Score", "FP Score", "AP Score"],
265
+
266
+ rows = [
267
+ [
268
+ f"{c.coldkey[:12]}",
269
+ c.uid,
270
+ format_score(c.uid, scores, "reward"),
271
+ format_score(c.uid, scores, "f1_score"),
272
+ format_score(c.uid, scores, "fp_score"),
273
+ format_score(c.uid, scores, "ap_score"),
274
+ ] for c in leaderboard if c.uid in scores
275
+ ]
276
+
277
+ sorted_rows = sorted(rows, key=lambda x: (x[2], x[0]), reverse=True)
278
+ if not show_stale:
279
+ sorted_rows = sorted_rows[:EVALUATION_STATS_AMOUNT]
280
+ return sorted_rows
281
+
282
+
283
+ def restart_space():
284
+ API.restart_space(repo_id=REPO_ID, token=H4_TOKEN)
285
+
286
+
287
+ def main():
288
+ # To avoid leaderboard failures, infinitely try until we get all data
289
+ # needed to populate the dashboard
290
+ while True:
291
+ # try:
292
+ subtensor, metagraph = get_subtensor_and_metagraph()
293
+
294
+ model_data: List[ModelData] = get_subnet_data(metagraph)
295
+ model_data.sort(key=lambda x: x.incentive, reverse=False)
296
+ time_now = datetime.datetime.now(datetime.timezone.utc)
297
+ n_days_ago = time_now - datetime.timedelta(hours=24)
298
+
299
+ vali_runs = get_wandb_runs(project=VALIDATOR_WANDB_PROJECT, filters={
300
+ "$and": [
301
+ {
302
+ 'created_at': {
303
+ '$gte': n_days_ago.isoformat()
304
+ }
305
+ },
306
+ {
307
+ 'state': {
308
+ "$in": ["finished"]
309
+ }
310
+ },
311
+ {
312
+ 'config.version': {
313
+ '$in': ["2.3.0", "2.3.1", "2.3.2", "2.4.0"]
314
+ }
315
+ },
316
+ {
317
+ 'config.uid': {
318
+ '$nin': [33, 86, 50, 106]
319
+ }
320
+ }
321
+ ]
322
+ })
323
+
324
+ scores = get_scores(vali_runs)
325
+
326
+ averaged_scores = {}
327
+ for vali_uid, vali_score in scores.items():
328
+ if len(vali_score) > 1:
329
+ averaged_scores.update({vali_uid: average_scores(vali_score)})
330
+ else:
331
+ averaged_scores.update({vali_uid: vali_score[0]})
332
+
333
+ scores = averaged_scores
334
+
335
+ rows = []
336
+ for validator_uid, miners in scores.items():
337
+ for miner_uid, stats in miners.items():
338
+ row = {'validator_uid': validator_uid}
339
+ row.update({k: v for k, v in stats.items()})
340
+ rows.append(row)
341
+
342
+ miners_stats = pd.DataFrame(rows)
343
+
344
+ miners_stats['stake_value'] = miners_stats['validator_uid'].apply(lambda x: metagraph.S[x].item())
345
+ miners_stats = miners_stats.sort_values(by='stake_value', ascending=False)
346
+ miners_stats = miners_stats.drop(columns='stake_value')
347
+
348
+ main_validator_scores = scores[UID_MAIN_VALIDATOR]
349
+
350
+ sorted_main_validator_scores = sorted(main_validator_scores.items(), key=lambda x: x[1]['reward'], reverse=True)
351
+
352
+ axons_info = metagraph.axons
353
+ top_miners = []
354
+ top_keys = []
355
+ for score_i in sorted_main_validator_scores:
356
+ if len(top_miners) >= BENCHMARK_TOP_AMOUNT:
357
+ break
358
+
359
+ coldkey_i = axons_info[score_i[0]].coldkey
360
+ if coldkey_i in top_keys:
361
+ continue
362
+
363
+ top_keys.append(coldkey_i)
364
+ top_miners.append(score_i)
365
+
366
+ top_miner_score = dict(top_miners)
367
+ data_list = [{'Model': f'miner_{key}',
368
+ 'Average': value['reward'],
369
+ 'F1 score': value['f1_score'],
370
+ 'FP score': value['fp_score'],
371
+ 'AP score': value['ap_score']} for key, value in top_miner_score.items()]
372
+
373
+ df = pd.DataFrame(data_list)
374
+ baseline_data = [
375
+ {'Model': 'baseline: deberta', 'F1 score': 0.863, 'FP score': 0.896, 'AP score': 0.789, 'Average': 0.849}
376
+ ]
377
+
378
+ benchmarks = pd.concat([df, pd.DataFrame(baseline_data)], ignore_index=True)
379
+ benchmarks = benchmarks.sort_values(by='Average', ascending=False)
380
+
381
+ validator_df = get_validator_weights(metagraph)
382
+ break
383
+ # except Exception as e:
384
+ # print(f"Failed to get data: {e}")
385
+ # time.sleep(30)
386
+
387
+ demo = gr.Blocks(css=".typewriter {font-family: 'JMH Typewriter', sans-serif;}")
388
+ with demo:
389
+ gr.HTML(FONT)
390
+ gr.HTML(TITLE)
391
+ gr.HTML(HEADER)
392
+
393
+ if benchmarks is not None:
394
+ with gr.Accordion("Top Model Benchmarks"):
395
+ gr.components.Dataframe(benchmarks)
396
+ gr.HTML("""<div>Fore more information about baseline miner architecture see <a href='https://github.com/It-s-AI/llm-detection/blob/main/neurons/miner.py'>here</a> for the full code.</div>""")
397
+
398
+ with gr.Accordion("Evaluation Stats"):
399
+ gr.HTML(EVALUATION_HEADER)
400
+ show_stale = gr.Checkbox(label="Show All Miners", interactive=True)
401
+ leaderboard_table = gr.components.Dataframe(
402
+ value=leaderboard_data(model_data, main_validator_scores, show_stale.value),
403
+ headers=["Coldkey", "UID", "Reward", "F1 Score", "FP Score", "AP Score"],
404
+ datatype=["markdown", "number", "number", "number", "number", "number"],
405
+ elem_id="leaderboard-table",
406
+ interactive=False,
407
+ visible=True,
408
+ )
409
+
410
+ gr.HTML(EVALUATION_DETAILS)
411
+ show_stale.change(
412
+ lambda stale: leaderboard_data(model_data, main_validator_scores, stale),
413
+ inputs=[show_stale],
414
+ outputs=leaderboard_table,
415
+ )
416
+
417
+ with gr.Accordion("Validator Stats"):
418
+ model_data.sort(key=lambda x: x.uid, reverse=False)
419
+
420
+ values = [
421
+ [uid, int(validator_df[uid][1]), round(validator_df[uid][0], 6)]
422
+ + [
423
+ validator_df[uid][-1].get(c.uid)
424
+ for c in model_data
425
+ if c.incentive
426
+ ]
427
+ for uid, _ in sorted(
428
+ zip(
429
+ validator_df.keys(),
430
+ [validator_df[x][1] for x in validator_df.keys()],
431
+ ),
432
+ key=lambda x: x[1],
433
+ reverse=True,
434
+ )
435
+ ]
436
+
437
+ averages = np.nanmean(np.array(values, dtype=float)[:, 3:], axis=0)
438
+ averages = np.around(averages, decimals=6)
439
+
440
+ values.append(["Average", 0, 0] + averages.tolist())
441
+
442
+ gr.components.Dataframe(
443
+ value=values,
444
+ headers=["UID", "Stake (ฯ„)", "V-Trust"]
445
+ + [
446
+ f"{c.uid}/reward"
447
+ for c in model_data
448
+ if c.incentive
449
+ ]
450
+ ,
451
+ datatype=["markdown", "number", "number"]
452
+ + ["number" for c in model_data if c.incentive]
453
+ ,
454
+ interactive=False,
455
+ visible=True,
456
+ )
457
+
458
+ def get_miner_stats(uid):
459
+ local_stats = miners_stats[miners_stats['uid'] == int(uid)]
460
+ local_stats.drop('penalty', axis=1, inplace=True)
461
+ local_stats.columns = ["Validator UID", "Reward", "FP Score", "F1 Score", "AP Score", "UID", "Weight"]
462
+ local_stats = local_stats[["Validator UID", "UID", "Weight", "Reward", "FP Score", "F1 Score", "AP Score"]]
463
+ return local_stats
464
+
465
+ with gr.Accordion("Get your miner stats"):
466
+ with gr.Row():
467
+ input_text = gr.Textbox(label="Enter your Miner ID")
468
+ submit_button = gr.Button("Get Stats")
469
+
470
+ output_df = gr.components.DataFrame(
471
+ headers=["Validator UID", "Miner UID"] + ["Weight", "Reward"] + ["FP Score", "F1 Score", "AP Score"],
472
+ datatype=["number", "number"] + ["number", "number", "number", "number", "number"],
473
+ interactive=False,
474
+ visible=True
475
+ )
476
+
477
+ submit_button.click(
478
+ fn=get_miner_stats,
479
+ inputs=input_text,
480
+ outputs=output_df
481
+ )
482
+
483
+ gr.HTML(value=get_last_updated_div())
484
+
485
+ scheduler = BackgroundScheduler()
486
+ scheduler.add_job(
487
+ restart_space, "interval", seconds=60 * 60 * 24
488
+ ) # restart every 45 minutes
489
+ scheduler.start()
490
+
491
+ demo.launch(share=True)
492
+
493
+ main()
requirements.txt ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ aiohttp==3.9.0b0
3
+ aiosignal==1.3.1
4
+ altair==5.3.0
5
+ ansible==6.7.0
6
+ ansible-core==2.13.13
7
+ ansible-vault==2.1.0
8
+ anyio==4.3.0
9
+ appdirs==1.4.4
10
+ APScheduler==3.10.4
11
+ async-timeout==4.0.3
12
+ attrs==23.2.0
13
+ backoff==2.2.1
14
+ base58==2.1.1
15
+ bittensor==6.11.0
16
+ black==23.7.0
17
+ certifi==2024.2.2
18
+ cffi==1.16.0
19
+ charset-normalizer==3.3.2
20
+ click==8.1.7
21
+ colorama==0.4.6
22
+ contourpy==1.2.1
23
+ cryptography==42.0.0
24
+ cycler==0.12.1
25
+ cytoolz==0.12.3
26
+ ddt==1.6.0
27
+ decorator==5.1.1
28
+ docker-pycreds==0.4.0
29
+ ecdsa==0.19.0
30
+ eth-hash==0.7.0
31
+ eth-keys==0.5.1
32
+ eth-typing==4.2.2
33
+ eth-utils==2.3.1
34
+ exceptiongroup==1.2.1
35
+ fastapi==0.99.1
36
+ ffmpy==0.3.2
37
+ filelock==3.14.0
38
+ fonttools==4.51.0
39
+ frozenlist==1.4.1
40
+ fsspec==2024.3.1
41
+ fuzzywuzzy==0.18.0
42
+ gitdb==4.0.11
43
+ GitPython==3.1.43
44
+ gradio==3.50.2
45
+ gradio_client==0.6.1
46
+ h11==0.14.0
47
+ httpcore==1.0.5
48
+ httpx==0.27.0
49
+ huggingface-hub==0.22.2
50
+ idna==3.7
51
+ importlib_resources==6.4.0
52
+ iniconfig==2.0.0
53
+ Jinja2==3.1.3
54
+ jsonschema==4.21.1
55
+ jsonschema-specifications==2023.12.1
56
+ kiwisolver==1.4.5
57
+ Levenshtein==0.25.1
58
+ markdown-it-py==3.0.0
59
+ MarkupSafe==2.1.5
60
+ matplotlib==3.8.4
61
+ mdurl==0.1.2
62
+ more-itertools==10.2.0
63
+ mpmath==1.3.0
64
+ msgpack==1.0.8
65
+ msgpack-numpy-opentensor==0.5.0
66
+ multidict==6.0.5
67
+ munch==2.5.0
68
+ mypy-extensions==1.0.0
69
+ nest-asyncio==1.6.0
70
+ netaddr==1.2.1
71
+ networkx==3.3
72
+ numpy==1.26.4
73
+ nvidia-cublas-cu12==12.1.3.1
74
+ nvidia-cuda-cupti-cu12==12.1.105
75
+ nvidia-cuda-nvrtc-cu12==12.1.105
76
+ nvidia-cuda-runtime-cu12==12.1.105
77
+ nvidia-cudnn-cu12==8.9.2.26
78
+ nvidia-cufft-cu12==11.0.2.54
79
+ nvidia-curand-cu12==10.3.2.106
80
+ nvidia-cusolver-cu12==11.4.5.107
81
+ nvidia-cusparse-cu12==12.1.0.106
82
+ nvidia-nccl-cu12==2.20.5
83
+ nvidia-nvjitlink-cu12==12.4.127
84
+ nvidia-nvtx-cu12==12.1.105
85
+ orjson==3.10.1
86
+ packaging==24.0
87
+ pandas==2.2.2
88
+ password-strength==0.0.3.post2
89
+ pathspec==0.12.1
90
+ pillow==10.3.0
91
+ platformdirs==4.2.1
92
+ pluggy==1.5.0
93
+ protobuf==4.25.3
94
+ psutil==5.9.8
95
+ py==1.11.0
96
+ py-bip39-bindings==0.1.11
97
+ py-ed25519-zebra-bindings==1.0.1
98
+ py-sr25519-bindings==0.2.0
99
+ pycparser==2.22
100
+ pycryptodome==3.20.0
101
+ pydantic==1.10.15
102
+ pydub==0.25.1
103
+ Pygments==2.17.2
104
+ PyNaCl==1.5.0
105
+ pyparsing==3.1.2
106
+ pytest==8.2.0
107
+ pytest-asyncio==0.23.6
108
+ python-dateutil==2.9.0.post0
109
+ python-dotenv==1.0.1
110
+ python-Levenshtein==0.25.1
111
+ python-multipart==0.0.9
112
+ python-statemachine==2.1.2
113
+ pytz==2024.1
114
+ PyYAML==6.0.1
115
+ rapidfuzz==3.8.1
116
+ referencing==0.35.0
117
+ requests==2.31.0
118
+ resolvelib==0.8.1
119
+ retry==0.9.2
120
+ rich==13.7.1
121
+ rpds-py==0.18.0
122
+ scalecodec==1.2.7
123
+ semantic-version==2.10.0
124
+ sentry-sdk==2.0.1
125
+ setproctitle==1.3.3
126
+ shtab==1.6.5
127
+ six==1.16.0
128
+ smmap==5.0.1
129
+ sniffio==1.3.1
130
+ starlette==0.27.0
131
+ substrate-interface==1.7.5
132
+ sympy==1.12
133
+ termcolor==2.4.0
134
+ tomli==2.0.1
135
+ toolz==0.12.1
136
+ torch==2.3.0
137
+ tqdm==4.66.2
138
+ triton==2.3.0
139
+ typing_extensions==4.11.0
140
+ tzdata==2024.1
141
+ tzlocal==5.2
142
+ urllib3==2.2.1
143
+ uvicorn==0.22.0
144
+ wandb==0.16.6
145
+ websocket-client==1.8.0
146
+ websockets==11.0.3
147
+ xxhash==3.4.1
148
+ yarl==1.9.4