Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 96 additions & 4 deletions reproducibility/site/scripts/build-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
*
* Outputs (gitignored, written to src/data/):
* - overview.json summary used on /
* - datasets.json [{id, name, run_count, eval_metrics}]
* - methods.json [{id, run_count}]
* - models.json [{id, run_count}]
* - datasets.json [{id, name, run_count, eval_metrics, hf_url?}]
* - methods.json [{id, run_count, display, paper?, paper_url?}]
* - models.json [{id, run_count, display, provider, slug}]
* - retrievers.json [{id, display_name, paradigm, run_count}]
* - matrix.json flat matrix: rows = (method, model, retriever), values per dataset
* - runs.json full run index, keyed by run_id
Expand Down Expand Up @@ -45,6 +45,17 @@ const RETRIEVER_REGISTRY_YAML = path.join(
"reproducibility",
"retriever_registry.yaml",
);
// Curated method→paper citations (single source of truth, shared with the
// marketing site). Keyed by logical method id; variant ids (e.g. query2doc-cot)
// fall back to their base id (query2doc).
const METHOD_CITATIONS_JSON = path.join(
REPO_ROOT,
"web",
"site",
"src",
"data",
"methods.json",
);

const OUT_DIR = path.join(SITE_ROOT, "src", "data");
const VIEWS_DIR = path.join(OUT_DIR, "views");
Expand Down Expand Up @@ -80,8 +91,46 @@ interface DatasetEntry {
bm25_weights?: { k1: number; b: number };
eval_metrics: string[];
run_count: number;
hf_url?: string;
}

// Canonical HuggingFace dataset/subset pages, keyed by dataset id. BEIR repos
// are first-party (BeIR org); BRIGHT links target the per-domain split in the
// `examples` config of the single xlangai/BRIGHT repo; the MS MARCO / TREC-DL
// links point to the cleanest public HF mirror of each passage task.
const DATASET_HF_URLS: Record<string, string> = {
"msmarco-v1-passage.trecdl2019": "https://huggingface.co/datasets/whybe-choi/trec-dl-2019",
"msmarco-v1-passage.trecdl2020": "https://huggingface.co/datasets/whybe-choi/trec-dl-2020",
"msmarco-v1-passage.dlhard": "https://huggingface.co/datasets/irds/msmarco-passage_trec-dl-hard",
"beir-v1.0.0-trec-covid": "https://huggingface.co/datasets/BeIR/trec-covid",
"beir-v1.0.0-fiqa": "https://huggingface.co/datasets/BeIR/fiqa",
"beir-v1.0.0-trec-news": "https://huggingface.co/datasets/BeIR/trec-news-generated-queries",
"beir-v1.0.0-arguana": "https://huggingface.co/datasets/BeIR/arguana",
"beir-v1.0.0-dbpedia-entity": "https://huggingface.co/datasets/BeIR/dbpedia-entity",
"beir-v1.0.0-scifact": "https://huggingface.co/datasets/BeIR/scifact",
"bright-biology": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/biology",
"bright-earth-science": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/earth_science",
"bright-economics": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/economics",
"bright-psychology": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/psychology",
"bright-robotics": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/robotics",
"bright-stackoverflow": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/stackoverflow",
"bright-sustainable-living": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/sustainable_living",
"bright-pony": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/pony",
"bright-leetcode": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/leetcode",
"bright-aops": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/aops",
"bright-theoremqa-theorems": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/theoremqa_theorems",
"bright-theoremqa-questions": "https://huggingface.co/datasets/xlangai/BRIGHT/viewer/examples/theoremqa_questions",
};

// Polished display name + provider slug per model id. Provider drives the logo
// icon shown next to the model in the UI; falls back to the org prefix.
const MODEL_META: Record<string, { display: string; provider: string }> = {
"openai/gpt-4.1": { display: "GPT-4.1", provider: "openai" },
"openai/gpt-4.1-nano": { display: "GPT-4.1 nano", provider: "openai" },
"Qwen/Qwen2.5-72B-Instruct": { display: "Qwen2.5 72B Instruct", provider: "qwen" },
"Qwen/Qwen2.5-7B-Instruct": { display: "Qwen2.5 7B Instruct", provider: "qwen" },
};

