import base64
import json
import os
import re
from datetime import date
from html import escape
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import Any
from urllib.parse import parse_qs, urlencode, urlparse
ROOT = Path(__file__).resolve().parent
DATASETS_PATH = ROOT / "data" / "datasets.json"
RESULTS_PATH = Path(os.getenv("RUSBEIR_RESULTS_PATH", ROOT / "data" / "results.jsonl"))
LOGO_PATH = ROOT / "assets" / "rusBeIR_logo.png"
PORT = int(os.getenv("PORT", "7860"))
DEFAULT_METRIC = "NDCG@10"
METRICS = ["NDCG@10", "MAP@10", "Recall@10", "P@10", "MRR@10"]
TRAILING_COLUMNS = ["Date", "Source URL"]
DISPLAY_COLUMN_NAMES = {
"Model ID": "Model
ID",
"Organization": "Org.",
"Source URL": "Source
URL",
"sberquad-retrieval": "sberquad
retrieval",
"ruscibench-retrieval": "ruscibench
retrieval",
"wikifacts-articles": "wikifacts
articles",
"wikifacts-para": "wikifacts
para",
"wikifacts-sents": "wikifacts
sents",
"wikifacts-window_2": "wikifacts
window 2",
"wikifacts-window_3": "wikifacts
window 3",
"wikifacts-window_4": "wikifacts
window 4",
"wikifacts-window_5": "wikifacts
window 5",
"wikifacts-window_6": "wikifacts
window 6",
}
CSS = """
:root {
--bg: #f9fafb;
--panel: #ffffff;
--panel-soft: #f6f7f9;
--text: #1f2937;
--muted: #6b7280;
--line: #e5e7eb;
--line-strong: #d1d5db;
--accent: #ff6f00;
--accent-soft: #fff7ed;
--shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px;
}
a { color: #c2410c; font-weight: 600; text-decoration: none; }
a:hover { text-decoration: underline; }
.page {
width: min(1480px, 100%);
margin: 0 auto;
padding: 24px;
}
.shell { display: flex; flex-direction: column; gap: 16px; }
.hero, .card, .panel {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
box-shadow: var(--shadow);
}
.hero {
display: grid;
grid-template-columns: 1fr auto;
gap: 18px;
align-items: start;
padding: 22px;
}
.logo { width: 132px; max-width: 24vw; height: auto; object-fit: contain; }
.kicker {
color: #9a3412;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
margin-bottom: 8px;
}
h1 { font-size: 36px; line-height: 1.12; margin: 0 0 10px; letter-spacing: 0; }
.subtitle { color: var(--muted); font-size: 15px; line-height: 1.55; margin: 0; max-width: 860px; }
.badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.badge {
display: inline-flex;
align-items: center;
border: 1px solid var(--line);
border-radius: 8px;
background: var(--panel-soft);
color: #374151;
padding: 5px 10px;
font-size: 13px;
font-weight: 600;
}
.cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.card { padding: 15px; }
.card-label { color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.card-value { font-size: 24px; line-height: 1.2; font-weight: 750; margin-top: 8px; overflow-wrap: anywhere; }
.card-note { color: var(--muted); font-size: 13px; margin-top: 6px; }
.nav {
display: flex;
gap: 4px;
flex-wrap: wrap;
border-bottom: 1px solid var(--line);
padding-left: 4px;
}
.nav a {
border: 1px solid transparent;
border-bottom: 0;
border-radius: 8px 8px 0 0;
background: transparent;
color: #4b5563;
padding: 9px 12px;
font-weight: 650;
}
.nav a.active {
background: var(--panel);
border-color: var(--line);
color: #111827;
margin-bottom: -1px;
}
.panel { padding: 16px; overflow-x: visible; }
.section-title { font-size: 18px; font-weight: 750; margin: 0 0 4px; }
.section-note { color: var(--muted); font-size: 13px; margin: 0 0 14px; }
.filters {
display: grid;
grid-template-columns: minmax(150px, 0.8fr) minmax(190px, 1fr) minmax(320px, 2fr) minmax(110px, 0.7fr) auto;
gap: 12px;
align-items: end;
margin: 14px 0;
}
label { display: grid; gap: 6px; color: #374151; font-size: 13px; font-weight: 650; }
label.checkbox-label { align-items: center; grid-template-columns: auto 1fr; gap: 8px; min-height: 38px; }
label.checkbox-label input { min-height: auto; width: 16px; height: 16px; padding: 0; }
input, select, textarea, button {
border: 1px solid var(--line-strong);
border-radius: 8px;
background: var(--panel);
color: var(--text);
font: inherit;
padding: 9px 11px;
min-height: 38px;
outline: none;
}
input:focus, select:focus, textarea:focus {
border-color: #fb923c;
box-shadow: 0 0 0 3px rgba(251, 146, 60, 0.18);
}
textarea { width: 100%; min-height: 260px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px; }
input[type="file"] { width: 100%; background: var(--panel-soft); }
button {
cursor: pointer;
font-weight: 700;
background: var(--panel-soft);
color: #111827;
}
button:hover { background: #eef0f4; }
.status { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-soft); padding: 10px 12px; margin-bottom: 12px; color: #374151; }
.submit-grid { display: grid; gap: 14px; }
.submit-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: end; }
.file-control { flex: 1 1 320px; }
.table-scroll {
width: 100%;
max-height: 720px;
overflow: auto;
border: 1px solid var(--line);
border-radius: 8px;
background: var(--panel);
}
table { border-collapse: separate; border-spacing: 0; min-width: 2600px; width: max-content; table-layout: fixed; font-size: 13px; }
th, td {
border-right: 1px solid var(--line);
border-bottom: 1px solid #eef0f3;
padding: 9px 10px;
background: var(--panel);
color: #1f2937;
vertical-align: middle;
overflow-wrap: anywhere;
}
th {
position: sticky;
top: 0;
z-index: 4;
background: #f6f7f9;
color: #374151;
font-weight: 750;
white-space: normal;
line-height: 1.15;
}
td { height: 46px; font-weight: 600; }
tr:nth-child(even) td { background: #fcfcfd; }
.col-rank { width: 58px; min-width: 58px; max-width: 58px; text-align: center; }
.col-model { width: 260px; min-width: 260px; max-width: 260px; }
.col-average { width: 104px; min-width: 104px; max-width: 104px; text-align: right; }
.col-meta { width: 110px; min-width: 110px; max-width: 110px; }
.col-model-id { width: 260px; min-width: 260px; max-width: 260px; }
.col-dataset { width: 96px; min-width: 96px; max-width: 96px; text-align: right; }
.col-date { width: 112px; min-width: 112px; max-width: 112px; }
.col-source { width: 220px; min-width: 220px; max-width: 220px; }
.sticky-rank, .sticky-model, .sticky-average { position: sticky; z-index: 3; }
th.sticky-rank, th.sticky-model, th.sticky-average { z-index: 6; }
.sticky-rank { left: 0; }
.sticky-model { left: 58px; }
.sticky-average { left: 318px; box-shadow: 8px 0 12px rgba(31, 41, 55, 0.06); }
.datasets { min-width: 100%; }
.datasets th, .datasets td { width: auto; min-width: 120px; }
@media (max-width: 900px) {
.page { padding: 12px; }
.hero { grid-template-columns: 1fr; }
h1 { font-size: 30px; }
.cards { grid-template-columns: 1fr; }
.filters { grid-template-columns: 1fr; }
}
"""
def read_json(path: Path, default: Any) -> Any:
if not path.exists():
return default
with path.open("r", encoding="utf-8") as file:
return json.load(file)
def read_jsonl(path: Path) -> list[dict[str, Any]]:
if not path.exists():
return []
records = []
with path.open("r", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line:
records.append(json.loads(line))
return records
def metric_value(metrics: dict[str, Any], metric: str) -> float | None:
value = metrics.get(metric)
if value is None:
return None
try:
return float(value)
except (TypeError, ValueError):
return None
def load_datasets() -> list[dict[str, Any]]:
return read_json(DATASETS_PATH, [])
def load_results() -> list[dict[str, Any]]:
return read_jsonl(RESULTS_PATH)
def logo_html() -> str:
if not LOGO_PATH.exists():
return ""
data = base64.b64encode(LOGO_PATH.read_bytes()).decode("ascii")
return f''
def dataset_names_for_task(task_filter: str) -> set[str]:
datasets = load_datasets()
if task_filter != "All":
datasets = [dataset for dataset in datasets if dataset.get("task") == task_filter]
return {dataset["name"] for dataset in datasets if dataset.get("official", True)}
def compute_average(record: dict[str, Any], metric: str, dataset_names: set[str]) -> float | None:
scores = record.get("scores", {})
explicit = metric_value(scores.get("average", {}), metric)
if explicit is not None:
return explicit
values = []
for dataset_name, dataset_metrics in scores.get("datasets", {}).items():
if dataset_name in dataset_names:
value = metric_value(dataset_metrics, metric)
if value is not None:
values.append(value)
return sum(values) / len(values) if values else None
def leaderboard_rows(metric: str, task_filter: str, verified_only: bool, query: str) -> tuple[list[dict[str, Any]], set[str]]:
dataset_names = dataset_names_for_task(task_filter)
rows = []
for record in load_results():
if verified_only and not record.get("verified", False):
continue
model_text = f"{record.get('model_id', '')} {record.get('model_name', '')}".lower()
if query and query.lower() not in model_text:
continue
dataset_scores = record.get("scores", {}).get("datasets", {})
row = {
"Rank": None,
"Model": record.get("model_name") or record.get("model_id"),
metric: compute_average(record, metric, dataset_names),
"Model ID": record.get("model_id", ""),
"Organization": record.get("organization", ""),
"Type": record.get("type", ""),
"Verified": "yes" if record.get("verified", False) else "no",
"Date": record.get("date", ""),
"Source URL": record.get("source_url", ""),
}
for dataset_name in sorted(dataset_names):
row[dataset_name] = metric_value(dataset_scores.get(dataset_name, {}), metric)
rows.append(row)
rows.sort(key=lambda row: row[metric] if row[metric] is not None else -1, reverse=True)
for index, row in enumerate(rows, start=1):
row["Rank"] = index
return rows, dataset_names
def format_score(value: Any) -> str:
if value is None:
return ""
try:
return f"{float(value):.4f}"
except (TypeError, ValueError):
return escape(str(value))
def column_class(column: str, metric: str, index: int) -> str:
if index == 0:
return "col-rank sticky-rank"
if index == 1:
return "col-model sticky-model"
if column == metric:
return "col-average sticky-average"
if column == "Model ID":
return "col-model-id"
if column in {"Organization", "Type", "Verified"}:
return "col-meta"
if column == "Date":
return "col-date"
if column == "Source URL":
return "col-source"
return "col-dataset"
def render_table(metric: str, task_filter: str, verified_only: bool, query: str) -> str:
rows, dataset_names = leaderboard_rows(metric, task_filter, verified_only, query)
columns = [
"Rank",
"Model",
metric,
"Model ID",
"Organization",
"Type",
"Verified",
*sorted(dataset_names),
*TRAILING_COLUMNS,
]
headers = "".join(
f'
Compare dense retrievers, sparse baselines, and reranker pipelines on official RusBEIR datasets. The default ranking is the macro-average of {escape(metric)}.
| Dataset | Task | Split | Corpus repo | Qrels repo | Origin |
|---|
RusBEIR tasks used for the default macro-average ranking.
Paste JSONL content or upload a ready JSONL file. Each record must include model_id, scores, and at least one numeric metric.
RusBEIR is a Russian BEIR-style benchmark for zero-shot information retrieval. The leaderboard is backed by a plain JSONL file.
Verified rows should point to reproducible logs or a commit with generated retrieval results.
Filter by task family, model name, or verification status. Scores are stored as fractions.
{render_filters(metric, task, verified, query)} {render_table(metric, task, verified, query)}