from collections import defaultdict
from enum import Enum
from enum import IntEnum
import gradio as gr
import pandas as pd
import plotly.graph_objects as go
from chain_data import sync_chain, fetch_commitments
from src import Key
from src.chain_data import get_neurons
from wandb_data import get_current_runs, Run, get_blacklisted_keys
class DuplicateStatus(IntEnum):
SAFE = 0
DUPLICATE = 1
PENDING_VERIFICATION = 2
class SubmissionStatus(Enum):
BLACKLISTED = ("Blacklisted", "gray")
DUPLICATE = ("Duplicate", "gray")
PENDING = ("Pending", "orange")
VERIFYING = ("Verifying", "aqua")
DONE = ("Done", "springgreen")
INVALID = ("Invalid", "red")
@staticmethod
def get_status(run: Run, hotkey: Key, coldkey: Key, block: int, revision: str) -> "SubmissionStatus":
if is_blacklisted(hotkey, coldkey):
return SubmissionStatus.BLACKLISTED
duplicate_status = is_duplicate_submission(hotkey, revision)
if duplicate_status == DuplicateStatus.DUPLICATE:
return SubmissionStatus.DUPLICATE
elif duplicate_status == DuplicateStatus.PENDING_VERIFICATION:
return SubmissionStatus.VERIFYING
if hotkey in run.submissions and block > run.submissions[hotkey].info.block and hotkey not in run.invalid_submissions:
return SubmissionStatus.PENDING
if hotkey in run.submissions:
return SubmissionStatus.DONE
if hotkey in run.invalid_submissions:
return SubmissionStatus.INVALID
return SubmissionStatus.PENDING
def is_blacklisted(hotkey: Key, coldkey: Key) -> bool:
return hotkey in get_blacklisted_keys().hotkeys or coldkey in get_blacklisted_keys().coldkeys
def is_duplicate_submission(hotkey: Key, revision: str) -> DuplicateStatus:
duplicate_selection = get_blacklisted_keys().duplicate_selection
if any(
submission.hotkey == hotkey and submission.revision == revision
for submission in duplicate_selection.duplicate_submissions
):
return DuplicateStatus.DUPLICATE
elif any(
submission.hotkey == hotkey and submission.revision == revision
for submission in duplicate_selection.safe_submissions
):
return DuplicateStatus.SAFE
return DuplicateStatus.PENDING_VERIFICATION
DROPDOWN_OPTIONS = [status.value[0] for status in SubmissionStatus]
def create_duplicate_submissions_plot() -> gr.Plot:
sync_chain()
submissions_by_coldkey = defaultdict(lambda: ([], []))
for hotkey, commitment in fetch_commitments().items():
neuron = get_neurons().get(hotkey)
if not neuron:
continue
coldkey = neuron.coldkey
if is_blacklisted(hotkey, coldkey):
continue
duplicate_status = is_duplicate_submission(hotkey, commitment.revision)
if duplicate_status == DuplicateStatus.DUPLICATE:
submissions_by_coldkey[coldkey][0].append(commitment)
elif duplicate_status == DuplicateStatus.SAFE:
submissions_by_coldkey[coldkey][1].append(commitment)
submissions_by_coldkey = dict(sorted(
submissions_by_coldkey.items(),
key=lambda x: len(x[1][0]) + len(x[1][1]),
reverse=True
))
figure = go.Figure()
for coldkey, (duplicate_commitments, safe_commitments) in submissions_by_coldkey.items():
urls_safe = [c.url for c in safe_commitments]
figure.add_trace(go.Bar(
x=[f"{coldkey[:6]}..."],
y=[len(safe_commitments)],
name="Safe",
marker_color="green", # type: ignore
hovertemplate="
".join([
"Submissions (%{y}):
" + "
".join(urls_safe)
]) + ""
))
urls_duplicate = [c.url for c in duplicate_commitments]
figure.add_trace(go.Bar(
x=[f"{coldkey[:6]}..."],
y=[len(duplicate_commitments)],
name="Duplicate",
marker_color="red", # type: ignore
hovertemplate="
".join([
"Submissions (%{y}):
" + "
".join(urls_duplicate)
]) + ""
))
figure.update_layout(
title="Duplicate Submissions",
xaxis_title="Coldkey",
yaxis_title="# of Submissions",
barmode="stack",
showlegend=False,
autosize=True,
margin=dict(l=50, r=50, t=50, b=50),
template="plotly_dark"
)
return gr.Plot(figure)
def create_submissions(submission_filters: list[str]) -> gr.Dataframe:
data: list[list] = []
sync_chain()
runs = sorted(get_current_runs(), key=lambda run: run.uid)
for hotkey, commitment in fetch_commitments().items():
neuron = get_neurons().get(hotkey)
if not neuron:
continue
coldkey = neuron.coldkey
row = [
neuron.uid,
f"[{'/'.join(commitment.url.split('/')[-2:])}]({commitment.url})",
f"[{commitment.block}](https://taostats.io/block/{commitment.block}/extrinsics)",
f"[{commitment.revision}]({commitment.url}/commit/{commitment.revision})",
f"[{hotkey[:6]}...](https://taostats.io/hotkey/{hotkey})",
f"[{coldkey[:6]}...](https://taostats.io/coldkey/{coldkey})",
commitment.contest.name,
]
has_data = False
for run in runs:
status = SubmissionStatus.get_status(run, hotkey, coldkey, commitment.block, commitment.revision)
if status.value[0] in submission_filters:
row.append(f"{status.value[0]}")
has_data = True
else:
row.append("")
if not has_data:
continue
data.append(row)
data.sort(key=lambda x: int(x[2].split('[')[1].split(']')[0]), reverse=True)
columns = ["UID", "Model", "Block", "Revision", "Hotkey", "Coldkey", "Contest"]
datatype = ["number", "markdown", "markdown", "markdown", "markdown", "markdown", "markdown"]
for run in runs:
columns.append(f"{run.uid}")
datatype.append("markdown")
return gr.Dataframe(
pd.DataFrame(data, columns=columns),
datatype=datatype,
interactive=False,
max_height=800,
)