Download index.html from rishhh/about: direct link, hf CLI and curl.
- Browser
- Download file 26.8 kB
-
https://huggingface.co/spaces/rishhh/about/resolve/main/index.html
- Command line
-
hf download hf://spaces/rishhh/about/index.html
-
curl -L -o index.html https://huggingface.co/spaces/rishhh/about/resolve/main/index.html
26.8 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Rishabh Patil: models, data and research</title> | |
| <meta name="description" content="AI engineer and researcher in London. Co-founder and CEO of Valuren. Claim verification, safe text-to-SQL, LLM evaluation and world models, with live download numbers from the Hugging Face Hub."> | |
| <style> | |
| :root { | |
| color-scheme: light; | |
| --bg: #ffffff; --surface: #f6f8fa; --panel: #ffffff; --border: #d0d7de; | |
| --ink: #1f2328; --ink2: #59636e; --muted: #6e7781; --grid: #d8dee4; --track: #cde2fb; | |
| --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --other: #8c959f; | |
| --goodtext: #006300; --good: #0ca30c; --link: #0969da; --focus: #2a78d6; | |
| --shadow: 0 8px 24px rgba(31, 35, 40, 0.12); | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root:where(:not([data-theme="light"])) { | |
| color-scheme: dark; | |
| --bg: #0d1117; --surface: #161b22; --panel: #0d1117; --border: #30363d; | |
| --ink: #f0f6fc; --ink2: #9198a1; --muted: #848d97; --grid: #30363d; --track: #104281; | |
| --s1: #3987e5; --s2: #d95926; --s3: #199e70; --other: #6e7781; | |
| --goodtext: #0ca30c; --good: #0ca30c; --link: #4493f8; --focus: #3987e5; | |
| --shadow: 0 8px 24px rgba(1, 4, 9, 0.6); | |
| } | |
| } | |
| :root[data-theme="dark"] { | |
| color-scheme: dark; | |
| --bg: #0d1117; --surface: #161b22; --panel: #0d1117; --border: #30363d; | |
| --ink: #f0f6fc; --ink2: #9198a1; --muted: #848d97; --grid: #30363d; --track: #104281; | |
| --s1: #3987e5; --s2: #d95926; --s3: #199e70; --other: #6e7781; | |
| --goodtext: #0ca30c; --good: #0ca30c; --link: #4493f8; --focus: #3987e5; | |
| --shadow: 0 8px 24px rgba(1, 4, 9, 0.6); | |
| } | |
| * { box-sizing: border-box; } | |
| html { -webkit-text-size-adjust: 100%; } | |
| body { | |
| margin: 0; background: var(--bg); color: var(--ink); | |
| font: 16px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | |
| } | |
| main { max-width: 880px; margin: 0 auto; padding: 24px 16px 56px; } | |
| a { color: var(--link); text-decoration: none; } | |
| a:hover { text-decoration: underline; } | |
| a:focus-visible, [tabindex]:focus-visible, summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 6px; } | |
| h2 { font-size: 1.3rem; line-height: 1.3; margin: 44px 0 6px; } | |
| h3 { font-size: 1.05rem; margin: 0 0 4px; } | |
| p { margin: 0 0 12px; } | |
| .art { display: block; width: 100%; height: auto; } | |
| .chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 18px; padding: 0; list-style: none; } | |
| .chips a { | |
| display: inline-block; padding: 5px 12px; border: 1px solid var(--border); border-radius: 999px; | |
| color: var(--ink); background: var(--surface); font-size: 0.9rem; | |
| } | |
| .chips a:hover { text-decoration: none; border-color: var(--ink2); } | |
| .lead { color: var(--ink2); font-size: 1.04rem; } | |
| .card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 22px 22px 18px; } | |
| .cardhead { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 16px; margin-bottom: 12px; } | |
| .cardhead h3 { margin: 0; font-size: 1rem; } | |
| .status { color: var(--muted); font-size: 0.82rem; } | |
| .status .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; background: var(--muted); vertical-align: 1px; } | |
| .status.live .dot { background: var(--good); } | |
| .kpis { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 16px; align-items: end; } | |
| .hero .value { font-size: 3rem; line-height: 1.05; font-weight: 600; letter-spacing: -0.5px; } | |
| .tile .value { font-size: 1.75rem; line-height: 1.1; font-weight: 600; } | |
| .label { color: var(--ink2); font-size: 0.92rem; } | |
| .delta { font-size: 0.9rem; color: var(--ink2); margin-top: 2px; } | |
| .delta strong { color: var(--goodtext); } | |
| .delta svg { vertical-align: -1px; margin-right: 4px; } | |
| .rule { border: 0; border-top: 1px solid var(--grid); margin: 20px 0 16px; } | |
| .legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 0 0 10px; padding: 0; list-style: none; font-size: 0.85rem; color: var(--ink2); } | |
| .legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 6px; vertical-align: -0.5px; } | |
| .chart { position: relative; } | |
| .row { padding: 4px 0 6px; border-radius: 6px; cursor: default; } | |
| .row:hover .bar, .row:focus-visible .bar { filter: brightness(1.12); } | |
| .row .name { font-size: 0.84rem; color: var(--ink2); overflow-wrap: anywhere; line-height: 1.35; } | |
| .row .name .kind { color: var(--muted); } | |
| .barline { display: flex; align-items: center; gap: 8px; height: 16px; } | |
| .bar { height: 12px; border-radius: 0 4px 4px 0; flex: none; min-width: 3px; } | |
| .val { font-size: 0.84rem; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; } | |
| .c-VeriSci { background: var(--s1); } .c-SchemaSage { background: var(--s2); } .c-Other { background: var(--other); } | |
| .tooltip { | |
| position: absolute; z-index: 5; pointer-events: none; min-width: 180px; max-width: 280px; | |
| background: var(--panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow); | |
| padding: 10px 12px; font-size: 0.84rem; opacity: 0; transition: opacity 0.12s; | |
| } | |
| .tooltip.on { opacity: 1; } | |
| .tooltip .tv { font-size: 1.05rem; font-weight: 600; color: var(--ink); } | |
| .tooltip .tl { color: var(--ink2); } | |
| .tooltip .key { display: inline-block; width: 12px; height: 2px; margin-right: 6px; vertical-align: 3px; } | |
| details { margin-top: 12px; } | |
| summary { cursor: pointer; color: var(--ink2); font-size: 0.9rem; } | |
| .table-wrap { overflow-x: auto; margin-top: 10px; border: 1px solid var(--border); border-radius: 10px; } | |
| table { width: 100%; border-collapse: collapse; font-size: 0.84rem; } | |
| th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--grid); vertical-align: top; } | |
| th { background: var(--panel); font-weight: 600; } | |
| td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; } | |
| tr:last-child td { border-bottom: 0; } | |
| .links { margin: 10px 0 0; padding-left: 20px; color: var(--ink2); } | |
| .links li { margin: 2px 0; } | |
| .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 12px; } | |
| .project { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 16px; display: flex; flex-direction: column; gap: 8px; } | |
| .project .fig { width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: contain; border-radius: 8px; border: 1px solid var(--border); background: #ffffff; } | |
| .project p { color: var(--ink2); font-size: 0.92rem; margin: 0; } | |
| .badges { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } | |
| .badges img { height: 20px; } | |
| .compact { list-style: none; padding: 0; margin: 16px 0 0; display: grid; gap: 10px; } | |
| .compact li { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 12px 16px; } | |
| .compact .meta { color: var(--ink2); font-size: 0.92rem; } | |
| footer { margin-top: 48px; padding-top: 16px; border-top: 1px solid var(--grid); color: var(--muted); font-size: 0.85rem; } | |
| .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; } | |
| @media (max-width: 720px) { | |
| .kpis { grid-template-columns: 1fr 1fr 1fr; } | |
| .hero { grid-column: 1 / -1; } | |
| .hero .value { font-size: 2.5rem; } | |
| .grid { grid-template-columns: 1fr; } | |
| .card { padding: 18px 16px 14px; } | |
| } | |
| @media (prefers-reduced-motion: reduce) { .tooltip { transition: none; } } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <header> | |
| <img class="art" data-art="banner" src="assets/banner-auto.svg" width="1000" height="250" | |
| alt="Rishabh Patil. AI engineer and researcher, co-founder and CEO of Valuren."> | |
| <ul class="chips"> | |
| <li><a href="https://huggingface.co/rishhh" target="_blank" rel="noopener noreferrer">Hugging Face</a></li> | |
| <li><a href="https://github.com/MrRobotop" target="_blank" rel="noopener noreferrer">GitHub</a></li> | |
| <li><a href="https://www.linkedin.com/in/rishabh-ashok-patil/" target="_blank" rel="noopener noreferrer">LinkedIn</a></li> | |
| <li><a href="https://orcid.org/0009-0007-0868-9673" target="_blank" rel="noopener noreferrer">ORCID</a></li> | |
| <li><a href="https://www.rishabhpatil.com" target="_blank" rel="noopener noreferrer">Website</a></li> | |
| <li><a href="mailto:rishabh.a.patil@outlook.com">Email</a></li> | |
| </ul> | |
| <p class="lead">AI engineer and researcher in London. Co-founder and CEO of <a href="https://www.linkedin.com/company/valuren/" target="_blank" rel="noopener noreferrer">Valuren</a>, which gives fashion and luxury brands digital product passports. I work on verification for AI: checking claims against evidence, evaluating LLM systems, and planning safely in learned latent spaces.</p> | |
| </header> | |
| <section aria-labelledby="hub-h"> | |
| <h2 id="hub-h">On the Hub</h2> | |
| <div class="card"> | |
| <div class="cardhead"> | |
| <h3>Downloads</h3> | |
| <span class="status" id="status"><span class="dot"></span><span id="status-text">Loading live numbers</span></span> | |
| </div> | |
| <div class="kpis"> | |
| <div class="hero"> | |
| <div class="value" id="k-total">2,788</div> | |
| <div class="label">downloads, all time</div> | |
| <div class="delta" id="k-delta"><svg width="12" height="10" viewBox="0 0 12 10" aria-hidden="true"><path d="M6 0l6 10H0z" fill="var(--good)"/></svg><strong id="k-d30">+308</strong> in the last 30 days</div> | |
| </div> | |
| <div class="tile"><div class="value" id="k-models">28</div><div class="label">models</div></div> | |
| <div class="tile"><div class="value" id="k-datasets">1</div><div class="label" id="k-datasets-l">dataset</div></div> | |
| <div class="tile"><div class="value" id="k-spaces">1</div><div class="label" id="k-spaces-l">Space</div></div> | |
| </div> | |
| <hr class="rule"> | |
| <div class="cardhead"><h3>Most downloaded repos</h3><span class="status">Hover or tab through the bars for 30-day numbers</span></div> | |
| <ul class="legend" id="legend"></ul> | |
| <div class="chart" id="chart" role="list" aria-label="Most downloaded repos, all time"></div> | |
| <details> | |
| <summary>Table view of every repo</summary> | |
| <div class="table-wrap"><table> | |
| <thead><tr><th>Repo</th><th>Type</th><th class="num">All time</th><th class="num">Last 30 days</th></tr></thead> | |
| <tbody id="table"></tbody> | |
| </table></div> | |
| </details> | |
| </div> | |
| </section> | |
| <section aria-labelledby="v-h"> | |
| <h2 id="v-h">VeriSci: scientific claim verification</h2> | |
| <p>Paste a scientific claim and get SUPPORTS, REFUTES or NOT ENOUGH INFO, with the sentences that justify the label.</p> | |
| <img class="art" data-art="verisci" src="assets/verisci-auto.svg" width="840" height="372" | |
| alt="VeriSci pipeline: claim, retrieve with BM25 and a fine-tuned e5 retriever, select evidence sentences, verify with a calibrated DeBERTa model, return a label with evidence. Retriever Recall@5 0.867. Verifier accuracy 0.905, macro-F1 0.874, calibration error 0.024. End to end on SciFact validation: 0.691 accuracy, 0.653 macro-F1."> | |
| <ul class="links"> | |
| <li><a href="https://huggingface.co/spaces/rishhh/verisci-claim-space" target="_blank" rel="noopener noreferrer">Live demo</a> (may take a minute to wake if idle)</li> | |
| <li><a href="https://huggingface.co/rishhh/verisci-claim-verifier-retrieval-adapted-seed123" target="_blank" rel="noopener noreferrer">Release verifier</a> and <a href="https://huggingface.co/rishhh/verisci-scifact-e5-retriever" target="_blank" rel="noopener noreferrer">retriever</a></li> | |
| <li>Seeded ablations of evidence selection, each with its own model card</li> | |
| </ul> | |
| </section> | |
| <section aria-labelledby="s-h"> | |
| <h2 id="s-h">SchemaSage-SQL: safe text-to-SQL</h2> | |
| <p>QLoRA adapters on Qwen3-4B that write read-only SQL grounded in the schema you give them, with a safety layer that refuses destructive requests.</p> | |
| <img class="art" data-art="schemasage" src="assets/schemasage-auto.svg" width="840" height="246" | |
| alt="SchemaSage-SQL release baseline on 64 cleaned held-out examples: 100% SQL parse validity, 98.3% schema adherence, 0% unsafe queries, 100% correct refusals. QLoRA on Qwen3-4B-Instruct-2507, trained on 111,444 cleaned examples, 10,862 of them refusals."> | |
| <ul class="links"> | |
| <li><a href="https://huggingface.co/rishhh/schemasage-sql-qwen3-4b-clean-balanced-200" target="_blank" rel="noopener noreferrer">Release baseline</a>; the <a href="https://huggingface.co/rishhh/schemasage-sql-qwen3-4b-clean-balanced-8k-600-v2" target="_blank" rel="noopener noreferrer">larger candidate</a> scored higher on exact match and execution accuracy but missed one blocked refusal, so it was not shipped</li> | |
| <li><a href="https://huggingface.co/datasets/rishhh/schemasage-sql-clean-text2sql" target="_blank" rel="noopener noreferrer">Dataset</a> and <a href="https://github.com/MrRobotop/schemasage-sql" target="_blank" rel="noopener noreferrer">code</a></li> | |
| </ul> | |
| </section> | |
| <section aria-labelledby="r-h"> | |
| <h2 id="r-h">Research code</h2> | |
| <p>Each library pairs installable code with a first-author preprint.</p> | |
| <div class="grid"> | |
| <article class="project"> | |
| <img class="fig" src="assets/toploss-sasp.png" width="1600" height="589" loading="lazy" | |
| alt="SASP results: test cross-entropy over 120 epochs against the baseline, and Hessian trace at convergence, about 171 for the baseline against about 100 with SASP."> | |
| <h3><a href="https://github.com/MrRobotop/toploss" target="_blank" rel="noopener noreferrer">toploss</a></h3> | |
| <p>Five optimiser-free PyTorch regularisers that rebuild SAM, cautious weight decay and AdEMAMix as loss penalties. SASP cut the Hessian trace 41% at +15% wall-clock, against +107% for SAM (three seeds, CPU).</p> | |
| <div class="badges"> | |
| <img alt="PyPI version" src="https://img.shields.io/pypi/v/toploss?style=flat-square&label=PyPI&color=2a78d6"> | |
| <img alt="CI, live status" src="https://img.shields.io/github/actions/workflow/status/MrRobotop/toploss/ci.yaml?style=flat-square&label=CI"> | |
| <a href="https://doi.org/10.5281/zenodo.20497841" target="_blank" rel="noopener noreferrer">Preprint</a> | |
| </div> | |
| </article> | |
| <article class="project"> | |
| <img class="fig" src="assets/clap-planning.png" width="1280" height="877" loading="lazy" | |
| alt="CLAP planning in a two-dimensional latent field: the trajectory reaches the safe target region and dwells there, avoiding a reward trap and an unsafe zone."> | |
| <h3><a href="https://github.com/MrRobotop/clap-family" target="_blank" rel="noopener noreferrer">clap-family</a></h3> | |
| <p>Conservative Lapse-Action Planning: reach the best safe region of a latent space, then stay there. Seven planner variants, 72 tests.</p> | |
| <div class="badges"> | |
| <img alt="PyPI version" src="https://img.shields.io/pypi/v/clap-family?style=flat-square&label=PyPI&color=2a78d6"> | |
| <img alt="Checks, live status" src="https://img.shields.io/github/check-runs/MrRobotop/clap-family/HEAD?style=flat-square&label=checks"> | |
| <a href="https://doi.org/10.5281/zenodo.20467271" target="_blank" rel="noopener noreferrer">Preprint</a> | |
| </div> | |
| </article> | |
| </div> | |
| <ul class="compact"> | |
| <li><a href="https://github.com/MrRobotop/micro-world-model" target="_blank" rel="noopener noreferrer"><strong>micro-world-model</strong></a> · <a href="https://doi.org/10.5281/zenodo.20480620" target="_blank" rel="noopener noreferrer">preprint</a><br><span class="meta">Hierarchical JEPA world model that plans in a 256-dimensional latent space with no reconstruction, no reward and no EMA target.</span></li> | |
| <li><a href="https://github.com/MrRobotop/ariadne-eval" target="_blank" rel="noopener noreferrer"><strong>ariadne-eval</strong></a><br><span class="meta">Trajectory-level tracing and scoring for multi-step, tool-using agents. 285 tests, mypy-strict.</span></li> | |
| <li><a href="https://github.com/MrRobotop/evalforge" target="_blank" rel="noopener noreferrer"><strong>evalforge</strong></a><br><span class="meta">LLM evaluation with bootstrapped confidence intervals, calibrated LLM-as-judge and a CI regression gate. 538 tests.</span></li> | |
| </ul> | |
| </section> | |
| <section aria-labelledby="b-h"> | |
| <h2 id="b-h">Background</h2> | |
| <p>MSc Artificial Intelligence, University of St Andrews (dissertation on dependent types for machine learning, supervised by Dr Edwin Brady). BSc Artificial Intelligence, VU Amsterdam. Before Valuren I co-founded RelAIable, an AI consultancy in Amsterdam, as Chief AI Officer.</p> | |
| </section> | |
| <footer> | |
| <p id="foot">Download numbers come live from the Hugging Face Hub API. If it can't be reached, the page shows a snapshot from 8 Oct 2026.</p> | |
| </footer> | |
| </main> | |
| <div class="tooltip" id="tip" role="status" aria-live="polite"></div> | |
| <script> | |
| (() => { | |
| "use strict"; | |
| const USER = "rishhh"; | |
| const SNAPSHOT = {"date":"2026-10-08","dateLabel":"8 Oct 2026","spaces":1,"repos":[{"id":"rishhh/schemasage-sql-qwen3-4b-smoke","type":"model","all":3,"d30":0},{"id":"rishhh/schemasage-sql-qwen3-4b-longer-200","type":"model","all":57,"d30":4},{"id":"rishhh/schemasage-sql-qwen3-4b-clean-200","type":"model","all":43,"d30":5},{"id":"rishhh/schemasage-sql-qwen3-4b-clean-balanced-200","type":"model","all":132,"d30":6},{"id":"rishhh/schemasage-sql-qwen3-4b-clean-balanced-8k-600","type":"model","all":33,"d30":4},{"id":"rishhh/schemasage-sql-qwen3-4b-clean-balanced-8k-600-v2","type":"model","all":135,"d30":4},{"id":"rishhh/verisci-claim-verifier","type":"model","all":55,"d30":0},{"id":"rishhh/verisci-claim-verifier-sentence-nli","type":"model","all":63,"d30":27},{"id":"rishhh/verisci-claim-verifier-sentence-nli-refute","type":"model","all":44,"d30":14},{"id":"rishhh/verisci-claim-verifier-sentence-nli-seed123","type":"model","all":419,"d30":25},{"id":"rishhh/verisci-scifact-e5-retriever","type":"model","all":320,"d30":61},{"id":"rishhh/verisci-claim-verifier-retrieval-aware-seed123","type":"model","all":83,"d30":53},{"id":"rishhh/verisci-claim-verifier-retrieval-adapted-seed123","type":"model","all":941,"d30":13},{"id":"rishhh/verisci-claim-verifier-dense-adapted-seed123","type":"model","all":99,"d30":14},{"id":"rishhh/verisci-claim-verifier-claim-aggregator-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-claim-aggregator-holdout-safe-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-joint-evidence-seed123","type":"model","all":56,"d30":17},{"id":"rishhh/verisci-claim-verifier-joint-evidence-selector-seed123","type":"model","all":46,"d30":15},{"id":"rishhh/verisci-claim-verifier-learned-selector-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-refutes-hard-selector-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-constrained-selector-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-hard-negative-selector-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-contradiction-adapted-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-scifact-sentence-reranker-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-evidence-gated-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-selective-evidence-gated-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-learned-selector-base-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/verisci-claim-verifier-learned-selector-nli-warm-joint-seed123","type":"model","all":0,"d30":0},{"id":"rishhh/schemasage-sql-clean-text2sql","type":"dataset","all":259,"d30":46}]}; | |
| const PROJECTS = [["VeriSci", "verisci"], ["SchemaSage", "schemasage"]]; | |
| const root = document.documentElement; | |
| // Hugging Face passes ?__theme=light|dark to Space iframes; follow it when present. | |
| const asked = new URLSearchParams(location.search).get("__theme"); | |
| if (asked === "light" || asked === "dark") root.dataset.theme = asked; | |
| const dark = matchMedia("(prefers-color-scheme: dark)"); | |
| const theme = () => (root.dataset.theme === "light" || root.dataset.theme === "dark") | |
| ? root.dataset.theme : (dark.matches ? "dark" : "light"); | |
| const swapArt = () => document.querySelectorAll("img[data-art]").forEach((img) => { | |
| img.src = `assets/${img.dataset.art}-${theme()}.svg`; | |
| }); | |
| swapArt(); | |
| dark.addEventListener("change", swapArt); | |
| const fmt = (n) => Number(n || 0).toLocaleString("en-GB"); | |
| const projectOf = (id) => { | |
| const name = id.split("/").pop().toLowerCase(); | |
| const hit = PROJECTS.find(([, prefix]) => name.startsWith(prefix)); | |
| return hit ? hit[0] : "Other"; | |
| }; | |
| const el = (tag, cls, text) => { | |
| const node = document.createElement(tag); | |
| if (cls) node.className = cls; | |
| if (text !== undefined) node.textContent = text; | |
| return node; | |
| }; | |
| const plural = (n, word) => (n === 1 ? word : word + "s"); | |
| async function getJSON(url) { | |
| const res = await fetch(url, { headers: { Accept: "application/json" } }); | |
| if (!res.ok) throw new Error(`${res.status} ${url}`); | |
| return res.json(); | |
| } | |
| async function load() { | |
| const q = "&limit=1000&expand%5B%5D=downloadsAllTime&expand%5B%5D=downloads"; | |
| try { | |
| const [models, datasets, spaces] = await Promise.all([ | |
| getJSON(`https://huggingface.co/api/models?author=${USER}${q}`), | |
| getJSON(`https://huggingface.co/api/datasets?author=${USER}${q}`), | |
| getJSON(`https://huggingface.co/api/spaces?author=${USER}&limit=1000`), | |
| ]); | |
| const repos = [ | |
| ...models.map((m) => ({ id: m.id, type: "model", all: m.downloadsAllTime || 0, d30: m.downloads || 0 })), | |
| ...datasets.map((d) => ({ id: d.id, type: "dataset", all: d.downloadsAllTime || 0, d30: d.downloads || 0 })), | |
| ]; | |
| render({ repos, spaces: spaces.length, live: true }); | |
| } catch (err) { | |
| render({ repos: SNAPSHOT.repos, spaces: SNAPSHOT.spaces, live: false }); | |
| } | |
| } | |
| function render({ repos, spaces, live }) { | |
| const models = repos.filter((r) => r.type === "model").length; | |
| const datasets = repos.filter((r) => r.type === "dataset").length; | |
| const total = repos.reduce((s, r) => s + r.all, 0); | |
| const d30 = repos.reduce((s, r) => s + r.d30, 0); | |
| document.getElementById("k-total").textContent = fmt(total); | |
| document.getElementById("k-d30").textContent = "+" + fmt(d30); | |
| document.getElementById("k-models").textContent = fmt(models); | |
| document.getElementById("k-datasets").textContent = fmt(datasets); | |
| document.getElementById("k-datasets-l").textContent = plural(datasets, "dataset"); | |
| document.getElementById("k-spaces").textContent = fmt(spaces); | |
| document.getElementById("k-spaces-l").textContent = plural(spaces, "Space"); | |
| const status = document.getElementById("status"); | |
| status.classList.toggle("live", live); | |
| document.getElementById("status-text").textContent = live | |
| ? "Live from the Hugging Face Hub" | |
| : `Snapshot from ${SNAPSHOT.dateLabel}`; | |
| const sorted = [...repos].sort((a, b) => b.all - a.all || a.id.localeCompare(b.id)); | |
| const top = sorted.filter((r) => r.all > 0).slice(0, 10); | |
| const max = Math.max(1, ...top.map((r) => r.all)); | |
| const used = [...new Set(top.map((r) => projectOf(r.id)))]; | |
| const order = ["VeriSci", "SchemaSage", "Other"].filter((p) => used.includes(p)); | |
| const legend = document.getElementById("legend"); | |
| legend.replaceChildren(...order.map((p) => { | |
| const li = el("li"); | |
| li.append(el("i", `c-${p}`), document.createTextNode(p)); | |
| return li; | |
| })); | |
| const chart = document.getElementById("chart"); | |
| chart.replaceChildren(...top.map((r) => { | |
| const project = projectOf(r.id); | |
| const name = r.id.split("/").pop(); | |
| const row = el("div", "row"); | |
| row.setAttribute("role", "listitem"); | |
| row.tabIndex = 0; | |
| row.setAttribute("aria-label", `${name}, ${r.type}, ${fmt(r.all)} downloads all time, ${fmt(r.d30)} in the last 30 days`); | |
| const label = el("div", "name"); | |
| label.append(document.createTextNode(name)); | |
| if (r.type === "dataset") label.append(el("span", "kind", " (dataset)")); | |
| const line = el("div", "barline"); | |
| const bar = el("div", `bar c-${project}`); | |
| bar.style.width = `calc((100% - 64px) * ${(r.all / max).toFixed(4)})`; | |
| line.append(bar, el("span", "val", fmt(r.all))); | |
| row.append(label, line); | |
| const show = (x, y) => showTip(r, project, x, y); | |
| row.addEventListener("pointermove", (e) => show(e.clientX, e.clientY)); | |
| row.addEventListener("pointerleave", hideTip); | |
| row.addEventListener("focus", () => { const b = row.getBoundingClientRect(); show(b.left + 24, b.bottom); }); | |
| row.addEventListener("blur", hideTip); | |
| return row; | |
| })); | |
| const tbody = document.getElementById("table"); | |
| tbody.replaceChildren(...sorted.map((r) => { | |
| const tr = el("tr"); | |
| const a = el("a", "", r.id.split("/").pop()); | |
| a.href = `https://huggingface.co/${r.type === "dataset" ? "datasets/" : ""}${r.id}`; | |
| a.target = "_blank"; a.rel = "noopener noreferrer"; | |
| const name = el("td"); name.append(a); | |
| tr.append(name, el("td", "", r.type), el("td", "num", fmt(r.all)), el("td", "num", fmt(r.d30))); | |
| return tr; | |
| })); | |
| } | |
| const tip = document.getElementById("tip"); | |
| function showTip(r, project, x, y) { | |
| const v = el("div", "tv", `${fmt(r.all)} downloads`); | |
| const l1 = el("div", "tl", `${fmt(r.d30)} in the last 30 days`); | |
| const l2 = el("div", "tl"); | |
| const key = el("span", `key c-${project}`); | |
| l2.append(key, document.createTextNode(`${project} ${r.type}`)); | |
| tip.replaceChildren(v, l1, l2); | |
| tip.classList.add("on"); | |
| const w = tip.offsetWidth, h = tip.offsetHeight; | |
| const left = Math.min(window.innerWidth - w - 8, Math.max(8, x + 14)) + window.scrollX; | |
| const top = (y + h + 20 > window.innerHeight ? y - h - 12 : y + 16) + window.scrollY; | |
| tip.style.left = `${left}px`; | |
| tip.style.top = `${top}px`; | |
| } | |
| function hideTip() { tip.classList.remove("on"); } | |
| render({ repos: SNAPSHOT.repos, spaces: SNAPSHOT.spaces, live: false }); | |
| document.getElementById("status-text").textContent = "Loading live numbers"; | |
| load(); | |
| })(); | |
| </script> | |
| </body> | |
| </html> | |