|
import json
|
|
import os
|
|
|
|
import pandas as pd
|
|
|
|
from src.display.formatting import has_no_nan_values, make_clickable_model
|
|
from src.display.utils import AutoEvalColumn, EvalQueueColumn
|
|
from src.leaderboard.read_evals import get_raw_eval_results
|
|
|
|
|
|
def get_leaderboard_df(results_path):
|
|
df = pd.read_csv(results_path)
|
|
|
|
df["ha_rag_rate"] = df["ha_rag_rate"].round(2)
|
|
df["ha_non_rag_rate"] = df["ha_non_rag_rate"].round(2)
|
|
|
|
|
|
pretty = {
|
|
"Models": "Models",
|
|
"ha_rag_rate": "RAG Hallucination Rate (%)",
|
|
"ha_non_rag_rate": "Non-RAG Hallucination Rate (%)",
|
|
}
|
|
df = df.rename(columns=pretty)
|
|
|
|
df["Average Hallucination Rate (%)"] = df[
|
|
["RAG Hallucination Rate (%)", "Non-RAG Hallucination Rate (%)"]
|
|
].mean(axis=1).round(2)
|
|
|
|
|
|
df = df.sort_values("Average Hallucination Rate (%)", ascending=True).reset_index(drop=True)
|
|
|
|
|
|
medal_map = {1: "π₯", 2: "π₯", 3: "π₯"}
|
|
|
|
def medal_html(rank):
|
|
"""Return an HTML span with the medal icon for the top 3 ranks.
|
|
|
|
The numeric rank is stored in the data-order attribute equal to the numerical rank so that
|
|
DataTables (used under-the-hood by the gradio_leaderboard component)
|
|
can sort the column by this hidden numeric value while still
|
|
displaying the pretty medal icon. For ranks > 3 we just return the
|
|
integer so the column remains fully numeric.
|
|
"""
|
|
medal = medal_map.get(rank)
|
|
if medal:
|
|
|
|
return (
|
|
f'<span style="display:none">{rank:04}</span>'
|
|
f'<span style="font-size:2.0rem;">{medal}</span>'
|
|
)
|
|
|
|
return f'<span style="display:none">{rank:04}</span>{rank}'
|
|
|
|
df["Rank"] = df.index + 1
|
|
df["Rank"] = df["Rank"].apply(medal_html)
|
|
|
|
|
|
|
|
df = df[[
|
|
"Rank",
|
|
"Models",
|
|
"Average Hallucination Rate (%)",
|
|
"RAG Hallucination Rate (%)",
|
|
"Non-RAG Hallucination Rate (%)",
|
|
]]
|
|
|
|
return df
|
|
|
|
|
|
|
|
|
|
def get_evaluation_queue_df(save_path: str, cols: list) -> list[pd.DataFrame]:
|
|
"""Creates the different dataframes for the evaluation queues requestes"""
|
|
entries = [entry for entry in os.listdir(save_path) if not entry.startswith(".")]
|
|
all_evals = []
|
|
|
|
for entry in entries:
|
|
if ".json" in entry:
|
|
file_path = os.path.join(save_path, entry)
|
|
with open(file_path) as fp:
|
|
data = json.load(fp)
|
|
|
|
data[EvalQueueColumn.model.name] = make_clickable_model(data["model"])
|
|
data[EvalQueueColumn.revision.name] = data.get("revision", "main")
|
|
|
|
all_evals.append(data)
|
|
elif ".md" not in entry:
|
|
|
|
sub_entries = [e for e in os.listdir(f"{save_path}/{entry}") if os.path.isfile(e) and not e.startswith(".")]
|
|
for sub_entry in sub_entries:
|
|
file_path = os.path.join(save_path, entry, sub_entry)
|
|
with open(file_path) as fp:
|
|
data = json.load(fp)
|
|
|
|
data[EvalQueueColumn.model.name] = make_clickable_model(data["model"])
|
|
data[EvalQueueColumn.revision.name] = data.get("revision", "main")
|
|
all_evals.append(data)
|
|
|
|
pending_list = [e for e in all_evals if e["status"] in ["PENDING", "RERUN"]]
|
|
running_list = [e for e in all_evals if e["status"] == "RUNNING"]
|
|
finished_list = [e for e in all_evals if e["status"].startswith("FINISHED") or e["status"] == "PENDING_NEW_EVAL"]
|
|
df_pending = pd.DataFrame.from_records(pending_list, columns=cols)
|
|
df_running = pd.DataFrame.from_records(running_list, columns=cols)
|
|
df_finished = pd.DataFrame.from_records(finished_list, columns=cols)
|
|
return df_finished[cols], df_running[cols], df_pending[cols]
|
|
|