interface RetrieverEntry {
id: string;
display_name: string;
Expand Down Expand Up @@ -173,6 +222,29 @@ function readRetrieverRegistry(): Record<string, { display_name: string; paradig
return doc.retrievers ?? {};
}

function readMethodCitations(): Record<string, { paper: string; paper_url: string }> {
if (!fs.existsSync(METHOD_CITATIONS_JSON)) return {};
const list = JSON.parse(fs.readFileSync(METHOD_CITATIONS_JSON, "utf-8")) as Array<{
id: string;
paper?: string;
paper_url?: string;
}>;
const map: Record<string, { paper: string; paper_url: string }> = {};
for (const m of list) {
if (m.paper && m.paper_url) map[m.id] = { paper: m.paper, paper_url: m.paper_url };
}
return map;
}

// Resolve a (possibly variant) method id to its citation, falling back to the
// base id before the first "-" (e.g. query2doc-cot → query2doc).
function citationFor(
id: string,
cites: Record<string, { paper: string; paper_url: string }>,
): { paper: string; paper_url: string } | null {
return cites[id] ?? cites[id.split("-")[0]] ?? null;
}

function* iterRunFiles(): Generator<string> {
if (!fs.existsSync(RUNS_DIR)) return;
const stack = [RUNS_DIR];
Expand Down Expand Up @@ -534,10 +606,19 @@ function encodePathSegment(s: string): string {
// Strip provider prefix from a model id for display: "openai/gpt-4.1" → "gpt-4.1".
// The canonical id stays in the data; this is purely cosmetic.
function displayModel(s: string): string {
if (MODEL_META[s]) return MODEL_META[s].display;
const i = s.indexOf("/");
return i >= 0 ? s.slice(i + 1) : s;
}

function modelProvider(s: string): string {
if (MODEL_META[s]) return MODEL_META[s].provider;
const org = s.includes("/") ? s.slice(0, s.indexOf("/")).toLowerCase() : "";
if (org.includes("openai")) return "openai";
if (org.includes("qwen")) return "qwen";
return "";
}

// ---------- main ------------------------------------------------------------

function main() {
Expand All @@ -548,6 +629,7 @@ function main() {
const manifest = readManifest();
const datasets = readDatasetRegistry();
const retrieverReg = readRetrieverRegistry();
const methodCites = readMethodCitations();
const runDetails = readRunDetails(retrieverReg);

// Counts.
Expand Down Expand Up @@ -591,19 +673,29 @@ function main() {
const datasetList: DatasetEntry[] = Object.values(datasets).map((d) => ({
...d,
run_count: datasetCounts.get(d.id) ?? 0,
...(DATASET_HF_URLS[d.id] ? { hf_url: DATASET_HF_URLS[d.id] } : {}),
}));
datasetList.sort((a, b) => a.id.localeCompare(b.id));
writeJSON(path.join(OUT_DIR, "datasets.json"), datasetList);

const methodList = Array.from(methodCounts.entries())
.map(([id, run_count]) => ({ id, run_count, display: methodDisplay.get(id) ?? id }))
.map(([id, run_count]) => {
const cite = citationFor(id, methodCites);
return {
id,
run_count,
display: methodDisplay.get(id) ?? id,
...(cite ? { paper: cite.paper, paper_url: cite.paper_url } : {}),
};
})
.sort((a, b) => a.id.localeCompare(b.id));
writeJSON(path.join(OUT_DIR, "methods.json"), methodList);

const modelList = Array.from(modelCounts.entries())
.map(([id, run_count]) => ({
id,
display: displayModel(id),
provider: modelProvider(id),
run_count,
slug: encodePathSegment(id),
}))
Expand Down
26 changes: 26 additions & 0 deletions reproducibility/site/src/lib/providerIcon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Inline monochrome provider logos (currentColor), shared by Astro pages and the
// home-page client script. Returns an empty string for unknown providers so
// callers can render name-only without a placeholder.

const ICONS: Record<string, string> = {
// OpenAI mark
openai:
'<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.0201 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/>',
// Qwen mark (Simple Icons)
qwen:
'<path d="M23.919 14.545 20.817 9.17l1.47-2.544a.56.56 0 0 0 0-.566l-1.633-2.83a.57.57 0 0 0-.49-.283h-6.207L12.487.402a.57.57 0 0 0-.49-.284H8.732a.56.56 0 0 0-.49.284L5.139 5.775h-2.94a.56.56 0 0 0-.49.284L.077 8.887a.56.56 0 0 0 0 .567L3.18 14.83l-1.47 2.545a.56.56 0 0 0 0 .566l1.634 2.83a.57.57 0 0 0 .49.283h6.205l1.47 2.545a.57.57 0 0 0 .49.284h3.266a.57.57 0 0 0 .49-.284l3.104-5.375h2.94a.57.57 0 0 0 .49-.283l1.634-2.828a.55.55 0 0 0-.004-.568M8.733.686l1.634 2.828-1.634 2.828H21.8L20.164 9.17H7.425L5.63 6.06Zm1.306 19.801-6.205-.002 1.634-2.83h3.265L2.201 6.344h3.267q3.182 5.517 6.367 11.032zm10.124-5.66L18.53 12l-6.532 11.315-1.634-2.83c2.129-3.673 4.25-7.351 6.373-11.028h3.592l3.102 5.374z"/>',
};

/** Inline SVG markup for a provider logo, sized to 1em and inheriting color. */
export function providerIconSvg(provider: string | undefined | null): string {
const body = ICONS[(provider ?? "").toLowerCase()];
if (!body) return "";
return `<svg class="lb-model-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false">${body}</svg>`;
}

/** provider → inline SVG map, for passing into client scripts via define:vars. */
export function providerIconMap(): Record<string, string> {
const out: Record<string, string> = {};
for (const k of Object.keys(ICONS)) out[k] = providerIconSvg(k);
return out;
}
10 changes: 10 additions & 0 deletions reproducibility/site/src/pages/datasets/[id].astro
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ const colCount = 4 + metricCols.length;
<a href="/datasets/" class="text-xs text-qg-fg-muted hover:text-qg-fg">← Datasets</a>
<h2 class="text-xl font-semibold text-qg-fg md:text-2xl">{title}</h2>
<span class="qg-mono text-xs text-qg-fg-muted">{id}</span>
{datasetMeta?.hf_url && (
<a
class="text-xs font-medium text-qg-accent hover:underline"
href={datasetMeta.hf_url}
target="_blank"
rel="noopener noreferrer"
>
HuggingFace ↗
</a>
)}
<div class="h-px flex-1 bg-qg-border"></div>
<span class="text-[11px] uppercase tracking-wider text-qg-fg-muted">
All results produced by
Expand Down
10 changes: 10 additions & 0 deletions reproducibility/site/src/pages/datasets/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ import datasets from "../../data/datasets.json";
</div>
<div class="mt-1 qg-mono text-xs text-qg-fg-muted">{d.id}</div>
</a>
{d.hf_url && (
<a
class="mt-2 inline-block text-xs font-medium text-qg-accent hover:underline"
href={d.hf_url}
target="_blank"
rel="noopener noreferrer"
>
HuggingFace ↗
</a>
)}
</li>
))
}
Expand Down
98 changes: 88 additions & 10 deletions reproducibility/site/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ import runs from "../data/runs.json";
import retrievers from "../data/retrievers.json";
import models from "../data/models.json";
import methods from "../data/methods.json";
import datasets from "../data/datasets.json";
import { buildReproduceCmds, retrieveHint, evaluateHint, type RunLike } from "../lib/reproduce";
import { providerIconMap } from "../lib/providerIcon";

// id → HuggingFace dataset URL, for the link beside the dataset selector.
const datasetHfMap: Record<string, string> = Object.fromEntries(
(datasets as any[]).filter((d) => d.hf_url).map((d) => [d.id, d.hf_url]),
);
// id → polished display + provider, for icons in the table's LLM column.
const modelMetaMap: Record<string, { display: string; provider: string }> = Object.fromEntries(
(models as any[]).map((m) => [m.id, { display: m.display ?? m.id, provider: m.provider ?? "" }]),
);
const PROVIDER_ICONS = providerIconMap();

const populated = overview.run_count > 0;

Expand Down Expand Up @@ -182,6 +194,7 @@ const jsonLd = JSON.stringify({
<span class="lb-selector-label">Dataset</span>
{/* populated entirely by JS on init */}
<select id="lb-ds-select" class="lb-ds-select"></select>
<a id="lb-ds-hf" class="lb-hf-link lb-hidden" target="_blank" rel="noopener noreferrer">HuggingFace ↗</a>
</div>
<div class="lb-divider"></div>
<div class="lb-ctrl-grp">
Expand All @@ -208,12 +221,25 @@ const jsonLd = JSON.stringify({
<div class="lb-divider"></div>
<div class="lb-ctrl-grp">
<span class="lb-filter-label">Method</span>
<select id="lb-method-select" class="lb-ds-select">
<option value="">All methods</option>
{(methods as any[]).map((m) => (
<option value={m.id}>{m.display ?? m.display_name ?? m.id}</option>
))}
</select>
{/* Custom dropdown: native <select> can't host the per-row paper link */}
<div class="lb-dropdown" id="lb-method-dd">
<button type="button" id="lb-method-toggle" class="lb-ds-select lb-dd-toggle" aria-haspopup="listbox" aria-expanded="false">
<span id="lb-method-label" class="lb-dd-toggle-label">All methods</span>
</button>
<div id="lb-method-menu" class="lb-dd-menu lb-hidden" role="listbox">
<div class="lb-dd-opt" role="option" data-value="">
<span class="lb-dd-opt-name">All methods</span>
</div>
{(methods as any[]).map((m) => (
<div class="lb-dd-opt" role="option" data-value={m.id}>
<span class="lb-dd-opt-name">{m.display ?? m.display_name ?? m.id}</span>
{m.paper_url && (
<a class="lb-dd-paper" href={m.paper_url} target="_blank" rel="noopener noreferrer" data-paper>paper ↗</a>
)}
</div>
))}
</div>
</div>
</div>
<div class="lb-divider"></div>
<div class="lb-search-wrap">
Expand Down Expand Up @@ -360,6 +386,9 @@ const jsonLd = JSON.stringify({
METRIC_LABEL,
methodsData: methods,
modelsData: models,
datasetHfMap,
modelMetaMap,
PROVIDER_ICONS,
}}>
// ------ viewport-width tracker for expand panel (sticky positioning) -------
const scrollEl = document.getElementById("lb-scroll");
Expand Down Expand Up @@ -422,6 +451,7 @@ const jsonLd = JSON.stringify({
const ids = datasets.map((d) => d.id);
state.dataset = ids.includes(state.dataset) ? state.dataset : (ids[0] ?? "");
dsSelect.value = state.dataset;
updateDatasetHf(state.dataset);
}

document.querySelectorAll("#lb-bench-pills button").forEach((btn) => {
Expand All @@ -434,8 +464,23 @@ const jsonLd = JSON.stringify({
});
});

// HuggingFace link beside the dataset selector — updates with selection.
const dsHfLink = document.getElementById("lb-ds-hf");
function updateDatasetHf(id) {
if (!dsHfLink) return;
const url = (datasetHfMap ?? {})[id];
if (url) {
dsHfLink.href = url;
dsHfLink.classList.remove("lb-hidden");
} else {
dsHfLink.removeAttribute("href");
dsHfLink.classList.add("lb-hidden");
}
}

dsSelect?.addEventListener("change", (e) => {
state.dataset = e.target.value;
updateDatasetHf(state.dataset);
renderTable();
});

Expand All @@ -457,9 +502,41 @@ const jsonLd = JSON.stringify({
filterState.model = e.target.value ?? "";
renderTable();
});
document.getElementById("lb-method-select")?.addEventListener("change", (e) => {
filterState.method = e.target.value ?? "";
renderTable();
// ------ method custom dropdown (per-row paper links) ------------------------
const methodDd = document.getElementById("lb-method-dd");
const methodToggle = document.getElementById("lb-method-toggle");
const methodMenu = document.getElementById("lb-method-menu");
const methodLabel = document.getElementById("lb-method-label");

function closeMethodMenu() {
methodMenu?.classList.add("lb-hidden");
methodToggle?.setAttribute("aria-expanded", "false");
}
function openMethodMenu() {
methodMenu?.classList.remove("lb-hidden");
methodToggle?.setAttribute("aria-expanded", "true");
}
methodToggle?.addEventListener("click", (e) => {
e.stopPropagation();
if (methodMenu?.classList.contains("lb-hidden")) openMethodMenu();
else closeMethodMenu();
});
methodMenu?.querySelectorAll(".lb-dd-opt").forEach((opt) => {
opt.addEventListener("click", (e) => {
// Clicks on the paper link open the paper without changing selection.
if (e.target.closest("[data-paper]")) { e.stopPropagation(); return; }
filterState.method = opt.dataset.value ?? "";
if (methodLabel) {
methodLabel.textContent = opt.querySelector(".lb-dd-opt-name")?.textContent ?? "All methods";
}
methodMenu.querySelectorAll(".lb-dd-opt").forEach((o) => o.classList.remove("selected"));
opt.classList.add("selected");
closeMethodMenu();
renderTable();
});
});
document.addEventListener("click", (e) => {
if (methodDd && !methodDd.contains(e.target)) closeMethodMenu();
});

// ------ search --------------------------------------------------------------
Expand Down Expand Up @@ -606,6 +683,7 @@ const jsonLd = JSON.stringify({

const mTagIdx = methodColorMap[row.method_id] ?? 0;
const mdTagIdx = modelColorMap[row.model] ?? 0;
const modelIcon = PROVIDER_ICONS[(modelMetaMap[row.model] ?? {}).provider] ?? "";
const retrieverCell = showRetrieverCol
? `<td class="lb-col-retriever">${escHtml(row.retriever_display ?? row.retriever_id)}</td>`
: "";
Expand All @@ -614,7 +692,7 @@ const jsonLd = JSON.stringify({
<tr class="data" data-row-key="${escHtml(rowKey)}" data-method="${escHtml(row.method_id)}" data-model="${escHtml(row.model)}" data-retriever="${escHtml(row.retriever_id)}">
<td class="lb-col-rank">${rankBadge(ranks[i])}</td>
<td class="lb-col-method"><span class="lb-badge lb-mtag-${mTagIdx}">${escHtml(row.method_display ?? row.method_id)}</span></td>
<td class="lb-col-model"><span class="lb-badge lb-mono lb-mdtag-${mdTagIdx}">${escHtml(row.model_display ?? row.model)}</span></td>
<td class="lb-col-model"><span class="lb-badge lb-mono lb-mdtag-${mdTagIdx}">${modelIcon}${escHtml(row.model_display ?? row.model)}</span></td>
${retrieverCell}
<td class="lb-col-metric${pBest ? " best" : ""}" data-primary-value="${pv ?? ""}">
<span class="metric-val">${pvStr}</span>
Expand Down
Loading
Loading