Spaces:
Running
Running
Artem Plastinkin commited on
Commit Β·
13b8f21
1
Parent(s): b4f7aa3
- NEW styles
Browse files- .claude/skills/regenerate-catalog/SKILL.md +70 -0
- .vscode/settings.json +4 -0
- CLAUDE.md +92 -0
- README.md +28 -8
- __pycache__/generate_models_json.cpython-313.pyc +0 -0
- app.js +703 -416
- assets/logo_renesas_blue.svg +13 -0
- assets/logo_renesas_light.svg +12 -13
- assets/logo_renesas_white.svg +13 -0
- generate_models_json.py +842 -0
- index.html +321 -102
- links.json +0 -17
- models.json +252 -1643
- styles.css +987 -476
.claude/skills/regenerate-catalog/SKILL.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: regenerate-catalog
|
| 3 |
+
description: Regenerate the dashboard's models.json from the live Hugging Face repos by running generate_models_json.py. Use when the user wants to refresh, update, or rebuild the model catalog, import benchmark numbers, or after repos change on Hugging Face.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Regenerate the model catalog (`models.json`)
|
| 7 |
+
|
| 8 |
+
This skill runs `generate_models_json.py` to rebuild `models.json` β the auto-generated
|
| 9 |
+
catalog the static dashboard reads. **Never hand-edit `models.json`; always regenerate it.**
|
| 10 |
+
|
| 11 |
+
## Steps
|
| 12 |
+
|
| 13 |
+
1. **Work from the project root** (where `generate_models_json.py` lives). Confirm it exists:
|
| 14 |
+
```bash
|
| 15 |
+
ls generate_models_json.py
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
2. **Ensure dependencies** are installed (idempotent β safe to re-run):
|
| 19 |
+
```bash
|
| 20 |
+
pip install requests pyyaml
|
| 21 |
+
```
|
| 22 |
+
`huggingface_hub` is optional β only used to auto-detect a cached login token.
|
| 23 |
+
|
| 24 |
+
3. **Decide whether a token is needed.** Gated Renesas repos are *listed* without a token, but
|
| 25 |
+
their *benchmark numbers* require an authorized one. Resolve a token from (in order):
|
| 26 |
+
`--token hf_xxx`, env `HF_TOKEN` / `HUGGINGFACE_TOKEN` / `HUGGING_FACE_HUB_TOKEN`, or a prior
|
| 27 |
+
`huggingface-cli login`. If the user hasn't supplied one and wants gated metrics, ask them to
|
| 28 |
+
either run `! huggingface-cli login` in this session or pass a token. Do **not** print or echo
|
| 29 |
+
a token; pass it through the environment or the `--token` flag they provide.
|
| 30 |
+
|
| 31 |
+
4. **Preview first (recommended).** A dry run prints the JSON and a summary without writing:
|
| 32 |
+
```bash
|
| 33 |
+
python generate_models_json.py --dry-run -v
|
| 34 |
+
```
|
| 35 |
+
Read the per-repo summary: configs, metric blocks, and any `[gated: metrics skipped]` flags.
|
| 36 |
+
|
| 37 |
+
5. **Write the catalog** once the preview looks right:
|
| 38 |
+
```bash
|
| 39 |
+
python generate_models_json.py # rewrites ./models.json (anonymous)
|
| 40 |
+
python generate_models_json.py --token hf_xxx # also imports gated repos' metrics
|
| 41 |
+
```
|
| 42 |
+
Other flags: `--org <name>` (default `Renesas`), `--output <path>`, `--include-private`
|
| 43 |
+
(needs a token with access), `--force` (write even if 0 models β overwrites existing file).
|
| 44 |
+
|
| 45 |
+
6. **Check the exit code and report it:**
|
| 46 |
+
- `0` β success (or a valid dry run).
|
| 47 |
+
- `2` β Hugging Face network/API error (rate-limited or unreachable). Suggest retrying later.
|
| 48 |
+
- `3` β could not write the output file (check path/permissions).
|
| 49 |
+
- `4` β produced **0 models** and refused to overwrite the existing `models.json`. This is a
|
| 50 |
+
safety guard β investigate *why* zero models came back (org name? token? API down?) before
|
| 51 |
+
ever reaching for `--force`.
|
| 52 |
+
|
| 53 |
+
## After regenerating
|
| 54 |
+
|
| 55 |
+
- Skim the run summary for gated repos whose metrics were skipped β if the user expected those
|
| 56 |
+
numbers, they need a token with access (request access on HF, then re-run with `--token`).
|
| 57 |
+
- The dashboard reads `models.json` over HTTP, so to eyeball the result locally:
|
| 58 |
+
```bash
|
| 59 |
+
python -m http.server 8000 # then open http://localhost:8000
|
| 60 |
+
```
|
| 61 |
+
(Opening `index.html` via `file://` will not work β `app.js` `fetch`es `models.json`.)
|
| 62 |
+
- If the user wants the refresh committed, stage and commit `models.json` only after confirming
|
| 63 |
+
the run succeeded and the diff looks reasonable.
|
| 64 |
+
|
| 65 |
+
## Notes
|
| 66 |
+
|
| 67 |
+
- The generator is the source of truth for the catalog schema; if a new accelerator/EP or
|
| 68 |
+
benchmark `type` appears and shows up wrong, the fix belongs in the Python (`EP_TO_UNIT`,
|
| 69 |
+
`HIL_TYPES`), not in `models.json`.
|
| 70 |
+
- Run this whenever the Hugging Face repos change to keep the dashboard current.
|
.vscode/settings.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"python-envs.defaultEnvManager": "ms-python.python:conda",
|
| 3 |
+
"python-envs.defaultPackageManager": "ms-python.python:conda"
|
| 4 |
+
}
|
CLAUDE.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md
|
| 2 |
+
|
| 3 |
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
| 4 |
+
|
| 5 |
+
## What this is
|
| 6 |
+
|
| 7 |
+
A **static** Hugging Face Space (`sdk: static` in `README.md` front matter) that lets users
|
| 8 |
+
browse the Renesas AI model catalog and route each model to the correct benchmark/estimation
|
| 9 |
+
Space. There is **no build step, no framework, no package manager, and no test suite** β it is
|
| 10 |
+
plain `index.html` + `app.js` (vanilla ES, loaded with `defer`) + `styles.css`, served as-is.
|
| 11 |
+
|
| 12 |
+
## Running and updating
|
| 13 |
+
|
| 14 |
+
```bash
|
| 15 |
+
# Serve locally (any static server works; the app fetches models.json/links.json over HTTP)
|
| 16 |
+
python -m http.server 8000 # then open http://localhost:8000
|
| 17 |
+
|
| 18 |
+
# Regenerate the catalog from the live Hugging Face repos
|
| 19 |
+
pip install requests pyyaml
|
| 20 |
+
python generate_models_json.py # rewrites ./models.json
|
| 21 |
+
python generate_models_json.py --token hf_xxx # also import gated repos' benchmark numbers
|
| 22 |
+
python generate_models_json.py --dry-run -v # print, don't write
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
Opening `index.html` via `file://` will not work β `app.js` `fetch`es `models.json` and
|
| 26 |
+
`links.json`, which requires an HTTP origin.
|
| 27 |
+
|
| 28 |
+
Generator exit codes: `0` ok, `2` network/API error, `3` write error, `4` produced 0 models
|
| 29 |
+
(refuses to overwrite an existing file β use `--force`).
|
| 30 |
+
|
| 31 |
+
## Architecture
|
| 32 |
+
|
| 33 |
+
The whole app is **data-driven from two JSON files** loaded at boot in `app.js` `init()`:
|
| 34 |
+
|
| 35 |
+
- **`models.json`** β the catalog. **Auto-generated; do not hand-edit.** Regenerate with the
|
| 36 |
+
Python script instead. Schema is defined implicitly by what `app.js` reads (see below).
|
| 37 |
+
- **`links.json`** β routing targets: HF Space ids for the benchmark tools (`spaces`) and
|
| 38 |
+
optional collection links. Hand-maintained.
|
| 39 |
+
|
| 40 |
+
### Data flow: `generate_models_json.py` β `models.json` β `app.js`
|
| 41 |
+
|
| 42 |
+
`generate_models_json.py` is the source of truth for the catalog schema. It scrapes the public
|
| 43 |
+
HF API for an org (default `Renesas`) and, for each model repo, reads:
|
| 44 |
+
|
| 45 |
+
- the repo info + recursive file tree (public even for gated repos),
|
| 46 |
+
- the root `.metadata.yaml` (identity: name, upstream, architecture, modality),
|
| 47 |
+
- each `<artifact>/.metadata.yaml` (per-precision artifact, e.g. `fp16`, `w4a16`),
|
| 48 |
+
- each `<artifact>/benchmarks/<chip>_<ep>.yaml` (the actual benchmark numbers).
|
| 49 |
+
|
| 50 |
+
Key transforms to know when changing either side:
|
| 51 |
+
|
| 52 |
+
- **Repos are grouped into one logical model** by `group_key()` (strips `-ONNX`/`-GGUF`
|
| 53 |
+
suffix). One model entry can therefore carry both `onnx_repo` + `gguf_repo` and their
|
| 54 |
+
separate `*_artifacts` lists.
|
| 55 |
+
- **`key`** is the join id between Python and JS β `app.js` builds `KEY_TO_MODEL` keyed by it.
|
| 56 |
+
The generator guarantees uniqueness (collisions get a `-2` suffix), because a duplicate key
|
| 57 |
+
silently drops a model from the dashboard.
|
| 58 |
+
- **Execution provider β target/unit** mapping lives in `EP_TO_UNIT` (`cpu`/`npu`/`dsp`).
|
| 59 |
+
Unknown EPs default to NPU with a warning β add new accelerators there.
|
| 60 |
+
- **`benchmark.type`** decides where numbers land: values in `HIL_TYPES` β the `hil` block
|
| 61 |
+
(measured on hardware), everything else β the `estimate` block. The UI shows both per
|
| 62 |
+
artifact per hardware config under `hardware_configs[].metrics.artifacts[<art>].{estimate,hil}`.
|
| 63 |
+
- Artifacts that actually have measured data are sorted first, because the table/Explore open
|
| 64 |
+
on the first artifact and should show real numbers, not `β`.
|
| 65 |
+
|
| 66 |
+
### `app.js` UI (three sections, switched by the top nav)
|
| 67 |
+
|
| 68 |
+
`app.js` is a single file of plain functions (no modules). The three sections map to the
|
| 69 |
+
`<section>` blocks in `index.html`:
|
| 70 |
+
|
| 71 |
+
1. **Overview** (`initOverview`, `drawConstellation`) β a `<canvas>` scatter plotting every
|
| 72 |
+
model/artifact by throughput vs size, plus stat tiles and a "recently updated" carousel.
|
| 73 |
+
2. **Catalog** (`initCatalog`, `renderCatalog`) β faceted card grid / table view with
|
| 74 |
+
search, sort, and a filter rail built from the catalog (`buildFacetRail`, `modelMatches`).
|
| 75 |
+
3. **Explore** (`updateExploreAny`, `renderActions`) β the routing tool: pick
|
| 76 |
+
architecture/modality/format/target/artifact and get the `hf download` command and a link to
|
| 77 |
+
the matching benchmark Space from `links.json`. Formatβpurpose rules are enforced by
|
| 78 |
+
`validatePurpose` (PerformanceEstimate/ORT = ONNX-only; llama.cpp = GGUF-only).
|
| 79 |
+
|
| 80 |
+
A shared **model-details modal** (`openModelModal`) is reused by the Catalog table and cards.
|
| 81 |
+
|
| 82 |
+
Global mutable state (`CATALOG`, `KEY_TO_MODEL`, `LINKS`, the `*_SELECTED_ARTIFACT` vars) is
|
| 83 |
+
module-level. Defaults (`DEFAULT_FMT`, `DEFAULT_COMPUTE`, etc.) are derived from the loaded
|
| 84 |
+
catalog so the UI always opens on data that actually exists.
|
| 85 |
+
|
| 86 |
+
## Conventions
|
| 87 |
+
|
| 88 |
+
- Build HTML via string templates; **always pass user/catalog strings through `esc()`** (the
|
| 89 |
+
existing builders do β match that).
|
| 90 |
+
- Element lookups use the `$`/`$$` helpers; missing data renders as `β` (`safeList`, null-guards
|
| 91 |
+
everywhere) rather than throwing.
|
| 92 |
+
- The on-page disclaimer banner shows `catalog_note` / `generated_at` from `models.json`.
|
README.md
CHANGED
|
@@ -7,20 +7,40 @@ sdk: static
|
|
| 7 |
pinned: true
|
| 8 |
short_description: Find models and route to the correct estimation or benchmark
|
| 9 |
---
|
| 10 |
-
# Renesas AI Dashboard
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
| 16 |
|
| 17 |
## Semantics
|
| 18 |
- π **ONNX** β PerformanceEstimate now; later custom ONNX Runtime provider benchmarking
|
| 19 |
- π§ͺ **GGUF** β llama.cpp execution benchmarking (**CPU-only** / **NPU-only**)
|
| 20 |
|
| 21 |
-
## How to update
|
| 22 |
-
|
| 23 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
|
| 26 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 7 |
pinned: true
|
| 8 |
short_description: Find models and route to the correct estimation or benchmark
|
| 9 |
---
|
| 10 |
+
# Renesas AI Dashboard
|
| 11 |
|
| 12 |
+
The catalog (`models.json`) is **auto-generated from the public Hugging Face
|
| 13 |
+
`Renesas` org repositories** β model identity, artifacts (e.g. `fp16` / `w4a16`),
|
| 14 |
+
hardware configs and benchmark numbers all come straight from each repo's
|
| 15 |
+
`.metadata.yaml` and `<artifact>/benchmarks/<chip>_<ep>.yaml` files. No hand
|
| 16 |
+
editing required.
|
| 17 |
|
| 18 |
## Semantics
|
| 19 |
- π **ONNX** β PerformanceEstimate now; later custom ONNX Runtime provider benchmarking
|
| 20 |
- π§ͺ **GGUF** β llama.cpp execution benchmarking (**CPU-only** / **NPU-only**)
|
| 21 |
|
| 22 |
+
## How to update the catalog
|
| 23 |
+
|
| 24 |
+
Re-run the generator whenever the repos change:
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
pip install requests pyyaml
|
| 28 |
+
python generate_models_json.py # rewrites models.json
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
- **Gated repos** (e.g. `Llama-3.2-1B/3B-Instruct-GGUF`): their listing is public,
|
| 32 |
+
but their benchmark numbers need an authorized token. Provide one via
|
| 33 |
+
`--token hf_xxx`, the `HF_TOKEN` env var, or a prior `huggingface-cli login`
|
| 34 |
+
(the cached token is picked up automatically). Without access, those repos are
|
| 35 |
+
still listed but their metrics are reported as skipped.
|
| 36 |
+
- Useful flags: `--org <owner>` (default `Renesas`), `--output <path>`,
|
| 37 |
+
`--dry-run` (print, don't write), `-v` (verbose). Exit codes: `0` ok,
|
| 38 |
+
`2` network/API error, `3` write error, `4` produced 0 models (refused to
|
| 39 |
+
overwrite β use `--force`).
|
| 40 |
+
- Update routing links (benchmark Spaces) in `links.json`.
|
| 41 |
+
|
| 42 |
+
> The on-page banner shows when the catalog was generated; metrics reflect each
|
| 43 |
+
> repo's published benchmark YAML at that time.
|
| 44 |
|
| 45 |
|
| 46 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
__pycache__/generate_models_json.cpython-313.pyc
ADDED
|
Binary file (45.9 kB). View file
|
|
|
app.js
CHANGED
|
@@ -21,7 +21,7 @@ function esc(str) {
|
|
| 21 |
|
| 22 |
let CATALOG_ROOT = { models: [] };
|
| 23 |
let CATALOG = [];
|
| 24 |
-
let CATALOG_NOTE = "
|
| 25 |
let LINKS = { spaces: {}, collections: {} };
|
| 26 |
|
| 27 |
let KEY_TO_MODEL = {};
|
|
@@ -90,10 +90,10 @@ function hwBadgesHTML(targets) {
|
|
| 90 |
function repoButtonsSmallHTML(model) {
|
| 91 |
const parts = [];
|
| 92 |
if (model.onnx_repo) {
|
| 93 |
-
parts.push(`<a class="link small" href="${esc(hfModelUrl(model.onnx_repo))}" target="_blank" rel="noopener noreferrer">ONNX
|
| 94 |
}
|
| 95 |
if (model.gguf_repo) {
|
| 96 |
-
parts.push(`<a class="link small" href="${esc(hfModelUrl(model.gguf_repo))}" target="_blank" rel="noopener noreferrer">GGUF
|
| 97 |
}
|
| 98 |
return `<div class="badges" style="gap:8px;">${parts.join("") || `<span class="subtle">β</span>`}</div>`;
|
| 99 |
}
|
|
@@ -195,6 +195,33 @@ function getArtifactsFor(modelKey, fmt) {
|
|
| 195 |
return (fmt === "ONNX") ? safeList(m.onnx_artifacts, []) : safeList(m.gguf_artifacts, []);
|
| 196 |
}
|
| 197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
/**
|
| 199 |
* Artifact-layer aware:
|
| 200 |
* - Preferred: cfg.metrics.artifacts[artifact].estimate/hil
|
|
@@ -315,6 +342,16 @@ function readRadio(name, fallback) {
|
|
| 315 |
return el ? el.value : fallback;
|
| 316 |
}
|
| 317 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
function readChecks(name) {
|
| 319 |
return Array.from(document.querySelectorAll(`input[name="${CSS.escape(name)}"]:checked`)).map(x => x.value);
|
| 320 |
}
|
|
@@ -353,7 +390,7 @@ function refreshModelList(keepSelection = true) {
|
|
| 353 |
|
| 354 |
/* ---------- Mini per-model scatter (accuracy vs runtime) (Explore only) ---------- */
|
| 355 |
function palette(i) {
|
| 356 |
-
const base = ["#
|
| 357 |
return base[i % base.length];
|
| 358 |
}
|
| 359 |
|
|
@@ -404,7 +441,7 @@ function drawArtifactScatter(canvas, points) {
|
|
| 404 |
const innerH = Math.max(1, h - pad.t - pad.b);
|
| 405 |
|
| 406 |
if (!points.length) {
|
| 407 |
-
ctx.fillStyle = "rgba(31,
|
| 408 |
ctx.font = "13px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 409 |
ctx.fillText("No artifact points available.", pad.l, pad.t + 24);
|
| 410 |
ARTIFACT_POINTS = [];
|
|
@@ -425,9 +462,9 @@ function drawArtifactScatter(canvas, points) {
|
|
| 425 |
|
| 426 |
const ticks = 4;
|
| 427 |
|
| 428 |
-
ctx.strokeStyle = "rgba(
|
| 429 |
ctx.lineWidth = 1;
|
| 430 |
-
ctx.fillStyle = "rgba(31,
|
| 431 |
ctx.font = "12px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 432 |
|
| 433 |
for (let i = 0; i <= ticks; i++) {
|
|
@@ -447,7 +484,7 @@ function drawArtifactScatter(canvas, points) {
|
|
| 447 |
ctx.fillText(`${Math.round(val)} ms`, tx - 18, h - 16);
|
| 448 |
}
|
| 449 |
|
| 450 |
-
ctx.fillStyle = "rgba(31,
|
| 451 |
ctx.font = "11px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 452 |
ctx.fillText("Runtime total (ms) β wheel=zoom β’ drag=pan β’ dblclick=reset", pad.l, h - 4);
|
| 453 |
ctx.fillText("Accuracy", pad.l, 12);
|
|
@@ -530,13 +567,39 @@ function renderDetails(modelKey, cfgId, fmt, compute, purpose, artifact) {
|
|
| 530 |
const cfgTargets = safeList(cfg.targets, safeList(m.targets, []));
|
| 531 |
const sizeM = m.model_size_m;
|
| 532 |
|
| 533 |
-
const arts =
|
| 534 |
const safeArt = (artifact && arts.includes(artifact)) ? artifact : (arts[0] || "default");
|
| 535 |
const { estimate: est, hil } = metricsForArtifact(cfg.metrics || {}, safeArt);
|
| 536 |
|
| 537 |
const onnxRepo = m.onnx_repo || "";
|
| 538 |
const ggufRepo = m.gguf_repo || "";
|
| 539 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 540 |
return `
|
| 541 |
<div class="md">
|
| 542 |
<h3>Summary</h3>
|
|
@@ -552,47 +615,54 @@ function renderDetails(modelKey, cfgId, fmt, compute, purpose, artifact) {
|
|
| 552 |
<li><b>Config Targets:</b> <code>${esc(cfgTargets.join(", ") || "β")}</code></li>
|
| 553 |
<li><b>Format:</b> <code>${esc(fmt)}</code></li>
|
| 554 |
<li><b>Compute:</b> <code>${esc(compute)}</code></li>
|
| 555 |
-
<li><b>Precision/Quant:</b> <code>${esc(safeArt)}</code></li>
|
| 556 |
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
|
| 558 |
-
|
| 559 |
-
<div class="subtle" style="font-weight:950; margin-bottom:8px;">
|
| 560 |
-
Available precision/quant (click to select)
|
| 561 |
-
</div>
|
| 562 |
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 566 |
<button type="button"
|
| 567 |
-
class="chip-btn ${
|
| 568 |
data-artifact="${esc(a)}"
|
| 569 |
-
aria-pressed="${
|
| 570 |
title="Select ${esc(a)}"
|
| 571 |
-
>
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
|
|
|
|
|
|
|
|
|
| 576 |
</div>
|
| 577 |
</div>
|
| 578 |
|
| 579 |
-
<div class="
|
| 580 |
-
|
| 581 |
-
${
|
|
|
|
|
|
|
| 582 |
</div>
|
| 583 |
-
</div>
|
| 584 |
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
<
|
| 591 |
-
<pre class="metric-pre">${esc(metricSummaryV2(est))}</pre>
|
| 592 |
-
</div>
|
| 593 |
-
<div class="metric-card">
|
| 594 |
-
<div class="metric-card-title">HIL</div>
|
| 595 |
-
<pre class="metric-pre">${esc(metricSummaryV2(hil))}</pre>
|
| 596 |
</div>
|
| 597 |
</div>
|
| 598 |
</div>
|
|
@@ -640,9 +710,8 @@ function buildArtifactAccuracyRuntimePoints(modelKey, cfgId, fmt) {
|
|
| 640 |
}
|
| 641 |
|
| 642 |
/**
|
| 643 |
-
* mode:
|
| 644 |
-
*
|
| 645 |
-
* - "modal": omits that section (requested)
|
| 646 |
*/
|
| 647 |
function renderActions(modelKey, fmt, compute, purpose, artifact, cfgId, mode = "explore") {
|
| 648 |
const m = KEY_TO_MODEL[modelKey];
|
|
@@ -655,52 +724,10 @@ function renderActions(modelKey, fmt, compute, purpose, artifact, cfgId, mode =
|
|
| 655 |
const include = downloadIncludePattern(fmt, artifact);
|
| 656 |
const cmd = repoId ? `hf download ${repoId} --repo-type=model --include "${include}"` : "";
|
| 657 |
|
| 658 |
-
const sp = (LINKS || {}).spaces || {};
|
| 659 |
-
let toolSection = "";
|
| 660 |
-
if (purpose === "ORT Benchmarking") {
|
| 661 |
-
const sid = sp.ort_benchmark;
|
| 662 |
-
toolSection = sid
|
| 663 |
-
? `<h3>Tool</h3><a class="link" href="${esc(hfSpaceUrl(sid))}" target="_blank" rel="noopener noreferrer">Open ORT Benchmark Space β</a>`
|
| 664 |
-
: `<h3>Tool</h3><i>ORT Benchmark Space: (set links.json)</i>`;
|
| 665 |
-
} else if (purpose === "llama.cpp Benchmarking") {
|
| 666 |
-
const sid = sp.gguf_llamacpp_benchmark;
|
| 667 |
-
toolSection = sid
|
| 668 |
-
? `<h3>Tool</h3><a class="link" href="${esc(hfSpaceUrl(sid))}" target="_blank" rel="noopener noreferrer">Open llama.cpp Benchmark Space β</a>`
|
| 669 |
-
: `<h3>Tool</h3><i>llama.cpp Benchmark Space: (set links.json)</i>`;
|
| 670 |
-
}
|
| 671 |
-
|
| 672 |
-
let accRuntimeSection = "";
|
| 673 |
-
if (mode === "explore") {
|
| 674 |
-
const { points, allAccMissing } = buildArtifactAccuracyRuntimePoints(modelKey, cfgId, fmt);
|
| 675 |
-
window.__artifactPlotPoints = points;
|
| 676 |
-
|
| 677 |
-
const accWarn = allAccMissing ? `
|
| 678 |
-
<div class="note note-warn tight" style="margin-top:10px;">
|
| 679 |
-
<b>Accuracy not yet published.</b> Plot uses <b>0</b> for accuracy until values are available.
|
| 680 |
-
</div>
|
| 681 |
-
` : "";
|
| 682 |
-
|
| 683 |
-
accRuntimeSection = `
|
| 684 |
-
<h3 style="margin-top:14px;">Precision/Quant β Accuracy vs Runtime</h3>
|
| 685 |
-
${accWarn}
|
| 686 |
-
<div class="mini-chart-wrap">
|
| 687 |
-
<div class="mini-chart-head">
|
| 688 |
-
<div class="mini-chart-title">Accuracy vs Runtime total</div>
|
| 689 |
-
<div class="mini-chart-subtle">${points.length ? `${points.length} variant(s)` : "No points"}</div>
|
| 690 |
-
</div>
|
| 691 |
-
<div style="padding:10px;">
|
| 692 |
-
<canvas id="artifactCanvas" style="width:100%; height:260px;"></canvas>
|
| 693 |
-
<div id="artifactTooltip" class="mini-tooltip"></div>
|
| 694 |
-
</div>
|
| 695 |
-
</div>
|
| 696 |
-
`;
|
| 697 |
-
}
|
| 698 |
-
|
| 699 |
return `
|
| 700 |
<div class="md">
|
| 701 |
-
<h3>Download</h3>
|
| 702 |
${repoId ? `
|
| 703 |
-
<div class="subtle tight">Downloads files matching: <code>${esc(include)}</code></div>
|
| 704 |
<div class="cmd-row">
|
| 705 |
<pre>${esc(cmd)}</pre>
|
| 706 |
<button class="copy-btn" type="button"
|
|
@@ -709,15 +736,11 @@ function renderActions(modelKey, fmt, compute, purpose, artifact, cfgId, mode =
|
|
| 709 |
aria-label="Copy download command"
|
| 710 |
title="Copy to clipboard"
|
| 711 |
>
|
| 712 |
-
<span class="icon">
|
| 713 |
<span class="txt">Copy</span>
|
| 714 |
</button>
|
| 715 |
</div>
|
| 716 |
` : `<i>Repo not set for the selected format (${esc(fmt)}).</i>`}
|
| 717 |
-
|
| 718 |
-
${accRuntimeSection}
|
| 719 |
-
|
| 720 |
-
${toolSection ? `<div style="margin-top:12px;">${toolSection}</div>` : ""}
|
| 721 |
</div>
|
| 722 |
`;
|
| 723 |
}
|
|
@@ -729,13 +752,15 @@ function setActiveSection(targetId) {
|
|
| 729 |
$$(".nav-item").forEach(btn => btn.classList.remove("active"));
|
| 730 |
document.querySelector(`.nav-item[data-target="${CSS.escape(targetId)}"]`)?.classList.add("active");
|
| 731 |
|
| 732 |
-
if (targetId === "sec-
|
| 733 |
-
if (targetId === "sec-
|
|
|
|
|
|
|
| 734 |
}
|
| 735 |
|
| 736 |
/* ---------- Explore pipeline ---------- */
|
| 737 |
function ensureExploreArtifact(modelKey, fmt) {
|
| 738 |
-
const arts =
|
| 739 |
if (!arts.length) { EXPLORE_SELECTED_ARTIFACT = null; return null; }
|
| 740 |
if (!EXPLORE_SELECTED_ARTIFACT || !arts.includes(EXPLORE_SELECTED_ARTIFACT)) EXPLORE_SELECTED_ARTIFACT = arts[0];
|
| 741 |
return EXPLORE_SELECTED_ARTIFACT;
|
|
@@ -750,6 +775,30 @@ function updateExploreFromFilters() {
|
|
| 750 |
refreshModelList(false);
|
| 751 |
}
|
| 752 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 753 |
function updateExploreOnModelChange() {
|
| 754 |
const key = $("modelKey").value;
|
| 755 |
const m = KEY_TO_MODEL[key];
|
|
@@ -758,7 +807,17 @@ function updateExploreOnModelChange() {
|
|
| 758 |
const def = ids.length ? ids[0] : null;
|
| 759 |
fillSelect($("hwCfg"), ids, def);
|
| 760 |
|
| 761 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 762 |
ensureExploreArtifact(key, fmt);
|
| 763 |
updateExploreAny();
|
| 764 |
}
|
|
@@ -792,27 +851,6 @@ function updateExploreAny() {
|
|
| 792 |
|
| 793 |
$("details").innerHTML = renderDetails(key, cfgId, fmt, compute, purpose, artifact);
|
| 794 |
$("actions").innerHTML = renderActions(key, fmt, compute, purpose, artifact, cfgId, "explore");
|
| 795 |
-
|
| 796 |
-
requestAnimationFrame(() => {
|
| 797 |
-
const canvas = $("artifactCanvas");
|
| 798 |
-
if (!canvas) return;
|
| 799 |
-
|
| 800 |
-
drawArtifactScatter(canvas, window.__artifactPlotPoints || []);
|
| 801 |
-
|
| 802 |
-
const tip = $("artifactTooltip");
|
| 803 |
-
if (!tip) return;
|
| 804 |
-
|
| 805 |
-
if (canvas.dataset.bound !== "1") {
|
| 806 |
-
canvas.dataset.bound = "1";
|
| 807 |
-
|
| 808 |
-
canvas.addEventListener("mousemove", (evt) => {
|
| 809 |
-
const hit = hitTestArtifact(evt, canvas);
|
| 810 |
-
if (!hit) return hideArtifactTip(tip);
|
| 811 |
-
showArtifactTip(hit, evt, tip, canvas);
|
| 812 |
-
});
|
| 813 |
-
canvas.addEventListener("mouseleave", () => hideArtifactTip(tip));
|
| 814 |
-
}
|
| 815 |
-
});
|
| 816 |
}
|
| 817 |
|
| 818 |
/* ---------- Modal (All Models -> Details) ---------- */
|
|
@@ -820,7 +858,7 @@ function updateModalAny() {
|
|
| 820 |
if (!MODAL_CTX) return;
|
| 821 |
const { key, cfgId, fmt, compute, purpose } = MODAL_CTX;
|
| 822 |
|
| 823 |
-
const arts =
|
| 824 |
if (!arts.length) MODAL_SELECTED_ARTIFACT = null;
|
| 825 |
else if (!MODAL_SELECTED_ARTIFACT || !arts.includes(MODAL_SELECTED_ARTIFACT)) MODAL_SELECTED_ARTIFACT = arts[0];
|
| 826 |
|
|
@@ -829,8 +867,6 @@ function updateModalAny() {
|
|
| 829 |
}
|
| 830 |
|
| 831 |
/* ---------- All Models (table) ---------- */
|
| 832 |
-
let FULL_ROWS = [];
|
| 833 |
-
let FILTERED_ROWS = [];
|
| 834 |
|
| 835 |
function defaultRowFmt(model) {
|
| 836 |
return model.onnx_repo ? "ONNX" : (model.gguf_repo ? "GGUF" : "ONNX");
|
|
@@ -852,7 +888,6 @@ function buildTableRows(models) {
|
|
| 852 |
const defArt = defaultRowArtifact(m, fmt);
|
| 853 |
|
| 854 |
const { estimate, hil } = metricsForArtifact(cfg.metrics || {}, defArt);
|
| 855 |
-
const cfgTargets = safeList(cfg.targets, safeList(m.targets, []));
|
| 856 |
|
| 857 |
const detailsBtn = `<button class="mini-btn" type="button"
|
| 858 |
data-open-model="1"
|
|
@@ -866,11 +901,9 @@ function buildTableRows(models) {
|
|
| 866 |
_cfg: cfg.id || "",
|
| 867 |
_fmt: fmt,
|
| 868 |
|
| 869 |
-
"Name": esc(m.display_name || m.key || ""),
|
| 870 |
"Modality": esc(m.modality || "LLM"),
|
| 871 |
-
"Task": "",
|
| 872 |
-
"Format": formatBadgesHTML(m),
|
| 873 |
-
"Supported HW": hwBadgesHTML(cfgTargets.length ? cfgTargets : safeList(m.targets, [])),
|
| 874 |
"Repo": repoButtonsSmallHTML(m),
|
| 875 |
"Precision/Quant": artifactsBadgesHTML(m),
|
| 876 |
"Estimate": metricBriefHTML(estimate),
|
|
@@ -882,38 +915,6 @@ function buildTableRows(models) {
|
|
| 882 |
return rows;
|
| 883 |
}
|
| 884 |
|
| 885 |
-
function applyAllFilters(rows, modality, formatFilter, hwFilter, needEst, needHil, searchQ) {
|
| 886 |
-
let out = rows.slice();
|
| 887 |
-
|
| 888 |
-
if (modality !== "All") out = out.filter(r => r["Modality"] === modality);
|
| 889 |
-
|
| 890 |
-
const fmtList = safeList(formatFilter, []);
|
| 891 |
-
if (fmtList.length) {
|
| 892 |
-
out = out.filter(r => fmtList.some(f => String(r["Format"] || "").toUpperCase().includes(f)));
|
| 893 |
-
}
|
| 894 |
-
|
| 895 |
-
const hwList = safeList(hwFilter, []);
|
| 896 |
-
if (hwList.length) {
|
| 897 |
-
out = out.filter(r => hwList.some(h => String(r["Supported HW"] || "").toUpperCase().includes(h)));
|
| 898 |
-
}
|
| 899 |
-
|
| 900 |
-
if (needEst) out = out.filter(r => !String(r["Estimate"] || "").includes("β"));
|
| 901 |
-
if (needHil) out = out.filter(r => !String(r["HIL"] || "").includes("β"));
|
| 902 |
-
|
| 903 |
-
const q = String(searchQ || "").trim().toLowerCase();
|
| 904 |
-
if (q) {
|
| 905 |
-
out = out.filter(r => {
|
| 906 |
-
const flat = Object.entries(r)
|
| 907 |
-
.filter(([k]) => !k.startsWith("_"))
|
| 908 |
-
.map(([, v]) => String(v ?? ""))
|
| 909 |
-
.join(" | ")
|
| 910 |
-
.toLowerCase();
|
| 911 |
-
return flat.includes(q);
|
| 912 |
-
});
|
| 913 |
-
}
|
| 914 |
-
return out;
|
| 915 |
-
}
|
| 916 |
-
|
| 917 |
function renderTable(rows) {
|
| 918 |
const table = $("modelsTable");
|
| 919 |
if (!table) return;
|
|
@@ -927,30 +928,34 @@ function renderTable(rows) {
|
|
| 927 |
}
|
| 928 |
|
| 929 |
const cols = Object.keys(rows[0]).filter(k => !k.startsWith("_"));
|
| 930 |
-
const pinCount =
|
| 931 |
|
| 932 |
thead.innerHTML = `<tr>${cols.map((c, i) => {
|
| 933 |
const isPinned = i < pinCount;
|
| 934 |
const isDetails = (c === "");
|
| 935 |
-
const
|
|
|
|
| 936 |
const pinAttr = isPinned ? ` data-pin="${i}"` : "";
|
| 937 |
const header = isDetails ? "" : esc(c);
|
| 938 |
return `<th class="${cls}"${pinAttr}>${header}</th>`;
|
| 939 |
}).join("")}</tr>`;
|
| 940 |
|
| 941 |
-
const htmlCols = new Set(["
|
| 942 |
|
| 943 |
tbody.innerHTML = rows.map((r, ri) => {
|
| 944 |
return `<tr data-row="${ri}" data-key="${esc(r._key)}" data-cfg="${esc(r._cfg)}" data-fmt="${esc(r._fmt)}">${
|
| 945 |
cols.map((c, i) => {
|
| 946 |
const isPinned = i < pinCount;
|
| 947 |
const isDetails = (c === "");
|
| 948 |
-
const
|
|
|
|
| 949 |
const pinAttr = isPinned ? ` data-pin="${i}"` : "";
|
|
|
|
|
|
|
| 950 |
const val = r[c];
|
| 951 |
|
| 952 |
-
if (htmlCols.has(c)) return `<td class="${cls}"${pinAttr}>${val ?? ""}</td>`;
|
| 953 |
-
return `<td class="${cls}"${pinAttr}>${esc(val)}</td>`;
|
| 954 |
}).join("")
|
| 955 |
}</tr>`;
|
| 956 |
}).join("\n");
|
|
@@ -976,19 +981,6 @@ function setupPinnedColumns(table, count) {
|
|
| 976 |
}
|
| 977 |
}
|
| 978 |
|
| 979 |
-
function updateAllModels() {
|
| 980 |
-
const modality = $("t_modality").value;
|
| 981 |
-
const fmtList = readChecks("t_format");
|
| 982 |
-
const hwList = readChecks("t_hw");
|
| 983 |
-
const needEst = $("t_need_est").checked;
|
| 984 |
-
const needHil = $("t_need_hil").checked;
|
| 985 |
-
const searchQ = $("t_search").value;
|
| 986 |
-
|
| 987 |
-
FILTERED_ROWS = applyAllFilters(FULL_ROWS, modality, fmtList, hwList, needEst, needHil, searchQ);
|
| 988 |
-
$("t_status").innerHTML = `Showing <b>${FILTERED_ROWS.length}</b> / <b>${FULL_ROWS.length}</b> models.`;
|
| 989 |
-
renderTable(FILTERED_ROWS);
|
| 990 |
-
}
|
| 991 |
-
|
| 992 |
/* ---------- Model modal ---------- */
|
| 993 |
function openModelModal(modelKey, cfgId, fmt) {
|
| 994 |
const m = KEY_TO_MODEL[modelKey];
|
|
@@ -1022,224 +1014,559 @@ function closeModelModal() {
|
|
| 1022 |
MODAL_SELECTED_ARTIFACT = null;
|
| 1023 |
}
|
| 1024 |
|
| 1025 |
-
/*
|
| 1026 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1027 |
if (!block) return null;
|
| 1028 |
-
|
| 1029 |
-
if (
|
| 1030 |
-
|
| 1031 |
-
return (lat != null) ? Number(lat) : null;
|
| 1032 |
}
|
| 1033 |
|
| 1034 |
-
|
| 1035 |
-
|
|
|
|
|
|
|
| 1036 |
|
|
|
|
|
|
|
| 1037 |
for (const m of CATALOG) {
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
|
| 1044 |
-
|
| 1045 |
-
|
| 1046 |
-
|
| 1047 |
-
|
| 1048 |
-
|
| 1049 |
-
|
| 1050 |
-
|
| 1051 |
-
const { estimate, hil } = metricsForArtifact(cfg.metrics || {}, defArt);
|
| 1052 |
-
|
| 1053 |
-
let block = null;
|
| 1054 |
-
let label = "β";
|
| 1055 |
-
if (metricSource === "Estimate") { block = estimate; label = "Estimate"; }
|
| 1056 |
-
else if (metricSource === "HIL") { block = hil; label = "HIL"; }
|
| 1057 |
-
else { block = hil || estimate; label = hil ? "HIL" : (estimate ? "Estimate" : "β"); }
|
| 1058 |
-
|
| 1059 |
-
if (!block) return;
|
| 1060 |
-
|
| 1061 |
-
const lat = latencyForCompute(block, compute);
|
| 1062 |
-
if (lat == null) return;
|
| 1063 |
-
|
| 1064 |
-
const fmtBadge = (m.onnx_repo ? "ONNX" : "") + (m.gguf_repo ? (m.onnx_repo ? "+GGUF" : "GGUF") : "");
|
| 1065 |
-
const hwBadge = safeList(cfg.targets, safeList(m.targets, [])).join("+") || "β";
|
| 1066 |
-
|
| 1067 |
-
let colorVal = m.modality || "LLM";
|
| 1068 |
-
if (colorBy === "Architecture") colorVal = m.architecture || "Unknown";
|
| 1069 |
-
else if (colorBy === "Modality") colorVal = m.modality || "LLM";
|
| 1070 |
-
else if (colorBy === "Variant") colorVal = m.variant || "Default";
|
| 1071 |
-
else if (colorBy === "Format") colorVal = fmtBadge || "β";
|
| 1072 |
-
else if (colorBy === "Supported HW") colorVal = hwBadge || "β";
|
| 1073 |
-
|
| 1074 |
-
rows.push({
|
| 1075 |
-
_key: m.key || "",
|
| 1076 |
-
_cfg: cfg.id || "",
|
| 1077 |
-
Model: (m.display_name || m.key || "") + suffix,
|
| 1078 |
-
"Size (M)": Number(sizeM),
|
| 1079 |
-
"Runtime p50 (ms)": Number(lat),
|
| 1080 |
-
"Runtime Source": label,
|
| 1081 |
-
Compute: compute,
|
| 1082 |
-
"HW Config": cfg.id || "",
|
| 1083 |
-
"HW Label": cfg.label || cfg.id || "",
|
| 1084 |
-
Architecture: m.architecture || "Unknown",
|
| 1085 |
-
Modality: m.modality || "LLM",
|
| 1086 |
-
Variant: m.variant || "Default",
|
| 1087 |
-
Color: String(colorVal)
|
| 1088 |
-
});
|
| 1089 |
-
};
|
| 1090 |
-
|
| 1091 |
-
if (pointMode === "Per hardware config") {
|
| 1092 |
-
for (const cfg of cfgs) addRow(cfg);
|
| 1093 |
-
} else {
|
| 1094 |
-
let bestCfg = null;
|
| 1095 |
-
let bestLat = null;
|
| 1096 |
-
for (const cfg of cfgs) {
|
| 1097 |
-
const { estimate, hil } = metricsForArtifact(cfg.metrics || {}, defArt);
|
| 1098 |
-
const block = (metricSource === "Estimate") ? estimate :
|
| 1099 |
-
(metricSource === "HIL") ? hil :
|
| 1100 |
-
(hil || estimate);
|
| 1101 |
-
if (!block) continue;
|
| 1102 |
-
const lat = latencyForCompute(block, compute);
|
| 1103 |
-
if (lat == null) continue;
|
| 1104 |
-
if (bestLat == null || lat < bestLat) { bestLat = lat; bestCfg = cfg; }
|
| 1105 |
}
|
| 1106 |
-
if (bestCfg && bestLat != null) addRow(bestCfg, " (best)");
|
| 1107 |
}
|
| 1108 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1109 |
|
| 1110 |
-
|
| 1111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1112 |
}
|
| 1113 |
|
| 1114 |
-
|
| 1115 |
-
function niceCeil(v) {
|
| 1116 |
-
const x = (v && isFinite(v)) ? v : 1;
|
| 1117 |
-
const pow = Math.pow(10, Math.floor(Math.log10(x || 1)));
|
| 1118 |
-
const n = x / pow;
|
| 1119 |
-
let nice = 1;
|
| 1120 |
-
if (n <= 1) nice = 1;
|
| 1121 |
-
else if (n <= 2) nice = 2;
|
| 1122 |
-
else if (n <= 5) nice = 5;
|
| 1123 |
-
else nice = 10;
|
| 1124 |
-
return nice * pow;
|
| 1125 |
-
}
|
| 1126 |
-
function paletteFor(categories) {
|
| 1127 |
-
const base = ["#4c6ef5","#16a34a","#f59e0b","#ef4444","#06b6d4","#a855f7","#f97316","#10b981","#3b82f6","#64748b"];
|
| 1128 |
-
const map = {}; let i = 0;
|
| 1129 |
-
for (const c of categories) { map[c] = base[i % base.length]; i++; }
|
| 1130 |
-
return map;
|
| 1131 |
-
}
|
| 1132 |
-
function drawScatter(canvas, rows) {
|
| 1133 |
const ctx = canvas.getContext("2d");
|
| 1134 |
-
const rect = canvas.getBoundingClientRect();
|
| 1135 |
const dpr = window.devicePixelRatio || 1;
|
| 1136 |
-
|
| 1137 |
-
canvas.
|
| 1138 |
-
|
| 1139 |
-
|
| 1140 |
-
|
| 1141 |
-
ctx.clearRect(0,0,w,h);
|
| 1142 |
|
| 1143 |
-
const pad = { l:
|
| 1144 |
const innerW = Math.max(1, w - pad.l - pad.r);
|
| 1145 |
const innerH = Math.max(1, h - pad.t - pad.b);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1146 |
|
| 1147 |
-
|
| 1148 |
-
|
| 1149 |
-
|
| 1150 |
-
|
| 1151 |
-
|
| 1152 |
-
|
| 1153 |
|
| 1154 |
-
const
|
| 1155 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1156 |
|
| 1157 |
-
const
|
| 1158 |
-
const
|
| 1159 |
|
| 1160 |
-
|
| 1161 |
-
|
| 1162 |
-
|
| 1163 |
-
const
|
| 1164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1165 |
|
| 1166 |
-
|
| 1167 |
-
|
| 1168 |
-
|
| 1169 |
-
|
| 1170 |
-
|
| 1171 |
-
|
| 1172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1173 |
|
| 1174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1175 |
}
|
| 1176 |
-
|
| 1177 |
-
|
| 1178 |
-
|
| 1179 |
-
|
| 1180 |
-
|
| 1181 |
-
|
| 1182 |
-
|
| 1183 |
-
|
| 1184 |
-
|
| 1185 |
-
|
| 1186 |
-
|
| 1187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1188 |
}
|
| 1189 |
return best;
|
| 1190 |
}
|
| 1191 |
-
function
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
-
|
| 1195 |
-
|
| 1196 |
-
|
| 1197 |
-
|
| 1198 |
-
const
|
| 1199 |
-
|
| 1200 |
-
|
| 1201 |
-
|
| 1202 |
-
|
| 1203 |
-
|
| 1204 |
-
|
| 1205 |
-
|
| 1206 |
-
|
| 1207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1208 |
}
|
| 1209 |
-
function hideTooltip(){ const tip = $("scatterTooltip"); if (tip) tip.style.display = "none"; }
|
| 1210 |
|
| 1211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1212 |
|
| 1213 |
-
function
|
| 1214 |
-
const
|
| 1215 |
-
|
| 1216 |
-
|
| 1217 |
-
|
| 1218 |
-
|
| 1219 |
-
|
| 1220 |
-
const colorBy = $("s_color_by").value;
|
| 1221 |
|
| 1222 |
-
|
| 1223 |
-
|
| 1224 |
|
| 1225 |
-
|
| 1226 |
-
|
| 1227 |
-
|
| 1228 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1229 |
|
| 1230 |
-
|
| 1231 |
-
|
| 1232 |
-
|
| 1233 |
-
|
| 1234 |
-
|
| 1235 |
-
|
| 1236 |
-
|
| 1237 |
-
|
| 1238 |
-
|
| 1239 |
-
hit.row.Compute,
|
| 1240 |
-
defaultPurposeForFormat("ONNX"),
|
| 1241 |
-
safeList(KEY_TO_MODEL[hit.row._key]?.onnx_artifacts, [])[0] || null
|
| 1242 |
-
);
|
| 1243 |
}
|
| 1244 |
|
| 1245 |
/* ---------- Boot ---------- */
|
|
@@ -1343,14 +1670,20 @@ async function init() {
|
|
| 1343 |
MODALITIES = ["All"].concat(uniqueSorted(CATALOG.map(m => m.modality || "LLM")));
|
| 1344 |
VARIANTS = ["All"].concat(uniqueSorted(CATALOG.map(m => m.variant || "Default")));
|
| 1345 |
|
| 1346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1347 |
|
| 1348 |
/* Explore init */
|
| 1349 |
fillSelect($("arch"), ARCHS, "All");
|
| 1350 |
buildRadioGroup($("modality"), "modality", MODALITIES, "All");
|
| 1351 |
-
buildRadioGroup($("fmt"), "fmt", ["ONNX", "GGUF"],
|
| 1352 |
-
buildRadioGroup($("compute"), "compute", ["CPU", "NPU", "DSP"],
|
| 1353 |
-
buildRadioGroup($("purpose"), "purpose", ["PerformanceEstimate", "ORT Benchmarking", "llama.cpp Benchmarking"],
|
| 1354 |
|
| 1355 |
EXPLORE_KEYS = filteredKeys("All", "All", "All");
|
| 1356 |
updateExploreFromFilters();
|
|
@@ -1366,62 +1699,16 @@ async function init() {
|
|
| 1366 |
$("modelKey").addEventListener("change", updateExploreOnModelChange);
|
| 1367 |
$("hwCfg").addEventListener("change", updateExploreAny);
|
| 1368 |
|
| 1369 |
-
/*
|
| 1370 |
-
|
| 1371 |
-
buildCheckGroup($("t_format"), "t_format", ALL_FORMATS, []);
|
| 1372 |
-
buildCheckGroup($("t_hw"), "t_hw", ALL_HW, []);
|
| 1373 |
|
| 1374 |
-
|
| 1375 |
-
|
| 1376 |
-
|
| 1377 |
-
$("t_modality").addEventListener("change", updateAllModels);
|
| 1378 |
-
$("t_need_est").addEventListener("change", updateAllModels);
|
| 1379 |
-
$("t_need_hil").addEventListener("change", updateAllModels);
|
| 1380 |
-
|
| 1381 |
-
$("t_search").addEventListener("input", () => {
|
| 1382 |
-
clearTimeout(window.__tSearchT);
|
| 1383 |
-
window.__tSearchT = setTimeout(updateAllModels, 80);
|
| 1384 |
-
});
|
| 1385 |
-
|
| 1386 |
-
document.addEventListener("change", (e) => {
|
| 1387 |
-
if (e.target && e.target.name === "t_format") { e.target.closest(".pill")?.classList.toggle("active", e.target.checked); updateAllModels(); }
|
| 1388 |
-
if (e.target && e.target.name === "t_hw") { e.target.closest(".pill")?.classList.toggle("active", e.target.checked); updateAllModels(); }
|
| 1389 |
-
});
|
| 1390 |
-
|
| 1391 |
-
/* Scatter init */
|
| 1392 |
-
fillSelect($("s_arch"), ARCHS, "All");
|
| 1393 |
-
fillSelect($("s_modality"), MODALITIES, "All");
|
| 1394 |
-
fillSelect($("s_variant"), VARIANTS, "All");
|
| 1395 |
-
fillSelect($("s_color_by"), ["Architecture", "Modality", "Variant", "Format", "Supported HW"], "Modality");
|
| 1396 |
-
buildRadioGroup($("s_compute"), "s_compute", ["CPU", "NPU", "DSP"], "CPU");
|
| 1397 |
-
buildRadioGroup($("s_source"), "s_source", ["Best available", "Estimate", "HIL"], "Best available");
|
| 1398 |
-
buildRadioGroup($("s_point_mode"), "s_point_mode", ["Per hardware config", "Per model (best across configs)"], "Per hardware config");
|
| 1399 |
-
|
| 1400 |
-
$("s_arch").addEventListener("change", updateScatter);
|
| 1401 |
-
$("s_modality").addEventListener("change", updateScatter);
|
| 1402 |
-
$("s_variant").addEventListener("change", updateScatter);
|
| 1403 |
-
$("s_color_by").addEventListener("change", updateScatter);
|
| 1404 |
-
|
| 1405 |
-
document.addEventListener("change", (e) => {
|
| 1406 |
-
if (e.target && (e.target.name === "s_compute" || e.target.name === "s_source" || e.target.name === "s_point_mode")) updateScatter();
|
| 1407 |
-
});
|
| 1408 |
-
|
| 1409 |
-
const sc = $("scatterCanvas");
|
| 1410 |
-
sc.addEventListener("mousemove", onScatterMove);
|
| 1411 |
-
sc.addEventListener("mouseleave", onScatterLeave);
|
| 1412 |
-
sc.addEventListener("click", onScatterClick);
|
| 1413 |
|
| 1414 |
window.addEventListener("resize", () => {
|
| 1415 |
-
|
| 1416 |
-
|
| 1417 |
-
requestAnimationFrame(() => {
|
| 1418 |
-
const c = $("artifactCanvas");
|
| 1419 |
-
const modalOpen = $("modelModal")?.classList.contains("open");
|
| 1420 |
-
if (!modalOpen && c) drawArtifactScatter(c, window.__artifactPlotPoints || []);
|
| 1421 |
-
});
|
| 1422 |
});
|
| 1423 |
-
|
| 1424 |
-
updateScatter();
|
| 1425 |
}
|
| 1426 |
|
| 1427 |
document.addEventListener("DOMContentLoaded", init);
|
|
|
|
| 21 |
|
| 22 |
let CATALOG_ROOT = { models: [] };
|
| 23 |
let CATALOG = [];
|
| 24 |
+
let CATALOG_NOTE = "Auto-generated from Hugging Face repositories.";
|
| 25 |
let LINKS = { spaces: {}, collections: {} };
|
| 26 |
|
| 27 |
let KEY_TO_MODEL = {};
|
|
|
|
| 90 |
function repoButtonsSmallHTML(model) {
|
| 91 |
const parts = [];
|
| 92 |
if (model.onnx_repo) {
|
| 93 |
+
parts.push(`<a class="link small" href="${esc(hfModelUrl(model.onnx_repo))}" target="_blank" rel="noopener noreferrer">ONNX</a>`);
|
| 94 |
}
|
| 95 |
if (model.gguf_repo) {
|
| 96 |
+
parts.push(`<a class="link small" href="${esc(hfModelUrl(model.gguf_repo))}" target="_blank" rel="noopener noreferrer">GGUF</a>`);
|
| 97 |
}
|
| 98 |
return `<div class="badges" style="gap:8px;">${parts.join("") || `<span class="subtle">β</span>`}</div>`;
|
| 99 |
}
|
|
|
|
| 195 |
return (fmt === "ONNX") ? safeList(m.onnx_artifacts, []) : safeList(m.gguf_artifacts, []);
|
| 196 |
}
|
| 197 |
|
| 198 |
+
/* True only if the artifact actually carries benchmark metadata (from its
|
| 199 |
+
benchmarks/ subfolder β an estimate or hil block). Checked against the
|
| 200 |
+
per-artifact map directly, NOT metricsForArtifact (whose legacy fallback
|
| 201 |
+
would make every artifact look benchmarked). A legacy config with no
|
| 202 |
+
artifacts map at all is treated as benchmarked so it isn't hidden. */
|
| 203 |
+
function artifactHasBenchmark(m, art) {
|
| 204 |
+
for (const cfg of safeList(m?.hardware_configs, [])) {
|
| 205 |
+
const metrics = cfg.metrics || {};
|
| 206 |
+
const artMap = metrics.artifacts;
|
| 207 |
+
if (artMap && typeof artMap === "object") {
|
| 208 |
+
const a = artMap[art];
|
| 209 |
+
if (a && (a.estimate || a.hil)) return true;
|
| 210 |
+
} else if (metrics.estimate || metrics.hil) {
|
| 211 |
+
return true;
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
return false;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
/* Artifacts to actually surface in the results UI: only those with benchmark
|
| 218 |
+
data (e.g. 8B's fp16 folder has no benchmark, so it must not appear). */
|
| 219 |
+
function benchmarkedArtifactsFor(modelKey, fmt) {
|
| 220 |
+
const m = KEY_TO_MODEL[modelKey];
|
| 221 |
+
if (!m) return [];
|
| 222 |
+
return getArtifactsFor(modelKey, fmt).filter(a => artifactHasBenchmark(m, a));
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
/**
|
| 226 |
* Artifact-layer aware:
|
| 227 |
* - Preferred: cfg.metrics.artifacts[artifact].estimate/hil
|
|
|
|
| 342 |
return el ? el.value : fallback;
|
| 343 |
}
|
| 344 |
|
| 345 |
+
/* Programmatically select a radio option and sync its .pill active state
|
| 346 |
+
(does not fire a change event β callers re-render explicitly). */
|
| 347 |
+
function setRadioValue(name, value) {
|
| 348 |
+
document.querySelectorAll(`input[name="${CSS.escape(name)}"]`).forEach(inp => {
|
| 349 |
+
const on = inp.value === value;
|
| 350 |
+
inp.checked = on;
|
| 351 |
+
inp.closest(".pill")?.classList.toggle("active", on);
|
| 352 |
+
});
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
function readChecks(name) {
|
| 356 |
return Array.from(document.querySelectorAll(`input[name="${CSS.escape(name)}"]:checked`)).map(x => x.value);
|
| 357 |
}
|
|
|
|
| 390 |
|
| 391 |
/* ---------- Mini per-model scatter (accuracy vs runtime) (Explore only) ---------- */
|
| 392 |
function palette(i) {
|
| 393 |
+
const base = ["#C96442", "#6E8B6A", "#C9A24B", "#5B7A99", "#A6573F", "#8E6E9E", "#4C8C7D", "#B07A3C"];
|
| 394 |
return base[i % base.length];
|
| 395 |
}
|
| 396 |
|
|
|
|
| 441 |
const innerH = Math.max(1, h - pad.t - pad.b);
|
| 442 |
|
| 443 |
if (!points.length) {
|
| 444 |
+
ctx.fillStyle = "rgba(31,30,28,0.62)";
|
| 445 |
ctx.font = "13px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 446 |
ctx.fillText("No artifact points available.", pad.l, pad.t + 24);
|
| 447 |
ARTIFACT_POINTS = [];
|
|
|
|
| 462 |
|
| 463 |
const ticks = 4;
|
| 464 |
|
| 465 |
+
ctx.strokeStyle = "rgba(31,30,28,0.08)";
|
| 466 |
ctx.lineWidth = 1;
|
| 467 |
+
ctx.fillStyle = "rgba(31,30,28,0.72)";
|
| 468 |
ctx.font = "12px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 469 |
|
| 470 |
for (let i = 0; i <= ticks; i++) {
|
|
|
|
| 484 |
ctx.fillText(`${Math.round(val)} ms`, tx - 18, h - 16);
|
| 485 |
}
|
| 486 |
|
| 487 |
+
ctx.fillStyle = "rgba(31,30,28,0.52)";
|
| 488 |
ctx.font = "11px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 489 |
ctx.fillText("Runtime total (ms) β wheel=zoom β’ drag=pan β’ dblclick=reset", pad.l, h - 4);
|
| 490 |
ctx.fillText("Accuracy", pad.l, 12);
|
|
|
|
| 567 |
const cfgTargets = safeList(cfg.targets, safeList(m.targets, []));
|
| 568 |
const sizeM = m.model_size_m;
|
| 569 |
|
| 570 |
+
const arts = benchmarkedArtifactsFor(modelKey, fmt);
|
| 571 |
const safeArt = (artifact && arts.includes(artifact)) ? artifact : (arts[0] || "default");
|
| 572 |
const { estimate: est, hil } = metricsForArtifact(cfg.metrics || {}, safeArt);
|
| 573 |
|
| 574 |
const onnxRepo = m.onnx_repo || "";
|
| 575 |
const ggufRepo = m.gguf_repo || "";
|
| 576 |
|
| 577 |
+
// Est-vs-HIL throughput (tok/s is the metric currently populated) + accuracy
|
| 578 |
+
// for the selected precision (HIL-first). These drive the small graph and the
|
| 579 |
+
// accuracy column of the merged block.
|
| 580 |
+
const estTok = tokSOf(est);
|
| 581 |
+
const hilTok = tokSOf(hil);
|
| 582 |
+
const maxTok = Math.max(estTok || 0, hilTok || 0) || 1;
|
| 583 |
+
const pctOf = (t) => (t != null && t > 0) ? Math.max(6, Math.round((t / maxTok) * 100)) : 0;
|
| 584 |
+
const estPct = pctOf(estTok), hilPct = pctOf(hilTok);
|
| 585 |
+
const graphHasData = (estTok != null || hilTok != null);
|
| 586 |
+
|
| 587 |
+
let acc = accuracyFromBlock(hil), accSrc = "HIL";
|
| 588 |
+
if (acc == null) { acc = accuracyFromBlock(est); accSrc = "Estimate"; }
|
| 589 |
+
const accIsPct = acc != null && acc <= 1.5;
|
| 590 |
+
const accText = acc == null ? "β" : `${accIsPct ? Math.round(acc * 1000) / 10 : Math.round(acc * 10) / 10}${accIsPct ? "%" : ""}`;
|
| 591 |
+
const updated = (hil && hil.last_updated) || (est && est.last_updated) || null; // benchmark freshness (HIL-first)
|
| 592 |
+
|
| 593 |
+
const barCol = (label, tok, pct, cls) => `
|
| 594 |
+
<div class="pm-bar-col">
|
| 595 |
+
<div class="pm-bar-val">${tok != null ? esc(Math.round(tok * 10) / 10) : "β"}</div>
|
| 596 |
+
<div class="pm-bar-track">
|
| 597 |
+
<div class="pm-bar-spacer" style="flex-grow:${100 - pct}"></div>
|
| 598 |
+
${tok != null ? `<div class="pm-bar-fill ${cls}" style="flex-grow:${pct}"></div>` : ""}
|
| 599 |
+
</div>
|
| 600 |
+
<div class="pm-bar-lbl">${label}</div>
|
| 601 |
+
</div>`;
|
| 602 |
+
|
| 603 |
return `
|
| 604 |
<div class="md">
|
| 605 |
<h3>Summary</h3>
|
|
|
|
| 615 |
<li><b>Config Targets:</b> <code>${esc(cfgTargets.join(", ") || "β")}</code></li>
|
| 616 |
<li><b>Format:</b> <code>${esc(fmt)}</code></li>
|
| 617 |
<li><b>Compute:</b> <code>${esc(compute)}</code></li>
|
|
|
|
| 618 |
</ul>
|
| 619 |
+
</div>
|
| 620 |
+
|
| 621 |
+
<div class="repo-buttons" aria-label="Model repos">
|
| 622 |
+
${onnxRepo ? `<a class="link" href="${esc(hfModelUrl(onnxRepo))}" target="_blank" rel="noopener noreferrer">Open ONNX Repo β</a>` : `<span class="link link-na" aria-disabled="true">No ONNX repo available</span>`}
|
| 623 |
+
${ggufRepo ? `<a class="link" href="${esc(hfModelUrl(ggufRepo))}" target="_blank" rel="noopener noreferrer">Open GGUF Repo β</a>` : `<span class="link link-na" aria-disabled="true">No GGUF repo available</span>`}
|
| 624 |
+
</div>
|
| 625 |
+
</div>
|
| 626 |
|
| 627 |
+
<h3 class="pm-heading">Precision & performance</h3>
|
|
|
|
|
|
|
|
|
|
| 628 |
|
| 629 |
+
<div class="pm-block">
|
| 630 |
+
<div class="pm-rail" role="group" aria-label="Available precision/quant β select to view its metrics">
|
| 631 |
+
<div class="pm-rail-cap">Precision / Quant</div>
|
| 632 |
+
<div class="pm-rail-list">
|
| 633 |
+
${arts.length
|
| 634 |
+
? arts.map(a => {
|
| 635 |
+
const on = a === safeArt;
|
| 636 |
+
return `
|
| 637 |
<button type="button"
|
| 638 |
+
class="chip-btn pm-opt ${on ? "active" : ""}"
|
| 639 |
data-artifact="${esc(a)}"
|
| 640 |
+
aria-pressed="${on ? "true" : "false"}"
|
| 641 |
title="Select ${esc(a)}"
|
| 642 |
+
>
|
| 643 |
+
<span class="pm-opt-dot" aria-hidden="true"></span>
|
| 644 |
+
<span class="pm-opt-label">${esc(a)}</span>
|
| 645 |
+
<span class="pm-opt-badge" aria-hidden="true">Selected</span>
|
| 646 |
+
</button>`;
|
| 647 |
+
}).join("")
|
| 648 |
+
: `<div class="pm-opt-empty subtle">No precision/quant variants</div>`
|
| 649 |
+
}
|
| 650 |
</div>
|
| 651 |
</div>
|
| 652 |
|
| 653 |
+
<div class="metric-card pm-graph" aria-live="polite">
|
| 654 |
+
<div class="metric-card-title">Est vs HIL Β· tok/s</div>
|
| 655 |
+
${graphHasData
|
| 656 |
+
? `<div class="pm-bars">${barCol("Est", estTok, estPct, "est")}${barCol("HIL", hilTok, hilPct, "hil")}</div>${updated ? `<div class="pm-graph-foot">Updated ${esc(updated)}</div>` : ""}`
|
| 657 |
+
: `<div class="pm-graph-empty subtle">No throughput yet</div>`}
|
| 658 |
</div>
|
|
|
|
| 659 |
|
| 660 |
+
<div class="metric-card pm-acc" aria-live="polite">
|
| 661 |
+
<div class="metric-card-title">Accuracy</div>
|
| 662 |
+
<div class="pm-acc-body">
|
| 663 |
+
<div class="pm-acc-num ${acc == null ? "empty" : ""}">${esc(accText)}</div>
|
| 664 |
+
<div class="pm-acc-sub">${acc == null ? "Not published yet" : esc(accSrc) + " Β· " + esc(safeArt)}</div>
|
| 665 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 666 |
</div>
|
| 667 |
</div>
|
| 668 |
</div>
|
|
|
|
| 710 |
}
|
| 711 |
|
| 712 |
/**
|
| 713 |
+
* mode: "explore" (Deploy result card) or "modal" (model details).
|
| 714 |
+
* Only differs in the Download heading's top spacing.
|
|
|
|
| 715 |
*/
|
| 716 |
function renderActions(modelKey, fmt, compute, purpose, artifact, cfgId, mode = "explore") {
|
| 717 |
const m = KEY_TO_MODEL[modelKey];
|
|
|
|
| 724 |
const include = downloadIncludePattern(fmt, artifact);
|
| 725 |
const cmd = repoId ? `hf download ${repoId} --repo-type=model --include "${include}"` : "";
|
| 726 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
return `
|
| 728 |
<div class="md">
|
| 729 |
+
<h3${mode === "explore" ? ' style="margin-top:18px;"' : ""}>Download</h3>
|
| 730 |
${repoId ? `
|
|
|
|
| 731 |
<div class="cmd-row">
|
| 732 |
<pre>${esc(cmd)}</pre>
|
| 733 |
<button class="copy-btn" type="button"
|
|
|
|
| 736 |
aria-label="Copy download command"
|
| 737 |
title="Copy to clipboard"
|
| 738 |
>
|
| 739 |
+
<span class="icon"><svg viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><rect x="4" y="3" width="9" height="11" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M6 3.2V2.2A1.2 1.2 0 0 1 7.2 1h1.6A1.2 1.2 0 0 1 10 2.2v1" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg></span>
|
| 740 |
<span class="txt">Copy</span>
|
| 741 |
</button>
|
| 742 |
</div>
|
| 743 |
` : `<i>Repo not set for the selected format (${esc(fmt)}).</i>`}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 744 |
</div>
|
| 745 |
`;
|
| 746 |
}
|
|
|
|
| 752 |
$$(".nav-item").forEach(btn => btn.classList.remove("active"));
|
| 753 |
document.querySelector(`.nav-item[data-target="${CSS.escape(targetId)}"]`)?.classList.add("active");
|
| 754 |
|
| 755 |
+
if (targetId === "sec-overview") requestAnimationFrame(redrawConstellation);
|
| 756 |
+
if (targetId === "sec-catalog" && CATALOG_STATE.view === "table") {
|
| 757 |
+
requestAnimationFrame(() => setupPinnedColumns($("modelsTable"), 1));
|
| 758 |
+
}
|
| 759 |
}
|
| 760 |
|
| 761 |
/* ---------- Explore pipeline ---------- */
|
| 762 |
function ensureExploreArtifact(modelKey, fmt) {
|
| 763 |
+
const arts = benchmarkedArtifactsFor(modelKey, fmt);
|
| 764 |
if (!arts.length) { EXPLORE_SELECTED_ARTIFACT = null; return null; }
|
| 765 |
if (!EXPLORE_SELECTED_ARTIFACT || !arts.includes(EXPLORE_SELECTED_ARTIFACT)) EXPLORE_SELECTED_ARTIFACT = arts[0];
|
| 766 |
return EXPLORE_SELECTED_ARTIFACT;
|
|
|
|
| 775 |
refreshModelList(false);
|
| 776 |
}
|
| 777 |
|
| 778 |
+
/* Pick a format the model actually provides, keeping the current one when it's
|
| 779 |
+
valid. Prefers artifacts (which drive the precision selector + graph) and
|
| 780 |
+
falls back to repo presence only when a model lists no artifacts at all. */
|
| 781 |
+
function bestFormatForModel(m, preferred) {
|
| 782 |
+
if (!m) return preferred;
|
| 783 |
+
// Prefer a format that has at least one benchmarked variant to display.
|
| 784 |
+
const onnxBench = safeList(m.onnx_artifacts, []).some(a => artifactHasBenchmark(m, a));
|
| 785 |
+
const ggufBench = safeList(m.gguf_artifacts, []).some(a => artifactHasBenchmark(m, a));
|
| 786 |
+
if (onnxBench || ggufBench) {
|
| 787 |
+
if (preferred === "ONNX" && onnxBench) return "ONNX";
|
| 788 |
+
if (preferred === "GGUF" && ggufBench) return "GGUF";
|
| 789 |
+
return onnxBench ? "ONNX" : "GGUF";
|
| 790 |
+
}
|
| 791 |
+
// No benchmarked variants anywhere β fall back to artifact/repo presence so
|
| 792 |
+
// the download command still resolves.
|
| 793 |
+
const hasOnnx = safeList(m.onnx_artifacts, []).length > 0 || !!m.onnx_repo;
|
| 794 |
+
const hasGguf = safeList(m.gguf_artifacts, []).length > 0 || !!m.gguf_repo;
|
| 795 |
+
if (preferred === "ONNX" && hasOnnx) return "ONNX";
|
| 796 |
+
if (preferred === "GGUF" && hasGguf) return "GGUF";
|
| 797 |
+
if (hasOnnx) return "ONNX";
|
| 798 |
+
if (hasGguf) return "GGUF";
|
| 799 |
+
return preferred;
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
function updateExploreOnModelChange() {
|
| 803 |
const key = $("modelKey").value;
|
| 804 |
const m = KEY_TO_MODEL[key];
|
|
|
|
| 807 |
const def = ids.length ? ids[0] : null;
|
| 808 |
fillSelect($("hwCfg"), ids, def);
|
| 809 |
|
| 810 |
+
/* Keep the format valid for the chosen model. Without this, selecting a model
|
| 811 |
+
that lacks the current format yields no artifacts/repo for it, so only the
|
| 812 |
+
(format-independent) Summary appears to refresh while the precision/quant,
|
| 813 |
+
graph, accuracy and download stay empty. */
|
| 814 |
+
const prevFmt = readRadio("fmt", "ONNX");
|
| 815 |
+
const fmt = bestFormatForModel(m, prevFmt);
|
| 816 |
+
if (fmt !== prevFmt) {
|
| 817 |
+
setRadioValue("fmt", fmt);
|
| 818 |
+
setRadioValue("purpose", defaultPurposeForFormat(fmt));
|
| 819 |
+
}
|
| 820 |
+
|
| 821 |
ensureExploreArtifact(key, fmt);
|
| 822 |
updateExploreAny();
|
| 823 |
}
|
|
|
|
| 851 |
|
| 852 |
$("details").innerHTML = renderDetails(key, cfgId, fmt, compute, purpose, artifact);
|
| 853 |
$("actions").innerHTML = renderActions(key, fmt, compute, purpose, artifact, cfgId, "explore");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 854 |
}
|
| 855 |
|
| 856 |
/* ---------- Modal (All Models -> Details) ---------- */
|
|
|
|
| 858 |
if (!MODAL_CTX) return;
|
| 859 |
const { key, cfgId, fmt, compute, purpose } = MODAL_CTX;
|
| 860 |
|
| 861 |
+
const arts = benchmarkedArtifactsFor(key, fmt);
|
| 862 |
if (!arts.length) MODAL_SELECTED_ARTIFACT = null;
|
| 863 |
else if (!MODAL_SELECTED_ARTIFACT || !arts.includes(MODAL_SELECTED_ARTIFACT)) MODAL_SELECTED_ARTIFACT = arts[0];
|
| 864 |
|
|
|
|
| 867 |
}
|
| 868 |
|
| 869 |
/* ---------- All Models (table) ---------- */
|
|
|
|
|
|
|
| 870 |
|
| 871 |
function defaultRowFmt(model) {
|
| 872 |
return model.onnx_repo ? "ONNX" : (model.gguf_repo ? "GGUF" : "ONNX");
|
|
|
|
| 888 |
const defArt = defaultRowArtifact(m, fmt);
|
| 889 |
|
| 890 |
const { estimate, hil } = metricsForArtifact(cfg.metrics || {}, defArt);
|
|
|
|
| 891 |
|
| 892 |
const detailsBtn = `<button class="mini-btn" type="button"
|
| 893 |
data-open-model="1"
|
|
|
|
| 901 |
_cfg: cfg.id || "",
|
| 902 |
_fmt: fmt,
|
| 903 |
|
| 904 |
+
"Name": `<span class="tc-name"><span class="mc-logo">${designerOf(m).svg}</span><span class="tc-name-txt">${esc(m.display_name || m.key || "")}</span></span>`,
|
| 905 |
"Modality": esc(m.modality || "LLM"),
|
| 906 |
+
"Task": esc(safeList(m.tasks, [])[0] || "β"),
|
|
|
|
|
|
|
| 907 |
"Repo": repoButtonsSmallHTML(m),
|
| 908 |
"Precision/Quant": artifactsBadgesHTML(m),
|
| 909 |
"Estimate": metricBriefHTML(estimate),
|
|
|
|
| 915 |
return rows;
|
| 916 |
}
|
| 917 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
function renderTable(rows) {
|
| 919 |
const table = $("modelsTable");
|
| 920 |
if (!table) return;
|
|
|
|
| 928 |
}
|
| 929 |
|
| 930 |
const cols = Object.keys(rows[0]).filter(k => !k.startsWith("_"));
|
| 931 |
+
const pinCount = 1; // pin only the identifier (Name) column
|
| 932 |
|
| 933 |
thead.innerHTML = `<tr>${cols.map((c, i) => {
|
| 934 |
const isPinned = i < pinCount;
|
| 935 |
const isDetails = (c === "");
|
| 936 |
+
const isName = (c === "Name");
|
| 937 |
+
const cls = `${isPinned ? "pin" : ""}${isDetails ? " details-col" : ""}${isName ? " cell-name" : ""}`.trim();
|
| 938 |
const pinAttr = isPinned ? ` data-pin="${i}"` : "";
|
| 939 |
const header = isDetails ? "" : esc(c);
|
| 940 |
return `<th class="${cls}"${pinAttr}>${header}</th>`;
|
| 941 |
}).join("")}</tr>`;
|
| 942 |
|
| 943 |
+
const htmlCols = new Set(["Name", "Repo", "Precision/Quant", "Estimate", "HIL", ""]);
|
| 944 |
|
| 945 |
tbody.innerHTML = rows.map((r, ri) => {
|
| 946 |
return `<tr data-row="${ri}" data-key="${esc(r._key)}" data-cfg="${esc(r._cfg)}" data-fmt="${esc(r._fmt)}">${
|
| 947 |
cols.map((c, i) => {
|
| 948 |
const isPinned = i < pinCount;
|
| 949 |
const isDetails = (c === "");
|
| 950 |
+
const isName = (c === "Name");
|
| 951 |
+
const cls = `${isPinned ? "pin" : ""}${isDetails ? " details-col" : ""}${isName ? " cell-name" : ""}`.trim();
|
| 952 |
const pinAttr = isPinned ? ` data-pin="${i}"` : "";
|
| 953 |
+
// data-label drives the stacked-card layout's field labels on narrow screens
|
| 954 |
+
const labelAttr = ` data-label="${esc(c)}"`;
|
| 955 |
const val = r[c];
|
| 956 |
|
| 957 |
+
if (htmlCols.has(c)) return `<td class="${cls}"${pinAttr}${labelAttr}>${val ?? ""}</td>`;
|
| 958 |
+
return `<td class="${cls}"${pinAttr}${labelAttr}>${esc(val)}</td>`;
|
| 959 |
}).join("")
|
| 960 |
}</tr>`;
|
| 961 |
}).join("\n");
|
|
|
|
| 981 |
}
|
| 982 |
}
|
| 983 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 984 |
/* ---------- Model modal ---------- */
|
| 985 |
function openModelModal(modelKey, cfgId, fmt) {
|
| 986 |
const m = KEY_TO_MODEL[modelKey];
|
|
|
|
| 1014 |
MODAL_SELECTED_ARTIFACT = null;
|
| 1015 |
}
|
| 1016 |
|
| 1017 |
+
/* ====================================================================== */
|
| 1018 |
+
/* OVERVIEW β constellation (size vs throughput) */
|
| 1019 |
+
/* ====================================================================== */
|
| 1020 |
+
const FAMILY_PALETTE = ["#C96442", "#6E8B6A", "#C9A24B", "#5B7A99", "#A6573F", "#8E6E9E", "#4C8C7D", "#B07A3C", "#9A6B6B", "#7C8B5A"];
|
| 1021 |
+
const COLOR_CACHE = {};
|
| 1022 |
+
function colorFor(label) {
|
| 1023 |
+
if (COLOR_CACHE[label] != null) return COLOR_CACHE[label];
|
| 1024 |
+
const c = FAMILY_PALETTE[Object.keys(COLOR_CACHE).length % FAMILY_PALETTE.length];
|
| 1025 |
+
COLOR_CACHE[label] = c;
|
| 1026 |
+
return c;
|
| 1027 |
+
}
|
| 1028 |
+
|
| 1029 |
+
function allArtifactsOf(m) {
|
| 1030 |
+
return uniqueSorted([...safeList(m.onnx_artifacts, []), ...safeList(m.gguf_artifacts, [])]);
|
| 1031 |
+
}
|
| 1032 |
+
function fmtOfArtifact(m, art) {
|
| 1033 |
+
if (safeList(m.gguf_artifacts, []).includes(art)) return "GGUF";
|
| 1034 |
+
if (safeList(m.onnx_artifacts, []).includes(art)) return "ONNX";
|
| 1035 |
+
return "β";
|
| 1036 |
+
}
|
| 1037 |
+
function pickBlock(cfgMetrics, art, source) {
|
| 1038 |
+
const { estimate, hil } = metricsForArtifact(cfgMetrics || {}, art);
|
| 1039 |
+
if (source === "HIL") return hil ? { block: hil, source: "HIL" } : null;
|
| 1040 |
+
if (source === "Estimate") return estimate ? { block: estimate, source: "Estimate" } : null;
|
| 1041 |
+
if (hil) return { block: hil, source: "HIL" };
|
| 1042 |
+
if (estimate) return { block: estimate, source: "Estimate" };
|
| 1043 |
+
return null;
|
| 1044 |
+
}
|
| 1045 |
+
function tokSOf(block) {
|
| 1046 |
if (!block) return null;
|
| 1047 |
+
let t = (block.total && block.total.tok_s != null) ? block.total.tok_s : null;
|
| 1048 |
+
if (t == null) t = block.npu?.tok_s ?? block.cpu?.tok_s ?? block.dsp?.tok_s ?? null;
|
| 1049 |
+
return (t != null && isFinite(Number(t))) ? Number(t) : null;
|
|
|
|
| 1050 |
}
|
| 1051 |
|
| 1052 |
+
const AXES = {
|
| 1053 |
+
tok: { get: p => p.tok, label: "Throughput (tok/s)", tick: v => `${Math.round(v * 10) / 10}` },
|
| 1054 |
+
size: { get: p => p.sizeM, label: "Model size", tick: v => (v >= 1000 ? `${Math.round(v / 100) / 10}B` : `${Math.round(v)}M`) },
|
| 1055 |
+
};
|
| 1056 |
|
| 1057 |
+
function buildConstellationPoints(source) {
|
| 1058 |
+
const pts = [];
|
| 1059 |
for (const m of CATALOG) {
|
| 1060 |
+
const sizeM = (m.model_size_m != null) ? Number(m.model_size_m) : null;
|
| 1061 |
+
for (const cfg of safeList(m.hardware_configs, [])) {
|
| 1062 |
+
for (const art of allArtifactsOf(m)) {
|
| 1063 |
+
const got = pickBlock(cfg.metrics || {}, art, source);
|
| 1064 |
+
if (!got) continue;
|
| 1065 |
+
const tok = tokSOf(got.block);
|
| 1066 |
+
if (tok == null) continue;
|
| 1067 |
+
pts.push({
|
| 1068 |
+
key: m.key, cfgId: cfg.id, fmt: fmtOfArtifact(m, art),
|
| 1069 |
+
name: m.display_name || m.key, family: m.architecture || "Unknown",
|
| 1070 |
+
quant: art, target: safeList(cfg.targets, safeList(m.targets, []))[0] || "β",
|
| 1071 |
+
hwLabel: cfg.label || cfg.id || "β", sizeM, tok, source: got.source,
|
| 1072 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1073 |
}
|
|
|
|
| 1074 |
}
|
| 1075 |
}
|
| 1076 |
+
return pts;
|
| 1077 |
+
}
|
| 1078 |
+
function colorKey(p, colorBy) {
|
| 1079 |
+
return colorBy === "quant" ? p.quant : colorBy === "format" ? p.fmt : colorBy === "target" ? p.target : p.family;
|
| 1080 |
+
}
|
| 1081 |
|
| 1082 |
+
let CSTL_HIT = [];
|
| 1083 |
+
|
| 1084 |
+
function hitTest(list, evt, canvas) {
|
| 1085 |
+
const rect = canvas.getBoundingClientRect();
|
| 1086 |
+
const x = evt.clientX - rect.left, y = evt.clientY - rect.top;
|
| 1087 |
+
let best = null, bestD = Infinity;
|
| 1088 |
+
for (const p of list) {
|
| 1089 |
+
const dx = x - p.x, dy = y - p.y, d = dx * dx + dy * dy;
|
| 1090 |
+
if (d <= p.r * p.r && d < bestD) { best = p; bestD = d; }
|
| 1091 |
+
}
|
| 1092 |
+
return best;
|
| 1093 |
}
|
| 1094 |
|
| 1095 |
+
function drawConstellation(canvas, points, opts) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1096 |
const ctx = canvas.getContext("2d");
|
| 1097 |
+
const rect = canvas.parentElement.getBoundingClientRect();
|
| 1098 |
const dpr = window.devicePixelRatio || 1;
|
| 1099 |
+
const h = canvas.clientHeight || 460, w = rect.width;
|
| 1100 |
+
canvas.width = Math.max(1, Math.floor(w * dpr));
|
| 1101 |
+
canvas.height = Math.max(1, Math.floor(h * dpr));
|
| 1102 |
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
| 1103 |
+
ctx.clearRect(0, 0, w, h);
|
|
|
|
| 1104 |
|
| 1105 |
+
const pad = { l: 66, r: 18, t: 22, b: 48 };
|
| 1106 |
const innerW = Math.max(1, w - pad.l - pad.r);
|
| 1107 |
const innerH = Math.max(1, h - pad.t - pad.b);
|
| 1108 |
+
const ax = AXES[opts.xKey] || AXES.tok;
|
| 1109 |
+
const ay = AXES[opts.yKey] || AXES.size;
|
| 1110 |
+
const txt = "rgba(31,30,28,0.72)";
|
| 1111 |
+
ctx.font = "12px system-ui, -apple-system, Segoe UI, Roboto, Arial";
|
| 1112 |
|
| 1113 |
+
CSTL_HIT = [];
|
| 1114 |
+
if (!points.length) {
|
| 1115 |
+
ctx.fillStyle = txt;
|
| 1116 |
+
ctx.fillText("No data points for this selection.", pad.l, pad.t + 24);
|
| 1117 |
+
return;
|
| 1118 |
+
}
|
| 1119 |
|
| 1120 |
+
const xs = points.map(ax.get).filter(v => v != null && isFinite(v));
|
| 1121 |
+
const ys = points.map(ay.get).filter(v => v != null && isFinite(v));
|
| 1122 |
+
let xMin = Math.min(0, ...xs), xMax = Math.max(...xs);
|
| 1123 |
+
let yMin = Math.min(0, ...ys), yMax = Math.max(...ys);
|
| 1124 |
+
if (xMax - xMin < 1e-9) xMax = xMin + 1;
|
| 1125 |
+
if (yMax - yMin < 1e-9) yMax = yMin + 1;
|
| 1126 |
+
xMax += (xMax - xMin) * 0.08;
|
| 1127 |
+
yMax += (yMax - yMin) * 0.12;
|
| 1128 |
|
| 1129 |
+
const xOf = v => pad.l + ((v - xMin) / (xMax - xMin)) * innerW;
|
| 1130 |
+
const yOf = v => pad.t + innerH - ((v - yMin) / (yMax - yMin)) * innerH;
|
| 1131 |
|
| 1132 |
+
const ticks = 4;
|
| 1133 |
+
ctx.lineWidth = 1;
|
| 1134 |
+
for (let i = 0; i <= ticks; i++) {
|
| 1135 |
+
const ty = pad.t + innerH - (innerH * i / ticks);
|
| 1136 |
+
ctx.strokeStyle = "rgba(31,30,28,0.08)";
|
| 1137 |
+
ctx.beginPath(); ctx.moveTo(pad.l, ty); ctx.lineTo(pad.l + innerW, ty); ctx.stroke();
|
| 1138 |
+
ctx.fillStyle = txt;
|
| 1139 |
+
ctx.fillText(ay.tick(yMin + (yMax - yMin) * (i / ticks)), 8, ty + 4);
|
| 1140 |
+
}
|
| 1141 |
+
for (let i = 0; i <= ticks; i++) {
|
| 1142 |
+
const tx = pad.l + (innerW * i / ticks);
|
| 1143 |
+
ctx.fillStyle = txt;
|
| 1144 |
+
ctx.fillText(ax.tick(xMin + (xMax - xMin) * (i / ticks)), tx - 12, h - 16);
|
| 1145 |
+
}
|
| 1146 |
+
ctx.fillStyle = "rgba(31,30,28,0.52)";
|
| 1147 |
+
ctx.fillText(ax.label + " β", pad.l, h - 2);
|
| 1148 |
+
ctx.fillText("β " + ay.label, 8, 14);
|
| 1149 |
+
|
| 1150 |
+
const maxSz = Math.max(1, ...points.map(p => p.sizeM || 0));
|
| 1151 |
+
const rOf = s => 6 + 16 * Math.sqrt((s || 0) / maxSz);
|
| 1152 |
+
|
| 1153 |
+
points.forEach(p => {
|
| 1154 |
+
const xv = ax.get(p), yv = ay.get(p);
|
| 1155 |
+
if (xv == null || yv == null) return;
|
| 1156 |
+
const x = xOf(xv), y = yOf(yv), r = rOf(p.sizeM);
|
| 1157 |
+
const col = colorFor(colorKey(p, opts.colorBy));
|
| 1158 |
+
ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI * 2);
|
| 1159 |
+
if (p.source === "HIL") { ctx.fillStyle = col + "C0"; ctx.fill(); ctx.strokeStyle = col; ctx.lineWidth = 1.5; ctx.stroke(); }
|
| 1160 |
+
else { ctx.fillStyle = col + "33"; ctx.fill(); ctx.strokeStyle = col; ctx.lineWidth = 1.8; ctx.stroke(); }
|
| 1161 |
+
CSTL_HIT.push({ x, y, r: Math.max(r, 10), data: p });
|
| 1162 |
+
});
|
| 1163 |
+
}
|
| 1164 |
|
| 1165 |
+
function buildLegend(points, colorBy) {
|
| 1166 |
+
const el = $("cstlLegend");
|
| 1167 |
+
if (!el) return;
|
| 1168 |
+
const seen = [];
|
| 1169 |
+
for (const p of points) { const k = colorKey(p, colorBy); if (!seen.includes(k)) seen.push(k); }
|
| 1170 |
+
el.innerHTML = seen.map(k =>
|
| 1171 |
+
`<span class="legend-item"><span class="legend-dot" style="background:${colorFor(k)}"></span>${esc(k)}</span>`
|
| 1172 |
+
).join("") + `<span class="legend-item">β HIL β Estimate</span>`;
|
| 1173 |
+
}
|
| 1174 |
+
|
| 1175 |
+
function redrawConstellation() {
|
| 1176 |
+
const canvas = $("cstlCanvas");
|
| 1177 |
+
if (!canvas) return;
|
| 1178 |
+
const xKey = $("cstlX")?.value || "tok";
|
| 1179 |
+
const yKey = $("cstlY")?.value || "size";
|
| 1180 |
+
const colorBy = $("cstlColor")?.value || "family";
|
| 1181 |
+
const srcRaw = readRadio("cstlSource", "Best available");
|
| 1182 |
+
const source = (srcRaw === "HIL" || srcRaw === "Estimate") ? srcRaw : "Best";
|
| 1183 |
+
const points = buildConstellationPoints(source);
|
| 1184 |
+
drawConstellation(canvas, points, { xKey, yKey, colorBy });
|
| 1185 |
+
buildLegend(points, colorBy);
|
| 1186 |
+
const status = $("cstlStatus");
|
| 1187 |
+
if (status) status.textContent = `${points.length} variant point(s) Β· ${srcRaw}`;
|
| 1188 |
+
}
|
| 1189 |
+
|
| 1190 |
+
function fillStatTiles() {
|
| 1191 |
+
const el = $("statTiles");
|
| 1192 |
+
if (!el) return;
|
| 1193 |
+
const variants = new Set();
|
| 1194 |
+
for (const m of CATALOG) {
|
| 1195 |
+
for (const cfg of safeList(m.hardware_configs, []))
|
| 1196 |
+
for (const art of allArtifactsOf(m))
|
| 1197 |
+
if (pickBlock(cfg.metrics || {}, art, "Best")) variants.add(`${m.key}|${art}`);
|
| 1198 |
+
}
|
| 1199 |
+
const tiles = [
|
| 1200 |
+
[CATALOG.length, "Models"],
|
| 1201 |
+
[variants.size, "Benchmarked variants"],
|
| 1202 |
+
];
|
| 1203 |
+
el.innerHTML = tiles.map(([n, l]) =>
|
| 1204 |
+
`<div class="stat-tile"><div class="stat-num">${esc(n)}</div><div class="stat-label">${esc(l)}</div></div>`
|
| 1205 |
+
).join("");
|
| 1206 |
+
}
|
| 1207 |
+
|
| 1208 |
+
/* ---------- Recently-added carousel ---------- */
|
| 1209 |
+
const RECENT_WINDOW_DAYS = 31;
|
| 1210 |
+
|
| 1211 |
+
function modelRecency(m) {
|
| 1212 |
+
const c = m.created_at ? Date.parse(m.created_at) : NaN;
|
| 1213 |
+
const u = m.last_modified ? Date.parse(m.last_modified) : NaN;
|
| 1214 |
+
const v = [c, u].filter(x => !isNaN(x));
|
| 1215 |
+
return v.length ? Math.max(...v) : NaN;
|
| 1216 |
+
}
|
| 1217 |
+
function timeAgo(ts) {
|
| 1218 |
+
if (isNaN(ts)) return "";
|
| 1219 |
+
const d = Math.floor((Date.now() - ts) / 86400000);
|
| 1220 |
+
if (d <= 0) return "today";
|
| 1221 |
+
if (d === 1) return "yesterday";
|
| 1222 |
+
if (d < 30) return `${d} days ago`;
|
| 1223 |
+
const mo = Math.round(d / 30);
|
| 1224 |
+
return `${mo} month${mo > 1 ? "s" : ""} ago`;
|
| 1225 |
+
}
|
| 1226 |
+
function recentLabel(m) {
|
| 1227 |
+
const c = m.created_at ? Date.parse(m.created_at) : NaN;
|
| 1228 |
+
const u = m.last_modified ? Date.parse(m.last_modified) : NaN;
|
| 1229 |
+
const cut = Date.now() - RECENT_WINDOW_DAYS * 86400000;
|
| 1230 |
+
if (!isNaN(c) && c >= cut) return { isNew: true, text: `added ${timeAgo(c)}` };
|
| 1231 |
+
if (!isNaN(u)) return { isNew: false, text: `updated ${timeAgo(u)}` };
|
| 1232 |
+
return { isNew: false, text: "" };
|
| 1233 |
+
}
|
| 1234 |
+
function recentModels() {
|
| 1235 |
+
const cut = Date.now() - RECENT_WINDOW_DAYS * 86400000;
|
| 1236 |
+
return CATALOG
|
| 1237 |
+
.filter(m => { const r = modelRecency(m); return !isNaN(r) && r >= cut; })
|
| 1238 |
+
.sort((a, b) => modelRecency(b) - modelRecency(a));
|
| 1239 |
+
}
|
| 1240 |
+
function recentCardHTML(m) {
|
| 1241 |
+
const col = colorFor(m.architecture || "Unknown");
|
| 1242 |
+
const best = bestHilFirstVariantOf(m);
|
| 1243 |
+
const firstCfg = safeFirstCfg(m);
|
| 1244 |
+
const defFmt = m.gguf_repo ? "GGUF" : (m.onnx_repo ? "ONNX" : "GGUF");
|
| 1245 |
+
const lbl = recentLabel(m);
|
| 1246 |
+
const srcTag = best
|
| 1247 |
+
? (best.source === "HIL"
|
| 1248 |
+
? `<span class="rc-src rc-src-hil">HIL</span>`
|
| 1249 |
+
: `<span class="rc-src rc-src-est">est</span>`)
|
| 1250 |
+
: "";
|
| 1251 |
+
const stat = best
|
| 1252 |
+
? `<div class="rc-stat"><b>${esc(Math.round(best.tok * 10) / 10)}</b> tok/s Β· ${esc(best.quant)} ${srcTag}</div>`
|
| 1253 |
+
: `<div class="rc-stat empty">No throughput yet</div>`;
|
| 1254 |
+
return `
|
| 1255 |
+
<div class="model-card rc-card" data-card="1" data-key="${esc(m.key)}" data-cfg="${esc(firstCfg?.id || "")}" data-fmt="${esc(defFmt)}">
|
| 1256 |
+
<div class="rc-meta ${lbl.isNew ? "is-new" : ""}">${lbl.isNew ? "β¦" : "β³"} ${esc(lbl.text)}</div>
|
| 1257 |
+
${designerRowHTML(m)}
|
| 1258 |
+
<div class="mc-head">
|
| 1259 |
+
<div class="mc-monogram" style="background:linear-gradient(135deg, ${col}, ${col}99)">${esc(monogramText(m))}</div>
|
| 1260 |
+
<div style="min-width:0">
|
| 1261 |
+
<div class="mc-title">${esc(m.display_name || m.key)}</div>
|
| 1262 |
+
<div class="mc-sub">${esc(m.architecture || "")}${m.variant ? " Β· " + esc(m.variant) : ""}</div>
|
| 1263 |
+
</div>
|
| 1264 |
+
</div>
|
| 1265 |
+
${stat}
|
| 1266 |
+
</div>`;
|
| 1267 |
+
}
|
| 1268 |
+
function renderRecentCarousel() {
|
| 1269 |
+
const sec = $("recentSection"), track = $("recentTrack");
|
| 1270 |
+
if (!sec || !track) return;
|
| 1271 |
+
const list = recentModels();
|
| 1272 |
+
if (!list.length) { sec.hidden = true; return; }
|
| 1273 |
+
sec.hidden = false;
|
| 1274 |
+
track.innerHTML = list.map(recentCardHTML).join("");
|
| 1275 |
+
const sub = $("recentSub");
|
| 1276 |
+
if (sub) sub.textContent = `${list.length} model${list.length > 1 ? "s" : ""} Β· last 30 days`;
|
| 1277 |
+
}
|
| 1278 |
+
|
| 1279 |
+
function initOverview() {
|
| 1280 |
+
fillStatTiles();
|
| 1281 |
+
renderRecentCarousel();
|
| 1282 |
+
|
| 1283 |
+
const track = $("recentTrack");
|
| 1284 |
+
$("recentPrev")?.addEventListener("click", () => track?.scrollBy({ left: -276, behavior: "smooth" }));
|
| 1285 |
+
$("recentNext")?.addEventListener("click", () => track?.scrollBy({ left: 276, behavior: "smooth" }));
|
| 1286 |
+
track?.addEventListener("click", (e) => {
|
| 1287 |
+
if (e.target.closest("a")) return;
|
| 1288 |
+
const card = e.target.closest('.model-card[data-card="1"]');
|
| 1289 |
+
if (card) openModelModal(card.getAttribute("data-key"), card.getAttribute("data-cfg") || "", card.getAttribute("data-fmt") || "GGUF");
|
| 1290 |
+
});
|
| 1291 |
|
| 1292 |
+
buildRadioGroup($("cstlSource"), "cstlSource", ["Best available", "HIL", "Estimate"], "Best available");
|
| 1293 |
+
["cstlX", "cstlY", "cstlColor"].forEach(id => $(id)?.addEventListener("change", redrawConstellation));
|
| 1294 |
+
document.addEventListener("change", (e) => { if (e.target && e.target.name === "cstlSource") redrawConstellation(); });
|
| 1295 |
+
|
| 1296 |
+
const canvas = $("cstlCanvas");
|
| 1297 |
+
if (canvas && canvas.dataset.bound !== "1") {
|
| 1298 |
+
canvas.dataset.bound = "1";
|
| 1299 |
+
const tip = $("cstlTooltip");
|
| 1300 |
+
canvas.addEventListener("mousemove", (evt) => {
|
| 1301 |
+
const hit = hitTest(CSTL_HIT, evt, canvas);
|
| 1302 |
+
if (!hit || !tip) { if (tip) tip.style.display = "none"; return; }
|
| 1303 |
+
const rect = canvas.parentElement.getBoundingClientRect();
|
| 1304 |
+
const x = evt.clientX - rect.left, y = evt.clientY - rect.top;
|
| 1305 |
+
const sz = hit.data.sizeM >= 1000 ? `${hit.data.sizeM / 1000}B` : `${hit.data.sizeM}M`;
|
| 1306 |
+
tip.innerHTML = `<b>${esc(hit.data.name)}</b><br/>${esc(hit.data.quant)} Β· ${esc(hit.data.target)} Β· ${esc(hit.data.source)}<br/>${esc(Math.round(hit.data.tok * 10) / 10)} tok/s Β· ${esc(sz)}`;
|
| 1307 |
+
tip.style.display = "block";
|
| 1308 |
+
tip.style.left = `${Math.min(x + 14, rect.width - 250)}px`;
|
| 1309 |
+
tip.style.top = `${Math.max(8, y - 10)}px`;
|
| 1310 |
+
});
|
| 1311 |
+
canvas.addEventListener("mouseleave", () => { if (tip) tip.style.display = "none"; });
|
| 1312 |
+
canvas.addEventListener("click", (evt) => {
|
| 1313 |
+
const hit = hitTest(CSTL_HIT, evt, canvas);
|
| 1314 |
+
if (hit) openModelModal(hit.data.key, hit.data.cfgId, hit.data.fmt);
|
| 1315 |
+
});
|
| 1316 |
}
|
| 1317 |
+
redrawConstellation();
|
| 1318 |
+
}
|
| 1319 |
+
|
| 1320 |
+
/* ====================================================================== */
|
| 1321 |
+
/* CATALOG β card gallery + facet rail + table view */
|
| 1322 |
+
/* ====================================================================== */
|
| 1323 |
+
const SIZE_BUCKETS = [
|
| 1324 |
+
{ id: "β€1B", test: s => s != null && s <= 1000 },
|
| 1325 |
+
{ id: "1β4B", test: s => s != null && s > 1000 && s <= 4000 },
|
| 1326 |
+
{ id: "4β10B", test: s => s != null && s > 4000 && s <= 10000 },
|
| 1327 |
+
{ id: ">10B", test: s => s != null && s > 10000 },
|
| 1328 |
+
];
|
| 1329 |
+
const CATALOG_STATE = {
|
| 1330 |
+
search: "", sort: "size_desc", view: "grid",
|
| 1331 |
+
facets: { family: new Set(), size: new Set(), format: new Set(), target: new Set(), quant: new Set() },
|
| 1332 |
+
hil: false,
|
| 1333 |
+
};
|
| 1334 |
+
|
| 1335 |
+
function bestVariantBySource(m, source) {
|
| 1336 |
+
let best = null;
|
| 1337 |
+
for (const cfg of safeList(m.hardware_configs, [])) {
|
| 1338 |
+
for (const art of allArtifactsOf(m)) {
|
| 1339 |
+
const got = pickBlock(cfg.metrics || {}, art, source);
|
| 1340 |
+
const tok = got ? tokSOf(got.block) : null;
|
| 1341 |
+
if (tok == null) continue;
|
| 1342 |
+
if (!best || tok > best.tok) {
|
| 1343 |
+
best = { tok, quant: art, source: got.source, target: safeList(cfg.targets, safeList(m.targets, []))[0] || "β" };
|
| 1344 |
+
}
|
| 1345 |
+
}
|
| 1346 |
}
|
| 1347 |
return best;
|
| 1348 |
}
|
| 1349 |
+
function bestVariantOf(m) { return bestVariantBySource(m, "Best"); }
|
| 1350 |
+
/* Recency cards prioritise measured HIL numbers: show the best HIL variant
|
| 1351 |
+
when any exists, only falling back to the best Estimate when it has none. */
|
| 1352 |
+
function bestHilFirstVariantOf(m) {
|
| 1353 |
+
return bestVariantBySource(m, "HIL") || bestVariantBySource(m, "Estimate");
|
| 1354 |
+
}
|
| 1355 |
+
function modelHasHil(m) {
|
| 1356 |
+
for (const cfg of safeList(m.hardware_configs, []))
|
| 1357 |
+
for (const art of allArtifactsOf(m))
|
| 1358 |
+
if (metricsForArtifact(cfg.metrics || {}, art).hil) return true;
|
| 1359 |
+
return false;
|
| 1360 |
+
}
|
| 1361 |
+
function sizeBucketOf(s) { const b = SIZE_BUCKETS.find(x => x.test(s)); return b ? b.id : "β"; }
|
| 1362 |
+
function modelFormats(m) { const f = []; if (m.gguf_repo) f.push("GGUF"); if (m.onnx_repo) f.push("ONNX"); return f; }
|
| 1363 |
+
|
| 1364 |
+
function facetDefs() {
|
| 1365 |
+
return [
|
| 1366 |
+
{ group: "family", title: "Family", opts: uniqueSorted(CATALOG.map(m => m.architecture || "Unknown")) },
|
| 1367 |
+
{ group: "size", title: "Size", opts: SIZE_BUCKETS.map(b => b.id).filter(id => CATALOG.some(m => sizeBucketOf(m.model_size_m) === id)) },
|
| 1368 |
+
{ group: "quant", title: "Quantization", opts: uniqueSorted(CATALOG.flatMap(allArtifactsOf)) },
|
| 1369 |
+
];
|
| 1370 |
+
}
|
| 1371 |
+
|
| 1372 |
+
function buildFacetRail() {
|
| 1373 |
+
const el = $("cgFacets");
|
| 1374 |
+
if (!el) return;
|
| 1375 |
+
let html = facetDefs().map(d => `
|
| 1376 |
+
<div class="facet-group">
|
| 1377 |
+
<div class="facet-group-title">${esc(d.title)}</div>
|
| 1378 |
+
${d.opts.map(o => {
|
| 1379 |
+
const checked = CATALOG_STATE.facets[d.group].has(o) ? "checked" : "";
|
| 1380 |
+
return `<label class="facet-opt"><input type="checkbox" data-facet-group="${esc(d.group)}" value="${esc(o)}" ${checked}/> <span>${esc(o)}</span></label>`;
|
| 1381 |
+
}).join("")}
|
| 1382 |
+
</div>`).join("");
|
| 1383 |
+
html += `
|
| 1384 |
+
<div class="facet-group">
|
| 1385 |
+
<div class="facet-group-title">Metrics</div>
|
| 1386 |
+
<label class="facet-opt"><input type="checkbox" id="cgHil" ${CATALOG_STATE.hil ? "checked" : ""}/> <span>Has HIL measurement</span></label>
|
| 1387 |
+
</div>`;
|
| 1388 |
+
el.innerHTML = html;
|
| 1389 |
+
}
|
| 1390 |
+
|
| 1391 |
+
function modelMatches(m) {
|
| 1392 |
+
const f = CATALOG_STATE.facets;
|
| 1393 |
+
if (f.family.size && !f.family.has(m.architecture || "Unknown")) return false;
|
| 1394 |
+
if (f.size.size && !f.size.has(sizeBucketOf(m.model_size_m))) return false;
|
| 1395 |
+
if (f.format.size && !modelFormats(m).some(x => f.format.has(x))) return false;
|
| 1396 |
+
if (f.target.size && !safeList(m.targets, []).some(x => f.target.has(x))) return false;
|
| 1397 |
+
if (f.quant.size && !allArtifactsOf(m).some(x => f.quant.has(x))) return false;
|
| 1398 |
+
if (CATALOG_STATE.hil && !modelHasHil(m)) return false;
|
| 1399 |
+
const q = CATALOG_STATE.search.trim().toLowerCase();
|
| 1400 |
+
if (q) {
|
| 1401 |
+
const hay = [m.display_name, m.key, m.architecture, m.base_model, m.license, safeList(m.tasks, []).join(" "), allArtifactsOf(m).join(" ")].join(" ").toLowerCase();
|
| 1402 |
+
if (!hay.includes(q)) return false;
|
| 1403 |
+
}
|
| 1404 |
+
return true;
|
| 1405 |
+
}
|
| 1406 |
+
|
| 1407 |
+
function sortModels(list) {
|
| 1408 |
+
const s = CATALOG_STATE.sort;
|
| 1409 |
+
const tok = m => { const b = bestVariantOf(m); return b ? b.tok : -1; };
|
| 1410 |
+
const arr = list.slice();
|
| 1411 |
+
if (s === "size_desc") arr.sort((a, b) => (b.model_size_m || 0) - (a.model_size_m || 0));
|
| 1412 |
+
else if (s === "size_asc") arr.sort((a, b) => (a.model_size_m || 0) - (b.model_size_m || 0));
|
| 1413 |
+
else if (s === "tok_desc") arr.sort((a, b) => tok(b) - tok(a));
|
| 1414 |
+
else if (s === "name_asc") arr.sort((a, b) => String(a.display_name || a.key).localeCompare(String(b.display_name || b.key)));
|
| 1415 |
+
return arr;
|
| 1416 |
+
}
|
| 1417 |
+
|
| 1418 |
+
function monogramText(m) {
|
| 1419 |
+
const s = m.model_size_m;
|
| 1420 |
+
if (s != null) return s >= 1000 ? `${Math.round(s / 100) / 10}B` : `${s}M`;
|
| 1421 |
+
return (m.display_name || m.key || "?").slice(0, 2).toUpperCase();
|
| 1422 |
+
}
|
| 1423 |
+
|
| 1424 |
+
/* ---- Model designer / publisher logos (derived from base_model org or architecture) ---- */
|
| 1425 |
+
const DESIGNERS = {
|
| 1426 |
+
meta: { name: "Meta", svg: `<svg viewBox="0 0 32 18" width="22" height="13" aria-hidden="true"><path d="M16 9.2C13.1 4 10.2 2.8 7.6 2.8 4.5 2.8 2 5.6 2 9s2.5 6.2 5.6 6.2c2.6 0 5.5-1.2 8.4-6.4 2.9 5.2 5.8 6.4 8.4 6.4 3.1 0 5.6-2.8 5.6-6.2s-2.5-6.2-5.6-6.2C21.8 2.8 18.9 4 16 9.2Z" fill="none" stroke="#0866FF" stroke-width="2.7" stroke-linejoin="round"/></svg>` },
|
| 1427 |
+
nvidia: { name: "NVIDIA", svg: `<svg viewBox="0 0 26 22" width="18" height="15" aria-hidden="true"><path d="M9 4C4.4 4.6 1.8 7.8 1 11c2.6 4.4 8 6.4 13 5.9 5.3-.5 8.8-3.4 10.4-6.4C22 6.2 15 3.4 9 4Z" fill="none" stroke="#76B900" stroke-width="2"/><path d="M9.7 7.6c-1.9.8-2.9 2.1-3.1 3.6 1.6 2.2 4.5 2.7 6.6 1.8 1.9-1 2.5-3.2 1.3-5C13.4 6.2 11.5 6.8 9.7 7.6Z" fill="#76B900"/></svg>` },
|
| 1428 |
+
google: { name: "Google", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M23 12.2c0-.8-.1-1.6-.2-2.3H12v4.5h6.2a5.3 5.3 0 0 1-2.3 3.5v2.9h3.7C21.7 18.7 23 15.8 23 12.2Z" fill="#4285F4"/><path d="M12 24c3.1 0 5.7-1 7.6-2.8l-3.7-2.9c-1 .7-2.3 1.1-3.9 1.1-3 0-5.5-2-6.4-4.7H1.8v3C3.7 21.4 7.6 24 12 24Z" fill="#34A853"/><path d="M5.6 14.7a7.2 7.2 0 0 1 0-4.6V7.1H1.8a12 12 0 0 0 0 10.6l3.8-3Z" fill="#FBBC05"/><path d="M12 4.8c1.7 0 3.2.6 4.4 1.7l3.3-3.3C17.7 1.2 15.1 0 12 0 7.6 0 3.7 2.6 1.8 6.4l3.8 3C6.5 6.7 9 4.8 12 4.8Z" fill="#EA4335"/></svg>` },
|
| 1429 |
+
microsoft: { name: "Microsoft", svg: `<svg viewBox="0 0 23 23" width="14" height="14" aria-hidden="true"><rect x="1" y="1" width="10" height="10" fill="#F25022"/><rect x="12" y="1" width="10" height="10" fill="#7FBA00"/><rect x="1" y="12" width="10" height="10" fill="#00A4EF"/><rect x="12" y="12" width="10" height="10" fill="#FFB900"/></svg>` },
|
| 1430 |
+
mistral: { name: "Mistral AI", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><g><rect x="2" y="3" width="5" height="4.5" fill="#F7D046"/><rect x="17" y="3" width="5" height="4.5" fill="#F7D046"/><rect x="2" y="8" width="5" height="4.5" fill="#F2A73B"/><rect x="9.5" y="8" width="5" height="4.5" fill="#F2A73B"/><rect x="17" y="8" width="5" height="4.5" fill="#F2A73B"/><rect x="2" y="13" width="5" height="4.5" fill="#EE792F"/><rect x="17" y="13" width="5" height="4.5" fill="#EE792F"/><rect x="2" y="18" width="5" height="4.5" fill="#EA3326"/><rect x="17" y="18" width="5" height="4.5" fill="#EA3326"/></g></svg>` },
|
| 1431 |
+
qwen: { name: "Qwen", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><circle cx="12" cy="12" r="11" fill="#615CED"/><path d="M7.5 7l4.5 10 4.5-10M9.3 13.2h5.4" stroke="#fff" stroke-width="1.7" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>` },
|
| 1432 |
+
deepseek: { name: "DeepSeek", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><circle cx="12" cy="12" r="11" fill="#4D6BFE"/><path d="M6 9.5c3.2.2 4 2.2 6 2.2s2.2-2 .2-3.2" stroke="#fff" stroke-width="1.6" fill="none" stroke-linecap="round"/><circle cx="9.2" cy="14.2" r="1.3" fill="#fff"/></svg>` },
|
| 1433 |
+
renesas: { name: "Renesas", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><rect width="24" height="24" rx="4" fill="#2A289D"/><text x="12" y="16.5" font-family="Arial, sans-serif" font-size="13" font-weight="700" fill="#fff" text-anchor="middle">R</text></svg>` },
|
| 1434 |
+
generic: { name: "AI Model", svg: `<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><circle cx="12" cy="12" r="11" fill="#8E8DA3"/><circle cx="12" cy="12" r="4" fill="#fff"/></svg>` },
|
| 1435 |
+
};
|
| 1436 |
+
function designerOf(m) {
|
| 1437 |
+
const base = (m.base_model || "").toLowerCase();
|
| 1438 |
+
const org = base.includes("/") ? base.split("/")[0] : "";
|
| 1439 |
+
const hay = `${org} ${(m.architecture || "").toLowerCase()} ${(m.key || "").toLowerCase()}`;
|
| 1440 |
+
if (org.includes("nvidia") || hay.includes("nemotron") || hay.includes("nemo")) return DESIGNERS.nvidia;
|
| 1441 |
+
if (org.includes("meta") || org.includes("facebook") || hay.includes("llama")) return DESIGNERS.meta;
|
| 1442 |
+
if (org.includes("google") || hay.includes("gemma")) return DESIGNERS.google;
|
| 1443 |
+
if (org.includes("microsoft") || hay.includes("phi")) return DESIGNERS.microsoft;
|
| 1444 |
+
if (org.includes("mistral") || hay.includes("mistral") || hay.includes("mixtral")) return DESIGNERS.mistral;
|
| 1445 |
+
if (org.includes("qwen") || org.includes("alibaba") || hay.includes("qwen")) return DESIGNERS.qwen;
|
| 1446 |
+
if (org.includes("deepseek") || hay.includes("deepseek")) return DESIGNERS.deepseek;
|
| 1447 |
+
if (org.includes("renesas")) return DESIGNERS.renesas;
|
| 1448 |
+
if (org) return { name: org.split(/[-_]/)[0].replace(/^\w/, c => c.toUpperCase()), svg: DESIGNERS.generic.svg };
|
| 1449 |
+
return DESIGNERS.generic;
|
| 1450 |
+
}
|
| 1451 |
+
function designerRowHTML(m) {
|
| 1452 |
+
const d = designerOf(m);
|
| 1453 |
+
return `<div class="mc-designer"><span class="mc-logo">${d.svg}</span><span class="mc-designer-name">${esc(d.name)}</span></div>`;
|
| 1454 |
+
}
|
| 1455 |
+
|
| 1456 |
+
function cardHTML(m) {
|
| 1457 |
+
const best = bestHilFirstVariantOf(m);
|
| 1458 |
+
const col = colorFor(m.architecture || "Unknown");
|
| 1459 |
+
const quantChips = allArtifactsOf(m).map(a => `<span class="badge art clickable" data-facet="quant" data-value="${esc(a)}">${esc(a)}</span>`).join("");
|
| 1460 |
+
const modalityChip = `<span class="badge modality">${esc(m.modality || "LLM")}</span>`;
|
| 1461 |
+
const _lbl = recentLabel(m);
|
| 1462 |
+
const statusChips = `${modelHasHil(m) ? `<span class="badge status-hil">HIL</span>` : ""}${_lbl.isNew ? `<span class="badge status-new">New</span>` : ""}`;
|
| 1463 |
+
const stat = best
|
| 1464 |
+
? `<div class="mc-stat"><span class="mc-stat-num">${esc(Math.round(best.tok * 10) / 10)}</span><span class="mc-stat-sub">tok/s Β· ${esc(best.target)} Β· ${esc(best.quant)}${best.source === "Estimate" ? " (est)" : ""}</span></div>`
|
| 1465 |
+
: `<div class="mc-stat empty"><span class="mc-stat-sub">No published throughput yet</span></div>`;
|
| 1466 |
+
const repo = m.gguf_repo || m.onnx_repo || "";
|
| 1467 |
+
const repoLink = repo ? `<a class="link small" href="${esc(hfModelUrl(repo))}" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">View repo</a>` : "";
|
| 1468 |
+
const firstCfg = safeFirstCfg(m);
|
| 1469 |
+
const defFmt = m.gguf_repo ? "GGUF" : (m.onnx_repo ? "ONNX" : "GGUF");
|
| 1470 |
+
return `
|
| 1471 |
+
<div class="model-card" data-card="1" data-key="${esc(m.key)}" data-cfg="${esc(firstCfg?.id || "")}" data-fmt="${esc(defFmt)}">
|
| 1472 |
+
${designerRowHTML(m)}
|
| 1473 |
+
<div class="mc-head">
|
| 1474 |
+
<div class="mc-monogram" style="background:linear-gradient(135deg, ${col}, ${col}99)">${esc(monogramText(m))}</div>
|
| 1475 |
+
<div style="min-width:0">
|
| 1476 |
+
<div class="mc-title">${esc(m.display_name || m.key)}</div>
|
| 1477 |
+
<div class="mc-sub">${esc(m.architecture || "")}${m.variant ? " Β· " + esc(m.variant) : ""}</div>
|
| 1478 |
+
</div>
|
| 1479 |
+
</div>
|
| 1480 |
+
<div class="mc-chips">${modalityChip}${statusChips}</div>
|
| 1481 |
+
${stat}
|
| 1482 |
+
${quantChips ? `<div class="mc-quants">${quantChips}</div>` : ""}
|
| 1483 |
+
${(m.license || repoLink) ? `<div class="mc-foot">
|
| 1484 |
+
<span class="mc-meta">${esc(m.license || "")}</span>
|
| 1485 |
+
${repoLink}
|
| 1486 |
+
</div>` : ""}
|
| 1487 |
+
</div>`;
|
| 1488 |
+
}
|
| 1489 |
+
|
| 1490 |
+
function renderCards(models) {
|
| 1491 |
+
const el = $("cardGrid");
|
| 1492 |
+
if (!el) return;
|
| 1493 |
+
el.innerHTML = models.length
|
| 1494 |
+
? models.map(cardHTML).join("")
|
| 1495 |
+
: `<div class="subtle" style="padding:24px;">No models match the current filters.</div>`;
|
| 1496 |
+
}
|
| 1497 |
+
|
| 1498 |
+
function renderCatalog() {
|
| 1499 |
+
const filtered = sortModels(CATALOG.filter(modelMatches));
|
| 1500 |
+
const count = $("cgCount");
|
| 1501 |
+
if (count) count.innerHTML = `<b>${filtered.length}</b> of ${CATALOG.length} models`;
|
| 1502 |
+
const grid = $("cardGrid"), table = $("tableView");
|
| 1503 |
+
if (CATALOG_STATE.view === "grid") {
|
| 1504 |
+
if (grid) grid.hidden = false;
|
| 1505 |
+
if (table) table.hidden = true;
|
| 1506 |
+
renderCards(filtered);
|
| 1507 |
+
} else {
|
| 1508 |
+
if (grid) grid.hidden = true;
|
| 1509 |
+
if (table) table.hidden = false;
|
| 1510 |
+
renderTable(buildTableRows(filtered));
|
| 1511 |
+
requestAnimationFrame(() => setupPinnedColumns($("modelsTable"), 1));
|
| 1512 |
+
}
|
| 1513 |
}
|
|
|
|
| 1514 |
|
| 1515 |
+
function setView(view) {
|
| 1516 |
+
CATALOG_STATE.view = view;
|
| 1517 |
+
$("cgViewGrid")?.classList.toggle("active", view === "grid");
|
| 1518 |
+
$("cgViewTable")?.classList.toggle("active", view === "table");
|
| 1519 |
+
$("cgViewGrid")?.setAttribute("aria-pressed", String(view === "grid"));
|
| 1520 |
+
$("cgViewTable")?.setAttribute("aria-pressed", String(view === "table"));
|
| 1521 |
+
renderCatalog();
|
| 1522 |
+
}
|
| 1523 |
|
| 1524 |
+
function toggleFacet(group, value) {
|
| 1525 |
+
const set = CATALOG_STATE.facets[group];
|
| 1526 |
+
if (!set) return;
|
| 1527 |
+
if (set.has(value)) set.delete(value); else set.add(value);
|
| 1528 |
+
buildFacetRail();
|
| 1529 |
+
renderCatalog();
|
| 1530 |
+
}
|
|
|
|
| 1531 |
|
| 1532 |
+
function initCatalog() {
|
| 1533 |
+
buildFacetRail();
|
| 1534 |
|
| 1535 |
+
$("cgSearch")?.addEventListener("input", () => {
|
| 1536 |
+
clearTimeout(window.__cgT);
|
| 1537 |
+
window.__cgT = setTimeout(() => { CATALOG_STATE.search = $("cgSearch").value; renderCatalog(); }, 90);
|
| 1538 |
+
});
|
| 1539 |
+
$("cgSort")?.addEventListener("change", () => { CATALOG_STATE.sort = $("cgSort").value; renderCatalog(); });
|
| 1540 |
+
$("cgReset")?.addEventListener("click", () => {
|
| 1541 |
+
CATALOG_STATE.search = ""; CATALOG_STATE.sort = "size_desc"; CATALOG_STATE.hil = false;
|
| 1542 |
+
Object.values(CATALOG_STATE.facets).forEach(s => s.clear());
|
| 1543 |
+
if ($("cgSearch")) $("cgSearch").value = "";
|
| 1544 |
+
if ($("cgSort")) $("cgSort").value = "size_desc";
|
| 1545 |
+
buildFacetRail();
|
| 1546 |
+
renderCatalog();
|
| 1547 |
+
});
|
| 1548 |
+
$("cgViewGrid")?.addEventListener("click", () => setView("grid"));
|
| 1549 |
+
$("cgViewTable")?.addEventListener("click", () => setView("table"));
|
| 1550 |
+
|
| 1551 |
+
$("cgFacets")?.addEventListener("change", (e) => {
|
| 1552 |
+
const t = e.target;
|
| 1553 |
+
if (t.id === "cgHil") { CATALOG_STATE.hil = t.checked; renderCatalog(); return; }
|
| 1554 |
+
const group = t.getAttribute("data-facet-group");
|
| 1555 |
+
if (!group) return;
|
| 1556 |
+
const set = CATALOG_STATE.facets[group];
|
| 1557 |
+
if (t.checked) set.add(t.value); else set.delete(t.value);
|
| 1558 |
+
renderCatalog();
|
| 1559 |
+
});
|
| 1560 |
|
| 1561 |
+
$("cardGrid")?.addEventListener("click", (e) => {
|
| 1562 |
+
const chip = e.target.closest("[data-facet]");
|
| 1563 |
+
if (chip) { e.stopPropagation(); toggleFacet(chip.getAttribute("data-facet"), chip.getAttribute("data-value")); return; }
|
| 1564 |
+
if (e.target.closest("a")) return;
|
| 1565 |
+
const card = e.target.closest('.model-card[data-card="1"]');
|
| 1566 |
+
if (card) openModelModal(card.getAttribute("data-key"), card.getAttribute("data-cfg") || "", card.getAttribute("data-fmt") || "GGUF");
|
| 1567 |
+
});
|
| 1568 |
+
|
| 1569 |
+
renderCatalog();
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1570 |
}
|
| 1571 |
|
| 1572 |
/* ---------- Boot ---------- */
|
|
|
|
| 1670 |
MODALITIES = ["All"].concat(uniqueSorted(CATALOG.map(m => m.modality || "LLM")));
|
| 1671 |
VARIANTS = ["All"].concat(uniqueSorted(CATALOG.map(m => m.variant || "Default")));
|
| 1672 |
|
| 1673 |
+
/* Defaults derived from the loaded catalog (so the UI opens on data that exists). */
|
| 1674 |
+
const hasOnnx = CATALOG.some(m => m.onnx_repo);
|
| 1675 |
+
const DEFAULT_FMT = hasOnnx ? "ONNX" : "GGUF";
|
| 1676 |
+
const DEFAULT_PURPOSE = defaultPurposeForFormat(DEFAULT_FMT);
|
| 1677 |
+
const allTargets = new Set();
|
| 1678 |
+
CATALOG.forEach(m => safeList(m.targets, []).forEach(t => allTargets.add(t)));
|
| 1679 |
+
const DEFAULT_COMPUTE = allTargets.has("CPU") ? "CPU" : (allTargets.has("NPU") ? "NPU" : "DSP");
|
| 1680 |
|
| 1681 |
/* Explore init */
|
| 1682 |
fillSelect($("arch"), ARCHS, "All");
|
| 1683 |
buildRadioGroup($("modality"), "modality", MODALITIES, "All");
|
| 1684 |
+
buildRadioGroup($("fmt"), "fmt", ["ONNX", "GGUF"], DEFAULT_FMT);
|
| 1685 |
+
buildRadioGroup($("compute"), "compute", ["CPU", "NPU", "DSP"], DEFAULT_COMPUTE);
|
| 1686 |
+
buildRadioGroup($("purpose"), "purpose", ["PerformanceEstimate", "ORT Benchmarking", "llama.cpp Benchmarking"], DEFAULT_PURPOSE);
|
| 1687 |
|
| 1688 |
EXPLORE_KEYS = filteredKeys("All", "All", "All");
|
| 1689 |
updateExploreFromFilters();
|
|
|
|
| 1699 |
$("modelKey").addEventListener("change", updateExploreOnModelChange);
|
| 1700 |
$("hwCfg").addEventListener("change", updateExploreAny);
|
| 1701 |
|
| 1702 |
+
/* Catalog (cards + table + facet rail) */
|
| 1703 |
+
initCatalog();
|
|
|
|
|
|
|
| 1704 |
|
| 1705 |
+
/* Overview (constellation) */
|
| 1706 |
+
initOverview();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1707 |
|
| 1708 |
window.addEventListener("resize", () => {
|
| 1709 |
+
if ($("sec-overview")?.classList.contains("visible")) redrawConstellation();
|
| 1710 |
+
if (CATALOG_STATE.view === "table") setupPinnedColumns($("modelsTable"), 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1711 |
});
|
|
|
|
|
|
|
| 1712 |
}
|
| 1713 |
|
| 1714 |
document.addEventListener("DOMContentLoaded", init);
|
assets/logo_renesas_blue.svg
ADDED
|
|
assets/logo_renesas_light.svg
CHANGED
|
|
|
|
assets/logo_renesas_white.svg
ADDED
|
|
generate_models_json.py
ADDED
|
@@ -0,0 +1,842 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
generate_models_json.py
|
| 4 |
+
=======================
|
| 5 |
+
|
| 6 |
+
Regenerate the dashboard's `models.json` directly from the Hugging Face repos of
|
| 7 |
+
an organization (default: "Renesas"), instead of maintaining the catalog by hand.
|
| 8 |
+
|
| 9 |
+
It reads, for every model repo in the org:
|
| 10 |
+
* the model-list / per-repo info API (always public, even for gated repos)
|
| 11 |
+
* the recursive file tree API (always public, even for gated repos)
|
| 12 |
+
* each `.metadata.yaml` (repo-level identity + per-artifact info)
|
| 13 |
+
* each `<artifact>/benchmarks/<chip>_<ep>.yaml` (the actual benchmark numbers)
|
| 14 |
+
|
| 15 |
+
and emits a `models.json` whose schema is the one `app.js` already consumes.
|
| 16 |
+
|
| 17 |
+
Gated repos
|
| 18 |
+
-----------
|
| 19 |
+
The org has gated ("gated: manual") repos. Their *listing* (ids, tags, file
|
| 20 |
+
tree, artifact dirs, benchmark file paths) is public, but their raw *file
|
| 21 |
+
contents* require an authorized token. Provide one to import their metrics:
|
| 22 |
+
|
| 23 |
+
* `--token hf_xxx`, or
|
| 24 |
+
* env HF_TOKEN / HUGGINGFACE_TOKEN / HUGGING_FACE_HUB_TOKEN, or
|
| 25 |
+
* a prior `huggingface-cli login` (cached token is picked up automatically).
|
| 26 |
+
|
| 27 |
+
Without an authorized token, gated repos are still listed (with their artifacts,
|
| 28 |
+
and -- where benchmark files exist in the public file tree -- their hardware
|
| 29 |
+
targets/config derived from the file paths) but their benchmark numbers are left
|
| 30 |
+
empty and reported as skipped.
|
| 31 |
+
|
| 32 |
+
Usage
|
| 33 |
+
-----
|
| 34 |
+
pip install requests pyyaml
|
| 35 |
+
python generate_models_json.py # writes ./models.json
|
| 36 |
+
python generate_models_json.py --org Renesas --output models.json
|
| 37 |
+
python generate_models_json.py --token hf_xxx # include gated repos' metrics
|
| 38 |
+
python generate_models_json.py --dry-run -v # print, don't write
|
| 39 |
+
|
| 40 |
+
Run it whenever the repos change to refresh the dashboard.
|
| 41 |
+
"""
|
| 42 |
+
|
| 43 |
+
from __future__ import annotations
|
| 44 |
+
|
| 45 |
+
import argparse
|
| 46 |
+
import datetime as _dt
|
| 47 |
+
import json
|
| 48 |
+
import os
|
| 49 |
+
import re
|
| 50 |
+
import sys
|
| 51 |
+
import time
|
| 52 |
+
from pathlib import Path
|
| 53 |
+
|
| 54 |
+
try:
|
| 55 |
+
import requests
|
| 56 |
+
except ImportError: # pragma: no cover
|
| 57 |
+
sys.exit("Missing dependency 'requests'. Install with: pip install requests pyyaml")
|
| 58 |
+
|
| 59 |
+
try:
|
| 60 |
+
import yaml
|
| 61 |
+
except ImportError: # pragma: no cover
|
| 62 |
+
sys.exit("Missing dependency 'pyyaml'. Install with: pip install requests pyyaml")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
HF_BASE = "https://huggingface.co"
|
| 66 |
+
DEFAULT_ORG = "Renesas"
|
| 67 |
+
|
| 68 |
+
# execution-provider / accelerator token -> (unit key in metric block, UI target)
|
| 69 |
+
EP_TO_UNIT = {
|
| 70 |
+
"cpu": ("cpu", "CPU"),
|
| 71 |
+
"npu": ("npu", "NPU"),
|
| 72 |
+
"dsp": ("dsp", "DSP"),
|
| 73 |
+
}
|
| 74 |
+
# benchmark.type values that mean "measured on real hardware" -> HIL block; everything
|
| 75 |
+
# else (projected / simulated / static estimate) -> Estimate block.
|
| 76 |
+
HIL_TYPES = {"hil", "measured", "hardware", "device", "hw", "hardware_in_the_loop"}
|
| 77 |
+
|
| 78 |
+
VARIANT_KEYWORDS = ["Instruct", "Chat", "Vision", "Guard", "Code", "Base"]
|
| 79 |
+
FORMAT_SUFFIXES = ["GGUF", "ONNX"]
|
| 80 |
+
|
| 81 |
+
# status codes worth retrying (rate limit + transient server errors)
|
| 82 |
+
RETRYABLE_STATUS = {429, 500, 502, 503, 504}
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def warn(msg: str) -> None:
|
| 86 |
+
print(f" ! {msg}", file=sys.stderr)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
# --------------------------------------------------------------------------- #
|
| 90 |
+
# HTTP helpers #
|
| 91 |
+
# --------------------------------------------------------------------------- #
|
| 92 |
+
class Client:
|
| 93 |
+
def __init__(self, token: str | None, verbose: bool = False):
|
| 94 |
+
self.session = requests.Session()
|
| 95 |
+
self.token = token
|
| 96 |
+
self.verbose = verbose
|
| 97 |
+
if token:
|
| 98 |
+
self.session.headers["Authorization"] = f"Bearer {token}"
|
| 99 |
+
self.session.headers["User-Agent"] = "renesas-ai-dashboard-generator/1.0"
|
| 100 |
+
|
| 101 |
+
def _get(self, url: str, *, params=None, retries: int = 3):
|
| 102 |
+
last = None
|
| 103 |
+
for attempt in range(retries + 1):
|
| 104 |
+
try:
|
| 105 |
+
r = self.session.get(url, params=params, timeout=30)
|
| 106 |
+
except requests.RequestException as exc: # network hiccup -> retry
|
| 107 |
+
last = exc
|
| 108 |
+
if attempt < retries:
|
| 109 |
+
time.sleep(1.0 + attempt)
|
| 110 |
+
continue
|
| 111 |
+
raise
|
| 112 |
+
# retry rate-limit / transient 5xx, honoring Retry-After when present
|
| 113 |
+
if r.status_code in RETRYABLE_STATUS and attempt < retries:
|
| 114 |
+
ra = r.headers.get("Retry-After")
|
| 115 |
+
try:
|
| 116 |
+
delay = float(ra) if ra is not None else None
|
| 117 |
+
except ValueError:
|
| 118 |
+
delay = None
|
| 119 |
+
if self.verbose:
|
| 120 |
+
warn(f"HTTP {r.status_code} from {url} β retrying (attempt {attempt + 1})")
|
| 121 |
+
time.sleep(delay if delay is not None else 1.5 * (attempt + 1))
|
| 122 |
+
continue
|
| 123 |
+
return r
|
| 124 |
+
raise last # type: ignore[misc]
|
| 125 |
+
|
| 126 |
+
def _json(self, r, url: str):
|
| 127 |
+
try:
|
| 128 |
+
return r.json()
|
| 129 |
+
except ValueError as exc: # non-JSON 200 (proxy / login interstitial / HTML)
|
| 130 |
+
snippet = (r.text or "")[:200].replace("\n", " ")
|
| 131 |
+
raise RuntimeError(
|
| 132 |
+
f"Expected JSON from {url} (HTTP {r.status_code}) but got non-JSON: {snippet!r}"
|
| 133 |
+
) from exc
|
| 134 |
+
|
| 135 |
+
def get_json(self, url: str, *, params=None):
|
| 136 |
+
r = self._get(url, params=params)
|
| 137 |
+
r.raise_for_status()
|
| 138 |
+
return self._json(r, url)
|
| 139 |
+
|
| 140 |
+
def get_json_pages(self, url: str, *, params=None):
|
| 141 |
+
"""Follow HF `Link: rel=next` pagination; return the concatenated array."""
|
| 142 |
+
out, next_url, next_params = [], url, params
|
| 143 |
+
while next_url:
|
| 144 |
+
r = self._get(next_url, params=next_params)
|
| 145 |
+
r.raise_for_status()
|
| 146 |
+
page = self._json(r, next_url)
|
| 147 |
+
if not isinstance(page, list):
|
| 148 |
+
raise RuntimeError(
|
| 149 |
+
f"Expected a JSON array from {next_url}, got {type(page).__name__}"
|
| 150 |
+
)
|
| 151 |
+
out.extend(page)
|
| 152 |
+
next_url = (r.links.get("next") or {}).get("url")
|
| 153 |
+
next_params = None # the cursor for later pages is embedded in the URL
|
| 154 |
+
return out
|
| 155 |
+
|
| 156 |
+
def get_text(self, path_url: str):
|
| 157 |
+
"""Fetch a raw file. Returns (text, status).
|
| 158 |
+
|
| 159 |
+
status: "ok" | "gated" | "missing" | "error".
|
| 160 |
+
"""
|
| 161 |
+
r = self._get(path_url)
|
| 162 |
+
if r.status_code == 200:
|
| 163 |
+
return r.text, "ok"
|
| 164 |
+
if r.status_code in (401, 403):
|
| 165 |
+
return None, "gated"
|
| 166 |
+
if r.status_code == 404:
|
| 167 |
+
return None, "missing"
|
| 168 |
+
return None, f"error:{r.status_code}"
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
# --------------------------------------------------------------------------- #
|
| 172 |
+
# Token resolution #
|
| 173 |
+
# --------------------------------------------------------------------------- #
|
| 174 |
+
def resolve_token(cli_token: str | None) -> str | None:
|
| 175 |
+
if cli_token:
|
| 176 |
+
return cli_token.strip()
|
| 177 |
+
for var in ("HF_TOKEN", "HUGGINGFACE_TOKEN", "HUGGING_FACE_HUB_TOKEN"):
|
| 178 |
+
val = os.environ.get(var)
|
| 179 |
+
if val:
|
| 180 |
+
return val.strip()
|
| 181 |
+
# huggingface_hub cached login token (huggingface-cli login)
|
| 182 |
+
try:
|
| 183 |
+
from huggingface_hub import get_token # type: ignore
|
| 184 |
+
|
| 185 |
+
tok = get_token()
|
| 186 |
+
if tok:
|
| 187 |
+
return tok.strip()
|
| 188 |
+
except Exception:
|
| 189 |
+
pass
|
| 190 |
+
for p in (
|
| 191 |
+
Path.home() / ".cache" / "huggingface" / "token",
|
| 192 |
+
Path.home() / ".huggingface" / "token",
|
| 193 |
+
):
|
| 194 |
+
try:
|
| 195 |
+
if p.is_file():
|
| 196 |
+
txt = p.read_text(encoding="utf-8").strip()
|
| 197 |
+
if txt:
|
| 198 |
+
return txt
|
| 199 |
+
except Exception:
|
| 200 |
+
pass
|
| 201 |
+
return None
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
# --------------------------------------------------------------------------- #
|
| 205 |
+
# Small parsing helpers #
|
| 206 |
+
# --------------------------------------------------------------------------- #
|
| 207 |
+
def tag_value(tags: list[str], prefix: str) -> str | None:
|
| 208 |
+
for t in tags:
|
| 209 |
+
if t.startswith(prefix):
|
| 210 |
+
return t[len(prefix):]
|
| 211 |
+
return None
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
def parse_base_model(tags: list[str], upstream: str | None) -> str | None:
|
| 215 |
+
"""The non-quantized base_model:* tag, else the metadata upstream."""
|
| 216 |
+
candidate = None
|
| 217 |
+
for t in tags:
|
| 218 |
+
if t.startswith("base_model:") and ":quantized:" not in t:
|
| 219 |
+
candidate = t.split(":", 1)[1]
|
| 220 |
+
break
|
| 221 |
+
if not candidate:
|
| 222 |
+
for t in tags:
|
| 223 |
+
if t.startswith("base_model:"):
|
| 224 |
+
candidate = t.split(":", 1)[-1]
|
| 225 |
+
break
|
| 226 |
+
return candidate or upstream
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
def short_name(repo_or_model_id: str) -> str:
|
| 230 |
+
return repo_or_model_id.split("/")[-1]
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def strip_format_suffix(name: str) -> str:
|
| 234 |
+
for suf in FORMAT_SUFFIXES:
|
| 235 |
+
name = re.sub(rf"[-_ ]{suf}$", "", name, flags=re.IGNORECASE)
|
| 236 |
+
return name
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def detect_variant(name: str) -> str:
|
| 240 |
+
low = name.lower()
|
| 241 |
+
for v in VARIANT_KEYWORDS:
|
| 242 |
+
if re.search(rf"(?:^|[-_ ]){v.lower()}(?:$|[-_ ])", low):
|
| 243 |
+
return v
|
| 244 |
+
return "Base"
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def architecture_from(name: str, variant: str) -> str:
|
| 248 |
+
"""Family + size label, e.g. 'Llama-3.1-8B' from 'Llama-3.1-8B-Instruct'."""
|
| 249 |
+
arch = strip_format_suffix(short_name(name))
|
| 250 |
+
arch = re.sub(rf"[-_ ]{re.escape(variant)}$", "", arch, flags=re.IGNORECASE)
|
| 251 |
+
return arch.strip("-_ ") or arch
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
def parse_size_m(*texts: str | None) -> int | None:
|
| 255 |
+
"""Parameter count in millions. Handles '8.0B', '8B', '500M', '1.5b'."""
|
| 256 |
+
for text in texts:
|
| 257 |
+
if not text:
|
| 258 |
+
continue
|
| 259 |
+
m = re.search(r"(\d+(?:\.\d+)?)\s*([BM])\b", str(text), flags=re.IGNORECASE)
|
| 260 |
+
if m:
|
| 261 |
+
val = float(m.group(1))
|
| 262 |
+
return int(round(val * (1000 if m.group(2).upper() == "B" else 1)))
|
| 263 |
+
return None
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
def map_modality(meta_modality, tags: list[str], pipeline_tag: str | None) -> str:
|
| 267 |
+
vals = []
|
| 268 |
+
if isinstance(meta_modality, list):
|
| 269 |
+
vals = [str(v).lower() for v in meta_modality]
|
| 270 |
+
elif isinstance(meta_modality, str):
|
| 271 |
+
vals = [meta_modality.lower()]
|
| 272 |
+
if any(v in ("vision", "image", "multimodal", "vlm") for v in vals):
|
| 273 |
+
return "VLM"
|
| 274 |
+
if any(v in ("audio", "speech") for v in vals):
|
| 275 |
+
return "ALM"
|
| 276 |
+
if vals: # language / text
|
| 277 |
+
return "LLM"
|
| 278 |
+
# fallback from tags / pipeline tag
|
| 279 |
+
low_tags = [t.lower() for t in tags]
|
| 280 |
+
if "vlm" in low_tags or "image-text-to-text" == (pipeline_tag or ""):
|
| 281 |
+
return "VLM"
|
| 282 |
+
return "LLM"
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
def detect_format(repo_id: str, meta_format_type: str | None) -> str:
|
| 286 |
+
ft = (meta_format_type or "").lower()
|
| 287 |
+
if "onnx" in ft:
|
| 288 |
+
return "ONNX"
|
| 289 |
+
if "gguf" in ft:
|
| 290 |
+
return "GGUF"
|
| 291 |
+
low = repo_id.lower()
|
| 292 |
+
if low.endswith("-onnx") or "onnx" in low:
|
| 293 |
+
return "ONNX"
|
| 294 |
+
if low.endswith("-gguf") or "gguf" in low:
|
| 295 |
+
return "GGUF"
|
| 296 |
+
return "GGUF" # sensible default for this org
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def normalize_chip_id(chip: str) -> str:
|
| 300 |
+
return re.sub(r"[^A-Za-z0-9]+", "-", chip).strip("-").upper()
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
def prettify_chip(chip: str) -> str:
|
| 304 |
+
parts = re.split(r"[-_]", chip)
|
| 305 |
+
out = ["R-Car" if p.lower() == "rcar" else p.upper() for p in parts if p]
|
| 306 |
+
return " ".join(out) if out else chip
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
def block_kind_for(bench_type: str | None) -> str:
|
| 310 |
+
return "hil" if str(bench_type or "").lower() in HIL_TYPES else "estimate"
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def as_number(v):
|
| 314 |
+
if v is None or isinstance(v, bool):
|
| 315 |
+
return None
|
| 316 |
+
if isinstance(v, (int, float)):
|
| 317 |
+
return v
|
| 318 |
+
try:
|
| 319 |
+
s = str(v).strip()
|
| 320 |
+
return float(s) if s else None
|
| 321 |
+
except (TypeError, ValueError):
|
| 322 |
+
return None
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
def normalize_accuracy(v):
|
| 326 |
+
"""app.js expects top-level accuracy as a 0..1 fraction; rescale percents."""
|
| 327 |
+
n = as_number(v)
|
| 328 |
+
if n is None:
|
| 329 |
+
return None
|
| 330 |
+
return n / 100.0 if n > 1.5 else n
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
# --------------------------------------------------------------------------- #
|
| 334 |
+
# Per-repo gathering #
|
| 335 |
+
# --------------------------------------------------------------------------- #
|
| 336 |
+
class RepoData:
|
| 337 |
+
def __init__(self, info: dict):
|
| 338 |
+
self.id: str = info.get("id") or info.get("modelId") or ""
|
| 339 |
+
if not self.id:
|
| 340 |
+
raise ValueError("repo info has no 'id'")
|
| 341 |
+
self.gated = info.get("gated") # False | "auto" | "manual"
|
| 342 |
+
self.private = bool(info.get("private"))
|
| 343 |
+
self.tags: list[str] = list(info.get("tags") or [])
|
| 344 |
+
self.pipeline_tag = info.get("pipeline_tag")
|
| 345 |
+
self.last_modified = info.get("lastModified") or info.get("last_modified")
|
| 346 |
+
self.created_at = info.get("createdAt") or info.get("created_at")
|
| 347 |
+
self.downloads = info.get("downloads")
|
| 348 |
+
self.likes = info.get("likes")
|
| 349 |
+
self.files: list[str] = []
|
| 350 |
+
self.artifact_dirs: list[str] = []
|
| 351 |
+
self.benchmark_files: list[str] = []
|
| 352 |
+
self.root_meta: dict | None = None
|
| 353 |
+
self.artifact_meta: dict[str, dict] = {}
|
| 354 |
+
self.bench_docs: dict[str, dict] = {} # path -> parsed yaml
|
| 355 |
+
self.bench_errors: list[tuple] = [] # (path, status) for fetch/parse failures
|
| 356 |
+
self.content_blocked = False # gated/forbidden file contents
|
| 357 |
+
self.license = (tag_value(self.tags, "license:") or info.get("license"))
|
| 358 |
+
self.base_model = parse_base_model(self.tags, None)
|
| 359 |
+
self.format = detect_format(self.id, None)
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
def list_org_repos(client: Client, org: str, include_private: bool) -> list[str]:
|
| 363 |
+
data = client.get_json_pages(
|
| 364 |
+
f"{HF_BASE}/api/models", params={"author": org, "limit": 100}
|
| 365 |
+
)
|
| 366 |
+
ids = []
|
| 367 |
+
for m in data:
|
| 368 |
+
if not isinstance(m, dict):
|
| 369 |
+
warn(f"unexpected listing entry (not an object) skipped: {m!r:.80}")
|
| 370 |
+
continue
|
| 371 |
+
rid = m.get("id")
|
| 372 |
+
if not rid:
|
| 373 |
+
warn(f"listing entry without 'id' skipped: {m!r:.80}")
|
| 374 |
+
continue
|
| 375 |
+
if m.get("private") and not include_private:
|
| 376 |
+
continue
|
| 377 |
+
ids.append(rid)
|
| 378 |
+
return sorted(ids)
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
def fetch_tree(client: Client, repo: str) -> list[str]:
|
| 382 |
+
"""Recursive file list. Public even for gated repos."""
|
| 383 |
+
try:
|
| 384 |
+
tree = client.get_json(
|
| 385 |
+
f"{HF_BASE}/api/models/{repo}/tree/main", params={"recursive": "true"}
|
| 386 |
+
)
|
| 387 |
+
return [e["path"] for e in tree if e.get("type") == "file"]
|
| 388 |
+
except requests.HTTPError:
|
| 389 |
+
return []
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
def raw_url(repo: str, path: str) -> str:
|
| 393 |
+
return f"{HF_BASE}/{repo}/raw/main/{path}"
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
def fetch_yaml(client: Client, repo: str, path: str):
|
| 397 |
+
"""Return (parsed_dict_or_None, status)."""
|
| 398 |
+
text, status = client.get_text(raw_url(repo, path))
|
| 399 |
+
if status != "ok" or text is None:
|
| 400 |
+
return None, status
|
| 401 |
+
try:
|
| 402 |
+
doc = yaml.safe_load(text)
|
| 403 |
+
return (doc if isinstance(doc, dict) else {}), "ok"
|
| 404 |
+
except yaml.YAMLError:
|
| 405 |
+
return None, "error:yaml"
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
def gather_repo(client: Client, repo: str, verbose: bool) -> RepoData:
|
| 409 |
+
info = client.get_json(f"{HF_BASE}/api/models/{repo}")
|
| 410 |
+
rd = RepoData(info)
|
| 411 |
+
rd.files = fetch_tree(client, repo) or [
|
| 412 |
+
s.get("rfilename") for s in info.get("siblings", []) if s.get("rfilename")
|
| 413 |
+
]
|
| 414 |
+
rd.format = detect_format(repo, None)
|
| 415 |
+
|
| 416 |
+
# artifact dirs = top-level dirs that carry a `.metadata.yaml`
|
| 417 |
+
art_dirs: list[str] = []
|
| 418 |
+
for f in rd.files:
|
| 419 |
+
parts = f.split("/")
|
| 420 |
+
if len(parts) == 2 and parts[1] == ".metadata.yaml":
|
| 421 |
+
art_dirs.append(parts[0])
|
| 422 |
+
rd.artifact_dirs = sorted(set(art_dirs))
|
| 423 |
+
|
| 424 |
+
# benchmark files: <artifact>/benchmarks/<name>.yaml|yml
|
| 425 |
+
rd.benchmark_files = sorted(
|
| 426 |
+
f for f in rd.files if re.search(r"/benchmarks/[^/]+\.ya?ml$", f)
|
| 427 |
+
)
|
| 428 |
+
|
| 429 |
+
# root .metadata.yaml
|
| 430 |
+
if ".metadata.yaml" in rd.files:
|
| 431 |
+
doc, status = fetch_yaml(client, repo, ".metadata.yaml")
|
| 432 |
+
if status == "gated":
|
| 433 |
+
rd.content_blocked = True
|
| 434 |
+
rd.root_meta = doc
|
| 435 |
+
if doc:
|
| 436 |
+
rd.format = detect_format(repo, (doc.get("format") or {}).get("type"))
|
| 437 |
+
up = (doc.get("model") or {}).get("upstream")
|
| 438 |
+
if not rd.base_model:
|
| 439 |
+
rd.base_model = up
|
| 440 |
+
|
| 441 |
+
# per-artifact .metadata.yaml (optional enrichment)
|
| 442 |
+
for d in rd.artifact_dirs:
|
| 443 |
+
p = f"{d}/.metadata.yaml"
|
| 444 |
+
if p in rd.files:
|
| 445 |
+
doc, status = fetch_yaml(client, repo, p)
|
| 446 |
+
if status == "gated":
|
| 447 |
+
rd.content_blocked = True
|
| 448 |
+
if doc:
|
| 449 |
+
rd.artifact_meta[d] = doc
|
| 450 |
+
|
| 451 |
+
# benchmark docs
|
| 452 |
+
for bf in rd.benchmark_files:
|
| 453 |
+
doc, status = fetch_yaml(client, repo, bf)
|
| 454 |
+
if status == "gated":
|
| 455 |
+
rd.content_blocked = True
|
| 456 |
+
elif status not in ("ok", "missing"):
|
| 457 |
+
rd.bench_errors.append((bf, status))
|
| 458 |
+
warn(f"{repo}: could not read benchmark {bf} ({status})")
|
| 459 |
+
if doc:
|
| 460 |
+
rd.bench_docs[bf] = doc
|
| 461 |
+
|
| 462 |
+
# warn if we could not confidently determine the repo format
|
| 463 |
+
low = repo.lower()
|
| 464 |
+
mft = str(((rd.root_meta or {}).get("format") or {}).get("type", "")).lower()
|
| 465 |
+
if not any(tok in low or tok in mft for tok in ("onnx", "gguf")):
|
| 466 |
+
warn(f"{repo}: could not determine format; defaulting to {rd.format}. "
|
| 467 |
+
f"Add explicit handling if this is a new format.")
|
| 468 |
+
|
| 469 |
+
if verbose:
|
| 470 |
+
state = "gated/no-access" if rd.content_blocked else "readable"
|
| 471 |
+
print(
|
| 472 |
+
f" Β· {repo}: format={rd.format} artifacts={rd.artifact_dirs} "
|
| 473 |
+
f"benchmarks={len(rd.benchmark_files)} contents={state}"
|
| 474 |
+
)
|
| 475 |
+
return rd
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
# --------------------------------------------------------------------------- #
|
| 479 |
+
# Benchmark file -> hardware config / metric block #
|
| 480 |
+
# --------------------------------------------------------------------------- #
|
| 481 |
+
def parse_bench_path(path: str):
|
| 482 |
+
"""Return (artifact_dir, chip_token, ep_token) from the file path."""
|
| 483 |
+
parts = path.split("/")
|
| 484 |
+
artifact = parts[0]
|
| 485 |
+
base = re.sub(r"\.ya?ml$", "", parts[-1])
|
| 486 |
+
seg = base.split("_")
|
| 487 |
+
if len(seg) >= 2:
|
| 488 |
+
ep = seg[-1]
|
| 489 |
+
chip = "_".join(seg[:-1])
|
| 490 |
+
else:
|
| 491 |
+
ep = seg[-1]
|
| 492 |
+
chip = seg[-1]
|
| 493 |
+
return artifact, chip, ep
|
| 494 |
+
|
| 495 |
+
|
| 496 |
+
def build_metric_block(doc: dict, ep: str, kind: str, repo_date: str | None, chip_label: str):
|
| 497 |
+
hardware = doc.get("hardware") or {}
|
| 498 |
+
runtime = doc.get("runtime") or {}
|
| 499 |
+
perf = doc.get("performance") or {}
|
| 500 |
+
metrics = doc.get("metrics") or {}
|
| 501 |
+
memory = doc.get("memory") or {}
|
| 502 |
+
bench = doc.get("benchmark") or {}
|
| 503 |
+
|
| 504 |
+
ep_token = (runtime.get("execution_provider") or ep or "").lower()
|
| 505 |
+
unit_key, _target = EP_TO_UNIT.get(ep_token, ("npu", "NPU"))
|
| 506 |
+
|
| 507 |
+
tok = as_number(perf.get("tokens_per_sec"))
|
| 508 |
+
if tok is None:
|
| 509 |
+
tok = as_number(perf.get("tok_s"))
|
| 510 |
+
peak = as_number(memory.get("peak_mb"))
|
| 511 |
+
if peak is None:
|
| 512 |
+
peak = as_number(memory.get("peak_mem_mb"))
|
| 513 |
+
lat = as_number(perf.get("latency_ms_p50"))
|
| 514 |
+
acc = normalize_accuracy(metrics.get("accuracy"))
|
| 515 |
+
|
| 516 |
+
# Nothing measured -> no block (keeps null so the UI shows "β").
|
| 517 |
+
if tok is None and peak is None and lat is None and acc is None:
|
| 518 |
+
return None
|
| 519 |
+
|
| 520 |
+
unit = {"tok_s": tok, "latency_ms_p50": lat, "peak_mem_mb": peak}
|
| 521 |
+
block = {
|
| 522 |
+
"accuracy": acc,
|
| 523 |
+
unit_key: unit,
|
| 524 |
+
"total": {"tok_s": tok, "latency_ms_p50": lat, "peak_mem_mb": peak},
|
| 525 |
+
"engine": runtime.get("engine"),
|
| 526 |
+
"execution_provider": ep_token or None,
|
| 527 |
+
"last_updated": (repo_date or "")[:10] or None,
|
| 528 |
+
}
|
| 529 |
+
bs = ((bench.get("parameters") or {}).get("batch_size"))
|
| 530 |
+
if bs is not None:
|
| 531 |
+
block["batch_size"] = bs
|
| 532 |
+
if kind == "hil":
|
| 533 |
+
block["setup"] = chip_label
|
| 534 |
+
return block
|
| 535 |
+
|
| 536 |
+
|
| 537 |
+
# --------------------------------------------------------------------------- #
|
| 538 |
+
# Model assembly (group repos that are the same model in different formats) #
|
| 539 |
+
# --------------------------------------------------------------------------- #
|
| 540 |
+
def group_key(repo_id: str) -> str:
|
| 541 |
+
return strip_format_suffix(repo_id).lower()
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
def build_model(repos: list[RepoData], verbose: bool) -> tuple[dict, dict]:
|
| 545 |
+
"""Build one models.json entry from one or more repos (same model, diff formats)."""
|
| 546 |
+
# Identity: prefer a repo whose root metadata is readable.
|
| 547 |
+
primary = next((r for r in repos if r.root_meta), repos[0])
|
| 548 |
+
rm = primary.root_meta or {}
|
| 549 |
+
rm_model = rm.get("model") or {}
|
| 550 |
+
rm_arch = rm.get("architecture") or {}
|
| 551 |
+
|
| 552 |
+
base_model = next((r.base_model for r in repos if r.base_model), None)
|
| 553 |
+
name_src = base_model or short_name(primary.id)
|
| 554 |
+
short = short_name(name_src)
|
| 555 |
+
|
| 556 |
+
variant = detect_variant(short)
|
| 557 |
+
display_name = rm_model.get("display_name") or strip_format_suffix(short)
|
| 558 |
+
key = (rm_model.get("name") or strip_format_suffix(short)).lower()
|
| 559 |
+
key = re.sub(r"[^a-z0-9.]+", "-", key).strip("-.")
|
| 560 |
+
architecture = architecture_from(name_src, variant)
|
| 561 |
+
size_m = parse_size_m(rm_arch.get("parameters"), short, primary.id)
|
| 562 |
+
modality = map_modality(rm_arch.get("modality"), primary.tags, primary.pipeline_tag)
|
| 563 |
+
license_ = next((r.license for r in repos if r.license), None)
|
| 564 |
+
tasks = rm.get("tasks") if isinstance(rm.get("tasks"), list) else None
|
| 565 |
+
|
| 566 |
+
model = {
|
| 567 |
+
"key": key,
|
| 568 |
+
"display_name": display_name,
|
| 569 |
+
"architecture": architecture,
|
| 570 |
+
"model_size_m": size_m,
|
| 571 |
+
"modality": modality,
|
| 572 |
+
"variant": variant,
|
| 573 |
+
"targets": [],
|
| 574 |
+
"onnx_repo": "",
|
| 575 |
+
"gguf_repo": "",
|
| 576 |
+
"onnx_artifacts": [],
|
| 577 |
+
"gguf_artifacts": [],
|
| 578 |
+
"base_model": base_model,
|
| 579 |
+
"license": license_,
|
| 580 |
+
"tasks": tasks,
|
| 581 |
+
"created_at": min([r.created_at for r in repos if r.created_at], default=None),
|
| 582 |
+
"last_modified": max([r.last_modified for r in repos if r.last_modified], default=None),
|
| 583 |
+
"hardware_configs": [],
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
# Per-format repo + artifacts
|
| 587 |
+
all_artifacts: list[str] = []
|
| 588 |
+
for r in repos:
|
| 589 |
+
if r.format == "ONNX":
|
| 590 |
+
model["onnx_repo"] = r.id
|
| 591 |
+
model["onnx_artifacts"] = r.artifact_dirs
|
| 592 |
+
else: # GGUF (and any default)
|
| 593 |
+
model["gguf_repo"] = r.id
|
| 594 |
+
model["gguf_artifacts"] = r.artifact_dirs
|
| 595 |
+
all_artifacts.extend(r.artifact_dirs)
|
| 596 |
+
all_artifacts = list(dict.fromkeys(all_artifacts)) # de-dupe, keep order
|
| 597 |
+
|
| 598 |
+
# Hardware configs keyed by chip, with metrics.artifacts[<art>].{estimate,hil}
|
| 599 |
+
configs: dict[str, dict] = {}
|
| 600 |
+
targets_seen: set[str] = set()
|
| 601 |
+
stats = {"id": primary.id, "configs": 0, "metric_blocks": 0,
|
| 602 |
+
"content_blocked": any(r.content_blocked for r in repos),
|
| 603 |
+
"bench_files": sum(len(r.benchmark_files) for r in repos),
|
| 604 |
+
"bench_errors": sum(len(r.bench_errors) for r in repos)}
|
| 605 |
+
|
| 606 |
+
for r in repos:
|
| 607 |
+
for bf in r.benchmark_files:
|
| 608 |
+
artifact, chip_tok, ep_tok = parse_bench_path(bf)
|
| 609 |
+
doc = r.bench_docs.get(bf)
|
| 610 |
+
|
| 611 |
+
chip = ((doc or {}).get("hardware") or {}).get("chip") or chip_tok
|
| 612 |
+
cfg_id = normalize_chip_id(chip)
|
| 613 |
+
ep = (((doc or {}).get("runtime") or {}).get("execution_provider")
|
| 614 |
+
or ep_tok).lower()
|
| 615 |
+
if ep not in EP_TO_UNIT:
|
| 616 |
+
warn(f"{r.id}: unknown execution_provider '{ep}' in {bf}; "
|
| 617 |
+
f"attributing to NPU β add it to EP_TO_UNIT if that is wrong.")
|
| 618 |
+
unit_key, target = EP_TO_UNIT.get(ep, ("npu", "NPU"))
|
| 619 |
+
targets_seen.add(target)
|
| 620 |
+
|
| 621 |
+
if cfg_id not in configs:
|
| 622 |
+
npu = ((doc or {}).get("hardware") or {}).get("npu")
|
| 623 |
+
label = prettify_chip(chip) + (f" ({str(npu).upper()})" if npu else "")
|
| 624 |
+
configs[cfg_id] = {
|
| 625 |
+
"id": cfg_id,
|
| 626 |
+
"label": label,
|
| 627 |
+
"targets": set(),
|
| 628 |
+
"notes": _hw_notes((doc or {}).get("hardware") or {}),
|
| 629 |
+
"metrics": {"artifacts": {a: {"estimate": None, "hil": None}
|
| 630 |
+
for a in all_artifacts}},
|
| 631 |
+
}
|
| 632 |
+
cfg = configs[cfg_id]
|
| 633 |
+
cfg["targets"].add(target)
|
| 634 |
+
cfg["metrics"]["artifacts"].setdefault(
|
| 635 |
+
artifact, {"estimate": None, "hil": None}
|
| 636 |
+
)
|
| 637 |
+
|
| 638 |
+
if doc:
|
| 639 |
+
kind = block_kind_for((doc.get("benchmark") or {}).get("type"))
|
| 640 |
+
block = build_metric_block(doc, ep, kind, r.last_modified, cfg["label"])
|
| 641 |
+
if block:
|
| 642 |
+
cfg["metrics"]["artifacts"][artifact][kind] = block
|
| 643 |
+
stats["metric_blocks"] += 1
|
| 644 |
+
|
| 645 |
+
# finalize configs (sets -> sorted lists)
|
| 646 |
+
hw_configs = []
|
| 647 |
+
for cfg in configs.values():
|
| 648 |
+
cfg["targets"] = sorted(cfg["targets"])
|
| 649 |
+
hw_configs.append(cfg)
|
| 650 |
+
hw_configs.sort(key=lambda c: c["id"])
|
| 651 |
+
model["hardware_configs"] = hw_configs
|
| 652 |
+
model["targets"] = sorted(targets_seen)
|
| 653 |
+
stats["configs"] = len(hw_configs)
|
| 654 |
+
|
| 655 |
+
# The dashboard's table + Explore open on the FIRST artifact. Put artifacts that
|
| 656 |
+
# actually have measured metrics first (stable sort keeps upstream order otherwise),
|
| 657 |
+
# so the default view shows real numbers instead of an empty "β" row.
|
| 658 |
+
def _has_data(art: str) -> bool:
|
| 659 |
+
for cfg in hw_configs:
|
| 660 |
+
a = cfg["metrics"]["artifacts"].get(art) or {}
|
| 661 |
+
if a.get("estimate") or a.get("hil"):
|
| 662 |
+
return True
|
| 663 |
+
return False
|
| 664 |
+
|
| 665 |
+
model["gguf_artifacts"] = sorted(model["gguf_artifacts"], key=lambda a: 0 if _has_data(a) else 1)
|
| 666 |
+
model["onnx_artifacts"] = sorted(model["onnx_artifacts"], key=lambda a: 0 if _has_data(a) else 1)
|
| 667 |
+
|
| 668 |
+
if verbose:
|
| 669 |
+
print(f" -> model '{key}' ({display_name}): {len(hw_configs)} config(s), "
|
| 670 |
+
f"{stats['metric_blocks']} metric block(s)")
|
| 671 |
+
return model, stats
|
| 672 |
+
|
| 673 |
+
|
| 674 |
+
def _hw_notes(hardware: dict) -> str:
|
| 675 |
+
if not hardware:
|
| 676 |
+
return ""
|
| 677 |
+
bits = []
|
| 678 |
+
for k in ("vendor", "chip", "cpu", "npu", "memory_mb"):
|
| 679 |
+
v = hardware.get(k)
|
| 680 |
+
if v not in (None, ""):
|
| 681 |
+
bits.append(f"{k}={v}")
|
| 682 |
+
return "; ".join(bits)
|
| 683 |
+
|
| 684 |
+
|
| 685 |
+
# --------------------------------------------------------------------------- #
|
| 686 |
+
# Main #
|
| 687 |
+
# --------------------------------------------------------------------------- #
|
| 688 |
+
def build_catalog(client: Client, org: str, include_private: bool, verbose: bool):
|
| 689 |
+
print(f"Listing models for org '{org}' ...")
|
| 690 |
+
repo_ids = list_org_repos(client, org, include_private)
|
| 691 |
+
print(f"Found {len(repo_ids)} repo(s): {', '.join(repo_ids) or '(none)'}")
|
| 692 |
+
|
| 693 |
+
repos: list[RepoData] = []
|
| 694 |
+
for rid in repo_ids:
|
| 695 |
+
try:
|
| 696 |
+
repos.append(gather_repo(client, rid, verbose))
|
| 697 |
+
except requests.HTTPError as exc:
|
| 698 |
+
print(f" ! skipping {rid}: HTTP {exc.response.status_code if exc.response else '?'}")
|
| 699 |
+
except Exception as exc: # noqa: BLE001 (keep going on a single bad repo)
|
| 700 |
+
print(f" ! skipping {rid}: {exc}")
|
| 701 |
+
|
| 702 |
+
# group repos that are the same logical model in different formats
|
| 703 |
+
groups: dict[str, list[RepoData]] = {}
|
| 704 |
+
for r in repos:
|
| 705 |
+
groups.setdefault(group_key(r.id), []).append(r)
|
| 706 |
+
|
| 707 |
+
models, all_stats = [], []
|
| 708 |
+
for gkey in sorted(groups):
|
| 709 |
+
model, stats = build_model(groups[gkey], verbose)
|
| 710 |
+
models.append(model)
|
| 711 |
+
all_stats.append(stats)
|
| 712 |
+
models.sort(key=lambda m: (m.get("model_size_m") or 0, m["key"]))
|
| 713 |
+
|
| 714 |
+
# guarantee unique keys β app.js builds KEY_TO_MODEL keyed by `key`, so a
|
| 715 |
+
# collision would silently drop a model from the dashboard.
|
| 716 |
+
seen: dict[str, int] = {}
|
| 717 |
+
for m in models:
|
| 718 |
+
base = m["key"] or "model"
|
| 719 |
+
key = base
|
| 720 |
+
while key in seen:
|
| 721 |
+
seen[base] = seen.get(base, 1) + 1
|
| 722 |
+
key = f"{base}-{seen[base]}"
|
| 723 |
+
if key != m["key"]:
|
| 724 |
+
warn(f"duplicate model key '{m['key']}' -> '{key}' (renamed to avoid collision)")
|
| 725 |
+
seen[key] = 1
|
| 726 |
+
m["key"] = key
|
| 727 |
+
return models, all_stats
|
| 728 |
+
|
| 729 |
+
|
| 730 |
+
def main(argv=None):
|
| 731 |
+
parser = argparse.ArgumentParser(description=__doc__,
|
| 732 |
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
| 733 |
+
parser.add_argument("--org", default=DEFAULT_ORG, help="HF org/owner (default: Renesas)")
|
| 734 |
+
parser.add_argument("--output", "-o", default=str(Path(__file__).with_name("models.json")),
|
| 735 |
+
help="output path (default: ./models.json next to this script)")
|
| 736 |
+
parser.add_argument("--token", default=None, help="HF token (else env / cached login)")
|
| 737 |
+
parser.add_argument("--include-private", action="store_true",
|
| 738 |
+
help="also include private repos (requires token with access)")
|
| 739 |
+
parser.add_argument("--dry-run", action="store_true", help="print JSON, do not write")
|
| 740 |
+
parser.add_argument("--force", action="store_true",
|
| 741 |
+
help="write even if 0 models were produced (overwrites existing file)")
|
| 742 |
+
parser.add_argument("--verbose", "-v", action="store_true")
|
| 743 |
+
args = parser.parse_args(argv)
|
| 744 |
+
|
| 745 |
+
token = resolve_token(args.token)
|
| 746 |
+
print(f"Auth: {'token present' if token else 'anonymous (gated repo metrics will be skipped)'}")
|
| 747 |
+
client = Client(token, verbose=args.verbose)
|
| 748 |
+
|
| 749 |
+
# Top-level network guard: a failure on the initial listing must not dump a
|
| 750 |
+
# raw traceback on the admin β report it and exit with a distinct code.
|
| 751 |
+
try:
|
| 752 |
+
models, stats = build_catalog(client, args.org, args.include_private, args.verbose)
|
| 753 |
+
except requests.HTTPError as exc:
|
| 754 |
+
code = exc.response.status_code if exc.response is not None else "?"
|
| 755 |
+
print(f"ERROR: Hugging Face API returned HTTP {code} while listing org '{args.org}' "
|
| 756 |
+
f"(rate-limited or unavailable). Try again later.", file=sys.stderr)
|
| 757 |
+
return 2
|
| 758 |
+
except requests.RequestException as exc:
|
| 759 |
+
print(f"ERROR: could not reach {HF_BASE} (network / DNS / proxy): {exc}", file=sys.stderr)
|
| 760 |
+
return 2
|
| 761 |
+
except RuntimeError as exc: # e.g. non-JSON response from a proxy/interstitial
|
| 762 |
+
print(f"ERROR: {exc}", file=sys.stderr)
|
| 763 |
+
return 2
|
| 764 |
+
|
| 765 |
+
now = _dt.datetime.now().astimezone()
|
| 766 |
+
gated_skipped = [s["id"] for s in stats if s["content_blocked"] and s["metric_blocks"] == 0]
|
| 767 |
+
note = (
|
| 768 |
+
f"Auto-generated from Hugging Face '{args.org}' repositories on "
|
| 769 |
+
f"{now.strftime('%Y-%m-%d %H:%M %Z')}. Metrics reflect each repo's published "
|
| 770 |
+
f"benchmark YAML files."
|
| 771 |
+
)
|
| 772 |
+
if gated_skipped:
|
| 773 |
+
reason = ("token not authorized for these repos" if token
|
| 774 |
+
else "no authorized token β re-run with --token")
|
| 775 |
+
note += (f" Benchmark metrics for gated repo(s) were not imported "
|
| 776 |
+
f"({reason}): {', '.join(gated_skipped)}.")
|
| 777 |
+
|
| 778 |
+
catalog = {
|
| 779 |
+
"version": "1.0-auto",
|
| 780 |
+
"generated_at": now.isoformat(timespec="seconds"),
|
| 781 |
+
"source": "huggingface",
|
| 782 |
+
"org": args.org,
|
| 783 |
+
"catalog_note": note,
|
| 784 |
+
"models": models,
|
| 785 |
+
}
|
| 786 |
+
|
| 787 |
+
payload = json.dumps(catalog, indent=2, ensure_ascii=False)
|
| 788 |
+
|
| 789 |
+
# ---- summary ----
|
| 790 |
+
print("\nSummary")
|
| 791 |
+
print("-------")
|
| 792 |
+
for s in stats:
|
| 793 |
+
flag = ""
|
| 794 |
+
if s["content_blocked"] and s["metric_blocks"] == 0:
|
| 795 |
+
flag = (" [gated: token lacks access β request access on HF]" if token
|
| 796 |
+
else " [gated: metrics skipped β provide --token]")
|
| 797 |
+
elif s["content_blocked"]:
|
| 798 |
+
flag = " [gated: imported with token]"
|
| 799 |
+
print(f" {s['id']}: {s['configs']} config(s), {s['metric_blocks']} metric block(s){flag}")
|
| 800 |
+
if s["bench_errors"]:
|
| 801 |
+
print(f" ! {s['bench_errors']} benchmark file(s) failed to parse/fetch "
|
| 802 |
+
f"(see warnings above) β those metrics were not imported")
|
| 803 |
+
elif not s["content_blocked"] and s["bench_files"] > s["metric_blocks"]:
|
| 804 |
+
missing = s["bench_files"] - s["metric_blocks"]
|
| 805 |
+
print(f" note: {missing} benchmark file(s) had no recognized metric values")
|
| 806 |
+
print(f"\n{len(models)} model(s) total.")
|
| 807 |
+
if gated_skipped and not token:
|
| 808 |
+
print("Tip: pass --token (or set HF_TOKEN / run `huggingface-cli login`) "
|
| 809 |
+
"to import gated repos' benchmark numbers.")
|
| 810 |
+
|
| 811 |
+
if args.dry_run:
|
| 812 |
+
print("\n--dry-run: not writing file. JSON follows:\n")
|
| 813 |
+
print(payload)
|
| 814 |
+
return 0
|
| 815 |
+
|
| 816 |
+
out = Path(args.output)
|
| 817 |
+
if not models and not args.force:
|
| 818 |
+
if out.exists():
|
| 819 |
+
print(f"\nERROR: produced 0 models; refusing to overwrite existing {out} "
|
| 820 |
+
f"(use --force to override).", file=sys.stderr)
|
| 821 |
+
return 4
|
| 822 |
+
warn("produced 0 models β writing an empty catalog (no existing file to protect)")
|
| 823 |
+
|
| 824 |
+
# Atomic write: write a sibling temp file then replace, so an interrupted or
|
| 825 |
+
# failed write never leaves the live models.json truncated.
|
| 826 |
+
tmp = out.with_name(out.name + ".tmp")
|
| 827 |
+
try:
|
| 828 |
+
tmp.write_text(payload + "\n", encoding="utf-8")
|
| 829 |
+
os.replace(tmp, out)
|
| 830 |
+
except OSError as exc:
|
| 831 |
+
print(f"\nERROR: could not write {out}: {exc}", file=sys.stderr)
|
| 832 |
+
try:
|
| 833 |
+
tmp.unlink(missing_ok=True)
|
| 834 |
+
except OSError:
|
| 835 |
+
pass
|
| 836 |
+
return 3
|
| 837 |
+
print(f"\nWrote {out} ({len(payload)} bytes)")
|
| 838 |
+
return 0
|
| 839 |
+
|
| 840 |
+
|
| 841 |
+
if __name__ == "__main__":
|
| 842 |
+
raise SystemExit(main())
|
index.html
CHANGED
|
@@ -3,153 +3,258 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="utf-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 6 |
-
<title>Renesas AI
|
|
|
|
|
|
|
|
|
|
| 7 |
<link rel="stylesheet" href="styles.css" />
|
| 8 |
</head>
|
| 9 |
|
| 10 |
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
<header class="topbar" role="banner">
|
| 12 |
<div class="topbar-inner">
|
| 13 |
-
<div class="brand" aria-label="Renesas AI
|
| 14 |
-
<img class="brand-icon" src="assets/
|
|
|
|
| 15 |
<div class="brand-text">
|
| 16 |
-
<div class="brand-title">AI
|
| 17 |
-
<div class="brand-subtitle">
|
| 18 |
</div>
|
| 19 |
</div>
|
| 20 |
|
| 21 |
-
<nav class="tabs" role="navigation" aria-label="Primary">
|
| 22 |
-
<button class="nav-item active" data-target="sec-
|
| 23 |
-
<button class="nav-item" data-target="sec-
|
|
|
|
| 24 |
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
</div>
|
| 26 |
</header>
|
| 27 |
|
| 28 |
<main class="content" role="main">
|
| 29 |
|
| 30 |
-
<!--
|
| 31 |
-
<section id="sec-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
<label class="field">
|
| 39 |
-
<span class="label">Architecture</span>
|
| 40 |
-
<select id="arch" class="filter-select"></select>
|
| 41 |
-
</label>
|
| 42 |
-
|
| 43 |
-
<label class="field">
|
| 44 |
-
<span class="label">Modality</span>
|
| 45 |
-
<div class="radio-row" id="modality"></div>
|
| 46 |
-
</label>
|
| 47 |
-
|
| 48 |
-
<label class="field">
|
| 49 |
-
<span class="label">Purpose</span>
|
| 50 |
-
<div class="radio-col" id="purpose"></div>
|
| 51 |
-
</label>
|
| 52 |
-
|
| 53 |
-
<div class="field-row two">
|
| 54 |
-
<label class="field">
|
| 55 |
-
<span class="label">Format</span>
|
| 56 |
-
<div class="radio-row" id="fmt"></div>
|
| 57 |
-
</label>
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
</div>
|
| 79 |
</div>
|
| 80 |
</div>
|
| 81 |
|
| 82 |
-
<div class="card">
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
<div
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
</div>
|
| 87 |
</div>
|
| 88 |
</div>
|
| 89 |
</section>
|
| 90 |
|
| 91 |
-
<!--
|
| 92 |
-
<section id="sec-
|
| 93 |
-
<div class="section-scroll">
|
| 94 |
<div class="section-head">
|
| 95 |
-
<h1 class="section-title">
|
| 96 |
-
<p class="subtle tight">
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
| 99 |
</div>
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
|
|
|
| 112 |
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
|
|
|
| 133 |
|
| 134 |
-
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
<
|
| 141 |
-
|
|
|
|
| 142 |
</div>
|
| 143 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
</div>
|
| 145 |
-
</div>
|
| 146 |
</section>
|
| 147 |
|
| 148 |
</main>
|
| 149 |
|
| 150 |
-
<
|
| 151 |
-
|
| 152 |
-
<!-- Model details modal (All Models -> Details) -->
|
| 153 |
<div id="modelModal" class="modal" aria-hidden="true" role="dialog" aria-label="Model details">
|
| 154 |
<div class="modal-backdrop" data-modal-close="1"></div>
|
| 155 |
<div class="modal-panel" role="document">
|
|
@@ -164,6 +269,120 @@
|
|
| 164 |
</div>
|
| 165 |
</div>
|
| 166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
<script src="app.js" defer></script>
|
| 168 |
</body>
|
| 169 |
</html>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="utf-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 6 |
+
<title>Renesas AI Models</title>
|
| 7 |
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
| 8 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
| 9 |
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo+Narrow:wght@400;500;600;700&display=swap" />
|
| 10 |
<link rel="stylesheet" href="styles.css" />
|
| 11 |
</head>
|
| 12 |
|
| 13 |
<body>
|
| 14 |
+
<div class="bg-fx" aria-hidden="true">
|
| 15 |
+
<canvas id="bgfx"></canvas>
|
| 16 |
+
<span class="blob b1"></span>
|
| 17 |
+
<span class="blob b2"></span>
|
| 18 |
+
</div>
|
| 19 |
<header class="topbar" role="banner">
|
| 20 |
<div class="topbar-inner">
|
| 21 |
+
<div class="brand" aria-label="Renesas AI Models">
|
| 22 |
+
<img class="brand-icon" src="assets/logo_renesas_blue.svg" alt="Renesas" onerror="this.style.display='none'"/>
|
| 23 |
+
<span class="brand-divider" aria-hidden="true"></span>
|
| 24 |
<div class="brand-text">
|
| 25 |
+
<div class="brand-title">AI Models</div>
|
| 26 |
+
<div class="brand-subtitle">Model Explorer</div>
|
| 27 |
</div>
|
| 28 |
</div>
|
| 29 |
|
| 30 |
+
<nav class="tabs" role="navigation" aria-label="Primary" id="primaryNav">
|
| 31 |
+
<button class="nav-item active" data-target="sec-overview" type="button">Overview</button>
|
| 32 |
+
<button class="nav-item" data-target="sec-catalog" type="button">Catalog</button>
|
| 33 |
+
<button class="nav-item" data-target="sec-explore" type="button">Deploy</button>
|
| 34 |
</nav>
|
| 35 |
+
|
| 36 |
+
<button class="nav-burger" id="navBurger" type="button" aria-label="Open menu" aria-expanded="false" aria-controls="primaryNav">
|
| 37 |
+
<span></span><span></span><span></span>
|
| 38 |
+
</button>
|
| 39 |
</div>
|
| 40 |
</header>
|
| 41 |
|
| 42 |
<main class="content" role="main">
|
| 43 |
|
| 44 |
+
<!-- ===================== OVERVIEW (constellation) ===================== -->
|
| 45 |
+
<section id="sec-overview" class="section visible">
|
| 46 |
+
<section class="carousel-section featured" id="recentSection" hidden>
|
| 47 |
+
<div class="carousel-head">
|
| 48 |
+
<h2 class="carousel-title">Last Update</h2>
|
| 49 |
+
<div class="carousel-actions">
|
| 50 |
+
<span class="carousel-sub" id="recentSub"></span>
|
| 51 |
+
<button class="carousel-nav" id="recentPrev" type="button" aria-label="Scroll left">βΉ</button>
|
| 52 |
+
<button class="carousel-nav" id="recentNext" type="button" aria-label="Scroll right">βΊ</button>
|
| 53 |
+
</div>
|
| 54 |
+
</div>
|
| 55 |
+
<div class="carousel-track" id="recentTrack"></div>
|
| 56 |
+
</section>
|
| 57 |
|
| 58 |
+
<div class="stat-tiles" id="statTiles"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
<div class="card constellation-card">
|
| 61 |
+
<div class="card-head">
|
| 62 |
+
<h2 class="card-head-title">Model constellation</h2>
|
| 63 |
+
<p class="subtle tight" style="margin:0;">Every model and quantization plotted by throughput and size. Bubble size β parameters. Click a point for details.</p>
|
| 64 |
+
</div>
|
| 65 |
+
<button class="filter-toggle" type="button" data-target="cstlControls" id="cstlFilterToggle" aria-controls="cstlControls" aria-expanded="false">
|
| 66 |
+
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path d="M1.5 3h13M3.5 8h9M6 13h4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
| 67 |
+
<span>Chart filters</span>
|
| 68 |
+
<svg class="ft-chevron" viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.7" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 69 |
+
</button>
|
| 70 |
+
<div class="cstl-controls" id="cstlControls">
|
| 71 |
+
<label class="field compact">
|
| 72 |
+
<span class="label">X axis</span>
|
| 73 |
+
<select id="cstlX" class="filter-select compact">
|
| 74 |
+
<option value="tok">Throughput (tok/s)</option>
|
| 75 |
+
<option value="size">Model size (params)</option>
|
| 76 |
+
</select>
|
| 77 |
+
</label>
|
| 78 |
+
<label class="field compact">
|
| 79 |
+
<span class="label">Y axis</span>
|
| 80 |
+
<select id="cstlY" class="filter-select compact">
|
| 81 |
+
<option value="size">Model size (params)</option>
|
| 82 |
+
<option value="tok">Throughput (tok/s)</option>
|
| 83 |
+
</select>
|
| 84 |
+
</label>
|
| 85 |
+
<label class="field compact">
|
| 86 |
+
<span class="label">Color by</span>
|
| 87 |
+
<select id="cstlColor" class="filter-select compact">
|
| 88 |
+
<option value="family">Family</option>
|
| 89 |
+
<option value="quant">Quantization</option>
|
| 90 |
+
<option value="format">Format</option>
|
| 91 |
+
<option value="target">Target</option>
|
| 92 |
+
</select>
|
| 93 |
+
</label>
|
| 94 |
+
<div class="field compact">
|
| 95 |
+
<span class="label">Source</span>
|
| 96 |
+
<div class="radio-row" id="cstlSource"></div>
|
| 97 |
+
</div>
|
| 98 |
+
</div>
|
| 99 |
|
| 100 |
+
<div class="constellation">
|
| 101 |
+
<canvas id="cstlCanvas"></canvas>
|
| 102 |
+
<div id="cstlTooltip" class="mini-tooltip"></div>
|
| 103 |
+
</div>
|
| 104 |
+
<div class="cstl-foot">
|
| 105 |
+
<div id="cstlLegend" class="legend"></div>
|
| 106 |
+
<div id="cstlStatus" class="subtle tight"></div>
|
| 107 |
+
</div>
|
| 108 |
+
</div>
|
| 109 |
+
</section>
|
| 110 |
|
| 111 |
+
<!-- ===================== CATALOG (cards + table) ===================== -->
|
| 112 |
+
<section id="sec-catalog" class="section">
|
| 113 |
+
<div class="catalog-layout">
|
| 114 |
+
<aside class="facets" aria-label="Filters">
|
| 115 |
+
<div class="facets-head">
|
| 116 |
+
<button class="filter-toggle" type="button" data-target="facetsBody" aria-controls="facetsBody" aria-expanded="false">
|
| 117 |
+
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path d="M1.5 3h13M3.5 8h9M6 13h4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
| 118 |
+
<span>Filters</span>
|
| 119 |
+
<svg class="ft-chevron" viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.7" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 120 |
+
</button>
|
| 121 |
+
<span class="facets-title">Filters</span>
|
| 122 |
+
<button class="link-btn" id="cgReset" type="button">Reset</button>
|
| 123 |
+
</div>
|
| 124 |
+
<div class="facets-body" id="facetsBody">
|
| 125 |
+
<label class="field">
|
| 126 |
+
<span class="label">Search</span>
|
| 127 |
+
<input id="cgSearch" class="filter-input" placeholder="Search modelsβ¦" />
|
| 128 |
+
</label>
|
| 129 |
+
<label class="field">
|
| 130 |
+
<span class="label">Sort</span>
|
| 131 |
+
<select id="cgSort" class="filter-select">
|
| 132 |
+
<option value="size_desc">Largest first</option>
|
| 133 |
+
<option value="size_asc">Smallest first</option>
|
| 134 |
+
<option value="tok_desc">Fastest (tok/s)</option>
|
| 135 |
+
<option value="name_asc">Name AβZ</option>
|
| 136 |
+
</select>
|
| 137 |
+
</label>
|
| 138 |
+
<div id="cgFacets" class="facet-groups"></div>
|
| 139 |
+
</div>
|
| 140 |
+
</aside>
|
| 141 |
|
| 142 |
+
<div class="catalog-main">
|
| 143 |
+
<div class="toolbar">
|
| 144 |
+
<div class="toolbar-count" id="cgCount"></div>
|
| 145 |
+
<div class="view-toggle" role="tablist" aria-label="View">
|
| 146 |
+
<button id="cgViewGrid" class="view-btn active" type="button" aria-pressed="true">β¦ Grid</button>
|
| 147 |
+
<button id="cgViewTable" class="view-btn" type="button" aria-pressed="false">β€ Table</button>
|
|
|
|
| 148 |
</div>
|
| 149 |
</div>
|
| 150 |
|
| 151 |
+
<div id="cardGrid" class="card-grid"></div>
|
| 152 |
+
|
| 153 |
+
<div id="tableView" class="table-view" hidden>
|
| 154 |
+
<div class="table-shell">
|
| 155 |
+
<div class="table-wrap">
|
| 156 |
+
<table class="table" id="modelsTable" aria-label="Models table">
|
| 157 |
+
<thead></thead>
|
| 158 |
+
<tbody></tbody>
|
| 159 |
+
</table>
|
| 160 |
+
</div>
|
| 161 |
+
</div>
|
| 162 |
</div>
|
| 163 |
</div>
|
| 164 |
</div>
|
| 165 |
</section>
|
| 166 |
|
| 167 |
+
<!-- ===================== EXPLORE (routing / download tool) ===================== -->
|
| 168 |
+
<section id="sec-explore" class="section">
|
|
|
|
| 169 |
<div class="section-head">
|
| 170 |
+
<h1 class="section-title">Configure & deploy</h1>
|
| 171 |
+
<p class="subtle tight">Set your format, target and hardware, pick a matching model, then copy the exact download command and open its benchmark tool.</p>
|
| 172 |
+
<ol class="deploy-steps">
|
| 173 |
+
<li><span class="ds-num">1</span><span class="ds-txt">Set constraints</span></li>
|
| 174 |
+
<li><span class="ds-num">2</span><span class="ds-txt">Pick a model</span></li>
|
| 175 |
+
<li><span class="ds-num">3</span><span class="ds-txt">Copy & run</span></li>
|
| 176 |
+
</ol>
|
| 177 |
</div>
|
| 178 |
+
<div class="grid explore-grid">
|
| 179 |
+
<div class="card">
|
| 180 |
+
<h3 class="no-border">Configure</h3>
|
| 181 |
|
| 182 |
+
<div class="form-grid explore-form">
|
| 183 |
+
<button class="filter-toggle" type="button" data-target="exploreFilters" aria-controls="exploreFilters" aria-expanded="false">
|
| 184 |
+
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path d="M1.5 3h13M3.5 8h9M6 13h4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
| 185 |
+
<span>Filters</span>
|
| 186 |
+
<svg class="ft-chevron" viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.7" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 187 |
+
</button>
|
| 188 |
+
<div class="explore-filters" id="exploreFilters">
|
| 189 |
+
<!-- Primary tier: always visible -->
|
| 190 |
+
<label class="field compact">
|
| 191 |
+
<span class="label">Architecture</span>
|
| 192 |
+
<select id="arch" class="filter-select compact"></select>
|
| 193 |
+
</label>
|
| 194 |
|
| 195 |
+
<div class="field-row two">
|
| 196 |
+
<label class="field compact">
|
| 197 |
+
<span class="label">Modality</span>
|
| 198 |
+
<div class="radio-row" id="modality"></div>
|
| 199 |
+
</label>
|
| 200 |
+
<label class="field compact">
|
| 201 |
+
<span class="label">Format</span>
|
| 202 |
+
<div class="radio-row" id="fmt"></div>
|
| 203 |
+
</label>
|
| 204 |
+
</div>
|
| 205 |
|
| 206 |
+
<!-- Reveal toggle for secondary filters (reuses the generic
|
| 207 |
+
delegated .filter-toggle handler below β no JS change) -->
|
| 208 |
+
<button class="filter-toggle filter-toggle--inline" type="button"
|
| 209 |
+
data-target="exploreAdvanced" aria-controls="exploreAdvanced" aria-expanded="false">
|
| 210 |
+
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path d="M2.5 5h11M4.5 8h7M6.5 11h3" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
|
| 211 |
+
<span>Advanced</span>
|
| 212 |
+
<svg class="ft-chevron" viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.7" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 213 |
+
</button>
|
| 214 |
|
| 215 |
+
<!-- Secondary tier: collapsed by default on desktop, one click to reveal -->
|
| 216 |
+
<div class="explore-advanced" id="exploreAdvanced">
|
| 217 |
+
<div class="field-row two">
|
| 218 |
+
<label class="field compact">
|
| 219 |
+
<span class="label">Compute Target</span>
|
| 220 |
+
<div class="radio-row" id="compute"></div>
|
| 221 |
+
</label>
|
| 222 |
+
<label class="field compact">
|
| 223 |
+
<span class="label">Hardware Config</span>
|
| 224 |
+
<select id="hwCfg" class="filter-select compact"></select>
|
| 225 |
+
</label>
|
| 226 |
+
</div>
|
| 227 |
|
| 228 |
+
<label class="field compact">
|
| 229 |
+
<span class="label">Purpose</span>
|
| 230 |
+
<div class="radio-row" id="purpose"></div>
|
| 231 |
+
</label>
|
| 232 |
+
</div>
|
| 233 |
+
</div>
|
| 234 |
|
| 235 |
+
<div class="matchline" id="matchCount"></div>
|
| 236 |
|
| 237 |
+
<div class="model-picker">
|
| 238 |
+
<div class="model-picker-head">
|
| 239 |
+
<div class="model-picker-title">Model</div>
|
| 240 |
+
<div class="model-picker-subtle" id="modelCountHint"></div>
|
| 241 |
+
</div>
|
| 242 |
+
<select id="modelKey" class="filter-select model-list" size="12"></select>
|
| 243 |
+
</div>
|
| 244 |
</div>
|
| 245 |
</div>
|
| 246 |
+
|
| 247 |
+
<div class="card result-card">
|
| 248 |
+
<div id="warning" class="note note-warn" style="display:none"></div>
|
| 249 |
+
<div id="details"></div>
|
| 250 |
+
<div id="actions"></div>
|
| 251 |
+
</div>
|
| 252 |
</div>
|
|
|
|
| 253 |
</section>
|
| 254 |
|
| 255 |
</main>
|
| 256 |
|
| 257 |
+
<!-- Model details modal -->
|
|
|
|
|
|
|
| 258 |
<div id="modelModal" class="modal" aria-hidden="true" role="dialog" aria-label="Model details">
|
| 259 |
<div class="modal-backdrop" data-modal-close="1"></div>
|
| 260 |
<div class="modal-panel" role="document">
|
|
|
|
| 269 |
</div>
|
| 270 |
</div>
|
| 271 |
|
| 272 |
+
<script>
|
| 273 |
+
/* Brand network-mesh background β inspired by the Renesas circuit-network artwork:
|
| 274 |
+
a faint blueprint grid, then a constellation of nodes (small dots + larger glowing
|
| 275 |
+
hubs) connected by hairlines, tinted on a leftβright blueβviolet gradient. */
|
| 276 |
+
(function () {
|
| 277 |
+
var c = document.getElementById("bgfx");
|
| 278 |
+
if (!c) return;
|
| 279 |
+
var ctx = c.getContext("2d");
|
| 280 |
+
var w = 0, h = 0, dpr = 1, nodes = [], N = 0, LINK = 168, raf = 0;
|
| 281 |
+
var reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
| 282 |
+
|
| 283 |
+
/* gradient stops: cool blue (left) -> Renesas blue -> violet (right) */
|
| 284 |
+
var C0 = [67, 171, 226], C1 = [42, 40, 157], C2 = [150, 104, 214];
|
| 285 |
+
function lerp(a, b, t) { return [a[0]+(b[0]-a[0])*t, a[1]+(b[1]-a[1])*t, a[2]+(b[2]-a[2])*t]; }
|
| 286 |
+
function tint(t) { return t < 0.5 ? lerp(C0, C1, t * 2) : lerp(C1, C2, (t - 0.5) * 2); }
|
| 287 |
+
function rgba(c, a) { return "rgba(" + (c[0]|0) + "," + (c[1]|0) + "," + (c[2]|0) + "," + a + ")"; }
|
| 288 |
+
|
| 289 |
+
function resize() {
|
| 290 |
+
dpr = Math.min(window.devicePixelRatio || 1, 2);
|
| 291 |
+
w = c.clientWidth; h = c.clientHeight;
|
| 292 |
+
c.width = Math.max(1, Math.floor(w * dpr));
|
| 293 |
+
c.height = Math.max(1, Math.floor(h * dpr));
|
| 294 |
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
| 295 |
+
}
|
| 296 |
+
function seed() {
|
| 297 |
+
N = Math.max(40, Math.min(110, Math.round((w * h) / 14000)));
|
| 298 |
+
nodes = [];
|
| 299 |
+
for (var i = 0; i < N; i++) {
|
| 300 |
+
var hub = Math.random() < 0.14;
|
| 301 |
+
nodes.push({
|
| 302 |
+
x: Math.random() * w, y: Math.random() * h,
|
| 303 |
+
vx: (Math.random() - 0.5) * 0.20, vy: (Math.random() - 0.5) * 0.20,
|
| 304 |
+
hub: hub, r: hub ? 3.2 + Math.random() * 3.4 : 1.0 + Math.random() * 1.6
|
| 305 |
+
});
|
| 306 |
+
}
|
| 307 |
+
}
|
| 308 |
+
function grid() {
|
| 309 |
+
var step = 44, g = "rgba(67,140,210,0.06)";
|
| 310 |
+
ctx.lineWidth = 1; ctx.strokeStyle = g; ctx.beginPath();
|
| 311 |
+
for (var x = 0; x <= w; x += step) { ctx.moveTo(x, 0); ctx.lineTo(x, h); }
|
| 312 |
+
for (var y = 0; y <= h; y += step) { ctx.moveTo(0, y); ctx.lineTo(w, y); }
|
| 313 |
+
ctx.stroke();
|
| 314 |
+
}
|
| 315 |
+
function draw(step) {
|
| 316 |
+
ctx.clearRect(0, 0, w, h);
|
| 317 |
+
grid();
|
| 318 |
+
if (step) for (var k = 0; k < N; k++) {
|
| 319 |
+
var n = nodes[k]; n.x += n.vx; n.y += n.vy;
|
| 320 |
+
if (n.x < 0 || n.x > w) n.vx *= -1; if (n.y < 0 || n.y > h) n.vy *= -1;
|
| 321 |
+
}
|
| 322 |
+
/* links */
|
| 323 |
+
for (var i = 0; i < N; i++) for (var j = i + 1; j < N; j++) {
|
| 324 |
+
var a = nodes[i], b = nodes[j], dx = a.x - b.x, dy = a.y - b.y, d = Math.sqrt(dx * dx + dy * dy);
|
| 325 |
+
if (d < LINK) {
|
| 326 |
+
var mid = ((a.x + b.x) / 2) / w;
|
| 327 |
+
ctx.strokeStyle = rgba(tint(mid), ((1 - d / LINK) * 0.16).toFixed(3));
|
| 328 |
+
ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.stroke();
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
/* nodes */
|
| 332 |
+
for (var m = 0; m < N; m++) {
|
| 333 |
+
var p = nodes[m], col = tint(p.x / w);
|
| 334 |
+
if (p.hub) {
|
| 335 |
+
var halo = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 4.5);
|
| 336 |
+
halo.addColorStop(0, rgba(col, 0.28)); halo.addColorStop(1, rgba(col, 0));
|
| 337 |
+
ctx.fillStyle = halo; ctx.beginPath(); ctx.arc(p.x, p.y, p.r * 4.5, 0, Math.PI * 2); ctx.fill();
|
| 338 |
+
}
|
| 339 |
+
ctx.fillStyle = rgba(col, p.hub ? 0.85 : 0.5);
|
| 340 |
+
ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.fill();
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
function tick() { draw(true); raf = requestAnimationFrame(tick); }
|
| 344 |
+
function start() { resize(); seed(); if (raf) cancelAnimationFrame(raf); if (reduce) draw(false); else tick(); }
|
| 345 |
+
window.addEventListener("resize", function () { resize(); seed(); if (reduce) draw(false); });
|
| 346 |
+
start();
|
| 347 |
+
})();
|
| 348 |
+
</script>
|
| 349 |
+
<script>
|
| 350 |
+
/* Mobile nav: burger toggles the menu; selecting an item closes it. */
|
| 351 |
+
(function () {
|
| 352 |
+
var burger = document.getElementById("navBurger");
|
| 353 |
+
var nav = document.getElementById("primaryNav");
|
| 354 |
+
if (!burger || !nav) return;
|
| 355 |
+
function setOpen(open) {
|
| 356 |
+
nav.classList.toggle("open", open);
|
| 357 |
+
burger.classList.toggle("active", open);
|
| 358 |
+
burger.setAttribute("aria-expanded", open ? "true" : "false");
|
| 359 |
+
}
|
| 360 |
+
burger.addEventListener("click", function (e) {
|
| 361 |
+
e.stopPropagation();
|
| 362 |
+
setOpen(!nav.classList.contains("open"));
|
| 363 |
+
});
|
| 364 |
+
nav.addEventListener("click", function (e) {
|
| 365 |
+
if (e.target.closest(".nav-item")) setOpen(false);
|
| 366 |
+
});
|
| 367 |
+
document.addEventListener("click", function (e) {
|
| 368 |
+
if (nav.classList.contains("open") && !nav.contains(e.target) && e.target !== burger) setOpen(false);
|
| 369 |
+
});
|
| 370 |
+
})();
|
| 371 |
+
</script>
|
| 372 |
+
<script>
|
| 373 |
+
/* Collapsible filter clusters (phone): a "Filters" button toggles each group. */
|
| 374 |
+
(function () {
|
| 375 |
+
document.addEventListener("click", function (e) {
|
| 376 |
+
var btn = e.target.closest(".filter-toggle");
|
| 377 |
+
if (!btn) return;
|
| 378 |
+
var t = document.getElementById(btn.getAttribute("data-target"));
|
| 379 |
+
if (!t) return;
|
| 380 |
+
var open = t.classList.toggle("open");
|
| 381 |
+
btn.classList.toggle("active", open);
|
| 382 |
+
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
| 383 |
+
});
|
| 384 |
+
})();
|
| 385 |
+
</script>
|
| 386 |
<script src="app.js" defer></script>
|
| 387 |
</body>
|
| 388 |
</html>
|
links.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"spaces": {
|
| 3 |
-
"onnx_perf_explorer": "Renesas/ONNX-Performance-Explorer",
|
| 4 |
-
"ort_benchmark": "Renesas/ORT-Benchmark",
|
| 5 |
-
"gguf_llamacpp_benchmark": "Renesas/GGUF-llamacpp-Benchmark"
|
| 6 |
-
},
|
| 7 |
-
"collections": {
|
| 8 |
-
"onnx": "",
|
| 9 |
-
"gguf": "",
|
| 10 |
-
"performanceestimate": "",
|
| 11 |
-
"cpu": "",
|
| 12 |
-
"npu": "",
|
| 13 |
-
"llm": "",
|
| 14 |
-
"vlm": "",
|
| 15 |
-
"llama32_1b": ""
|
| 16 |
-
}
|
| 17 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
models.json
CHANGED
|
@@ -1,659 +1,127 @@
|
|
| 1 |
{
|
| 2 |
-
"version": "
|
| 3 |
-
"
|
|
|
|
|
|
|
|
|
|
| 4 |
"models": [
|
| 5 |
{
|
| 6 |
-
"key": "
|
| 7 |
-
"display_name": "
|
| 8 |
-
"architecture": "
|
| 9 |
"model_size_m": 1000,
|
| 10 |
"modality": "LLM",
|
| 11 |
"variant": "Instruct",
|
| 12 |
"targets": [
|
| 13 |
-
"CPU",
|
| 14 |
"NPU"
|
| 15 |
],
|
| 16 |
-
"onnx_repo": "Renesas/
|
| 17 |
-
"gguf_repo": "Renesas/
|
| 18 |
"onnx_artifacts": [
|
| 19 |
"fp16",
|
| 20 |
-
"
|
|
|
|
| 21 |
],
|
| 22 |
"gguf_artifacts": [
|
| 23 |
-
"
|
| 24 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
],
|
|
|
|
|
|
|
| 26 |
"hardware_configs": [
|
| 27 |
{
|
| 28 |
-
"id": "
|
| 29 |
-
"label": "X5H
|
| 30 |
"targets": [
|
| 31 |
-
"CPU",
|
| 32 |
"NPU"
|
| 33 |
],
|
| 34 |
-
"notes": "
|
| 35 |
"metrics": {
|
| 36 |
"artifacts": {
|
| 37 |
"fp16": {
|
| 38 |
"estimate": {
|
| 39 |
-
"accuracy":
|
| 40 |
-
"llm_metrics": {
|
| 41 |
-
"overall": 63.0,
|
| 42 |
-
"mmlu": 45.0,
|
| 43 |
-
"gsm8k": 22.0,
|
| 44 |
-
"hellaswag": 64.5,
|
| 45 |
-
"truthfulqa": 38.0,
|
| 46 |
-
"winogrande": 59.0,
|
| 47 |
-
"arc_challenge": 35.0,
|
| 48 |
-
"mt_bench": 6.2
|
| 49 |
-
},
|
| 50 |
-
"cpu": {
|
| 51 |
-
"tok_s": 18.0,
|
| 52 |
-
"latency_ms_p50": 55.0,
|
| 53 |
-
"peak_mem_mb": 820
|
| 54 |
-
},
|
| 55 |
"npu": {
|
| 56 |
-
"tok_s":
|
| 57 |
-
"latency_ms_p50":
|
| 58 |
-
"peak_mem_mb":
|
| 59 |
},
|
| 60 |
-
"dsp": null,
|
| 61 |
"total": {
|
| 62 |
-
"tok_s":
|
| 63 |
-
"
|
| 64 |
-
"
|
| 65 |
},
|
| 66 |
-
"
|
|
|
|
|
|
|
| 67 |
},
|
| 68 |
"hil": {
|
| 69 |
-
"accuracy":
|
| 70 |
-
"llm_metrics": {
|
| 71 |
-
"overall": 62.4,
|
| 72 |
-
"mmlu": 44.4,
|
| 73 |
-
"gsm8k": 21.4,
|
| 74 |
-
"hellaswag": 63.9,
|
| 75 |
-
"truthfulqa": 37.4,
|
| 76 |
-
"winogrande": 58.4,
|
| 77 |
-
"arc_challenge": 34.4,
|
| 78 |
-
"mt_bench": 6.1
|
| 79 |
-
},
|
| 80 |
-
"cpu": {
|
| 81 |
-
"tok_s": 16.5,
|
| 82 |
-
"latency_ms_p50": 60.0,
|
| 83 |
-
"peak_mem_mb": 840
|
| 84 |
-
},
|
| 85 |
"npu": {
|
| 86 |
-
"tok_s":
|
| 87 |
-
"latency_ms_p50":
|
| 88 |
-
"peak_mem_mb":
|
| 89 |
},
|
| 90 |
-
"dsp": null,
|
| 91 |
"total": {
|
| 92 |
-
"tok_s":
|
| 93 |
-
"
|
| 94 |
-
"
|
| 95 |
},
|
| 96 |
-
"
|
| 97 |
-
"
|
|
|
|
|
|
|
|
|
|
| 98 |
}
|
| 99 |
},
|
| 100 |
-
"
|
| 101 |
-
"estimate": {
|
| 102 |
-
"accuracy": 0.622,
|
| 103 |
-
"llm_metrics": {
|
| 104 |
-
"overall": 62.2,
|
| 105 |
-
"mmlu": 44.2,
|
| 106 |
-
"gsm8k": 21.2,
|
| 107 |
-
"hellaswag": 63.7,
|
| 108 |
-
"truthfulqa": 37.2,
|
| 109 |
-
"winogrande": 58.2,
|
| 110 |
-
"arc_challenge": 34.2,
|
| 111 |
-
"mt_bench": 6.1
|
| 112 |
-
},
|
| 113 |
-
"cpu": {
|
| 114 |
-
"tok_s": 18.0,
|
| 115 |
-
"latency_ms_p50": 55.0,
|
| 116 |
-
"peak_mem_mb": 820
|
| 117 |
-
},
|
| 118 |
-
"npu": {
|
| 119 |
-
"tok_s": 45.0,
|
| 120 |
-
"latency_ms_p50": 22.0,
|
| 121 |
-
"peak_mem_mb": 610
|
| 122 |
-
},
|
| 123 |
-
"dsp": null,
|
| 124 |
-
"total": {
|
| 125 |
-
"tok_s": 45.0,
|
| 126 |
-
"peak_mem_mb": 900,
|
| 127 |
-
"latency_ms_p50": 77.0
|
| 128 |
-
},
|
| 129 |
-
"last_updated": "2026-03-01"
|
| 130 |
-
},
|
| 131 |
-
"hil": {
|
| 132 |
-
"accuracy": 0.616,
|
| 133 |
-
"llm_metrics": {
|
| 134 |
-
"overall": 61.6,
|
| 135 |
-
"mmlu": 43.6,
|
| 136 |
-
"gsm8k": 20.6,
|
| 137 |
-
"hellaswag": 63.1,
|
| 138 |
-
"truthfulqa": 36.6,
|
| 139 |
-
"winogrande": 57.6,
|
| 140 |
-
"arc_challenge": 33.6,
|
| 141 |
-
"mt_bench": 6.1
|
| 142 |
-
},
|
| 143 |
-
"cpu": {
|
| 144 |
-
"tok_s": 16.5,
|
| 145 |
-
"latency_ms_p50": 60.0,
|
| 146 |
-
"peak_mem_mb": 840
|
| 147 |
-
},
|
| 148 |
-
"npu": {
|
| 149 |
-
"tok_s": 38.0,
|
| 150 |
-
"latency_ms_p50": 25.0,
|
| 151 |
-
"peak_mem_mb": 640
|
| 152 |
-
},
|
| 153 |
-
"dsp": null,
|
| 154 |
-
"total": {
|
| 155 |
-
"tok_s": 38.0,
|
| 156 |
-
"peak_mem_mb": 920,
|
| 157 |
-
"latency_ms_p50": 85.0
|
| 158 |
-
},
|
| 159 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 160 |
-
"last_updated": "2026-03-01"
|
| 161 |
-
}
|
| 162 |
-
},
|
| 163 |
-
"Q4_K_M": {
|
| 164 |
-
"estimate": {
|
| 165 |
-
"accuracy": 0.595,
|
| 166 |
-
"llm_metrics": {
|
| 167 |
-
"overall": 59.5,
|
| 168 |
-
"mmlu": 41.5,
|
| 169 |
-
"gsm8k": 18.5,
|
| 170 |
-
"hellaswag": 61.0,
|
| 171 |
-
"truthfulqa": 34.5,
|
| 172 |
-
"winogrande": 55.5,
|
| 173 |
-
"arc_challenge": 31.5,
|
| 174 |
-
"mt_bench": 6.0
|
| 175 |
-
},
|
| 176 |
-
"cpu": {
|
| 177 |
-
"tok_s": 18.0,
|
| 178 |
-
"latency_ms_p50": 55.0,
|
| 179 |
-
"peak_mem_mb": 820
|
| 180 |
-
},
|
| 181 |
-
"npu": {
|
| 182 |
-
"tok_s": 45.0,
|
| 183 |
-
"latency_ms_p50": 22.0,
|
| 184 |
-
"peak_mem_mb": 610
|
| 185 |
-
},
|
| 186 |
-
"dsp": null,
|
| 187 |
-
"total": {
|
| 188 |
-
"tok_s": 45.0,
|
| 189 |
-
"peak_mem_mb": 900,
|
| 190 |
-
"latency_ms_p50": 77.0
|
| 191 |
-
},
|
| 192 |
-
"last_updated": "2026-03-01"
|
| 193 |
-
},
|
| 194 |
-
"hil": {
|
| 195 |
-
"accuracy": 0.589,
|
| 196 |
-
"llm_metrics": {
|
| 197 |
-
"overall": 58.9,
|
| 198 |
-
"mmlu": 40.9,
|
| 199 |
-
"gsm8k": 17.9,
|
| 200 |
-
"hellaswag": 60.4,
|
| 201 |
-
"truthfulqa": 33.9,
|
| 202 |
-
"winogrande": 54.9,
|
| 203 |
-
"arc_challenge": 30.9,
|
| 204 |
-
"mt_bench": 5.9
|
| 205 |
-
},
|
| 206 |
-
"cpu": {
|
| 207 |
-
"tok_s": 16.5,
|
| 208 |
-
"latency_ms_p50": 60.0,
|
| 209 |
-
"peak_mem_mb": 840
|
| 210 |
-
},
|
| 211 |
-
"npu": {
|
| 212 |
-
"tok_s": 38.0,
|
| 213 |
-
"latency_ms_p50": 25.0,
|
| 214 |
-
"peak_mem_mb": 640
|
| 215 |
-
},
|
| 216 |
-
"dsp": null,
|
| 217 |
-
"total": {
|
| 218 |
-
"tok_s": 38.0,
|
| 219 |
-
"peak_mem_mb": 920,
|
| 220 |
-
"latency_ms_p50": 85.0
|
| 221 |
-
},
|
| 222 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 223 |
-
"last_updated": "2026-03-01"
|
| 224 |
-
}
|
| 225 |
-
},
|
| 226 |
-
"Q8_0": {
|
| 227 |
-
"estimate": {
|
| 228 |
-
"accuracy": 0.617,
|
| 229 |
-
"llm_metrics": {
|
| 230 |
-
"overall": 61.7,
|
| 231 |
-
"mmlu": 43.7,
|
| 232 |
-
"gsm8k": 20.7,
|
| 233 |
-
"hellaswag": 63.2,
|
| 234 |
-
"truthfulqa": 36.7,
|
| 235 |
-
"winogrande": 57.7,
|
| 236 |
-
"arc_challenge": 33.7,
|
| 237 |
-
"mt_bench": 6.1
|
| 238 |
-
},
|
| 239 |
-
"cpu": {
|
| 240 |
-
"tok_s": 18.0,
|
| 241 |
-
"latency_ms_p50": 55.0,
|
| 242 |
-
"peak_mem_mb": 820
|
| 243 |
-
},
|
| 244 |
-
"npu": {
|
| 245 |
-
"tok_s": 45.0,
|
| 246 |
-
"latency_ms_p50": 22.0,
|
| 247 |
-
"peak_mem_mb": 610
|
| 248 |
-
},
|
| 249 |
-
"dsp": null,
|
| 250 |
-
"total": {
|
| 251 |
-
"tok_s": 45.0,
|
| 252 |
-
"peak_mem_mb": 900,
|
| 253 |
-
"latency_ms_p50": 77.0
|
| 254 |
-
},
|
| 255 |
-
"last_updated": "2026-03-01"
|
| 256 |
-
},
|
| 257 |
-
"hil": {
|
| 258 |
-
"accuracy": 0.611,
|
| 259 |
-
"llm_metrics": {
|
| 260 |
-
"overall": 61.1,
|
| 261 |
-
"mmlu": 43.1,
|
| 262 |
-
"gsm8k": 20.1,
|
| 263 |
-
"hellaswag": 62.6,
|
| 264 |
-
"truthfulqa": 36.1,
|
| 265 |
-
"winogrande": 57.1,
|
| 266 |
-
"arc_challenge": 33.1,
|
| 267 |
-
"mt_bench": 6.1
|
| 268 |
-
},
|
| 269 |
-
"cpu": {
|
| 270 |
-
"tok_s": 16.5,
|
| 271 |
-
"latency_ms_p50": 60.0,
|
| 272 |
-
"peak_mem_mb": 840
|
| 273 |
-
},
|
| 274 |
-
"npu": {
|
| 275 |
-
"tok_s": 38.0,
|
| 276 |
-
"latency_ms_p50": 25.0,
|
| 277 |
-
"peak_mem_mb": 640
|
| 278 |
-
},
|
| 279 |
-
"dsp": null,
|
| 280 |
-
"total": {
|
| 281 |
-
"tok_s": 38.0,
|
| 282 |
-
"peak_mem_mb": 920,
|
| 283 |
-
"latency_ms_p50": 85.0
|
| 284 |
-
},
|
| 285 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 286 |
-
"last_updated": "2026-03-01"
|
| 287 |
-
}
|
| 288 |
-
}
|
| 289 |
-
}
|
| 290 |
-
}
|
| 291 |
-
},
|
| 292 |
-
{
|
| 293 |
-
"id": "X5H-200TOPS-LOWPWR",
|
| 294 |
-
"label": "X5H 200TOPS Reference Platform β Low Power",
|
| 295 |
-
"targets": [
|
| 296 |
-
"CPU",
|
| 297 |
-
"NPU"
|
| 298 |
-
],
|
| 299 |
-
"notes": "Lower clocks / lower power envelope",
|
| 300 |
-
"metrics": {
|
| 301 |
-
"artifacts": {
|
| 302 |
-
"fp16": {
|
| 303 |
-
"estimate": {
|
| 304 |
-
"accuracy": 0.628,
|
| 305 |
-
"llm_metrics": {
|
| 306 |
-
"overall": 62.8,
|
| 307 |
-
"mmlu": 44.8,
|
| 308 |
-
"gsm8k": 21.8,
|
| 309 |
-
"hellaswag": 64.3,
|
| 310 |
-
"truthfulqa": 37.8,
|
| 311 |
-
"winogrande": 58.8,
|
| 312 |
-
"arc_challenge": 34.8,
|
| 313 |
-
"mt_bench": 6.1
|
| 314 |
-
},
|
| 315 |
-
"cpu": {
|
| 316 |
-
"tok_s": 17.0,
|
| 317 |
-
"latency_ms_p50": 58.0,
|
| 318 |
-
"peak_mem_mb": 820
|
| 319 |
-
},
|
| 320 |
-
"npu": {
|
| 321 |
-
"tok_s": 41.0,
|
| 322 |
-
"latency_ms_p50": 24.0,
|
| 323 |
-
"peak_mem_mb": 610
|
| 324 |
-
},
|
| 325 |
-
"dsp": null,
|
| 326 |
-
"total": {
|
| 327 |
-
"tok_s": 41.0,
|
| 328 |
-
"peak_mem_mb": 900,
|
| 329 |
-
"latency_ms_p50": 82.0
|
| 330 |
-
},
|
| 331 |
-
"last_updated": "2026-03-01"
|
| 332 |
-
},
|
| 333 |
-
"hil": null
|
| 334 |
-
},
|
| 335 |
-
"int8": {
|
| 336 |
-
"estimate": {
|
| 337 |
-
"accuracy": 0.62,
|
| 338 |
-
"llm_metrics": {
|
| 339 |
-
"overall": 62.0,
|
| 340 |
-
"mmlu": 44.0,
|
| 341 |
-
"gsm8k": 21.0,
|
| 342 |
-
"hellaswag": 63.5,
|
| 343 |
-
"truthfulqa": 37.0,
|
| 344 |
-
"winogrande": 58.0,
|
| 345 |
-
"arc_challenge": 34.0,
|
| 346 |
-
"mt_bench": 6.1
|
| 347 |
-
},
|
| 348 |
-
"cpu": {
|
| 349 |
-
"tok_s": 17.0,
|
| 350 |
-
"latency_ms_p50": 58.0,
|
| 351 |
-
"peak_mem_mb": 820
|
| 352 |
-
},
|
| 353 |
-
"npu": {
|
| 354 |
-
"tok_s": 41.0,
|
| 355 |
-
"latency_ms_p50": 24.0,
|
| 356 |
-
"peak_mem_mb": 610
|
| 357 |
-
},
|
| 358 |
-
"dsp": null,
|
| 359 |
-
"total": {
|
| 360 |
-
"tok_s": 41.0,
|
| 361 |
-
"peak_mem_mb": 900,
|
| 362 |
-
"latency_ms_p50": 82.0
|
| 363 |
-
},
|
| 364 |
-
"last_updated": "2026-03-01"
|
| 365 |
-
},
|
| 366 |
-
"hil": null
|
| 367 |
-
},
|
| 368 |
-
"Q4_K_M": {
|
| 369 |
-
"estimate": {
|
| 370 |
-
"accuracy": 0.593,
|
| 371 |
-
"llm_metrics": {
|
| 372 |
-
"overall": 59.3,
|
| 373 |
-
"mmlu": 41.3,
|
| 374 |
-
"gsm8k": 18.3,
|
| 375 |
-
"hellaswag": 60.8,
|
| 376 |
-
"truthfulqa": 34.3,
|
| 377 |
-
"winogrande": 55.3,
|
| 378 |
-
"arc_challenge": 31.3,
|
| 379 |
-
"mt_bench": 6.0
|
| 380 |
-
},
|
| 381 |
-
"cpu": {
|
| 382 |
-
"tok_s": 17.0,
|
| 383 |
-
"latency_ms_p50": 58.0,
|
| 384 |
-
"peak_mem_mb": 820
|
| 385 |
-
},
|
| 386 |
-
"npu": {
|
| 387 |
-
"tok_s": 41.0,
|
| 388 |
-
"latency_ms_p50": 24.0,
|
| 389 |
-
"peak_mem_mb": 610
|
| 390 |
-
},
|
| 391 |
-
"dsp": null,
|
| 392 |
-
"total": {
|
| 393 |
-
"tok_s": 41.0,
|
| 394 |
-
"peak_mem_mb": 900,
|
| 395 |
-
"latency_ms_p50": 82.0
|
| 396 |
-
},
|
| 397 |
-
"last_updated": "2026-03-01"
|
| 398 |
-
},
|
| 399 |
-
"hil": null
|
| 400 |
-
},
|
| 401 |
-
"Q8_0": {
|
| 402 |
-
"estimate": {
|
| 403 |
-
"accuracy": 0.615,
|
| 404 |
-
"llm_metrics": {
|
| 405 |
-
"overall": 61.5,
|
| 406 |
-
"mmlu": 43.5,
|
| 407 |
-
"gsm8k": 20.5,
|
| 408 |
-
"hellaswag": 63.0,
|
| 409 |
-
"truthfulqa": 36.5,
|
| 410 |
-
"winogrande": 57.5,
|
| 411 |
-
"arc_challenge": 33.5,
|
| 412 |
-
"mt_bench": 6.1
|
| 413 |
-
},
|
| 414 |
-
"cpu": {
|
| 415 |
-
"tok_s": 17.0,
|
| 416 |
-
"latency_ms_p50": 58.0,
|
| 417 |
-
"peak_mem_mb": 820
|
| 418 |
-
},
|
| 419 |
-
"npu": {
|
| 420 |
-
"tok_s": 41.0,
|
| 421 |
-
"latency_ms_p50": 24.0,
|
| 422 |
-
"peak_mem_mb": 610
|
| 423 |
-
},
|
| 424 |
-
"dsp": null,
|
| 425 |
-
"total": {
|
| 426 |
-
"tok_s": 41.0,
|
| 427 |
-
"peak_mem_mb": 900,
|
| 428 |
-
"latency_ms_p50": 82.0
|
| 429 |
-
},
|
| 430 |
-
"last_updated": "2026-03-01"
|
| 431 |
-
},
|
| 432 |
-
"hil": null
|
| 433 |
-
}
|
| 434 |
-
}
|
| 435 |
-
}
|
| 436 |
-
}
|
| 437 |
-
]
|
| 438 |
-
},
|
| 439 |
-
{
|
| 440 |
-
"key": "llama32-1b-base",
|
| 441 |
-
"display_name": "Llama3.2-1B Base",
|
| 442 |
-
"architecture": "Llama3.2-1B",
|
| 443 |
-
"model_size_m": 1000,
|
| 444 |
-
"modality": "LLM",
|
| 445 |
-
"variant": "Base",
|
| 446 |
-
"targets": [
|
| 447 |
-
"CPU"
|
| 448 |
-
],
|
| 449 |
-
"onnx_repo": "Renesas/Llama3.2-1B-Base-ONNX",
|
| 450 |
-
"gguf_repo": "Renesas/Llama3.2-1B-Base-GGUF",
|
| 451 |
-
"onnx_artifacts": [
|
| 452 |
-
"fp16"
|
| 453 |
-
],
|
| 454 |
-
"gguf_artifacts": [
|
| 455 |
-
"Q4_K_M"
|
| 456 |
-
],
|
| 457 |
-
"hardware_configs": [
|
| 458 |
-
{
|
| 459 |
-
"id": "X5H-200TOPS",
|
| 460 |
-
"label": "X5H 200TOPS Reference Platform",
|
| 461 |
-
"targets": [
|
| 462 |
-
"CPU"
|
| 463 |
-
],
|
| 464 |
-
"metrics": {
|
| 465 |
-
"artifacts": {
|
| 466 |
-
"fp16": {
|
| 467 |
"estimate": null,
|
| 468 |
"hil": {
|
| 469 |
-
"accuracy":
|
| 470 |
-
"
|
| 471 |
-
"
|
| 472 |
-
"
|
| 473 |
-
"
|
| 474 |
-
"hellaswag": 56.4,
|
| 475 |
-
"truthfulqa": 29.9,
|
| 476 |
-
"winogrande": 50.9,
|
| 477 |
-
"arc_challenge": 26.9,
|
| 478 |
-
"mt_bench": 5.7
|
| 479 |
-
},
|
| 480 |
-
"cpu": {
|
| 481 |
-
"tok_s": 20.0,
|
| 482 |
-
"latency_ms_p50": 52.0,
|
| 483 |
-
"peak_mem_mb": 760
|
| 484 |
},
|
| 485 |
-
"npu": null,
|
| 486 |
-
"dsp": null,
|
| 487 |
"total": {
|
| 488 |
-
"tok_s":
|
| 489 |
-
"
|
| 490 |
-
"
|
| 491 |
},
|
| 492 |
-
"
|
| 493 |
-
"
|
|
|
|
|
|
|
|
|
|
| 494 |
}
|
| 495 |
},
|
| 496 |
-
"
|
| 497 |
"estimate": null,
|
| 498 |
-
"hil": {
|
| 499 |
-
"accuracy": 0.514,
|
| 500 |
-
"llm_metrics": {
|
| 501 |
-
"overall": 51.4,
|
| 502 |
-
"mmlu": 33.4,
|
| 503 |
-
"gsm8k": 10.4,
|
| 504 |
-
"hellaswag": 52.9,
|
| 505 |
-
"truthfulqa": 26.4,
|
| 506 |
-
"winogrande": 47.4,
|
| 507 |
-
"arc_challenge": 23.4,
|
| 508 |
-
"mt_bench": 5.6
|
| 509 |
-
},
|
| 510 |
-
"cpu": {
|
| 511 |
-
"tok_s": 20.0,
|
| 512 |
-
"latency_ms_p50": 52.0,
|
| 513 |
-
"peak_mem_mb": 760
|
| 514 |
-
},
|
| 515 |
-
"npu": null,
|
| 516 |
-
"dsp": null,
|
| 517 |
-
"total": {
|
| 518 |
-
"tok_s": 20.0,
|
| 519 |
-
"peak_mem_mb": 810,
|
| 520 |
-
"latency_ms_p50": 52.0
|
| 521 |
-
},
|
| 522 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 523 |
-
"last_updated": "2026-03-01"
|
| 524 |
-
}
|
| 525 |
-
}
|
| 526 |
-
}
|
| 527 |
-
}
|
| 528 |
-
}
|
| 529 |
-
]
|
| 530 |
-
},
|
| 531 |
-
{
|
| 532 |
-
"key": "vlm-tiny-visionchat",
|
| 533 |
-
"display_name": "VLM Tiny VisionChat",
|
| 534 |
-
"architecture": "VLM-Tiny-450M",
|
| 535 |
-
"model_size_m": 450,
|
| 536 |
-
"modality": "VLM",
|
| 537 |
-
"variant": "Instruct",
|
| 538 |
-
"targets": [
|
| 539 |
-
"CPU",
|
| 540 |
-
"NPU"
|
| 541 |
-
],
|
| 542 |
-
"onnx_repo": "Renesas/VLM-Tiny-VisionChat-ONNX",
|
| 543 |
-
"gguf_repo": "Renesas/VLM-Tiny-VisionChat-GGUF",
|
| 544 |
-
"onnx_artifacts": [
|
| 545 |
-
"fp16",
|
| 546 |
-
"int8"
|
| 547 |
-
],
|
| 548 |
-
"gguf_artifacts": [
|
| 549 |
-
"Q4_K_M"
|
| 550 |
-
],
|
| 551 |
-
"hardware_configs": [
|
| 552 |
-
{
|
| 553 |
-
"id": "X5H-200TOPS",
|
| 554 |
-
"label": "X5H 200TOPS Reference Platform",
|
| 555 |
-
"targets": [
|
| 556 |
-
"CPU",
|
| 557 |
-
"NPU"
|
| 558 |
-
],
|
| 559 |
-
"metrics": {
|
| 560 |
-
"artifacts": {
|
| 561 |
-
"fp16": {
|
| 562 |
-
"estimate": {
|
| 563 |
-
"accuracy": 0.55,
|
| 564 |
-
"vlm_metrics": {
|
| 565 |
-
"overall": 55.0,
|
| 566 |
-
"mmbench": 50.0,
|
| 567 |
-
"vqav2": 57.0,
|
| 568 |
-
"seedbench": 47.0,
|
| 569 |
-
"pope": 52.0
|
| 570 |
-
},
|
| 571 |
-
"cpu": {
|
| 572 |
-
"tok_s": 5.0,
|
| 573 |
-
"latency_ms_p50": 180.0,
|
| 574 |
-
"peak_mem_mb": 920
|
| 575 |
-
},
|
| 576 |
-
"npu": {
|
| 577 |
-
"tok_s": 14.0,
|
| 578 |
-
"latency_ms_p50": 70.0,
|
| 579 |
-
"peak_mem_mb": 690
|
| 580 |
-
},
|
| 581 |
-
"dsp": {
|
| 582 |
-
"latency_ms_p50": 12.0,
|
| 583 |
-
"peak_mem_mb": 32
|
| 584 |
-
},
|
| 585 |
-
"total": {
|
| 586 |
-
"tok_s": 14.0,
|
| 587 |
-
"peak_mem_mb": 980,
|
| 588 |
-
"latency_ms_p50": 262.0
|
| 589 |
-
},
|
| 590 |
-
"last_updated": "2026-03-01"
|
| 591 |
-
},
|
| 592 |
"hil": null
|
| 593 |
},
|
| 594 |
-
"
|
| 595 |
"estimate": {
|
| 596 |
-
"accuracy":
|
| 597 |
-
"vlm_metrics": {
|
| 598 |
-
"overall": 54.2,
|
| 599 |
-
"mmbench": 49.2,
|
| 600 |
-
"vqav2": 56.2,
|
| 601 |
-
"seedbench": 46.2,
|
| 602 |
-
"pope": 51.2
|
| 603 |
-
},
|
| 604 |
-
"cpu": {
|
| 605 |
-
"tok_s": 5.0,
|
| 606 |
-
"latency_ms_p50": 180.0,
|
| 607 |
-
"peak_mem_mb": 920
|
| 608 |
-
},
|
| 609 |
"npu": {
|
| 610 |
-
"tok_s":
|
| 611 |
-
"latency_ms_p50":
|
| 612 |
-
"peak_mem_mb":
|
| 613 |
-
},
|
| 614 |
-
"dsp": {
|
| 615 |
-
"latency_ms_p50": 12.0,
|
| 616 |
-
"peak_mem_mb": 32
|
| 617 |
-
},
|
| 618 |
-
"total": {
|
| 619 |
-
"tok_s": 14.0,
|
| 620 |
-
"peak_mem_mb": 980,
|
| 621 |
-
"latency_ms_p50": 262.0
|
| 622 |
-
},
|
| 623 |
-
"last_updated": "2026-03-01"
|
| 624 |
-
},
|
| 625 |
-
"hil": null
|
| 626 |
-
},
|
| 627 |
-
"Q4_K_M": {
|
| 628 |
-
"estimate": {
|
| 629 |
-
"accuracy": 0.515,
|
| 630 |
-
"vlm_metrics": {
|
| 631 |
-
"overall": 51.5,
|
| 632 |
-
"mmbench": 46.5,
|
| 633 |
-
"vqav2": 53.5,
|
| 634 |
-
"seedbench": 43.5,
|
| 635 |
-
"pope": 48.5
|
| 636 |
-
},
|
| 637 |
-
"cpu": {
|
| 638 |
-
"tok_s": 5.0,
|
| 639 |
-
"latency_ms_p50": 180.0,
|
| 640 |
-
"peak_mem_mb": 920
|
| 641 |
-
},
|
| 642 |
-
"npu": {
|
| 643 |
-
"tok_s": 14.0,
|
| 644 |
-
"latency_ms_p50": 70.0,
|
| 645 |
-
"peak_mem_mb": 690
|
| 646 |
-
},
|
| 647 |
-
"dsp": {
|
| 648 |
-
"latency_ms_p50": 12.0,
|
| 649 |
-
"peak_mem_mb": 32
|
| 650 |
},
|
| 651 |
"total": {
|
| 652 |
-
"tok_s":
|
| 653 |
-
"
|
| 654 |
-
"
|
| 655 |
},
|
| 656 |
-
"
|
|
|
|
|
|
|
| 657 |
},
|
| 658 |
"hil": null
|
| 659 |
}
|
|
@@ -663,99 +131,81 @@
|
|
| 663 |
]
|
| 664 |
},
|
| 665 |
{
|
| 666 |
-
"key": "
|
| 667 |
-
"display_name": "
|
| 668 |
-
"architecture": "
|
| 669 |
-
"model_size_m":
|
| 670 |
"modality": "LLM",
|
| 671 |
"variant": "Instruct",
|
| 672 |
"targets": [
|
| 673 |
-
"CPU",
|
| 674 |
"NPU"
|
| 675 |
],
|
| 676 |
"onnx_repo": "",
|
| 677 |
-
"gguf_repo": "Renesas/
|
| 678 |
"onnx_artifacts": [],
|
| 679 |
"gguf_artifacts": [
|
| 680 |
-
"
|
| 681 |
-
"
|
| 682 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
"hardware_configs": [
|
| 684 |
{
|
| 685 |
-
"id": "
|
| 686 |
-
"label": "X5H
|
| 687 |
"targets": [
|
| 688 |
-
"CPU",
|
| 689 |
"NPU"
|
| 690 |
],
|
|
|
|
| 691 |
"metrics": {
|
| 692 |
"artifacts": {
|
| 693 |
-
"
|
| 694 |
"estimate": null,
|
| 695 |
"hil": {
|
| 696 |
-
"accuracy":
|
| 697 |
-
"llm_metrics": {
|
| 698 |
-
"overall": 55.8,
|
| 699 |
-
"mmlu": 37.8,
|
| 700 |
-
"gsm8k": 14.8,
|
| 701 |
-
"hellaswag": 57.3,
|
| 702 |
-
"truthfulqa": 30.8,
|
| 703 |
-
"winogrande": 51.8,
|
| 704 |
-
"arc_challenge": 27.8,
|
| 705 |
-
"mt_bench": 5.8
|
| 706 |
-
},
|
| 707 |
-
"cpu": {
|
| 708 |
-
"tok_s": 24.0,
|
| 709 |
-
"latency_ms_p50": 40.0,
|
| 710 |
-
"peak_mem_mb": 740
|
| 711 |
-
},
|
| 712 |
"npu": {
|
| 713 |
-
"tok_s":
|
| 714 |
-
"latency_ms_p50":
|
| 715 |
-
"peak_mem_mb":
|
| 716 |
},
|
| 717 |
-
"dsp": null,
|
| 718 |
"total": {
|
| 719 |
-
"tok_s":
|
| 720 |
-
"
|
| 721 |
-
"
|
| 722 |
},
|
| 723 |
-
"
|
| 724 |
-
"
|
|
|
|
|
|
|
|
|
|
| 725 |
}
|
| 726 |
},
|
| 727 |
-
"
|
| 728 |
"estimate": null,
|
| 729 |
"hil": {
|
| 730 |
-
"accuracy":
|
| 731 |
-
"llm_metrics": {
|
| 732 |
-
"overall": 58.0,
|
| 733 |
-
"mmlu": 40.0,
|
| 734 |
-
"gsm8k": 17.0,
|
| 735 |
-
"hellaswag": 59.5,
|
| 736 |
-
"truthfulqa": 33.0,
|
| 737 |
-
"winogrande": 54.0,
|
| 738 |
-
"arc_challenge": 30.0,
|
| 739 |
-
"mt_bench": 5.9
|
| 740 |
-
},
|
| 741 |
-
"cpu": {
|
| 742 |
-
"tok_s": 24.0,
|
| 743 |
-
"latency_ms_p50": 40.0,
|
| 744 |
-
"peak_mem_mb": 740
|
| 745 |
-
},
|
| 746 |
"npu": {
|
| 747 |
-
"tok_s":
|
| 748 |
-
"latency_ms_p50":
|
| 749 |
-
"peak_mem_mb":
|
| 750 |
},
|
| 751 |
-
"dsp": null,
|
| 752 |
"total": {
|
| 753 |
-
"tok_s":
|
| 754 |
-
"
|
| 755 |
-
"
|
| 756 |
},
|
| 757 |
-
"
|
| 758 |
-
"
|
|
|
|
|
|
|
|
|
|
| 759 |
}
|
| 760 |
}
|
| 761 |
}
|
|
@@ -764,286 +214,82 @@
|
|
| 764 |
]
|
| 765 |
},
|
| 766 |
{
|
| 767 |
-
"key": "
|
| 768 |
-
"display_name": "
|
| 769 |
-
"architecture": "
|
| 770 |
"model_size_m": 3000,
|
| 771 |
"modality": "LLM",
|
| 772 |
"variant": "Instruct",
|
| 773 |
"targets": [
|
| 774 |
-
"CPU",
|
| 775 |
"NPU"
|
| 776 |
],
|
| 777 |
-
"onnx_repo": "
|
| 778 |
-
"gguf_repo": "Renesas/
|
| 779 |
-
"onnx_artifacts": [
|
|
|
|
| 780 |
"fp16",
|
| 781 |
-
"
|
| 782 |
],
|
| 783 |
-
"
|
| 784 |
-
|
| 785 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 786 |
],
|
|
|
|
|
|
|
| 787 |
"hardware_configs": [
|
| 788 |
{
|
| 789 |
-
"id": "
|
| 790 |
-
"label": "X5H
|
| 791 |
"targets": [
|
| 792 |
-
"CPU",
|
| 793 |
"NPU"
|
| 794 |
],
|
|
|
|
| 795 |
"metrics": {
|
| 796 |
"artifacts": {
|
| 797 |
"fp16": {
|
| 798 |
-
"estimate":
|
| 799 |
-
"accuracy": 0.7,
|
| 800 |
-
"llm_metrics": {
|
| 801 |
-
"overall": 70.0,
|
| 802 |
-
"mmlu": 52.0,
|
| 803 |
-
"gsm8k": 29.0,
|
| 804 |
-
"hellaswag": 71.5,
|
| 805 |
-
"truthfulqa": 45.0,
|
| 806 |
-
"winogrande": 66.0,
|
| 807 |
-
"arc_challenge": 42.0,
|
| 808 |
-
"mt_bench": 6.5
|
| 809 |
-
},
|
| 810 |
-
"cpu": {
|
| 811 |
-
"tok_s": 7.5,
|
| 812 |
-
"latency_ms_p50": 125.0,
|
| 813 |
-
"peak_mem_mb": 1850
|
| 814 |
-
},
|
| 815 |
-
"npu": {
|
| 816 |
-
"tok_s": 19.0,
|
| 817 |
-
"latency_ms_p50": 52.0,
|
| 818 |
-
"peak_mem_mb": 1320
|
| 819 |
-
},
|
| 820 |
-
"dsp": null,
|
| 821 |
-
"total": {
|
| 822 |
-
"tok_s": 19.0,
|
| 823 |
-
"peak_mem_mb": 1980,
|
| 824 |
-
"latency_ms_p50": 177.0
|
| 825 |
-
},
|
| 826 |
-
"last_updated": "2026-03-01"
|
| 827 |
-
},
|
| 828 |
-
"hil": {
|
| 829 |
-
"accuracy": 0.694,
|
| 830 |
-
"llm_metrics": {
|
| 831 |
-
"overall": 69.4,
|
| 832 |
-
"mmlu": 51.4,
|
| 833 |
-
"gsm8k": 28.4,
|
| 834 |
-
"hellaswag": 70.9,
|
| 835 |
-
"truthfulqa": 44.4,
|
| 836 |
-
"winogrande": 65.4,
|
| 837 |
-
"arc_challenge": 41.4,
|
| 838 |
-
"mt_bench": 6.5
|
| 839 |
-
},
|
| 840 |
-
"cpu": {
|
| 841 |
-
"tok_s": 6.8,
|
| 842 |
-
"latency_ms_p50": 138.0,
|
| 843 |
-
"peak_mem_mb": 1900
|
| 844 |
-
},
|
| 845 |
-
"npu": {
|
| 846 |
-
"tok_s": 16.5,
|
| 847 |
-
"latency_ms_p50": 58.0,
|
| 848 |
-
"peak_mem_mb": 1400
|
| 849 |
-
},
|
| 850 |
-
"dsp": null,
|
| 851 |
-
"total": {
|
| 852 |
-
"tok_s": 16.5,
|
| 853 |
-
"peak_mem_mb": 2050,
|
| 854 |
-
"latency_ms_p50": 196.0
|
| 855 |
-
},
|
| 856 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 857 |
-
"last_updated": "2026-03-02"
|
| 858 |
-
}
|
| 859 |
-
},
|
| 860 |
-
"int8": {
|
| 861 |
-
"estimate": {
|
| 862 |
-
"accuracy": 0.692,
|
| 863 |
-
"llm_metrics": {
|
| 864 |
-
"overall": 69.2,
|
| 865 |
-
"mmlu": 51.2,
|
| 866 |
-
"gsm8k": 28.2,
|
| 867 |
-
"hellaswag": 70.7,
|
| 868 |
-
"truthfulqa": 44.2,
|
| 869 |
-
"winogrande": 65.2,
|
| 870 |
-
"arc_challenge": 41.2,
|
| 871 |
-
"mt_bench": 6.5
|
| 872 |
-
},
|
| 873 |
-
"cpu": {
|
| 874 |
-
"tok_s": 7.5,
|
| 875 |
-
"latency_ms_p50": 125.0,
|
| 876 |
-
"peak_mem_mb": 1850
|
| 877 |
-
},
|
| 878 |
-
"npu": {
|
| 879 |
-
"tok_s": 19.0,
|
| 880 |
-
"latency_ms_p50": 52.0,
|
| 881 |
-
"peak_mem_mb": 1320
|
| 882 |
-
},
|
| 883 |
-
"dsp": null,
|
| 884 |
-
"total": {
|
| 885 |
-
"tok_s": 19.0,
|
| 886 |
-
"peak_mem_mb": 1980,
|
| 887 |
-
"latency_ms_p50": 177.0
|
| 888 |
-
},
|
| 889 |
-
"last_updated": "2026-03-01"
|
| 890 |
-
},
|
| 891 |
-
"hil": {
|
| 892 |
-
"accuracy": 0.686,
|
| 893 |
-
"llm_metrics": {
|
| 894 |
-
"overall": 68.6,
|
| 895 |
-
"mmlu": 50.6,
|
| 896 |
-
"gsm8k": 27.6,
|
| 897 |
-
"hellaswag": 70.1,
|
| 898 |
-
"truthfulqa": 43.6,
|
| 899 |
-
"winogrande": 64.6,
|
| 900 |
-
"arc_challenge": 40.6,
|
| 901 |
-
"mt_bench": 6.4
|
| 902 |
-
},
|
| 903 |
-
"cpu": {
|
| 904 |
-
"tok_s": 6.8,
|
| 905 |
-
"latency_ms_p50": 138.0,
|
| 906 |
-
"peak_mem_mb": 1900
|
| 907 |
-
},
|
| 908 |
-
"npu": {
|
| 909 |
-
"tok_s": 16.5,
|
| 910 |
-
"latency_ms_p50": 58.0,
|
| 911 |
-
"peak_mem_mb": 1400
|
| 912 |
-
},
|
| 913 |
-
"dsp": null,
|
| 914 |
-
"total": {
|
| 915 |
-
"tok_s": 16.5,
|
| 916 |
-
"peak_mem_mb": 2050,
|
| 917 |
-
"latency_ms_p50": 196.0
|
| 918 |
-
},
|
| 919 |
-
"setup": "DEMO-HIL-RIG-1",
|
| 920 |
-
"last_updated": "2026-03-02"
|
| 921 |
-
}
|
| 922 |
-
},
|
| 923 |
-
"Q4_K_M": {
|
| 924 |
-
"estimate": {
|
| 925 |
-
"accuracy": 0.665,
|
| 926 |
-
"llm_metrics": {
|
| 927 |
-
"overall": 66.5,
|
| 928 |
-
"mmlu": 48.5,
|
| 929 |
-
"gsm8k": 25.5,
|
| 930 |
-
"hellaswag": 68.0,
|
| 931 |
-
"truthfulqa": 41.5,
|
| 932 |
-
"winogrande": 62.5,
|
| 933 |
-
"arc_challenge": 38.5,
|
| 934 |
-
"mt_bench": 6.3
|
| 935 |
-
},
|
| 936 |
-
"cpu": {
|
| 937 |
-
"tok_s": 7.5,
|
| 938 |
-
"latency_ms_p50": 125.0,
|
| 939 |
-
"peak_mem_mb": 1850
|
| 940 |
-
},
|
| 941 |
-
"npu": {
|
| 942 |
-
"tok_s": 19.0,
|
| 943 |
-
"latency_ms_p50": 52.0,
|
| 944 |
-
"peak_mem_mb": 1320
|
| 945 |
-
},
|
| 946 |
-
"dsp": null,
|
| 947 |
-
"total": {
|
| 948 |
-
"tok_s": 19.0,
|
| 949 |
-
"peak_mem_mb": 1980,
|
| 950 |
-
"latency_ms_p50": 177.0
|
| 951 |
-
},
|
| 952 |
-
"last_updated": "2026-03-01"
|
| 953 |
-
},
|
| 954 |
"hil": {
|
| 955 |
-
"accuracy":
|
| 956 |
-
"llm_metrics": {
|
| 957 |
-
"overall": 65.9,
|
| 958 |
-
"mmlu": 47.9,
|
| 959 |
-
"gsm8k": 24.9,
|
| 960 |
-
"hellaswag": 67.4,
|
| 961 |
-
"truthfulqa": 40.9,
|
| 962 |
-
"winogrande": 61.9,
|
| 963 |
-
"arc_challenge": 37.9,
|
| 964 |
-
"mt_bench": 6.3
|
| 965 |
-
},
|
| 966 |
-
"cpu": {
|
| 967 |
-
"tok_s": 6.8,
|
| 968 |
-
"latency_ms_p50": 138.0,
|
| 969 |
-
"peak_mem_mb": 1900
|
| 970 |
-
},
|
| 971 |
"npu": {
|
| 972 |
-
"tok_s":
|
| 973 |
-
"latency_ms_p50":
|
| 974 |
-
"peak_mem_mb":
|
| 975 |
},
|
| 976 |
-
"dsp": null,
|
| 977 |
"total": {
|
| 978 |
-
"tok_s":
|
| 979 |
-
"
|
| 980 |
-
"
|
| 981 |
},
|
| 982 |
-
"
|
| 983 |
-
"
|
|
|
|
|
|
|
|
|
|
| 984 |
}
|
| 985 |
},
|
| 986 |
-
"
|
| 987 |
-
"estimate":
|
| 988 |
-
"accuracy": 0.687,
|
| 989 |
-
"llm_metrics": {
|
| 990 |
-
"overall": 68.7,
|
| 991 |
-
"mmlu": 50.7,
|
| 992 |
-
"gsm8k": 27.7,
|
| 993 |
-
"hellaswag": 70.2,
|
| 994 |
-
"truthfulqa": 43.7,
|
| 995 |
-
"winogrande": 64.7,
|
| 996 |
-
"arc_challenge": 40.7,
|
| 997 |
-
"mt_bench": 6.4
|
| 998 |
-
},
|
| 999 |
-
"cpu": {
|
| 1000 |
-
"tok_s": 7.5,
|
| 1001 |
-
"latency_ms_p50": 125.0,
|
| 1002 |
-
"peak_mem_mb": 1850
|
| 1003 |
-
},
|
| 1004 |
-
"npu": {
|
| 1005 |
-
"tok_s": 19.0,
|
| 1006 |
-
"latency_ms_p50": 52.0,
|
| 1007 |
-
"peak_mem_mb": 1320
|
| 1008 |
-
},
|
| 1009 |
-
"dsp": null,
|
| 1010 |
-
"total": {
|
| 1011 |
-
"tok_s": 19.0,
|
| 1012 |
-
"peak_mem_mb": 1980,
|
| 1013 |
-
"latency_ms_p50": 177.0
|
| 1014 |
-
},
|
| 1015 |
-
"last_updated": "2026-03-01"
|
| 1016 |
-
},
|
| 1017 |
"hil": {
|
| 1018 |
-
"accuracy":
|
| 1019 |
-
"llm_metrics": {
|
| 1020 |
-
"overall": 68.1,
|
| 1021 |
-
"mmlu": 50.1,
|
| 1022 |
-
"gsm8k": 27.1,
|
| 1023 |
-
"hellaswag": 69.6,
|
| 1024 |
-
"truthfulqa": 43.1,
|
| 1025 |
-
"winogrande": 64.1,
|
| 1026 |
-
"arc_challenge": 40.1,
|
| 1027 |
-
"mt_bench": 6.4
|
| 1028 |
-
},
|
| 1029 |
-
"cpu": {
|
| 1030 |
-
"tok_s": 6.8,
|
| 1031 |
-
"latency_ms_p50": 138.0,
|
| 1032 |
-
"peak_mem_mb": 1900
|
| 1033 |
-
},
|
| 1034 |
"npu": {
|
| 1035 |
-
"tok_s":
|
| 1036 |
-
"latency_ms_p50":
|
| 1037 |
-
"peak_mem_mb":
|
| 1038 |
},
|
| 1039 |
-
"dsp": null,
|
| 1040 |
"total": {
|
| 1041 |
-
"tok_s":
|
| 1042 |
-
"
|
| 1043 |
-
"
|
| 1044 |
},
|
| 1045 |
-
"
|
| 1046 |
-
"
|
|
|
|
|
|
|
|
|
|
| 1047 |
}
|
| 1048 |
}
|
| 1049 |
}
|
|
@@ -1052,256 +298,82 @@
|
|
| 1052 |
]
|
| 1053 |
},
|
| 1054 |
{
|
| 1055 |
-
"key": "
|
| 1056 |
-
"display_name": "
|
| 1057 |
-
"architecture": "
|
| 1058 |
-
"model_size_m":
|
| 1059 |
"modality": "LLM",
|
| 1060 |
-
"variant": "
|
| 1061 |
"targets": [
|
| 1062 |
-
"CPU",
|
| 1063 |
"NPU"
|
| 1064 |
],
|
| 1065 |
-
"onnx_repo": "
|
| 1066 |
-
"gguf_repo": "",
|
| 1067 |
-
"onnx_artifacts": [
|
|
|
|
| 1068 |
"fp16",
|
| 1069 |
-
"
|
| 1070 |
],
|
| 1071 |
-
"
|
| 1072 |
-
"
|
| 1073 |
-
|
| 1074 |
-
|
| 1075 |
-
|
| 1076 |
-
|
| 1077 |
-
|
| 1078 |
-
"NPU"
|
| 1079 |
-
],
|
| 1080 |
-
"metrics": {
|
| 1081 |
-
"artifacts": {
|
| 1082 |
-
"fp16": {
|
| 1083 |
-
"estimate": {
|
| 1084 |
-
"accuracy": 0.575,
|
| 1085 |
-
"llm_metrics": {
|
| 1086 |
-
"overall": 57.5,
|
| 1087 |
-
"mmlu": 39.5,
|
| 1088 |
-
"gsm8k": 16.5,
|
| 1089 |
-
"hellaswag": 59.0,
|
| 1090 |
-
"truthfulqa": 32.5,
|
| 1091 |
-
"winogrande": 53.5,
|
| 1092 |
-
"arc_challenge": 29.5,
|
| 1093 |
-
"mt_bench": 5.9
|
| 1094 |
-
},
|
| 1095 |
-
"cpu": {
|
| 1096 |
-
"tok_s": 26.0,
|
| 1097 |
-
"latency_ms_p50": 38.0,
|
| 1098 |
-
"peak_mem_mb": 880
|
| 1099 |
-
},
|
| 1100 |
-
"npu": {
|
| 1101 |
-
"tok_s": 62.0,
|
| 1102 |
-
"latency_ms_p50": 15.0,
|
| 1103 |
-
"peak_mem_mb": 520
|
| 1104 |
-
},
|
| 1105 |
-
"dsp": null,
|
| 1106 |
-
"total": {
|
| 1107 |
-
"tok_s": 62.0,
|
| 1108 |
-
"peak_mem_mb": 940,
|
| 1109 |
-
"latency_ms_p50": 53.0
|
| 1110 |
-
},
|
| 1111 |
-
"last_updated": "2026-03-02"
|
| 1112 |
-
},
|
| 1113 |
-
"hil": null
|
| 1114 |
-
},
|
| 1115 |
-
"int8": {
|
| 1116 |
-
"estimate": {
|
| 1117 |
-
"accuracy": 0.567,
|
| 1118 |
-
"llm_metrics": {
|
| 1119 |
-
"overall": 56.7,
|
| 1120 |
-
"mmlu": 38.7,
|
| 1121 |
-
"gsm8k": 15.7,
|
| 1122 |
-
"hellaswag": 58.2,
|
| 1123 |
-
"truthfulqa": 31.7,
|
| 1124 |
-
"winogrande": 52.7,
|
| 1125 |
-
"arc_challenge": 28.7,
|
| 1126 |
-
"mt_bench": 5.8
|
| 1127 |
-
},
|
| 1128 |
-
"cpu": {
|
| 1129 |
-
"tok_s": 26.0,
|
| 1130 |
-
"latency_ms_p50": 38.0,
|
| 1131 |
-
"peak_mem_mb": 880
|
| 1132 |
-
},
|
| 1133 |
-
"npu": {
|
| 1134 |
-
"tok_s": 62.0,
|
| 1135 |
-
"latency_ms_p50": 15.0,
|
| 1136 |
-
"peak_mem_mb": 520
|
| 1137 |
-
},
|
| 1138 |
-
"dsp": null,
|
| 1139 |
-
"total": {
|
| 1140 |
-
"tok_s": 62.0,
|
| 1141 |
-
"peak_mem_mb": 940,
|
| 1142 |
-
"latency_ms_p50": 53.0
|
| 1143 |
-
},
|
| 1144 |
-
"last_updated": "2026-03-02"
|
| 1145 |
-
},
|
| 1146 |
-
"hil": null
|
| 1147 |
-
}
|
| 1148 |
-
}
|
| 1149 |
-
}
|
| 1150 |
-
}
|
| 1151 |
-
]
|
| 1152 |
-
},
|
| 1153 |
-
{
|
| 1154 |
-
"key": "mamba2-1p3b",
|
| 1155 |
-
"display_name": "Mamba2-1.3B",
|
| 1156 |
-
"architecture": "Mamba2-1.3B",
|
| 1157 |
-
"model_size_m": 1300,
|
| 1158 |
-
"modality": "LLM",
|
| 1159 |
-
"variant": "Base",
|
| 1160 |
-
"targets": [
|
| 1161 |
-
"CPU",
|
| 1162 |
-
"NPU"
|
| 1163 |
],
|
| 1164 |
-
"
|
| 1165 |
-
"
|
| 1166 |
-
"onnx_artifacts": [
|
| 1167 |
-
"fp16",
|
| 1168 |
-
"int8"
|
| 1169 |
-
],
|
| 1170 |
-
"gguf_artifacts": [],
|
| 1171 |
"hardware_configs": [
|
| 1172 |
{
|
| 1173 |
-
"id": "
|
| 1174 |
-
"label": "X5H
|
| 1175 |
"targets": [
|
| 1176 |
-
"CPU",
|
| 1177 |
"NPU"
|
| 1178 |
],
|
|
|
|
| 1179 |
"metrics": {
|
| 1180 |
"artifacts": {
|
| 1181 |
"fp16": {
|
| 1182 |
-
"estimate":
|
| 1183 |
-
"accuracy": 0.594,
|
| 1184 |
-
"llm_metrics": {
|
| 1185 |
-
"overall": 59.4,
|
| 1186 |
-
"mmlu": 41.4,
|
| 1187 |
-
"gsm8k": 18.4,
|
| 1188 |
-
"hellaswag": 60.9,
|
| 1189 |
-
"truthfulqa": 34.4,
|
| 1190 |
-
"winogrande": 55.4,
|
| 1191 |
-
"arc_challenge": 31.4,
|
| 1192 |
-
"mt_bench": 6.0
|
| 1193 |
-
},
|
| 1194 |
-
"cpu": {
|
| 1195 |
-
"tok_s": 28.0,
|
| 1196 |
-
"latency_ms_p50": 35.0,
|
| 1197 |
-
"peak_mem_mb": 860
|
| 1198 |
-
},
|
| 1199 |
-
"npu": {
|
| 1200 |
-
"tok_s": 68.0,
|
| 1201 |
-
"latency_ms_p50": 14.0,
|
| 1202 |
-
"peak_mem_mb": 500
|
| 1203 |
-
},
|
| 1204 |
-
"dsp": null,
|
| 1205 |
-
"total": {
|
| 1206 |
-
"tok_s": 68.0,
|
| 1207 |
-
"peak_mem_mb": 920,
|
| 1208 |
-
"latency_ms_p50": 49.0
|
| 1209 |
-
},
|
| 1210 |
-
"last_updated": "2026-03-02"
|
| 1211 |
-
},
|
| 1212 |
"hil": {
|
| 1213 |
-
"accuracy":
|
| 1214 |
-
"llm_metrics": {
|
| 1215 |
-
"overall": 58.8,
|
| 1216 |
-
"mmlu": 40.8,
|
| 1217 |
-
"gsm8k": 17.8,
|
| 1218 |
-
"hellaswag": 60.3,
|
| 1219 |
-
"truthfulqa": 33.8,
|
| 1220 |
-
"winogrande": 54.8,
|
| 1221 |
-
"arc_challenge": 30.8,
|
| 1222 |
-
"mt_bench": 5.9
|
| 1223 |
-
},
|
| 1224 |
-
"cpu": {
|
| 1225 |
-
"tok_s": 25.5,
|
| 1226 |
-
"latency_ms_p50": 39.0,
|
| 1227 |
-
"peak_mem_mb": 900
|
| 1228 |
-
},
|
| 1229 |
"npu": {
|
| 1230 |
-
"tok_s":
|
| 1231 |
-
"latency_ms_p50":
|
| 1232 |
-
"peak_mem_mb":
|
| 1233 |
},
|
| 1234 |
-
"dsp": null,
|
| 1235 |
"total": {
|
| 1236 |
-
"tok_s":
|
| 1237 |
-
"
|
| 1238 |
-
"
|
| 1239 |
},
|
| 1240 |
-
"
|
| 1241 |
-
"
|
|
|
|
|
|
|
|
|
|
| 1242 |
}
|
| 1243 |
},
|
| 1244 |
-
"
|
| 1245 |
-
"estimate":
|
| 1246 |
-
"accuracy": 0.586,
|
| 1247 |
-
"llm_metrics": {
|
| 1248 |
-
"overall": 58.6,
|
| 1249 |
-
"mmlu": 40.6,
|
| 1250 |
-
"gsm8k": 17.6,
|
| 1251 |
-
"hellaswag": 60.1,
|
| 1252 |
-
"truthfulqa": 33.6,
|
| 1253 |
-
"winogrande": 54.6,
|
| 1254 |
-
"arc_challenge": 30.6,
|
| 1255 |
-
"mt_bench": 5.9
|
| 1256 |
-
},
|
| 1257 |
-
"cpu": {
|
| 1258 |
-
"tok_s": 28.0,
|
| 1259 |
-
"latency_ms_p50": 35.0,
|
| 1260 |
-
"peak_mem_mb": 860
|
| 1261 |
-
},
|
| 1262 |
-
"npu": {
|
| 1263 |
-
"tok_s": 68.0,
|
| 1264 |
-
"latency_ms_p50": 14.0,
|
| 1265 |
-
"peak_mem_mb": 500
|
| 1266 |
-
},
|
| 1267 |
-
"dsp": null,
|
| 1268 |
-
"total": {
|
| 1269 |
-
"tok_s": 68.0,
|
| 1270 |
-
"peak_mem_mb": 920,
|
| 1271 |
-
"latency_ms_p50": 49.0
|
| 1272 |
-
},
|
| 1273 |
-
"last_updated": "2026-03-02"
|
| 1274 |
-
},
|
| 1275 |
"hil": {
|
| 1276 |
-
"accuracy":
|
| 1277 |
-
"llm_metrics": {
|
| 1278 |
-
"overall": 58.0,
|
| 1279 |
-
"mmlu": 40.0,
|
| 1280 |
-
"gsm8k": 17.0,
|
| 1281 |
-
"hellaswag": 59.5,
|
| 1282 |
-
"truthfulqa": 33.0,
|
| 1283 |
-
"winogrande": 54.0,
|
| 1284 |
-
"arc_challenge": 30.0,
|
| 1285 |
-
"mt_bench": 5.9
|
| 1286 |
-
},
|
| 1287 |
-
"cpu": {
|
| 1288 |
-
"tok_s": 25.5,
|
| 1289 |
-
"latency_ms_p50": 39.0,
|
| 1290 |
-
"peak_mem_mb": 900
|
| 1291 |
-
},
|
| 1292 |
"npu": {
|
| 1293 |
-
"tok_s":
|
| 1294 |
-
"latency_ms_p50":
|
| 1295 |
-
"peak_mem_mb":
|
| 1296 |
},
|
| 1297 |
-
"dsp": null,
|
| 1298 |
"total": {
|
| 1299 |
-
"tok_s":
|
| 1300 |
-
"
|
| 1301 |
-
"
|
| 1302 |
},
|
| 1303 |
-
"
|
| 1304 |
-
"
|
|
|
|
|
|
|
|
|
|
| 1305 |
}
|
| 1306 |
}
|
| 1307 |
}
|
|
@@ -1310,533 +382,70 @@
|
|
| 1310 |
]
|
| 1311 |
},
|
| 1312 |
{
|
| 1313 |
-
"key": "
|
| 1314 |
-
"display_name": "
|
| 1315 |
-
"architecture": "
|
| 1316 |
-
"model_size_m":
|
| 1317 |
"modality": "LLM",
|
| 1318 |
"variant": "Instruct",
|
| 1319 |
"targets": [
|
| 1320 |
-
"CPU",
|
| 1321 |
"NPU"
|
| 1322 |
],
|
| 1323 |
-
"onnx_repo": "
|
| 1324 |
-
"gguf_repo": "Renesas/
|
| 1325 |
-
"onnx_artifacts": [
|
| 1326 |
-
"fp16",
|
| 1327 |
-
"int8"
|
| 1328 |
-
],
|
| 1329 |
"gguf_artifacts": [
|
| 1330 |
-
"
|
| 1331 |
-
"
|
| 1332 |
-
],
|
| 1333 |
-
"hardware_configs": [
|
| 1334 |
-
{
|
| 1335 |
-
"id": "X5H-200TOPS",
|
| 1336 |
-
"label": "X5H 200TOPS Reference Platform",
|
| 1337 |
-
"targets": [
|
| 1338 |
-
"CPU",
|
| 1339 |
-
"NPU"
|
| 1340 |
-
],
|
| 1341 |
-
"metrics": {
|
| 1342 |
-
"artifacts": {
|
| 1343 |
-
"fp16": {
|
| 1344 |
-
"estimate": {
|
| 1345 |
-
"accuracy": 0.66,
|
| 1346 |
-
"llm_metrics": {
|
| 1347 |
-
"overall": 66.0,
|
| 1348 |
-
"mmlu": 48.0,
|
| 1349 |
-
"gsm8k": 25.0,
|
| 1350 |
-
"hellaswag": 67.5,
|
| 1351 |
-
"truthfulqa": 41.0,
|
| 1352 |
-
"winogrande": 62.0,
|
| 1353 |
-
"arc_challenge": 38.0,
|
| 1354 |
-
"mt_bench": 6.3
|
| 1355 |
-
},
|
| 1356 |
-
"cpu": {
|
| 1357 |
-
"tok_s": 14.0,
|
| 1358 |
-
"latency_ms_p50": 72.0,
|
| 1359 |
-
"peak_mem_mb": 1050
|
| 1360 |
-
},
|
| 1361 |
-
"npu": {
|
| 1362 |
-
"tok_s": 34.0,
|
| 1363 |
-
"latency_ms_p50": 28.0,
|
| 1364 |
-
"peak_mem_mb": 720
|
| 1365 |
-
},
|
| 1366 |
-
"dsp": null,
|
| 1367 |
-
"total": {
|
| 1368 |
-
"tok_s": 34.0,
|
| 1369 |
-
"peak_mem_mb": 1120,
|
| 1370 |
-
"latency_ms_p50": 100.0
|
| 1371 |
-
},
|
| 1372 |
-
"last_updated": "2026-03-02"
|
| 1373 |
-
},
|
| 1374 |
-
"hil": null
|
| 1375 |
-
},
|
| 1376 |
-
"int8": {
|
| 1377 |
-
"estimate": {
|
| 1378 |
-
"accuracy": 0.652,
|
| 1379 |
-
"llm_metrics": {
|
| 1380 |
-
"overall": 65.2,
|
| 1381 |
-
"mmlu": 47.2,
|
| 1382 |
-
"gsm8k": 24.2,
|
| 1383 |
-
"hellaswag": 66.7,
|
| 1384 |
-
"truthfulqa": 40.2,
|
| 1385 |
-
"winogrande": 61.2,
|
| 1386 |
-
"arc_challenge": 37.2,
|
| 1387 |
-
"mt_bench": 6.3
|
| 1388 |
-
},
|
| 1389 |
-
"cpu": {
|
| 1390 |
-
"tok_s": 14.0,
|
| 1391 |
-
"latency_ms_p50": 72.0,
|
| 1392 |
-
"peak_mem_mb": 1050
|
| 1393 |
-
},
|
| 1394 |
-
"npu": {
|
| 1395 |
-
"tok_s": 34.0,
|
| 1396 |
-
"latency_ms_p50": 28.0,
|
| 1397 |
-
"peak_mem_mb": 720
|
| 1398 |
-
},
|
| 1399 |
-
"dsp": null,
|
| 1400 |
-
"total": {
|
| 1401 |
-
"tok_s": 34.0,
|
| 1402 |
-
"peak_mem_mb": 1120,
|
| 1403 |
-
"latency_ms_p50": 100.0
|
| 1404 |
-
},
|
| 1405 |
-
"last_updated": "2026-03-02"
|
| 1406 |
-
},
|
| 1407 |
-
"hil": null
|
| 1408 |
-
},
|
| 1409 |
-
"Q4_K_M": {
|
| 1410 |
-
"estimate": {
|
| 1411 |
-
"accuracy": 0.625,
|
| 1412 |
-
"llm_metrics": {
|
| 1413 |
-
"overall": 62.5,
|
| 1414 |
-
"mmlu": 44.5,
|
| 1415 |
-
"gsm8k": 21.5,
|
| 1416 |
-
"hellaswag": 64.0,
|
| 1417 |
-
"truthfulqa": 37.5,
|
| 1418 |
-
"winogrande": 58.5,
|
| 1419 |
-
"arc_challenge": 34.5,
|
| 1420 |
-
"mt_bench": 6.1
|
| 1421 |
-
},
|
| 1422 |
-
"cpu": {
|
| 1423 |
-
"tok_s": 14.0,
|
| 1424 |
-
"latency_ms_p50": 72.0,
|
| 1425 |
-
"peak_mem_mb": 1050
|
| 1426 |
-
},
|
| 1427 |
-
"npu": {
|
| 1428 |
-
"tok_s": 34.0,
|
| 1429 |
-
"latency_ms_p50": 28.0,
|
| 1430 |
-
"peak_mem_mb": 720
|
| 1431 |
-
},
|
| 1432 |
-
"dsp": null,
|
| 1433 |
-
"total": {
|
| 1434 |
-
"tok_s": 34.0,
|
| 1435 |
-
"peak_mem_mb": 1120,
|
| 1436 |
-
"latency_ms_p50": 100.0
|
| 1437 |
-
},
|
| 1438 |
-
"last_updated": "2026-03-02"
|
| 1439 |
-
},
|
| 1440 |
-
"hil": null
|
| 1441 |
-
},
|
| 1442 |
-
"Q8_0": {
|
| 1443 |
-
"estimate": {
|
| 1444 |
-
"accuracy": 0.647,
|
| 1445 |
-
"llm_metrics": {
|
| 1446 |
-
"overall": 64.7,
|
| 1447 |
-
"mmlu": 46.7,
|
| 1448 |
-
"gsm8k": 23.7,
|
| 1449 |
-
"hellaswag": 66.2,
|
| 1450 |
-
"truthfulqa": 39.7,
|
| 1451 |
-
"winogrande": 60.7,
|
| 1452 |
-
"arc_challenge": 36.7,
|
| 1453 |
-
"mt_bench": 6.2
|
| 1454 |
-
},
|
| 1455 |
-
"cpu": {
|
| 1456 |
-
"tok_s": 14.0,
|
| 1457 |
-
"latency_ms_p50": 72.0,
|
| 1458 |
-
"peak_mem_mb": 1050
|
| 1459 |
-
},
|
| 1460 |
-
"npu": {
|
| 1461 |
-
"tok_s": 34.0,
|
| 1462 |
-
"latency_ms_p50": 28.0,
|
| 1463 |
-
"peak_mem_mb": 720
|
| 1464 |
-
},
|
| 1465 |
-
"dsp": null,
|
| 1466 |
-
"total": {
|
| 1467 |
-
"tok_s": 34.0,
|
| 1468 |
-
"peak_mem_mb": 1120,
|
| 1469 |
-
"latency_ms_p50": 100.0
|
| 1470 |
-
},
|
| 1471 |
-
"last_updated": "2026-03-02"
|
| 1472 |
-
},
|
| 1473 |
-
"hil": null
|
| 1474 |
-
}
|
| 1475 |
-
}
|
| 1476 |
-
}
|
| 1477 |
-
}
|
| 1478 |
-
]
|
| 1479 |
-
},
|
| 1480 |
-
{
|
| 1481 |
-
"key": "zamba-2p7b-instruct",
|
| 1482 |
-
"display_name": "Zamba-2.7B Instruct",
|
| 1483 |
-
"architecture": "Zamba-2.7B",
|
| 1484 |
-
"model_size_m": 2700,
|
| 1485 |
-
"modality": "LLM",
|
| 1486 |
-
"variant": "Instruct",
|
| 1487 |
-
"targets": [
|
| 1488 |
-
"CPU",
|
| 1489 |
-
"NPU"
|
| 1490 |
-
],
|
| 1491 |
-
"onnx_repo": "Renesas/Zamba-2.7B-Instruct-ONNX",
|
| 1492 |
-
"gguf_repo": "Renesas/Zamba-2.7B-Instruct-GGUF",
|
| 1493 |
-
"onnx_artifacts": [
|
| 1494 |
-
"fp16",
|
| 1495 |
-
"int8"
|
| 1496 |
],
|
| 1497 |
-
"
|
| 1498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1499 |
],
|
|
|
|
|
|
|
| 1500 |
"hardware_configs": [
|
| 1501 |
{
|
| 1502 |
-
"id": "
|
| 1503 |
-
"label": "X5H
|
| 1504 |
"targets": [
|
| 1505 |
-
"CPU",
|
| 1506 |
"NPU"
|
| 1507 |
],
|
|
|
|
| 1508 |
"metrics": {
|
| 1509 |
"artifacts": {
|
| 1510 |
"fp16": {
|
| 1511 |
-
"estimate":
|
| 1512 |
-
|
| 1513 |
-
"llm_metrics": {
|
| 1514 |
-
"overall": 71.9,
|
| 1515 |
-
"mmlu": 53.9,
|
| 1516 |
-
"gsm8k": 30.9,
|
| 1517 |
-
"hellaswag": 73.4,
|
| 1518 |
-
"truthfulqa": 46.9,
|
| 1519 |
-
"winogrande": 67.9,
|
| 1520 |
-
"arc_challenge": 43.9,
|
| 1521 |
-
"mt_bench": 6.6
|
| 1522 |
-
},
|
| 1523 |
-
"cpu": {
|
| 1524 |
-
"tok_s": 8.5,
|
| 1525 |
-
"latency_ms_p50": 112.0,
|
| 1526 |
-
"peak_mem_mb": 1620
|
| 1527 |
-
},
|
| 1528 |
-
"npu": {
|
| 1529 |
-
"tok_s": 22.0,
|
| 1530 |
-
"latency_ms_p50": 46.0,
|
| 1531 |
-
"peak_mem_mb": 1180
|
| 1532 |
-
},
|
| 1533 |
-
"dsp": null,
|
| 1534 |
-
"total": {
|
| 1535 |
-
"tok_s": 22.0,
|
| 1536 |
-
"peak_mem_mb": 1720,
|
| 1537 |
-
"latency_ms_p50": 158.0
|
| 1538 |
-
},
|
| 1539 |
-
"last_updated": "2026-03-02"
|
| 1540 |
-
},
|
| 1541 |
-
"hil": {
|
| 1542 |
-
"accuracy": 0.713,
|
| 1543 |
-
"llm_metrics": {
|
| 1544 |
-
"overall": 71.3,
|
| 1545 |
-
"mmlu": 53.3,
|
| 1546 |
-
"gsm8k": 30.3,
|
| 1547 |
-
"hellaswag": 72.8,
|
| 1548 |
-
"truthfulqa": 46.3,
|
| 1549 |
-
"winogrande": 67.3,
|
| 1550 |
-
"arc_challenge": 43.3,
|
| 1551 |
-
"mt_bench": 6.6
|
| 1552 |
-
},
|
| 1553 |
-
"cpu": {
|
| 1554 |
-
"tok_s": 7.9,
|
| 1555 |
-
"latency_ms_p50": 120.0,
|
| 1556 |
-
"peak_mem_mb": 1680
|
| 1557 |
-
},
|
| 1558 |
-
"npu": {
|
| 1559 |
-
"tok_s": 19.5,
|
| 1560 |
-
"latency_ms_p50": 52.0,
|
| 1561 |
-
"peak_mem_mb": 1240
|
| 1562 |
-
},
|
| 1563 |
-
"dsp": null,
|
| 1564 |
-
"total": {
|
| 1565 |
-
"tok_s": 19.5,
|
| 1566 |
-
"peak_mem_mb": 1800,
|
| 1567 |
-
"latency_ms_p50": 172.0
|
| 1568 |
-
},
|
| 1569 |
-
"setup": "DEMO-HIL-RIG-2",
|
| 1570 |
-
"last_updated": "2026-03-03"
|
| 1571 |
-
}
|
| 1572 |
-
},
|
| 1573 |
-
"int8": {
|
| 1574 |
-
"estimate": {
|
| 1575 |
-
"accuracy": 0.711,
|
| 1576 |
-
"llm_metrics": {
|
| 1577 |
-
"overall": 71.1,
|
| 1578 |
-
"mmlu": 53.1,
|
| 1579 |
-
"gsm8k": 30.1,
|
| 1580 |
-
"hellaswag": 72.6,
|
| 1581 |
-
"truthfulqa": 46.1,
|
| 1582 |
-
"winogrande": 67.1,
|
| 1583 |
-
"arc_challenge": 43.1,
|
| 1584 |
-
"mt_bench": 6.6
|
| 1585 |
-
},
|
| 1586 |
-
"cpu": {
|
| 1587 |
-
"tok_s": 8.5,
|
| 1588 |
-
"latency_ms_p50": 112.0,
|
| 1589 |
-
"peak_mem_mb": 1620
|
| 1590 |
-
},
|
| 1591 |
-
"npu": {
|
| 1592 |
-
"tok_s": 22.0,
|
| 1593 |
-
"latency_ms_p50": 46.0,
|
| 1594 |
-
"peak_mem_mb": 1180
|
| 1595 |
-
},
|
| 1596 |
-
"dsp": null,
|
| 1597 |
-
"total": {
|
| 1598 |
-
"tok_s": 22.0,
|
| 1599 |
-
"peak_mem_mb": 1720,
|
| 1600 |
-
"latency_ms_p50": 158.0
|
| 1601 |
-
},
|
| 1602 |
-
"last_updated": "2026-03-02"
|
| 1603 |
-
},
|
| 1604 |
-
"hil": {
|
| 1605 |
-
"accuracy": 0.705,
|
| 1606 |
-
"llm_metrics": {
|
| 1607 |
-
"overall": 70.5,
|
| 1608 |
-
"mmlu": 52.5,
|
| 1609 |
-
"gsm8k": 29.5,
|
| 1610 |
-
"hellaswag": 72.0,
|
| 1611 |
-
"truthfulqa": 45.5,
|
| 1612 |
-
"winogrande": 66.5,
|
| 1613 |
-
"arc_challenge": 42.5,
|
| 1614 |
-
"mt_bench": 6.5
|
| 1615 |
-
},
|
| 1616 |
-
"cpu": {
|
| 1617 |
-
"tok_s": 7.9,
|
| 1618 |
-
"latency_ms_p50": 120.0,
|
| 1619 |
-
"peak_mem_mb": 1680
|
| 1620 |
-
},
|
| 1621 |
-
"npu": {
|
| 1622 |
-
"tok_s": 19.5,
|
| 1623 |
-
"latency_ms_p50": 52.0,
|
| 1624 |
-
"peak_mem_mb": 1240
|
| 1625 |
-
},
|
| 1626 |
-
"dsp": null,
|
| 1627 |
-
"total": {
|
| 1628 |
-
"tok_s": 19.5,
|
| 1629 |
-
"peak_mem_mb": 1800,
|
| 1630 |
-
"latency_ms_p50": 172.0
|
| 1631 |
-
},
|
| 1632 |
-
"setup": "DEMO-HIL-RIG-2",
|
| 1633 |
-
"last_updated": "2026-03-03"
|
| 1634 |
-
}
|
| 1635 |
},
|
| 1636 |
-
"
|
| 1637 |
-
"estimate":
|
| 1638 |
-
"accuracy": 0.684,
|
| 1639 |
-
"llm_metrics": {
|
| 1640 |
-
"overall": 68.4,
|
| 1641 |
-
"mmlu": 50.4,
|
| 1642 |
-
"gsm8k": 27.4,
|
| 1643 |
-
"hellaswag": 69.9,
|
| 1644 |
-
"truthfulqa": 43.4,
|
| 1645 |
-
"winogrande": 64.4,
|
| 1646 |
-
"arc_challenge": 40.4,
|
| 1647 |
-
"mt_bench": 6.4
|
| 1648 |
-
},
|
| 1649 |
-
"cpu": {
|
| 1650 |
-
"tok_s": 8.5,
|
| 1651 |
-
"latency_ms_p50": 112.0,
|
| 1652 |
-
"peak_mem_mb": 1620
|
| 1653 |
-
},
|
| 1654 |
-
"npu": {
|
| 1655 |
-
"tok_s": 22.0,
|
| 1656 |
-
"latency_ms_p50": 46.0,
|
| 1657 |
-
"peak_mem_mb": 1180
|
| 1658 |
-
},
|
| 1659 |
-
"dsp": null,
|
| 1660 |
-
"total": {
|
| 1661 |
-
"tok_s": 22.0,
|
| 1662 |
-
"peak_mem_mb": 1720,
|
| 1663 |
-
"latency_ms_p50": 158.0
|
| 1664 |
-
},
|
| 1665 |
-
"last_updated": "2026-03-02"
|
| 1666 |
-
},
|
| 1667 |
"hil": {
|
| 1668 |
-
"accuracy":
|
| 1669 |
-
"llm_metrics": {
|
| 1670 |
-
"overall": 67.8,
|
| 1671 |
-
"mmlu": 49.8,
|
| 1672 |
-
"gsm8k": 26.8,
|
| 1673 |
-
"hellaswag": 69.3,
|
| 1674 |
-
"truthfulqa": 42.8,
|
| 1675 |
-
"winogrande": 63.8,
|
| 1676 |
-
"arc_challenge": 39.8,
|
| 1677 |
-
"mt_bench": 6.4
|
| 1678 |
-
},
|
| 1679 |
-
"cpu": {
|
| 1680 |
-
"tok_s": 7.9,
|
| 1681 |
-
"latency_ms_p50": 120.0,
|
| 1682 |
-
"peak_mem_mb": 1680
|
| 1683 |
-
},
|
| 1684 |
"npu": {
|
| 1685 |
-
"tok_s":
|
| 1686 |
-
"latency_ms_p50":
|
| 1687 |
-
"peak_mem_mb":
|
| 1688 |
},
|
| 1689 |
-
"dsp": null,
|
| 1690 |
"total": {
|
| 1691 |
-
"tok_s":
|
| 1692 |
-
"
|
| 1693 |
-
"
|
| 1694 |
},
|
| 1695 |
-
"
|
| 1696 |
-
"
|
|
|
|
|
|
|
|
|
|
| 1697 |
}
|
| 1698 |
}
|
| 1699 |
}
|
| 1700 |
}
|
| 1701 |
}
|
| 1702 |
]
|
| 1703 |
-
},
|
| 1704 |
-
{
|
| 1705 |
-
"key": "llava-7b",
|
| 1706 |
-
"display_name": "LLaVA-7B",
|
| 1707 |
-
"architecture": "LLaVA-7B",
|
| 1708 |
-
"model_size_m": 7000,
|
| 1709 |
-
"modality": "VLM",
|
| 1710 |
-
"variant": "Chat",
|
| 1711 |
-
"targets": [
|
| 1712 |
-
"CPU",
|
| 1713 |
-
"NPU",
|
| 1714 |
-
"DSP"
|
| 1715 |
-
],
|
| 1716 |
-
"onnx_repo": "Renesas/LLaVA-7B-ONNX",
|
| 1717 |
-
"gguf_repo": "Renesas/LLaVA-7B-GGUF",
|
| 1718 |
-
"onnx_artifacts": [
|
| 1719 |
-
"fp16",
|
| 1720 |
-
"int8"
|
| 1721 |
-
],
|
| 1722 |
-
"gguf_artifacts": [
|
| 1723 |
-
"Q4_K_M"
|
| 1724 |
-
],
|
| 1725 |
-
"hardware_configs": [
|
| 1726 |
-
{
|
| 1727 |
-
"id": "X5H-100TOPS",
|
| 1728 |
-
"label": "X5H 100TOPS Reference Platform",
|
| 1729 |
-
"targets": [
|
| 1730 |
-
"CPU",
|
| 1731 |
-
"NPU",
|
| 1732 |
-
"DSP"
|
| 1733 |
-
],
|
| 1734 |
-
"notes": "Example showing DSP used for vision preprocessing",
|
| 1735 |
-
"metrics": {
|
| 1736 |
-
"artifacts": {
|
| 1737 |
-
"fp16": {
|
| 1738 |
-
"estimate": {
|
| 1739 |
-
"accuracy": 0.699,
|
| 1740 |
-
"vlm_metrics": {
|
| 1741 |
-
"overall": 69.9,
|
| 1742 |
-
"mmbench": 64.9,
|
| 1743 |
-
"vqav2": 71.9,
|
| 1744 |
-
"seedbench": 61.9,
|
| 1745 |
-
"pope": 66.9
|
| 1746 |
-
},
|
| 1747 |
-
"cpu": {
|
| 1748 |
-
"tok_s": 2.2,
|
| 1749 |
-
"latency_ms_p50": 420.0,
|
| 1750 |
-
"peak_mem_mb": 4100
|
| 1751 |
-
},
|
| 1752 |
-
"npu": {
|
| 1753 |
-
"tok_s": 6.0,
|
| 1754 |
-
"latency_ms_p50": 155.0,
|
| 1755 |
-
"peak_mem_mb": 2800
|
| 1756 |
-
},
|
| 1757 |
-
"dsp": {
|
| 1758 |
-
"latency_ms_p50": 18.0,
|
| 1759 |
-
"peak_mem_mb": 64
|
| 1760 |
-
},
|
| 1761 |
-
"total": {
|
| 1762 |
-
"tok_s": 6.0,
|
| 1763 |
-
"peak_mem_mb": 4300,
|
| 1764 |
-
"latency_ms_p50": 593.0
|
| 1765 |
-
},
|
| 1766 |
-
"last_updated": "2026-03-03"
|
| 1767 |
-
},
|
| 1768 |
-
"hil": null
|
| 1769 |
-
},
|
| 1770 |
-
"int8": {
|
| 1771 |
-
"estimate": {
|
| 1772 |
-
"accuracy": 0.691,
|
| 1773 |
-
"vlm_metrics": {
|
| 1774 |
-
"overall": 69.1,
|
| 1775 |
-
"mmbench": 64.1,
|
| 1776 |
-
"vqav2": 71.1,
|
| 1777 |
-
"seedbench": 61.1,
|
| 1778 |
-
"pope": 66.1
|
| 1779 |
-
},
|
| 1780 |
-
"cpu": {
|
| 1781 |
-
"tok_s": 2.2,
|
| 1782 |
-
"latency_ms_p50": 420.0,
|
| 1783 |
-
"peak_mem_mb": 4100
|
| 1784 |
-
},
|
| 1785 |
-
"npu": {
|
| 1786 |
-
"tok_s": 6.0,
|
| 1787 |
-
"latency_ms_p50": 155.0,
|
| 1788 |
-
"peak_mem_mb": 2800
|
| 1789 |
-
},
|
| 1790 |
-
"dsp": {
|
| 1791 |
-
"latency_ms_p50": 18.0,
|
| 1792 |
-
"peak_mem_mb": 64
|
| 1793 |
-
},
|
| 1794 |
-
"total": {
|
| 1795 |
-
"tok_s": 6.0,
|
| 1796 |
-
"peak_mem_mb": 4300,
|
| 1797 |
-
"latency_ms_p50": 593.0
|
| 1798 |
-
},
|
| 1799 |
-
"last_updated": "2026-03-03"
|
| 1800 |
-
},
|
| 1801 |
-
"hil": null
|
| 1802 |
-
},
|
| 1803 |
-
"Q4_K_M": {
|
| 1804 |
-
"estimate": {
|
| 1805 |
-
"accuracy": 0.664,
|
| 1806 |
-
"vlm_metrics": {
|
| 1807 |
-
"overall": 66.4,
|
| 1808 |
-
"mmbench": 61.4,
|
| 1809 |
-
"vqav2": 68.4,
|
| 1810 |
-
"seedbench": 58.4,
|
| 1811 |
-
"pope": 63.4
|
| 1812 |
-
},
|
| 1813 |
-
"cpu": {
|
| 1814 |
-
"tok_s": 2.2,
|
| 1815 |
-
"latency_ms_p50": 420.0,
|
| 1816 |
-
"peak_mem_mb": 4100
|
| 1817 |
-
},
|
| 1818 |
-
"npu": {
|
| 1819 |
-
"tok_s": 6.0,
|
| 1820 |
-
"latency_ms_p50": 155.0,
|
| 1821 |
-
"peak_mem_mb": 2800
|
| 1822 |
-
},
|
| 1823 |
-
"dsp": {
|
| 1824 |
-
"latency_ms_p50": 18.0,
|
| 1825 |
-
"peak_mem_mb": 64
|
| 1826 |
-
},
|
| 1827 |
-
"total": {
|
| 1828 |
-
"tok_s": 6.0,
|
| 1829 |
-
"peak_mem_mb": 4300,
|
| 1830 |
-
"latency_ms_p50": 593.0
|
| 1831 |
-
},
|
| 1832 |
-
"last_updated": "2026-03-03"
|
| 1833 |
-
},
|
| 1834 |
-
"hil": null
|
| 1835 |
-
}
|
| 1836 |
-
}
|
| 1837 |
-
}
|
| 1838 |
-
}
|
| 1839 |
-
]
|
| 1840 |
}
|
| 1841 |
]
|
| 1842 |
-
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"version": "1.0-auto",
|
| 3 |
+
"generated_at": "2026-06-23T16:50:24+02:00",
|
| 4 |
+
"source": "huggingface",
|
| 5 |
+
"org": "Renesas",
|
| 6 |
+
"catalog_note": "Auto-generated from Hugging Face 'Renesas' repositories on 2026-06-23 16:50 W. Europe Daylight Time. Metrics reflect each repo's published benchmark YAML files.",
|
| 7 |
"models": [
|
| 8 |
{
|
| 9 |
+
"key": "llama-3.2-1b-instruct",
|
| 10 |
+
"display_name": "Llama-3.2-1B-Instruct",
|
| 11 |
+
"architecture": "Llama-3.2-1B",
|
| 12 |
"model_size_m": 1000,
|
| 13 |
"modality": "LLM",
|
| 14 |
"variant": "Instruct",
|
| 15 |
"targets": [
|
|
|
|
| 16 |
"NPU"
|
| 17 |
],
|
| 18 |
+
"onnx_repo": "Renesas/Llama-3.2-1B-Instruct-ONNX",
|
| 19 |
+
"gguf_repo": "Renesas/Llama-3.2-1B-Instruct-GGUF",
|
| 20 |
"onnx_artifacts": [
|
| 21 |
"fp16",
|
| 22 |
+
"w4a8",
|
| 23 |
+
"fp32"
|
| 24 |
],
|
| 25 |
"gguf_artifacts": [
|
| 26 |
+
"fp16",
|
| 27 |
+
"w4a16"
|
| 28 |
+
],
|
| 29 |
+
"base_model": "meta-llama/Llama-3.2-1B-Instruct",
|
| 30 |
+
"license": "llama3.2",
|
| 31 |
+
"tasks": [
|
| 32 |
+
"text-generation",
|
| 33 |
+
"instruction-following",
|
| 34 |
+
"chat"
|
| 35 |
],
|
| 36 |
+
"created_at": "2026-02-20T08:59:16.000Z",
|
| 37 |
+
"last_modified": "2026-06-22T09:24:19.000Z",
|
| 38 |
"hardware_configs": [
|
| 39 |
{
|
| 40 |
+
"id": "RCAR-X5H",
|
| 41 |
+
"label": "R-Car X5H (NPX6-48K)",
|
| 42 |
"targets": [
|
|
|
|
| 43 |
"NPU"
|
| 44 |
],
|
| 45 |
+
"notes": "vendor=renesas; chip=rcar-x5h; cpu=arm-cortex-a720; npu=npx6-48k; memory_mb=8192",
|
| 46 |
"metrics": {
|
| 47 |
"artifacts": {
|
| 48 |
"fp16": {
|
| 49 |
"estimate": {
|
| 50 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
"npu": {
|
| 52 |
+
"tok_s": 18.73,
|
| 53 |
+
"latency_ms_p50": null,
|
| 54 |
+
"peak_mem_mb": null
|
| 55 |
},
|
|
|
|
| 56 |
"total": {
|
| 57 |
+
"tok_s": 18.73,
|
| 58 |
+
"latency_ms_p50": null,
|
| 59 |
+
"peak_mem_mb": null
|
| 60 |
},
|
| 61 |
+
"engine": "ppa-estimator",
|
| 62 |
+
"execution_provider": "npu",
|
| 63 |
+
"last_updated": "2026-03-09"
|
| 64 |
},
|
| 65 |
"hil": {
|
| 66 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
"npu": {
|
| 68 |
+
"tok_s": 20.25,
|
| 69 |
+
"latency_ms_p50": null,
|
| 70 |
+
"peak_mem_mb": null
|
| 71 |
},
|
|
|
|
| 72 |
"total": {
|
| 73 |
+
"tok_s": 20.25,
|
| 74 |
+
"latency_ms_p50": null,
|
| 75 |
+
"peak_mem_mb": null
|
| 76 |
},
|
| 77 |
+
"engine": "llama.cpp",
|
| 78 |
+
"execution_provider": "npu",
|
| 79 |
+
"last_updated": "2026-06-22",
|
| 80 |
+
"batch_size": 1,
|
| 81 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 82 |
}
|
| 83 |
},
|
| 84 |
+
"w4a16": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
"estimate": null,
|
| 86 |
"hil": {
|
| 87 |
+
"accuracy": null,
|
| 88 |
+
"npu": {
|
| 89 |
+
"tok_s": 41.38,
|
| 90 |
+
"latency_ms_p50": null,
|
| 91 |
+
"peak_mem_mb": null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
},
|
|
|
|
|
|
|
| 93 |
"total": {
|
| 94 |
+
"tok_s": 41.38,
|
| 95 |
+
"latency_ms_p50": null,
|
| 96 |
+
"peak_mem_mb": null
|
| 97 |
},
|
| 98 |
+
"engine": "llama.cpp",
|
| 99 |
+
"execution_provider": "npu",
|
| 100 |
+
"last_updated": "2026-06-22",
|
| 101 |
+
"batch_size": 1,
|
| 102 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 103 |
}
|
| 104 |
},
|
| 105 |
+
"fp32": {
|
| 106 |
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
"hil": null
|
| 108 |
},
|
| 109 |
+
"w4a8": {
|
| 110 |
"estimate": {
|
| 111 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
"npu": {
|
| 113 |
+
"tok_s": 72.98,
|
| 114 |
+
"latency_ms_p50": null,
|
| 115 |
+
"peak_mem_mb": null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
},
|
| 117 |
"total": {
|
| 118 |
+
"tok_s": 72.98,
|
| 119 |
+
"latency_ms_p50": null,
|
| 120 |
+
"peak_mem_mb": null
|
| 121 |
},
|
| 122 |
+
"engine": "ppa-estimator",
|
| 123 |
+
"execution_provider": "bw",
|
| 124 |
+
"last_updated": "2026-03-09"
|
| 125 |
},
|
| 126 |
"hil": null
|
| 127 |
}
|
|
|
|
| 131 |
]
|
| 132 |
},
|
| 133 |
{
|
| 134 |
+
"key": "llama-3.2-3b-instruct",
|
| 135 |
+
"display_name": "Llama-3.2-3B-Instruct",
|
| 136 |
+
"architecture": "Llama-3.2-3B",
|
| 137 |
+
"model_size_m": 3000,
|
| 138 |
"modality": "LLM",
|
| 139 |
"variant": "Instruct",
|
| 140 |
"targets": [
|
|
|
|
| 141 |
"NPU"
|
| 142 |
],
|
| 143 |
"onnx_repo": "",
|
| 144 |
+
"gguf_repo": "Renesas/Llama-3.2-3B-Instruct-GGUF",
|
| 145 |
"onnx_artifacts": [],
|
| 146 |
"gguf_artifacts": [
|
| 147 |
+
"fp16",
|
| 148 |
+
"w4a16"
|
| 149 |
],
|
| 150 |
+
"base_model": "meta-llama/Llama-3.2-3B-Instruct",
|
| 151 |
+
"license": "llama3.2",
|
| 152 |
+
"tasks": [
|
| 153 |
+
"text-generation",
|
| 154 |
+
"instruction-following",
|
| 155 |
+
"chat"
|
| 156 |
+
],
|
| 157 |
+
"created_at": "2026-05-11T09:18:02.000Z",
|
| 158 |
+
"last_modified": "2026-06-22T09:30:11.000Z",
|
| 159 |
"hardware_configs": [
|
| 160 |
{
|
| 161 |
+
"id": "RCAR-X5H",
|
| 162 |
+
"label": "R-Car X5H (NPX6-48K)",
|
| 163 |
"targets": [
|
|
|
|
| 164 |
"NPU"
|
| 165 |
],
|
| 166 |
+
"notes": "vendor=renesas; chip=rcar-x5h; cpu=arm-cortex-a720; npu=npx6-48k; memory_mb=8192",
|
| 167 |
"metrics": {
|
| 168 |
"artifacts": {
|
| 169 |
+
"fp16": {
|
| 170 |
"estimate": null,
|
| 171 |
"hil": {
|
| 172 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
"npu": {
|
| 174 |
+
"tok_s": 8.76,
|
| 175 |
+
"latency_ms_p50": null,
|
| 176 |
+
"peak_mem_mb": null
|
| 177 |
},
|
|
|
|
| 178 |
"total": {
|
| 179 |
+
"tok_s": 8.76,
|
| 180 |
+
"latency_ms_p50": null,
|
| 181 |
+
"peak_mem_mb": null
|
| 182 |
},
|
| 183 |
+
"engine": "llama.cpp",
|
| 184 |
+
"execution_provider": "npu",
|
| 185 |
+
"last_updated": "2026-06-22",
|
| 186 |
+
"batch_size": 1,
|
| 187 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 188 |
}
|
| 189 |
},
|
| 190 |
+
"w4a16": {
|
| 191 |
"estimate": null,
|
| 192 |
"hil": {
|
| 193 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
"npu": {
|
| 195 |
+
"tok_s": 17.46,
|
| 196 |
+
"latency_ms_p50": null,
|
| 197 |
+
"peak_mem_mb": null
|
| 198 |
},
|
|
|
|
| 199 |
"total": {
|
| 200 |
+
"tok_s": 17.46,
|
| 201 |
+
"latency_ms_p50": null,
|
| 202 |
+
"peak_mem_mb": null
|
| 203 |
},
|
| 204 |
+
"engine": "llama.cpp",
|
| 205 |
+
"execution_provider": "npu",
|
| 206 |
+
"last_updated": "2026-06-22",
|
| 207 |
+
"batch_size": 1,
|
| 208 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 209 |
}
|
| 210 |
}
|
| 211 |
}
|
|
|
|
| 214 |
]
|
| 215 |
},
|
| 216 |
{
|
| 217 |
+
"key": "qwen2.5-vl-3b-instruct",
|
| 218 |
+
"display_name": "Qwen2.5-VL-3B-Instruct",
|
| 219 |
+
"architecture": "Qwen2.5-VL-3B",
|
| 220 |
"model_size_m": 3000,
|
| 221 |
"modality": "LLM",
|
| 222 |
"variant": "Instruct",
|
| 223 |
"targets": [
|
|
|
|
| 224 |
"NPU"
|
| 225 |
],
|
| 226 |
+
"onnx_repo": "",
|
| 227 |
+
"gguf_repo": "Renesas/Qwen2.5-VL-3B-Instruct-GGUF",
|
| 228 |
+
"onnx_artifacts": [],
|
| 229 |
+
"gguf_artifacts": [
|
| 230 |
"fp16",
|
| 231 |
+
"w4a16"
|
| 232 |
],
|
| 233 |
+
"base_model": "Qwen/Qwen2.5-VL-3B-Instruct",
|
| 234 |
+
"license": "other",
|
| 235 |
+
"tasks": [
|
| 236 |
+
"image-text-to-text",
|
| 237 |
+
"text-generation",
|
| 238 |
+
"instruction-following",
|
| 239 |
+
"chat"
|
| 240 |
],
|
| 241 |
+
"created_at": "2026-05-13T09:09:11.000Z",
|
| 242 |
+
"last_modified": "2026-06-23T10:48:46.000Z",
|
| 243 |
"hardware_configs": [
|
| 244 |
{
|
| 245 |
+
"id": "RCAR-X5H",
|
| 246 |
+
"label": "R-Car X5H (NPX6-48K)",
|
| 247 |
"targets": [
|
|
|
|
| 248 |
"NPU"
|
| 249 |
],
|
| 250 |
+
"notes": "vendor=renesas; chip=rcar-x5h; cpu=arm-cortex-a720; npu=npx6-48k; memory_mb=8192",
|
| 251 |
"metrics": {
|
| 252 |
"artifacts": {
|
| 253 |
"fp16": {
|
| 254 |
+
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
"hil": {
|
| 256 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
"npu": {
|
| 258 |
+
"tok_s": 8.21,
|
| 259 |
+
"latency_ms_p50": null,
|
| 260 |
+
"peak_mem_mb": null
|
| 261 |
},
|
|
|
|
| 262 |
"total": {
|
| 263 |
+
"tok_s": 8.21,
|
| 264 |
+
"latency_ms_p50": null,
|
| 265 |
+
"peak_mem_mb": null
|
| 266 |
},
|
| 267 |
+
"engine": "llama.cpp",
|
| 268 |
+
"execution_provider": "npu",
|
| 269 |
+
"last_updated": "2026-06-23",
|
| 270 |
+
"batch_size": 1,
|
| 271 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 272 |
}
|
| 273 |
},
|
| 274 |
+
"w4a16": {
|
| 275 |
+
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
"hil": {
|
| 277 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
"npu": {
|
| 279 |
+
"tok_s": 14.09,
|
| 280 |
+
"latency_ms_p50": null,
|
| 281 |
+
"peak_mem_mb": null
|
| 282 |
},
|
|
|
|
| 283 |
"total": {
|
| 284 |
+
"tok_s": 14.09,
|
| 285 |
+
"latency_ms_p50": null,
|
| 286 |
+
"peak_mem_mb": null
|
| 287 |
},
|
| 288 |
+
"engine": "llama.cpp",
|
| 289 |
+
"execution_provider": "npu",
|
| 290 |
+
"last_updated": "2026-06-23",
|
| 291 |
+
"batch_size": 1,
|
| 292 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 293 |
}
|
| 294 |
}
|
| 295 |
}
|
|
|
|
| 298 |
]
|
| 299 |
},
|
| 300 |
{
|
| 301 |
+
"key": "qwen3-vl-4b-instruct",
|
| 302 |
+
"display_name": "Qwen3-VL-4B-Instruct",
|
| 303 |
+
"architecture": "Qwen3-VL-4B",
|
| 304 |
+
"model_size_m": 4000,
|
| 305 |
"modality": "LLM",
|
| 306 |
+
"variant": "Instruct",
|
| 307 |
"targets": [
|
|
|
|
| 308 |
"NPU"
|
| 309 |
],
|
| 310 |
+
"onnx_repo": "",
|
| 311 |
+
"gguf_repo": "Renesas/Qwen3-VL-4B-Instruct-GGUF",
|
| 312 |
+
"onnx_artifacts": [],
|
| 313 |
+
"gguf_artifacts": [
|
| 314 |
"fp16",
|
| 315 |
+
"w4a16"
|
| 316 |
],
|
| 317 |
+
"base_model": "Qwen/Qwen3-VL-4B-Instruct",
|
| 318 |
+
"license": "apache-2.0",
|
| 319 |
+
"tasks": [
|
| 320 |
+
"image-text-to-text",
|
| 321 |
+
"text-generation",
|
| 322 |
+
"instruction-following",
|
| 323 |
+
"chat"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
],
|
| 325 |
+
"created_at": "2026-05-15T09:37:33.000Z",
|
| 326 |
+
"last_modified": "2026-06-23T13:01:38.000Z",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
"hardware_configs": [
|
| 328 |
{
|
| 329 |
+
"id": "RCAR-X5H",
|
| 330 |
+
"label": "R-Car X5H (NPX6-48K)",
|
| 331 |
"targets": [
|
|
|
|
| 332 |
"NPU"
|
| 333 |
],
|
| 334 |
+
"notes": "vendor=renesas; chip=rcar-x5h; cpu=arm-cortex-a720; npu=npx6-48k; memory_mb=8192",
|
| 335 |
"metrics": {
|
| 336 |
"artifacts": {
|
| 337 |
"fp16": {
|
| 338 |
+
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
"hil": {
|
| 340 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
"npu": {
|
| 342 |
+
"tok_s": 6.29,
|
| 343 |
+
"latency_ms_p50": null,
|
| 344 |
+
"peak_mem_mb": null
|
| 345 |
},
|
|
|
|
| 346 |
"total": {
|
| 347 |
+
"tok_s": 6.29,
|
| 348 |
+
"latency_ms_p50": null,
|
| 349 |
+
"peak_mem_mb": null
|
| 350 |
},
|
| 351 |
+
"engine": "llama.cpp",
|
| 352 |
+
"execution_provider": "npu",
|
| 353 |
+
"last_updated": "2026-06-23",
|
| 354 |
+
"batch_size": 1,
|
| 355 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 356 |
}
|
| 357 |
},
|
| 358 |
+
"w4a16": {
|
| 359 |
+
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
"hil": {
|
| 361 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
"npu": {
|
| 363 |
+
"tok_s": 11.48,
|
| 364 |
+
"latency_ms_p50": null,
|
| 365 |
+
"peak_mem_mb": null
|
| 366 |
},
|
|
|
|
| 367 |
"total": {
|
| 368 |
+
"tok_s": 11.48,
|
| 369 |
+
"latency_ms_p50": null,
|
| 370 |
+
"peak_mem_mb": null
|
| 371 |
},
|
| 372 |
+
"engine": "llama.cpp",
|
| 373 |
+
"execution_provider": "npu",
|
| 374 |
+
"last_updated": "2026-06-23",
|
| 375 |
+
"batch_size": 1,
|
| 376 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 377 |
}
|
| 378 |
}
|
| 379 |
}
|
|
|
|
| 382 |
]
|
| 383 |
},
|
| 384 |
{
|
| 385 |
+
"key": "llama-3.1-8b-instruct",
|
| 386 |
+
"display_name": "Llama-3.1-8B-Instruct",
|
| 387 |
+
"architecture": "Llama-3.1-8B",
|
| 388 |
+
"model_size_m": 8000,
|
| 389 |
"modality": "LLM",
|
| 390 |
"variant": "Instruct",
|
| 391 |
"targets": [
|
|
|
|
| 392 |
"NPU"
|
| 393 |
],
|
| 394 |
+
"onnx_repo": "",
|
| 395 |
+
"gguf_repo": "Renesas/Llama-3.1-8B-Instruct-GGUF",
|
| 396 |
+
"onnx_artifacts": [],
|
|
|
|
|
|
|
|
|
|
| 397 |
"gguf_artifacts": [
|
| 398 |
+
"w4a16",
|
| 399 |
+
"fp16"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
],
|
| 401 |
+
"base_model": "meta-llama/Llama-3.1-8B-Instruct",
|
| 402 |
+
"license": "llama3.1",
|
| 403 |
+
"tasks": [
|
| 404 |
+
"text-generation",
|
| 405 |
+
"instruction-following",
|
| 406 |
+
"chat"
|
| 407 |
],
|
| 408 |
+
"created_at": "2026-06-12T09:43:03.000Z",
|
| 409 |
+
"last_modified": "2026-06-19T11:01:35.000Z",
|
| 410 |
"hardware_configs": [
|
| 411 |
{
|
| 412 |
+
"id": "RCAR-X5H",
|
| 413 |
+
"label": "R-Car X5H (NPX6-48K)",
|
| 414 |
"targets": [
|
|
|
|
| 415 |
"NPU"
|
| 416 |
],
|
| 417 |
+
"notes": "vendor=renesas; chip=rcar-x5h; cpu=arm-cortex-a720; npu=npx6-48k; memory_mb=8192",
|
| 418 |
"metrics": {
|
| 419 |
"artifacts": {
|
| 420 |
"fp16": {
|
| 421 |
+
"estimate": null,
|
| 422 |
+
"hil": null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 423 |
},
|
| 424 |
+
"w4a16": {
|
| 425 |
+
"estimate": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
"hil": {
|
| 427 |
+
"accuracy": null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
"npu": {
|
| 429 |
+
"tok_s": 8.59,
|
| 430 |
+
"latency_ms_p50": null,
|
| 431 |
+
"peak_mem_mb": null
|
| 432 |
},
|
|
|
|
| 433 |
"total": {
|
| 434 |
+
"tok_s": 8.59,
|
| 435 |
+
"latency_ms_p50": null,
|
| 436 |
+
"peak_mem_mb": null
|
| 437 |
},
|
| 438 |
+
"engine": "llama.cpp",
|
| 439 |
+
"execution_provider": "npu",
|
| 440 |
+
"last_updated": "2026-06-19",
|
| 441 |
+
"batch_size": 1,
|
| 442 |
+
"setup": "R-Car X5H (NPX6-48K)"
|
| 443 |
}
|
| 444 |
}
|
| 445 |
}
|
| 446 |
}
|
| 447 |
}
|
| 448 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 449 |
}
|
| 450 |
]
|
| 451 |
+
}
|
styles.css
CHANGED
|
@@ -1,18 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
:root {
|
| 2 |
-
--
|
| 3 |
-
--
|
| 4 |
-
--
|
| 5 |
-
--
|
|
|
|
| 6 |
|
| 7 |
-
|
| 8 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
-
--pad: 12px;
|
| 11 |
--radius: 16px;
|
| 12 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
}
|
| 14 |
|
|
|
|
|
|
|
|
|
|
| 15 |
* { box-sizing: border-box; }
|
|
|
|
| 16 |
html, body { height: 100%; }
|
| 17 |
|
| 18 |
body {
|
|
@@ -21,559 +99,992 @@ body {
|
|
| 21 |
display: flex;
|
| 22 |
flex-direction: column;
|
| 23 |
overflow: hidden;
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
/*
|
|
|
|
|
|
|
| 31 |
.topbar {
|
| 32 |
flex: 0 0 auto;
|
| 33 |
z-index: 50;
|
| 34 |
-
border-bottom: 1px solid var(--border);
|
| 35 |
-
background:
|
| 36 |
-
backdrop-filter:
|
|
|
|
|
|
|
| 37 |
}
|
| 38 |
-
|
| 39 |
.topbar-inner {
|
| 40 |
width: 100%;
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
display: grid;
|
| 44 |
-
grid-template-columns: 1fr auto;
|
| 45 |
-
gap: 12px;
|
| 46 |
align-items: center;
|
|
|
|
| 47 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
-
.
|
| 50 |
-
.brand-icon{ height: 34px; width: auto; max-width: 180px; object-fit: contain; }
|
| 51 |
-
.brand-title{ color: var(--text); font-weight: 900; font-size: 1.02rem; line-height: 1.15; }
|
| 52 |
-
.brand-subtitle{ color: rgba(232, 238, 252, 0.72); font-size: 0.82rem; margin-top: 4px; }
|
| 53 |
-
|
| 54 |
-
/* Tabs */
|
| 55 |
-
.tabs { display: flex; gap: 8px; align-items: center; justify-content: flex-end; flex-wrap: wrap; }
|
| 56 |
.nav-item {
|
| 57 |
appearance: none;
|
| 58 |
-
border: 1px solid
|
| 59 |
-
background:
|
| 60 |
-
color:
|
| 61 |
-
border-radius:
|
| 62 |
-
padding: 9px
|
| 63 |
-
font-
|
| 64 |
-
font-
|
|
|
|
|
|
|
| 65 |
cursor: pointer;
|
|
|
|
| 66 |
}
|
|
|
|
| 67 |
.nav-item.active {
|
| 68 |
-
background:
|
| 69 |
-
|
| 70 |
-
box-shadow: 0
|
| 71 |
}
|
| 72 |
|
| 73 |
-
/*
|
| 74 |
-
.
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
width:
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
-
/*
|
|
|
|
|
|
|
|
|
|
| 84 |
.section {
|
| 85 |
display: none;
|
| 86 |
height: 100%;
|
| 87 |
min-height: 0;
|
| 88 |
-
|
| 89 |
-
color: var(--content-text);
|
| 90 |
border-radius: var(--radius);
|
| 91 |
-
border: 1px solid
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
| 93 |
overflow: hidden;
|
| 94 |
}
|
| 95 |
.section.visible { display: flex; flex-direction: column; }
|
| 96 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
-
/*
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
.note { background:
|
| 105 |
-
.note.note-warn{ background:
|
| 106 |
-
.subtle { color:
|
| 107 |
.tight { margin-top: 0.35rem; }
|
| 108 |
-
.no-border{ border-bottom:none !important; padding-bottom:0 !important; }
|
| 109 |
-
|
| 110 |
-
/* Disclaimer overlay */
|
| 111 |
-
.poc-overlay{
|
| 112 |
-
position: fixed;
|
| 113 |
-
top: 10px;
|
| 114 |
-
left: 50%;
|
| 115 |
-
transform: translateX(-50%);
|
| 116 |
-
z-index: 9999;
|
| 117 |
-
max-width: min(820px, calc(100vw - 32px));
|
| 118 |
-
background: rgba(240, 244, 255, 0.70);
|
| 119 |
-
border: 1px solid rgba(76, 110, 245, 0.25);
|
| 120 |
-
border-left: 4px solid var(--accent);
|
| 121 |
-
border-radius: 12px;
|
| 122 |
-
padding: 10px 12px;
|
| 123 |
-
box-shadow: 0 16px 40px rgba(0,0,0,0.22);
|
| 124 |
-
backdrop-filter: blur(10px);
|
| 125 |
-
color: #111827;
|
| 126 |
-
font-size: 0.92rem;
|
| 127 |
-
line-height: 1.25;
|
| 128 |
-
pointer-events: none;
|
| 129 |
-
}
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
.
|
| 134 |
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
background:
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
}
|
| 142 |
|
| 143 |
-
/*
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
.
|
| 147 |
-
.
|
| 148 |
-
.
|
| 149 |
-
.
|
|
|
|
|
|
|
| 150 |
|
| 151 |
-
.pill{
|
| 152 |
-
display:inline-flex; align-items:center; gap:8px;
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
cursor:pointer; user-select:none; font-size: 0.
|
|
|
|
| 156 |
}
|
| 157 |
-
.pill
|
|
|
|
|
|
|
| 158 |
|
| 159 |
.filter-input, .filter-select {
|
| 160 |
-
height:
|
| 161 |
-
border: 1px solid
|
| 162 |
-
|
| 163 |
-
outline: none; font-size: 0.
|
| 164 |
}
|
| 165 |
-
|
| 166 |
-
select.filter-select{
|
| 167 |
-
appearance:none; -webkit-appearance:none; -moz-appearance:none;
|
| 168 |
-
padding-right:40px;
|
| 169 |
background-image:
|
| 170 |
-
linear-gradient(45deg, transparent 50%,
|
| 171 |
-
linear-gradient(135deg,
|
| 172 |
-
|
| 173 |
-
background-
|
| 174 |
-
calc(100% - 18px) 16px,
|
| 175 |
-
calc(100% - 12px) 16px,
|
| 176 |
-
calc(100% - 36px) 50%;
|
| 177 |
-
background-size: 6px 6px, 6px 6px, 1px 60%;
|
| 178 |
-
background-repeat:no-repeat;
|
| 179 |
-
}
|
| 180 |
-
.filter-input:focus, .filter-select:focus{
|
| 181 |
-
border-color: rgba(76,110,245,0.55);
|
| 182 |
-
box-shadow: 0 0 0 4px rgba(76,110,245,0.12);
|
| 183 |
-
}
|
| 184 |
-
|
| 185 |
-
.matchline{
|
| 186 |
-
font-size: 0.92rem;
|
| 187 |
-
color: #111827;
|
| 188 |
-
font-weight: 850;
|
| 189 |
-
padding: 8px 10px;
|
| 190 |
-
border-radius: 12px;
|
| 191 |
-
background: rgba(76,110,245,0.08);
|
| 192 |
-
border: 1px solid rgba(76,110,245,0.18);
|
| 193 |
-
}
|
| 194 |
-
|
| 195 |
-
/* Model list */
|
| 196 |
-
.model-picker{ border: 1px solid rgba(17,24,39,0.10); background: rgba(255,255,255,0.85); border-radius: 14px; padding: 10px; }
|
| 197 |
-
.model-picker-head{ display:flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
|
| 198 |
-
.model-picker-title{ font-weight: 950; color: #111827; font-size: 0.95rem; }
|
| 199 |
-
.model-picker-subtle{ font-size: 0.82rem; color: rgba(75,85,99,0.85); font-weight: 700; }
|
| 200 |
-
.model-list{ height:auto; min-height:280px; padding: 8px 10px; line-height:1.3; border-radius:12px; background-image:none !important; padding-right: 12px !important; }
|
| 201 |
-
.model-list option{ padding: 6px 6px; }
|
| 202 |
-
|
| 203 |
-
/* Link buttons */
|
| 204 |
-
.link{
|
| 205 |
-
display:inline-flex; gap:6px; align-items:center;
|
| 206 |
-
font-weight: 850; color: #1d4ed8; text-decoration:none;
|
| 207 |
-
padding: 8px 10px; border-radius:10px;
|
| 208 |
-
border: 1px solid rgba(29,78,216,0.18);
|
| 209 |
-
background: rgba(29,78,216,0.06);
|
| 210 |
-
}
|
| 211 |
-
.link:hover{ background: rgba(29,78,216,0.10); }
|
| 212 |
-
.link.small{
|
| 213 |
-
padding: 6px 8px;
|
| 214 |
-
font-size: 0.82rem;
|
| 215 |
-
border-radius: 9px;
|
| 216 |
-
}
|
| 217 |
-
|
| 218 |
-
/* Summary grid + repo buttons */
|
| 219 |
-
.summary-grid{ display:grid; grid-template-columns: 1fr 320px; gap: 12px; align-items:start; }
|
| 220 |
-
.repo-buttons{ display:grid; gap: 10px; justify-items:end; padding: 6px 8px 0 0; }
|
| 221 |
-
.repo-buttons .link{ width: 100%; justify-content:center; }
|
| 222 |
-
|
| 223 |
-
/* Chips */
|
| 224 |
-
.chips{ display:flex; flex-wrap:wrap; gap:10px; }
|
| 225 |
-
.chip-btn{
|
| 226 |
-
appearance:none; border:1px solid rgba(17,24,39,0.14);
|
| 227 |
-
background: rgba(255,255,255,0.96);
|
| 228 |
-
border-radius:999px; padding: 7px 12px;
|
| 229 |
-
cursor:pointer; font-weight:900; font-size:0.9rem;
|
| 230 |
-
color: rgba(17,24,39,0.88);
|
| 231 |
-
transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease, background 120ms ease;
|
| 232 |
}
|
| 233 |
-
.
|
| 234 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
|
| 236 |
-
/*
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
.
|
| 240 |
-
.
|
| 241 |
-
.
|
| 242 |
-
|
| 243 |
-
background: rgba(15,26,48,0.92); color: rgba(232,238,252,0.95);
|
| 244 |
-
border: 1px solid rgba(232,238,252,0.18); box-shadow: 0 18px 40px rgba(0,0,0,0.28);
|
| 245 |
-
font-size: 0.82rem; max-width: 280px; line-height: 1.25; display:none;
|
| 246 |
-
}
|
| 247 |
-
.mini-chart-wrap canvas { cursor: grab; }
|
| 248 |
-
.mini-chart-wrap canvas:active { cursor: grabbing; }
|
| 249 |
|
| 250 |
-
/*
|
| 251 |
-
.
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
|
|
|
| 256 |
}
|
| 257 |
-
.
|
| 258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
}
|
| 260 |
-
.
|
| 261 |
-
.
|
| 262 |
-
.
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
}
|
| 268 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
|
| 270 |
-
.
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
|
|
|
| 274 |
}
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
}
|
| 280 |
-
.
|
| 281 |
-
|
| 282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
|
| 285 |
-
/*
|
| 286 |
-
|
| 287 |
-
.
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
font-
|
| 294 |
-
|
| 295 |
-
border: 1px solid rgba(17,24,39,0.12);
|
| 296 |
-
background: rgba(255,255,255,0.9);
|
| 297 |
-
color: rgba(17,24,39,0.88);
|
| 298 |
-
}
|
| 299 |
-
.badge.onnx{ background: rgba(59,130,246,0.10); border-color: rgba(59,130,246,0.25); }
|
| 300 |
-
.badge.gguf{ background: rgba(16,185,129,0.10); border-color: rgba(16,185,129,0.25); }
|
| 301 |
-
.badge.cpu{ background: rgba(148,163,184,0.14); border-color: rgba(148,163,184,0.35); }
|
| 302 |
-
.badge.npu{ background: rgba(245,158,11,0.12); border-color: rgba(245,158,11,0.30); }
|
| 303 |
-
.badge.dsp{ background: rgba(168,85,247,0.12); border-color: rgba(168,85,247,0.30); }
|
| 304 |
-
|
| 305 |
-
/* Precision/Quant badge */
|
| 306 |
-
.badge.art{
|
| 307 |
-
background: rgba(17,24,39,0.06);
|
| 308 |
-
border-color: rgba(17,24,39,0.14);
|
| 309 |
-
font-weight: 950;
|
| 310 |
-
}
|
| 311 |
-
|
| 312 |
-
/* Table + pinned cols */
|
| 313 |
-
.table-wrap{ margin-top:10px; border:1px solid rgba(17,24,39,0.10); border-radius:12px; overflow:auto; max-height:650px; background:#fff; }
|
| 314 |
-
table.table{ width:100%; border-collapse: collapse; background:#fff; }
|
| 315 |
-
.table th, .table td{ padding:10px 12px; border-bottom:1px solid rgba(17,24,39,0.08); font-size:0.94rem; color:#111827; vertical-align: top; }
|
| 316 |
-
.table th{ background: rgba(76,110,245,0.06); font-weight: 900; }
|
| 317 |
-
.table thead th{ position: sticky; top: 0; z-index: 3; }
|
| 318 |
-
.pin{ position: sticky; left:0; z-index:2; background:#fff; }
|
| 319 |
-
.table thead .pin{ z-index:4; background: rgba(76,110,245,0.06); }
|
| 320 |
-
.table tr.selected-row td{ background: rgba(76,110,245,0.08); }
|
| 321 |
-
|
| 322 |
-
/* Stack badges vertically in table cells by default */
|
| 323 |
-
.table .badges{
|
| 324 |
-
flex-direction: column;
|
| 325 |
-
align-items: flex-start;
|
| 326 |
-
gap: 6px;
|
| 327 |
}
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 333 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 334 |
|
| 335 |
-
/*
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
|
|
|
|
|
|
| 340 |
}
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
|
|
|
|
|
|
| 346 |
}
|
| 347 |
-
.
|
| 348 |
-
|
| 349 |
-
|
| 350 |
}
|
|
|
|
| 351 |
|
| 352 |
-
/*
|
| 353 |
-
.
|
| 354 |
-
display:flex;
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
white-space: normal;
|
| 358 |
-
line-height: 1.15;
|
| 359 |
}
|
| 360 |
-
.
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
}
|
| 365 |
-
.
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
flex: 0 0 auto;
|
|
|
|
|
|
|
| 371 |
}
|
| 372 |
-
.
|
| 373 |
-
|
| 374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
}
|
|
|
|
|
|
|
| 376 |
|
| 377 |
-
|
| 378 |
-
.
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
background:
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
font-weight: 900;
|
| 386 |
-
font-size: 0.84rem;
|
| 387 |
-
cursor: pointer;
|
| 388 |
-
align-self: flex-start;
|
| 389 |
-
margin-top: 4px;
|
| 390 |
}
|
| 391 |
-
.
|
| 392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
}
|
| 394 |
|
| 395 |
-
|
| 396 |
-
.
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
}
|
| 405 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
display: grid;
|
| 407 |
-
grid-template-columns:
|
| 408 |
-
gap:
|
| 409 |
-
align-items: stretch;
|
| 410 |
-
margin-top:
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
min-width: 0;
|
| 418 |
}
|
| 419 |
-
.
|
| 420 |
-
font-
|
| 421 |
-
|
| 422 |
-
font-size: 0.
|
| 423 |
-
|
|
|
|
|
|
|
|
|
|
| 424 |
}
|
| 425 |
-
.
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
}
|
|
|
|
|
|
|
| 431 |
|
| 432 |
-
/* -
|
| 433 |
-
.
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
}
|
| 439 |
-
|
|
|
|
|
|
|
| 440 |
flex: 1 1 auto;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 441 |
}
|
| 442 |
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
background: rgba(255,255,255,0.92);
|
| 447 |
-
border-radius: 10px;
|
| 448 |
-
padding: 8px 10px;
|
| 449 |
-
cursor: pointer;
|
| 450 |
-
font-weight: 950;
|
| 451 |
-
line-height: 1;
|
| 452 |
-
display:inline-flex;
|
| 453 |
-
align-items:center;
|
| 454 |
-
gap:8px;
|
| 455 |
-
color: rgba(17,24,39,0.88);
|
| 456 |
-
white-space: nowrap;
|
| 457 |
-
}
|
| 458 |
-
.copy-btn:hover{
|
| 459 |
-
background: rgba(76,110,245,0.10);
|
| 460 |
-
border-color: rgba(76,110,245,0.35);
|
| 461 |
-
box-shadow: 0 0 0 4px rgba(76,110,245,0.10);
|
| 462 |
-
}
|
| 463 |
-
.copy-btn .icon{ font-size: 1rem; }
|
| 464 |
-
.copy-btn.copied{
|
| 465 |
-
background: rgba(16,185,129,0.10);
|
| 466 |
-
border-color: rgba(16,185,129,0.35);
|
| 467 |
-
box-shadow: 0 0 0 4px rgba(16,185,129,0.10);
|
| 468 |
-
}
|
| 469 |
-
|
| 470 |
-
/* Scatter */
|
| 471 |
-
.chart-wrap{
|
| 472 |
-
width:100%; border-radius:12px; border:1px solid rgba(17,24,39,0.08);
|
| 473 |
-
background: linear-gradient(180deg, rgba(76,110,245,0.04), transparent);
|
| 474 |
-
overflow:hidden;
|
| 475 |
-
}
|
| 476 |
-
.tooltip{
|
| 477 |
-
position:absolute; pointer-events:none; padding:10px 10px; border-radius:12px;
|
| 478 |
-
background: rgba(15,26,48,0.92); color: rgba(232,238,252,0.95);
|
| 479 |
-
border:1px solid rgba(232,238,252,0.18); box-shadow: 0 18px 40px rgba(0,0,0,0.28);
|
| 480 |
-
font-size:0.85rem; max-width:320px; line-height:1.25;
|
| 481 |
-
}
|
| 482 |
-
|
| 483 |
-
/* Modal */
|
| 484 |
-
.modal{
|
| 485 |
-
position: fixed;
|
| 486 |
-
inset: 0;
|
| 487 |
-
z-index: 10000;
|
| 488 |
display: none;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
}
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
border-
|
| 507 |
-
|
| 508 |
-
box-shadow: 0 25px 80px rgba(0,0,0,0.35);
|
| 509 |
-
}
|
| 510 |
-
.modal-head{
|
| 511 |
-
position: sticky;
|
| 512 |
-
top: 0;
|
| 513 |
-
z-index: 5;
|
| 514 |
-
background: rgba(255,255,255,0.92);
|
| 515 |
-
backdrop-filter: blur(8px);
|
| 516 |
-
border-bottom: 1px solid rgba(17,24,39,0.08);
|
| 517 |
-
padding: 12px 14px;
|
| 518 |
-
display:flex;
|
| 519 |
-
align-items:center;
|
| 520 |
-
justify-content: space-between;
|
| 521 |
-
gap: 12px;
|
| 522 |
-
}
|
| 523 |
-
.modal-title{
|
| 524 |
-
font-weight: 950;
|
| 525 |
-
font-size: x-large;
|
| 526 |
-
color: #111827;
|
| 527 |
-
}
|
| 528 |
-
.icon-btn{
|
| 529 |
-
appearance:none;
|
| 530 |
-
border: 1px solid rgba(17,24,39,0.12);
|
| 531 |
-
background: rgba(255,255,255,0.9);
|
| 532 |
-
border-radius: 12px;
|
| 533 |
-
padding: 8px 10px;
|
| 534 |
-
cursor: pointer;
|
| 535 |
-
font-weight: 950;
|
| 536 |
}
|
| 537 |
-
.
|
| 538 |
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
}
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 552 |
}
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
|
|
|
|
|
|
|
|
|
| 558 |
}
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 565 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 566 |
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
.grid.two, .grid.explore-grid { grid-template-columns: 1fr; }
|
| 572 |
-
.field-row.two{ grid-template-columns: 1fr; }
|
| 573 |
-
.summary-grid{ grid-template-columns: 1fr; }
|
| 574 |
-
.repo-buttons{ justify-items: start;
|
| 575 |
-
.repo-buttons .link{ width: auto;
|
| 576 |
-
.
|
| 577 |
-
|
| 578 |
-
.
|
| 579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* =====================================================================
|
| 2 |
+
Renesas AI Models β restyle
|
| 3 |
+
Three switchable directions on data-theme:
|
| 4 |
+
a = Brand Light (true to Renesas brand: flat, squared, hairlines)
|
| 5 |
+
b = Frosted Light (light branded backdrop + liquid-glass surfaces)
|
| 6 |
+
c = Midnight Glass (refined dark, premium frosted glass)
|
| 7 |
+
All share Renesas Blue #2A289D and the brand condensed display type.
|
| 8 |
+
Drop-in: works with the existing app.js unchanged.
|
| 9 |
+
===================================================================== */
|
| 10 |
+
|
| 11 |
+
/* ---------- Brand constants (all themes) ---------- */
|
| 12 |
:root {
|
| 13 |
+
--brand: #2A289D; /* Renesas Blue β corporate */
|
| 14 |
+
--brand-press: #1F1D78;
|
| 15 |
+
--brand-2: #43ABE2; /* secondary sky blue */
|
| 16 |
+
--font-display: "Archivo Narrow", "Arial Narrow", Arial, sans-serif;
|
| 17 |
+
--font-body: "Helvetica Neue", Arial, "Liberation Sans", sans-serif;
|
| 18 |
|
| 19 |
+
/* badge accent colors (brand secondary palette) */
|
| 20 |
+
--bc-onnx: #306683;
|
| 21 |
+
--bc-gguf: #609A3B;
|
| 22 |
+
--bc-cpu: #706F6F;
|
| 23 |
+
--bc-npu: #EB6209;
|
| 24 |
+
--bc-dsp: #883D90;
|
| 25 |
+
--bc-modal: var(--brand);
|
| 26 |
+
--bc-art: #706F6F;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
/* =====================================================================
|
| 30 |
+
Frosted Light β the single theme: liquid glass over a living,
|
| 31 |
+
branded backdrop. Renesas Blue #2A289D + brand condensed display.
|
| 32 |
+
===================================================================== */
|
| 33 |
+
:root {
|
| 34 |
+
--bg: linear-gradient(165deg, #EEF1F8 0%, #E4E9F4 48%, #EAE6F2 100%);
|
| 35 |
+
--bg-dots: radial-gradient(rgba(42,40,157,0.10) 1.4px, transparent 1.6px);
|
| 36 |
+
--text: #2C2B45;
|
| 37 |
+
--text-dim: #5C5B72;
|
| 38 |
+
--text-mute: #908FA3;
|
| 39 |
|
|
|
|
| 40 |
--radius: 16px;
|
| 41 |
+
--radius-sm: 12px;
|
| 42 |
+
--card-radius: 16px;
|
| 43 |
+
--card-blur: blur(20px) saturate(155%);
|
| 44 |
+
|
| 45 |
+
--panel-bg: rgba(255,255,255,0.55);
|
| 46 |
+
--panel-border: rgba(255,255,255,0.75);
|
| 47 |
+
--panel-shadow: 0 18px 44px rgba(42,40,157,0.10), inset 0 1px 0 rgba(255,255,255,0.65);
|
| 48 |
+
|
| 49 |
+
--card-bg: rgba(255,255,255,0.58);
|
| 50 |
+
--card-border: rgba(255,255,255,0.8);
|
| 51 |
+
--card-shadow: 0 12px 32px rgba(42,40,157,0.10), inset 0 1px 0 rgba(255,255,255,0.7);
|
| 52 |
+
--card-rule: 0px;
|
| 53 |
+
--card-hover-bg: rgba(255,255,255,0.74);
|
| 54 |
+
--card-hover-border: rgba(42,40,157,0.45);
|
| 55 |
+
--card-hover-shadow: 0 20px 46px rgba(42,40,157,0.18), inset 0 1px 0 rgba(255,255,255,0.8);
|
| 56 |
+
|
| 57 |
+
--surface: rgba(255,255,255,0.5);
|
| 58 |
+
--surface-strong: rgba(255,255,255,0.7);
|
| 59 |
+
--surface-border: rgba(255,255,255,0.85);
|
| 60 |
+
|
| 61 |
+
--header-bg: rgba(255,255,255,0.6);
|
| 62 |
+
--header-border: rgba(255,255,255,0.7);
|
| 63 |
+
--header-shadow: 0 8px 30px rgba(42,40,157,0.12), inset 0 1px 0 rgba(255,255,255,0.8);
|
| 64 |
+
--header-text: #2C2B45;
|
| 65 |
+
--header-blur: blur(22px) saturate(160%);
|
| 66 |
+
|
| 67 |
+
--input-bg: rgba(255,255,255,0.7);
|
| 68 |
+
--input-border: rgba(255,255,255,0.9);
|
| 69 |
+
--chip-bg: rgba(255,255,255,0.65);
|
| 70 |
+
--chip-border: rgba(255,255,255,0.85);
|
| 71 |
+
|
| 72 |
+
--brand-tint: rgba(42,40,157,0.12);
|
| 73 |
+
--brand-ring: rgba(42,40,157,0.22);
|
| 74 |
+
--hairline: rgba(42,40,157,0.12);
|
| 75 |
+
--canvas-bg: rgba(255,255,255,0.92);
|
| 76 |
+
--canvas-border: rgba(255,255,255,0.8);
|
| 77 |
+
--table-head-bg: var(--brand);
|
| 78 |
+
--table-head-text: #FFFFFF;
|
| 79 |
+
--code-bg: rgba(42,40,157,0.06);
|
| 80 |
+
--scroll-thumb: rgba(42,40,157,0.28);
|
| 81 |
+
--link-bg: rgba(42,40,157,0.12);
|
| 82 |
+
--link-text: var(--brand);
|
| 83 |
+
--link-border: rgba(42,40,157,0.3);
|
| 84 |
+
--modal-backdrop: rgba(38,40,80,0.4);
|
| 85 |
+
|
| 86 |
+
--brand-active: var(--brand);
|
| 87 |
}
|
| 88 |
|
| 89 |
+
/* =====================================================================
|
| 90 |
+
Base
|
| 91 |
+
===================================================================== */
|
| 92 |
* { box-sizing: border-box; }
|
| 93 |
+
[hidden] { display: none !important; }
|
| 94 |
html, body { height: 100%; }
|
| 95 |
|
| 96 |
body {
|
|
|
|
| 99 |
display: flex;
|
| 100 |
flex-direction: column;
|
| 101 |
overflow: hidden;
|
| 102 |
+
color: var(--text);
|
| 103 |
+
font-family: var(--font-body);
|
| 104 |
+
background: var(--bg);
|
| 105 |
+
background-attachment: fixed;
|
| 106 |
}
|
| 107 |
+
/* ---------- Dynamic, living background: brand network mesh + soft color blooms ---------- */
|
| 108 |
+
.bg-fx { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
|
| 109 |
+
.bg-fx canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
|
| 110 |
+
.bg-fx .blob { position: absolute; border-radius: 50%; filter: blur(70px); opacity: 0.42; will-change: transform; }
|
| 111 |
+
.bg-fx .b1 { width: 46vw; height: 46vw; left: -12vw; top: -16vh; background: radial-gradient(circle, rgba(67,171,226,0.70), transparent 68%); animation: fx1 30s ease-in-out infinite; }
|
| 112 |
+
.bg-fx .b2 { width: 42vw; height: 42vw; right: -10vw; bottom: -18vh; background: radial-gradient(circle, rgba(150,104,214,0.62), transparent 68%); animation: fx2 36s ease-in-out infinite; }
|
| 113 |
+
@keyframes fx1 { 0%, 100% { transform: translate(0,0) scale(1); } 50% { transform: translate(14vw,10vh) scale(1.15); } }
|
| 114 |
+
@keyframes fx2 { 0%, 100% { transform: translate(0,0) scale(1.05); } 50% { transform: translate(-12vw,12vh) scale(0.92); } }
|
| 115 |
+
@media (prefers-reduced-motion: reduce) { .bg-fx .blob { animation: none !important; } }
|
| 116 |
+
.topbar, .content { position: relative; z-index: 1; }
|
| 117 |
|
| 118 |
+
/* =====================================================================
|
| 119 |
+
Topbar
|
| 120 |
+
===================================================================== */
|
| 121 |
.topbar {
|
| 122 |
flex: 0 0 auto;
|
| 123 |
z-index: 50;
|
| 124 |
+
border-bottom: 1px solid var(--header-border);
|
| 125 |
+
background: var(--header-bg);
|
| 126 |
+
backdrop-filter: var(--header-blur);
|
| 127 |
+
-webkit-backdrop-filter: var(--header-blur);
|
| 128 |
+
box-shadow: var(--header-shadow);
|
| 129 |
}
|
| 130 |
+
:root[data-theme="a"] .topbar { border-top: 3px solid var(--brand); }
|
| 131 |
.topbar-inner {
|
| 132 |
width: 100%;
|
| 133 |
+
padding: 11px 22px;
|
| 134 |
+
display: flex;
|
|
|
|
|
|
|
|
|
|
| 135 |
align-items: center;
|
| 136 |
+
gap: 22px;
|
| 137 |
}
|
| 138 |
+
.brand { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 0 0 auto; }
|
| 139 |
+
.brand-icon { height: 22px; width: auto; max-width: 168px; object-fit: contain; display: block; }
|
| 140 |
+
.brand-divider { width: 1px; height: 26px; background: var(--hairline); flex: 0 0 auto; }
|
| 141 |
+
.brand-title {
|
| 142 |
+
color: var(--header-text);
|
| 143 |
+
font-family: var(--font-display);
|
| 144 |
+
font-weight: 700;
|
| 145 |
+
font-size: 1.18rem;
|
| 146 |
+
line-height: 1;
|
| 147 |
+
letter-spacing: 0.04em;
|
| 148 |
+
text-transform: uppercase;
|
| 149 |
+
}
|
| 150 |
+
.brand-subtitle { color: var(--text-dim); font-size: 0.74rem; margin-top: 3px; letter-spacing: 0.04em; }
|
| 151 |
|
| 152 |
+
.tabs { display: flex; gap: 6px; align-items: center; margin-left: auto; flex-wrap: wrap; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
.nav-item {
|
| 154 |
appearance: none;
|
| 155 |
+
border: 1px solid transparent;
|
| 156 |
+
background: transparent;
|
| 157 |
+
color: var(--text-dim);
|
| 158 |
+
border-radius: var(--radius-sm);
|
| 159 |
+
padding: 9px 16px;
|
| 160 |
+
font-family: var(--font-display);
|
| 161 |
+
font-weight: 600;
|
| 162 |
+
font-size: 0.96rem;
|
| 163 |
+
letter-spacing: 0.02em;
|
| 164 |
cursor: pointer;
|
| 165 |
+
transition: background 140ms ease, color 140ms ease, box-shadow 140ms ease;
|
| 166 |
}
|
| 167 |
+
.nav-item:hover { color: var(--text); background: var(--brand-tint); }
|
| 168 |
.nav-item.active {
|
| 169 |
+
background: var(--brand-active);
|
| 170 |
+
color: #fff;
|
| 171 |
+
box-shadow: 0 4px 14px rgba(42,40,157,0.32);
|
| 172 |
}
|
| 173 |
|
| 174 |
+
/* Burger (mobile nav trigger) β hidden until the phone breakpoint */
|
| 175 |
+
.nav-burger {
|
| 176 |
+
display: none;
|
| 177 |
+
appearance: none; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
|
| 178 |
+
width: 44px; height: 44px; flex: 0 0 auto; margin-left: auto; cursor: pointer;
|
| 179 |
+
border: 1px solid var(--chip-border); background: var(--chip-bg);
|
| 180 |
+
border-radius: var(--radius-sm);
|
| 181 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 182 |
+
transition: border-color 140ms ease, background 140ms ease;
|
| 183 |
+
}
|
| 184 |
+
.nav-burger:hover { border-color: var(--brand-ring); }
|
| 185 |
+
.nav-burger span { display: block; width: 19px; height: 2px; border-radius: 2px; background: var(--text); transition: transform 180ms ease, opacity 150ms ease; }
|
| 186 |
+
.nav-burger.active span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
|
| 187 |
+
.nav-burger.active span:nth-child(2) { opacity: 0; }
|
| 188 |
+
.nav-burger.active span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
|
| 189 |
+
|
| 190 |
+
/* Theme switch */
|
| 191 |
+
.theme-switch {
|
| 192 |
+
display: flex;
|
| 193 |
+
gap: 2px;
|
| 194 |
+
padding: 3px;
|
| 195 |
+
border-radius: var(--radius-sm);
|
| 196 |
+
border: 1px solid var(--chip-border);
|
| 197 |
+
background: var(--surface);
|
| 198 |
+
flex: 0 0 auto;
|
| 199 |
}
|
| 200 |
+
.theme-btn {
|
| 201 |
+
appearance: none;
|
| 202 |
+
border: none;
|
| 203 |
+
background: transparent;
|
| 204 |
+
color: var(--text-dim);
|
| 205 |
+
border-radius: calc(var(--radius-sm) - 2px);
|
| 206 |
+
padding: 6px 10px;
|
| 207 |
+
font-family: var(--font-body);
|
| 208 |
+
font-weight: 600;
|
| 209 |
+
font-size: 0.74rem;
|
| 210 |
+
letter-spacing: 0.02em;
|
| 211 |
+
cursor: pointer;
|
| 212 |
+
display: inline-flex;
|
| 213 |
+
align-items: center;
|
| 214 |
+
gap: 6px;
|
| 215 |
+
transition: background 140ms ease, color 140ms ease;
|
| 216 |
+
}
|
| 217 |
+
.theme-btn:hover { color: var(--text); }
|
| 218 |
+
.theme-btn.active { background: var(--brand-active); color: #fff; box-shadow: 0 2px 8px rgba(42,40,157,0.28); }
|
| 219 |
+
.theme-btn .sw { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; border: 1px solid rgba(0,0,0,0.12); }
|
| 220 |
+
.sw-a { background: #FFFFFF; }
|
| 221 |
+
.sw-b { background: linear-gradient(135deg, #E7ECF8, #DCD9EF); }
|
| 222 |
+
.sw-c { background: linear-gradient(135deg, #1A1C36, #3937C4); border-color: rgba(255,255,255,0.2); }
|
| 223 |
|
| 224 |
+
/* =====================================================================
|
| 225 |
+
Content / sections
|
| 226 |
+
===================================================================== */
|
| 227 |
+
.content { flex: 1 1 auto; min-height: 0; width: 100%; padding: 8px; overflow: hidden; }
|
| 228 |
.section {
|
| 229 |
display: none;
|
| 230 |
height: 100%;
|
| 231 |
min-height: 0;
|
| 232 |
+
color: var(--text);
|
|
|
|
| 233 |
border-radius: var(--radius);
|
| 234 |
+
border: 1px solid var(--panel-border);
|
| 235 |
+
background: var(--panel-bg);
|
| 236 |
+
backdrop-filter: var(--card-blur);
|
| 237 |
+
-webkit-backdrop-filter: var(--card-blur);
|
| 238 |
+
box-shadow: var(--panel-shadow);
|
| 239 |
overflow: hidden;
|
| 240 |
}
|
| 241 |
.section.visible { display: flex; flex-direction: column; }
|
| 242 |
+
#sec-overview.visible, #sec-explore.visible { overflow: auto; padding: 9px; }
|
| 243 |
+
/* Overview content sits directly on the page (no panel frame). */
|
| 244 |
+
#sec-overview { border: none; background: none; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
|
| 245 |
+
|
| 246 |
+
.section-head { margin-bottom: 18px; }
|
| 247 |
+
.section-title {
|
| 248 |
+
margin: 0 0 4px; border: none; padding: 0;
|
| 249 |
+
font-family: var(--font-display); font-weight: 700; font-size: 1.9rem;
|
| 250 |
+
letter-spacing: 0.02em; text-transform: uppercase; color: var(--text);
|
| 251 |
+
}
|
| 252 |
|
| 253 |
+
/* =====================================================================
|
| 254 |
+
Typography
|
| 255 |
+
===================================================================== */
|
| 256 |
+
h1, h2, h3 { color: var(--text); margin-top: 0.2rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--hairline); }
|
| 257 |
+
h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--brand); }
|
| 258 |
+
:root[data-theme="c"] h3 { color: #B9C0FF; }
|
| 259 |
+
pre, code { font-family: "Consolas", ui-monospace, SFMono-Regular, Menlo, monospace; }
|
| 260 |
+
pre { background: var(--code-bg); color: var(--text); padding: 11px 13px; border-radius: var(--radius-sm); overflow-x: auto; border: 1px solid var(--hairline); margin: 0; font-size: 0.86rem; }
|
| 261 |
+
code { background: var(--code-bg); color: var(--text); padding: 0.1rem 0.34rem; border-radius: 4px; font-size: 0.88em; }
|
| 262 |
|
| 263 |
+
.note { background: var(--surface); border-left: 3px solid var(--brand); padding: 11px 13px; margin: 10px 0 12px; border-radius: var(--radius-sm); color: var(--text); }
|
| 264 |
+
.note.note-warn { background: color-mix(in srgb, var(--bc-npu) 12%, transparent); border-left-color: var(--bc-npu); }
|
| 265 |
+
.subtle { color: var(--text-dim); margin-top: 0.4rem; }
|
| 266 |
.tight { margin-top: 0.35rem; }
|
| 267 |
+
.no-border { border-bottom: none !important; padding-bottom: 0 !important; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
+
.link-btn { appearance: none; background: none; border: none; cursor: pointer; color: var(--brand); font-weight: 700; font-size: 0.82rem; padding: 2px 4px; letter-spacing: 0.02em; }
|
| 270 |
+
:root[data-theme="c"] .link-btn { color: #B9C0FF; }
|
| 271 |
+
.link-btn:hover { text-decoration: underline; }
|
| 272 |
|
| 273 |
+
/* =====================================================================
|
| 274 |
+
Card base (big panels) + glass surfaces
|
| 275 |
+
===================================================================== */
|
| 276 |
+
.card, .stat-tile, .model-card, .metric-card, .model-picker, .constellation {
|
| 277 |
+
background: var(--card-bg);
|
| 278 |
+
border: 1px solid var(--card-border);
|
| 279 |
+
backdrop-filter: var(--card-blur);
|
| 280 |
+
-webkit-backdrop-filter: var(--card-blur);
|
| 281 |
+
box-shadow: var(--card-shadow);
|
| 282 |
+
}
|
| 283 |
+
.card { border-radius: var(--card-radius); padding: 8px; min-width: 0; position: relative; }
|
| 284 |
+
.card::before {
|
| 285 |
+
content: "";
|
| 286 |
+
position: absolute; top: 0; left: 0; right: 0;
|
| 287 |
+
height: var(--card-rule);
|
| 288 |
+
background: var(--brand);
|
| 289 |
+
border-radius: var(--card-radius) var(--card-radius) 0 0;
|
| 290 |
+
}
|
| 291 |
+
.card-head { margin-bottom: 14px; }
|
| 292 |
+
.card-head-title {
|
| 293 |
+
margin: 0 0 4px; border: none; padding: 0;
|
| 294 |
+
font-family: var(--font-display); font-weight: 700; font-size: 1.28rem;
|
| 295 |
+
letter-spacing: 0.03em; text-transform: uppercase; color: var(--text);
|
| 296 |
}
|
| 297 |
|
| 298 |
+
/* =====================================================================
|
| 299 |
+
Form controls
|
| 300 |
+
===================================================================== */
|
| 301 |
+
.form-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
|
| 302 |
+
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
| 303 |
+
.label { font-size: 0.72rem; color: var(--text-dim); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
|
| 304 |
+
.radio-row { display: flex; flex-wrap: wrap; gap: 8px; }
|
| 305 |
+
.radio-col { display: grid; gap: 8px; }
|
| 306 |
+
.field-row.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
| 307 |
|
| 308 |
+
.pill {
|
| 309 |
+
display: inline-flex; align-items: center; gap: 8px; padding: 7px 13px;
|
| 310 |
+
border: 1px solid var(--chip-border); background: var(--chip-bg);
|
| 311 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 312 |
+
border-radius: var(--radius-sm); cursor: pointer; user-select: none; font-size: 0.88rem; color: var(--text);
|
| 313 |
+
transition: background 130ms ease, border-color 130ms ease, box-shadow 130ms ease;
|
| 314 |
}
|
| 315 |
+
.pill:hover { border-color: var(--brand-ring); }
|
| 316 |
+
.pill.active { background: var(--brand-tint); border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-tint); color: var(--text); font-weight: 600; }
|
| 317 |
+
.pill input { accent-color: var(--brand); }
|
| 318 |
|
| 319 |
.filter-input, .filter-select {
|
| 320 |
+
height: 40px; padding: 0 13px; border-radius: var(--radius-sm);
|
| 321 |
+
border: 1px solid var(--input-border); background: var(--input-bg);
|
| 322 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 323 |
+
color: var(--text); outline: none; font-size: 0.92rem; width: 100%; font-family: var(--font-body);
|
| 324 |
}
|
| 325 |
+
.filter-input::placeholder { color: var(--text-mute); }
|
| 326 |
+
select.filter-select {
|
| 327 |
+
appearance: none; -webkit-appearance: none; -moz-appearance: none; padding-right: 38px; cursor: pointer;
|
|
|
|
| 328 |
background-image:
|
| 329 |
+
linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
|
| 330 |
+
linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
|
| 331 |
+
background-position: calc(100% - 18px) 17px, calc(100% - 12px) 17px;
|
| 332 |
+
background-size: 6px 6px, 6px 6px; background-repeat: no-repeat;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 333 |
}
|
| 334 |
+
.filter-select option { background: var(--input-bg); color: var(--text); }
|
| 335 |
+
:root[data-theme="c"] .filter-select option { background: #1B1D33; color: var(--text); }
|
| 336 |
+
.filter-input:focus, .filter-select:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-tint); }
|
| 337 |
+
.filter-input.compact, .filter-select.compact { height: 36px; font-size: 0.88rem; }
|
| 338 |
+
.field.compact { gap: 5px; }
|
| 339 |
+
.field.compact .label { font-size: 0.7rem; }
|
| 340 |
|
| 341 |
+
/* =====================================================================
|
| 342 |
+
OVERVIEW
|
| 343 |
+
===================================================================== */
|
| 344 |
+
.stat-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 12px; }
|
| 345 |
+
.stat-tile { border-radius: var(--card-radius); padding: 8px 9px 8px 10px; position: relative; border-left: 3px solid var(--brand); }
|
| 346 |
+
.stat-num { font-family: var(--font-display); font-size: 2rem; font-weight: 700; color: var(--text); line-height: 1; }
|
| 347 |
+
.stat-label { margin-top: 6px; font-size: 0.78rem; color: var(--text-dim); font-weight: 600; letter-spacing: 0.03em; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
|
| 349 |
+
/* Carousel */
|
| 350 |
+
.carousel-section { margin-bottom: 20px; }
|
| 351 |
+
.carousel-section.featured {
|
| 352 |
+
padding: 8px 10px 4px; margin-bottom: 14px; border-radius: var(--card-radius);
|
| 353 |
+
background: var(--card-bg); border: 1px solid var(--card-border);
|
| 354 |
+
box-shadow: var(--card-shadow); backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 355 |
+
position: relative;
|
| 356 |
}
|
| 357 |
+
:root[data-theme="a"] .carousel-section.featured { border-top: 3px solid var(--brand); }
|
| 358 |
+
.carousel-section.featured .carousel-title { font-size: 1.42rem; }
|
| 359 |
+
.carousel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
|
| 360 |
+
.carousel-title { font-family: var(--font-display); font-size: 1.22rem; font-weight: 700; margin: 0; border: none; padding: 0; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text); }
|
| 361 |
+
.carousel-actions { display: flex; align-items: center; gap: 8px; }
|
| 362 |
+
.carousel-sub { color: var(--text-dim); font-size: 0.8rem; font-weight: 600; margin-right: 4px; }
|
| 363 |
+
.carousel-nav {
|
| 364 |
+
width: 34px; height: 34px; border-radius: var(--radius-sm); display: grid; place-items: center;
|
| 365 |
+
cursor: pointer; font-size: 1.15rem; line-height: 1; color: var(--text);
|
| 366 |
+
border: 1px solid var(--chip-border); background: var(--chip-bg);
|
| 367 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 368 |
+
transition: border-color 130ms ease, color 130ms ease, background 130ms ease;
|
| 369 |
}
|
| 370 |
+
.carousel-nav:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-tint); }
|
| 371 |
+
.carousel-track { display: flex; gap: 14px; overflow-x: auto; scroll-behavior: smooth; scroll-snap-type: x proximity; padding: 4px 2px 14px; }
|
| 372 |
+
.rc-card { flex: 0 0 252px; scroll-snap-align: start; gap: 10px; }
|
| 373 |
+
.rc-meta { font-size: 0.72rem; font-weight: 700; color: var(--text-dim); display: flex; align-items: center; gap: 5px; letter-spacing: 0.02em; }
|
| 374 |
+
.rc-meta.is-new { color: var(--brand); }
|
| 375 |
+
:root[data-theme="c"] .rc-meta.is-new { color: #B9C0FF; }
|
| 376 |
+
.rc-stat { font-size: 0.84rem; color: var(--text-dim); }
|
| 377 |
+
.rc-stat b { font-family: var(--font-display); font-size: 1.15rem; color: var(--text); font-weight: 700; }
|
| 378 |
+
.rc-stat.empty { color: var(--text-mute); }
|
| 379 |
+
/* Source tag on the recency stat β measured HIL is the priority, estimates
|
| 380 |
+
are clearly marked as fallback. */
|
| 381 |
+
.rc-src { display: inline-block; font-family: var(--font-display); font-weight: 700; font-size: 0.6rem; letter-spacing: 0.06em; text-transform: uppercase; padding: 1px 6px; border-radius: 999px; vertical-align: middle; line-height: 1.45; }
|
| 382 |
+
.rc-src-hil { background: var(--brand); color: #fff; }
|
| 383 |
+
.rc-src-est { background: transparent; color: var(--text-mute); border: 1px solid var(--hairline); }
|
| 384 |
+
:root[data-theme="c"] .rc-src-hil { background: #6670E6; }
|
| 385 |
+
|
| 386 |
+
/* Constellation */
|
| 387 |
+
.constellation-card { padding: 8px; }
|
| 388 |
+
.cstl-controls { display: flex; flex-wrap: wrap; gap: 12px 18px; align-items: flex-end; padding-bottom: 14px; border-bottom: 1px solid var(--hairline); margin-bottom: 14px; }
|
| 389 |
+
.cstl-controls .field { min-width: 150px; }
|
| 390 |
+
.constellation { border-radius: var(--radius-sm); overflow: hidden; position: relative; background: var(--canvas-bg); border: 1px solid var(--canvas-border); box-shadow: none; }
|
| 391 |
+
.constellation canvas { width: 100%; height: 460px; display: block; cursor: grab; }
|
| 392 |
+
.constellation canvas:active { cursor: grabbing; }
|
| 393 |
+
.cstl-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px; margin-top: 12px; align-items: center; }
|
| 394 |
+
.legend { display: flex; flex-wrap: wrap; gap: 8px 14px; }
|
| 395 |
+
.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 0.8rem; color: var(--text-dim); font-weight: 600; }
|
| 396 |
+
.legend-dot { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
|
| 397 |
|
| 398 |
+
.mini-tooltip {
|
| 399 |
+
position: absolute; pointer-events: none; padding: 9px 11px; border-radius: var(--radius-sm);
|
| 400 |
+
background: rgba(28,30,52,0.95); color: #F4F5FB; backdrop-filter: blur(6px);
|
| 401 |
+
border: 1px solid rgba(255,255,255,0.14); box-shadow: 0 18px 40px rgba(0,0,0,0.35);
|
| 402 |
+
font-size: 0.8rem; max-width: 280px; line-height: 1.35; display: none; z-index: 5;
|
| 403 |
}
|
| 404 |
+
|
| 405 |
+
/* =====================================================================
|
| 406 |
+
CATALOG
|
| 407 |
+
===================================================================== */
|
| 408 |
+
.catalog-layout { flex: 1 1 auto; min-width: 0; min-height: 0; display: grid; grid-template-columns: 196px minmax(0, 1fr); }
|
| 409 |
+
.facets {
|
| 410 |
+
border-right: 1px solid var(--hairline); padding: 9px 8px; overflow: auto;
|
| 411 |
+
display: flex; flex-direction: column; gap: 12px;
|
| 412 |
}
|
| 413 |
+
.facets-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
|
| 414 |
+
.facets-title { font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text); }
|
| 415 |
+
|
| 416 |
+
/* Collapsible filter clusters (the toggle button is shown only on phones) */
|
| 417 |
+
.filter-toggle {
|
| 418 |
+
display: none; align-items: center; gap: 8px; width: 100%; cursor: pointer;
|
| 419 |
+
appearance: none; border: 1px solid var(--chip-border); background: var(--chip-bg);
|
| 420 |
+
color: var(--text); font-family: var(--font-display); font-weight: 700; font-size: 0.95rem;
|
| 421 |
+
letter-spacing: 0.03em; padding: 11px 14px; border-radius: var(--radius-sm);
|
| 422 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 423 |
+
transition: border-color 140ms ease, background 140ms ease;
|
| 424 |
}
|
| 425 |
+
.filter-toggle:hover { border-color: var(--brand-ring); }
|
| 426 |
+
.filter-toggle.active { border-color: var(--brand); background: var(--brand-tint); }
|
| 427 |
+
.filter-toggle .ft-chevron { margin-left: auto; transition: transform 200ms ease; }
|
| 428 |
+
.filter-toggle[aria-expanded="true"] .ft-chevron { transform: rotate(180deg); }
|
| 429 |
+
.facets-body { display: flex; flex-direction: column; gap: 12px; }
|
| 430 |
+
.explore-filters { display: grid; gap: 10px; }
|
| 431 |
|
| 432 |
+
/* Explore filters: dense progressive-disclosure redesign.
|
| 433 |
+
Secondary ("Advanced") tier is collapsed by default on desktop; the generic
|
| 434 |
+
delegated .filter-toggle handler (index.html) toggles .open on it β no JS. */
|
| 435 |
+
.explore-advanced { display: none; }
|
| 436 |
+
.explore-advanced.open { display: grid; gap: 10px; }
|
| 437 |
+
/* Desktop-visible variant of the toggle (base .filter-toggle is display:none
|
| 438 |
+
>680px). Slimmer + dimmer so it reads as a secondary affordance. */
|
| 439 |
+
.filter-toggle--inline {
|
| 440 |
+
display: flex; padding: 7px 12px; font-size: 0.82rem; font-family: var(--font-body);
|
| 441 |
+
letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-dim);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
}
|
| 443 |
+
.filter-toggle--inline svg:first-of-type { opacity: 0.75; }
|
| 444 |
+
/* Dense packing, SCOPED to Explore so Catalog/Overview pills are untouched. */
|
| 445 |
+
.explore-filters .field-row.two, .explore-advanced .field-row.two { gap: 10px; }
|
| 446 |
+
.explore-filters .field.compact { gap: 4px; }
|
| 447 |
+
.explore-filters .field.compact .label { font-size: 0.68rem; }
|
| 448 |
+
.explore-filters .filter-select.compact { height: 34px; font-size: 0.86rem; padding: 0 10px; }
|
| 449 |
+
.explore-filters select.filter-select.compact { background-position: calc(100% - 16px) 14px, calc(100% - 10px) 14px; padding-right: 32px; }
|
| 450 |
+
.explore-filters .radio-row { gap: 6px; row-gap: 6px; }
|
| 451 |
+
.explore-filters .radio-row .pill { padding: 5px 10px; gap: 6px; font-size: 0.82rem; line-height: 1.15; }
|
| 452 |
+
.facet-groups { display: flex; flex-direction: column; gap: 12px; }
|
| 453 |
+
.facet-group-title { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-mute); font-weight: 700; margin-bottom: 5px; }
|
| 454 |
+
.facet-opt { display: flex; align-items: center; gap: 8px; padding: 3px 5px; font-size: 0.82rem; color: var(--text); cursor: pointer; border-radius: 6px; }
|
| 455 |
+
.facet-opt:hover { background: var(--brand-tint); }
|
| 456 |
+
.facet-opt input { appearance: none; -webkit-appearance: none; flex: 0 0 auto; width: 30px; height: 17px; border-radius: 999px; background: rgba(42,40,157,0.18); position: relative; cursor: pointer; transition: background 150ms ease; }
|
| 457 |
+
.facet-opt input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.28); transition: left 150ms ease; }
|
| 458 |
+
.facet-opt input:checked { background: var(--brand); }
|
| 459 |
+
.facet-opt input:checked::after { left: 15px; }
|
| 460 |
+
|
| 461 |
+
.catalog-main { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
|
| 462 |
+
.toolbar {
|
| 463 |
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
| 464 |
+
padding: 7px 9px; border-bottom: 1px solid var(--hairline); flex: 0 0 auto;
|
| 465 |
}
|
| 466 |
+
.toolbar-count { color: var(--text-dim); font-weight: 600; font-size: 0.9rem; }
|
| 467 |
+
.toolbar-count b { color: var(--text); font-family: var(--font-display); }
|
| 468 |
+
.view-toggle { display: inline-flex; border: 1px solid var(--chip-border); border-radius: var(--radius-sm); overflow: hidden; background: var(--chip-bg); }
|
| 469 |
+
.view-btn { appearance: none; border: none; background: transparent; color: var(--text-dim); padding: 8px 14px; font-weight: 700; font-size: 0.84rem; cursor: pointer; font-family: var(--font-body); }
|
| 470 |
+
.view-btn.active { background: var(--brand-active); color: #fff; }
|
| 471 |
+
|
| 472 |
+
.card-grid { flex: 1 1 auto; min-width: 0; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 9px; display: grid; grid-template-columns: repeat(auto-fill, minmax(247px, 1fr)); gap: 12px; align-content: start; }
|
| 473 |
+
.table-view { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: 14px 18px 18px; }
|
| 474 |
|
| 475 |
+
/* Model card β squared Renesas brand language: a top gradient accent that
|
| 476 |
+
sweeps wider on hover, a framed hero stat with a solid left bar, and
|
| 477 |
+
hairline-divided publisher row + footer with a solid-fill repo CTA. */
|
| 478 |
+
.model-card {
|
| 479 |
+
position: relative; overflow: hidden;
|
| 480 |
+
border-radius: var(--card-radius); padding: 17px 17px 15px; display: flex; flex-direction: column; gap: 13px; cursor: pointer;
|
| 481 |
+
transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease, background 150ms ease;
|
| 482 |
}
|
| 483 |
+
/* Signature top accent: 3px brandβbrand-2 bar, 34% wide at rest, sweeping to
|
| 484 |
+
full width + full opacity on hover. Keep this motif on card-like surfaces. */
|
| 485 |
+
.model-card::before {
|
| 486 |
+
content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
|
| 487 |
+
background: linear-gradient(90deg, var(--brand), var(--brand-2));
|
| 488 |
+
transform: scaleX(0.34); transform-origin: left; opacity: 0.8;
|
| 489 |
+
transition: transform 220ms ease, opacity 220ms ease;
|
| 490 |
}
|
| 491 |
+
.model-card:hover {
|
| 492 |
+
transform: translateY(-4px); border-color: var(--card-hover-border); background: var(--card-hover-bg);
|
| 493 |
+
box-shadow: var(--card-hover-shadow);
|
| 494 |
}
|
| 495 |
+
.model-card:hover::before { transform: scaleX(1); opacity: 1; }
|
| 496 |
|
| 497 |
+
/* Publisher row β uppercase, divided from the body by a hairline rule */
|
| 498 |
+
.mc-designer {
|
| 499 |
+
display: flex; align-items: center; gap: 8px; min-width: 0;
|
| 500 |
+
padding-bottom: 12px; border-bottom: 1px solid var(--hairline);
|
| 501 |
+
text-transform: uppercase; letter-spacing: 0.04em;
|
|
|
|
|
|
|
| 502 |
}
|
| 503 |
+
.mc-logo { display: inline-flex; align-items: center; flex: 0 0 auto; }
|
| 504 |
+
.mc-logo svg { display: block; }
|
| 505 |
+
.mc-designer-name { font-family: var(--font-display); font-weight: 700; font-size: 0.85rem; letter-spacing: 0.04em; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
| 506 |
+
.mc-head { display: flex; gap: 12px; align-items: center; }
|
| 507 |
+
.mc-monogram {
|
| 508 |
+
flex: 0 0 auto; width: 46px; height: 46px; border-radius: var(--radius-sm); display: grid; place-items: center;
|
| 509 |
+
font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; color: #fff;
|
| 510 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 4px 12px rgba(42,40,157,0.18);
|
| 511 |
}
|
| 512 |
+
.mc-title { font-family: var(--font-display); font-weight: 700; font-size: 1rem; line-height: 1.15; color: var(--text); word-break: break-word; letter-spacing: 0.01em; }
|
| 513 |
+
.mc-sub { font-size: 0.8rem; color: var(--text-dim); margin-top: 2px; }
|
| 514 |
+
.mc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
| 515 |
+
/* Throughput hero β tinted brand panel, framed all round, with a solid brand
|
| 516 |
+
left bar via ::before (squared accent, not a left-border-only card). */
|
| 517 |
+
.mc-stat {
|
| 518 |
+
position: relative; overflow: hidden;
|
| 519 |
+
display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
|
| 520 |
+
padding: 9px 12px 9px 16px; border-radius: var(--radius-sm);
|
| 521 |
+
background: linear-gradient(115deg, rgba(42,40,157,0.08), rgba(67,171,226,0.05));
|
| 522 |
+
border: 1px solid rgba(42,40,157,0.16);
|
| 523 |
+
}
|
| 524 |
+
.mc-stat::before {
|
| 525 |
+
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
|
| 526 |
+
background: var(--brand);
|
| 527 |
+
}
|
| 528 |
+
.mc-stat-num { font-family: var(--font-display); font-size: 1.78rem; font-weight: 700; color: var(--brand); line-height: 1; }
|
| 529 |
+
:root[data-theme="c"] .mc-stat-num { color: #C3C8FF; }
|
| 530 |
+
.mc-stat-sub { font-size: 0.74rem; color: var(--text-dim); font-weight: 600; line-height: 1.25; }
|
| 531 |
+
/* Empty state β greyed bar + dashed frame, transparent, italic placeholder */
|
| 532 |
+
.mc-stat.empty { align-items: center; text-align: center; background: transparent; border: 1px dashed var(--hairline); }
|
| 533 |
+
.mc-stat.empty::before { background: var(--hairline); }
|
| 534 |
+
.mc-stat.empty .mc-stat-sub { color: var(--text-mute); font-style: italic; font-weight: 500; }
|
| 535 |
+
.mc-quants { display: flex; flex-wrap: wrap; gap: 6px; }
|
| 536 |
+
/* Footer β hairline rule on top; uppercase meta, solid-fill repo CTA */
|
| 537 |
+
.mc-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; padding-top: 13px; border-top: 1px solid var(--hairline); }
|
| 538 |
+
.mc-meta { flex: 1 1 0; min-width: 0; font-size: 0.72rem; color: var(--text-mute); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
| 539 |
+
.mc-foot .link {
|
| 540 |
flex: 0 0 auto;
|
| 541 |
+
background: var(--brand); border-color: var(--brand); color: #fff;
|
| 542 |
+
box-shadow: 0 4px 12px rgba(42,40,157,0.24);
|
| 543 |
}
|
| 544 |
+
.mc-foot .link:hover { background: var(--brand-press); border-color: var(--brand-press); color: #fff; }
|
| 545 |
+
|
| 546 |
+
/* Chips / badges */
|
| 547 |
+
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
| 548 |
+
.chip-btn {
|
| 549 |
+
appearance: none; border: 1px solid var(--chip-border); background: var(--chip-bg);
|
| 550 |
+
backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 551 |
+
border-radius: var(--radius-sm); padding: 7px 12px; cursor: pointer; font-weight: 700; font-size: 0.86rem; color: var(--text);
|
| 552 |
+
transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease, background 120ms ease;
|
| 553 |
}
|
| 554 |
+
.chip-btn:hover { border-color: var(--brand); transform: translateY(-1px); }
|
| 555 |
+
.chip-btn.active { background: var(--brand-tint); border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-tint); }
|
| 556 |
|
| 557 |
+
.badges { display: flex; flex-wrap: wrap; gap: 6px; }
|
| 558 |
+
.badge {
|
| 559 |
+
display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px; border-radius: 999px;
|
| 560 |
+
font-weight: 700; font-size: 0.76rem; letter-spacing: 0.02em;
|
| 561 |
+
background: color-mix(in srgb, var(--bc) 13%, transparent);
|
| 562 |
+
border: 1px solid color-mix(in srgb, var(--bc) 38%, transparent);
|
| 563 |
+
color: var(--bc);
|
| 564 |
+
--bc: var(--bc-art);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 565 |
}
|
| 566 |
+
:root[data-theme="c"] .badge { color: color-mix(in srgb, var(--bc) 55%, white); background: color-mix(in srgb, var(--bc) 24%, transparent); border-color: color-mix(in srgb, var(--bc) 45%, transparent); }
|
| 567 |
+
.badge.clickable { cursor: pointer; }
|
| 568 |
+
.badge.clickable:hover { border-color: var(--bc); filter: brightness(0.97); }
|
| 569 |
+
.badge.onnx { --bc: var(--bc-onnx); }
|
| 570 |
+
.badge.gguf { --bc: var(--bc-gguf); }
|
| 571 |
+
.badge.cpu { --bc: var(--bc-cpu); }
|
| 572 |
+
.badge.npu { --bc: var(--bc-npu); }
|
| 573 |
+
.badge.dsp { --bc: var(--bc-dsp); }
|
| 574 |
+
.badge.modality { --bc: var(--bc-modal); }
|
| 575 |
+
.badge.art { --bc: var(--bc-art); }
|
| 576 |
+
|
| 577 |
+
/* status badges (mockup-style: uppercase pills) */
|
| 578 |
+
.badge.status { text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.68rem; padding: 3px 9px; }
|
| 579 |
+
.badge.status-hil { text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.68rem; padding: 3px 9px; background: var(--brand); border-color: var(--brand); color: #fff; }
|
| 580 |
+
.badge.status-new { text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.68rem; padding: 3px 9px; background: rgba(223,177,24,0.16); border-color: rgba(223,177,24,0.5); color: #9C7B0F; }
|
| 581 |
+
:root[data-theme="c"] .badge.status-new { color: #E7C657; }
|
| 582 |
+
|
| 583 |
+
/* =====================================================================
|
| 584 |
+
EXPLORE
|
| 585 |
+
===================================================================== */
|
| 586 |
+
.grid.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 10px; }
|
| 587 |
+
.grid.explore-grid { display: grid; grid-template-columns: minmax(320px, 32%) 1fr; gap: 16px; margin-top: 10px; }
|
| 588 |
+
/* Wide screens: the Configure rail and the result card each fill the full
|
| 589 |
+
section height and scroll internally (the page itself doesn't scroll).
|
| 590 |
+
On smaller screens the columns stack and the section scrolls normally. */
|
| 591 |
+
@media (min-width: 1041px) {
|
| 592 |
+
#sec-explore.visible { overflow: hidden; }
|
| 593 |
+
#sec-explore .explore-grid { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
|
| 594 |
+
/* Both columns fill the section height and scroll internally if content
|
| 595 |
+
overflows. The model list keeps its own natural (size=12) height β a
|
| 596 |
+
native <select> does NOT flex reliably, so we don't stretch it. */
|
| 597 |
+
#sec-explore .explore-grid > .card { min-height: 0; overflow: auto; }
|
| 598 |
}
|
| 599 |
|
| 600 |
+
.matchline { font-size: 0.9rem; color: var(--text); font-weight: 700; padding: 10px 12px; border-radius: var(--radius-sm); background: var(--brand-tint); border: 1px solid var(--brand-ring); }
|
| 601 |
+
.matchline b { font-family: var(--font-display); color: var(--brand); }
|
| 602 |
+
:root[data-theme="c"] .matchline b { color: #C3C8FF; }
|
| 603 |
+
.model-picker { border-radius: var(--radius-sm); padding: 12px; }
|
| 604 |
+
.model-picker-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
|
| 605 |
+
.model-picker-title { font-family: var(--font-display); font-weight: 700; color: var(--text); font-size: 1rem; letter-spacing: 0.03em; text-transform: uppercase; }
|
| 606 |
+
.model-picker-subtle { font-size: 0.8rem; color: var(--text-dim); font-weight: 600; }
|
| 607 |
+
.model-list { height: auto; min-height: 280px; padding: 8px 10px; line-height: 1.4; border-radius: var(--radius-sm); background-image: none !important; padding-right: 12px !important; cursor: auto; }
|
| 608 |
+
.model-list option { padding: 7px 8px; border-radius: 4px; }
|
| 609 |
+
|
| 610 |
+
/* Deploy page: numbered step strip under the section head */
|
| 611 |
+
.deploy-steps { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; padding: 0; list-style: none; }
|
| 612 |
+
.deploy-steps li {
|
| 613 |
+
display: inline-flex; align-items: center; gap: 9px; padding: 6px 14px 6px 7px;
|
| 614 |
+
border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--surface);
|
| 615 |
+
font-family: var(--font-display); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.03em;
|
| 616 |
+
text-transform: uppercase; color: var(--text-dim);
|
| 617 |
+
}
|
| 618 |
+
.deploy-steps .ds-num {
|
| 619 |
+
flex: 0 0 auto; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center;
|
| 620 |
+
background: var(--brand); color: #fff; font-size: 0.8rem; line-height: 1;
|
| 621 |
+
}
|
| 622 |
+
.deploy-steps .ds-txt { white-space: nowrap; }
|
| 623 |
+
/* Hero terminal for the download command (the only non-token colors allowed) */
|
| 624 |
+
#actions .cmd-row pre {
|
| 625 |
+
background: #18172B; color: #EAEBFB; margin: 0; padding: 12px 14px; border-radius: var(--radius-sm);
|
| 626 |
+
border: 1px solid rgba(42,40,157,0.55); border-left: 4px solid var(--brand-2);
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
.link { display: inline-flex; gap: 6px; align-items: center; font-weight: 700; color: var(--link-text); text-decoration: none; padding: 9px 13px; border-radius: var(--radius-sm); border: 1px solid var(--link-border); background: var(--link-bg); transition: background 130ms ease, border-color 130ms ease; }
|
| 630 |
+
.link:hover { border-color: var(--brand); filter: brightness(1.02); }
|
| 631 |
+
.link.small { padding: 6px 10px; font-size: 0.8rem; }
|
| 632 |
+
.link.link-na {
|
| 633 |
+
color: var(--text-mute); background: transparent;
|
| 634 |
+
border: 1px dashed var(--input-border); cursor: default; font-weight: 600;
|
| 635 |
}
|
| 636 |
+
.link.link-na:hover { border-color: var(--input-border); filter: none; }
|
| 637 |
+
|
| 638 |
+
.summary-grid { display: grid; grid-template-columns: 1fr 300px; gap: 16px; align-items: start; }
|
| 639 |
+
.summary-grid ul { margin: 0; padding-left: 0; list-style: none; }
|
| 640 |
+
.summary-grid li { margin: 6px 0; color: var(--text); padding-left: 18px; position: relative; }
|
| 641 |
+
.summary-grid li::before { content: ""; position: absolute; left: 0; top: 0.5em; width: 8px; height: 8px; background: var(--brand); }
|
| 642 |
+
:root[data-theme="c"] .summary-grid li::before { background: #6670E6; }
|
| 643 |
+
.repo-buttons { display: grid; gap: 10px; justify-items: end; }
|
| 644 |
+
.repo-buttons .link { width: 100%; justify-content: center; }
|
| 645 |
+
|
| 646 |
+
/* Metrics cards */
|
| 647 |
+
.metric-banner { margin: 10px 0; padding: 9px 12px; border-radius: var(--radius-sm); background: var(--surface); border: 1px solid var(--surface-border); font-weight: 700; color: var(--text); }
|
| 648 |
+
.metric-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; margin-top: 10px; }
|
| 649 |
+
.metric-card { border-radius: var(--radius-sm); padding: 14px; min-width: 0; }
|
| 650 |
+
.metric-card-title { font-family: var(--font-display); font-weight: 700; color: var(--text); font-size: 0.95rem; margin-bottom: 8px; letter-spacing: 0.04em; text-transform: uppercase; }
|
| 651 |
+
.metric-pre { white-space: pre-wrap; word-break: break-word; margin: 0; border-radius: var(--radius-sm); }
|
| 652 |
+
|
| 653 |
+
/* =====================================================================
|
| 654 |
+
Merged "Precision & performance" block (selector + metrics)
|
| 655 |
+
Replaces the old precision/quant chip label and the standalone
|
| 656 |
+
"Metrics" heading. The selector drives the metrics shown beside it β
|
| 657 |
+
each option keeps .chip-btn + data-artifact, so the click handler is
|
| 658 |
+
unchanged (zero JS change).
|
| 659 |
+
===================================================================== */
|
| 660 |
+
.pm-heading { margin-top: 20px; }
|
| 661 |
+
|
| 662 |
+
.pm-block {
|
| 663 |
display: grid;
|
| 664 |
+
grid-template-columns: minmax(140px, 3fr) minmax(0, 4fr) minmax(0, 3fr); /* precision | est-vs-HIL graph | accuracy */
|
| 665 |
+
gap: 14px;
|
| 666 |
+
align-items: stretch; /* all three columns share the same height */
|
| 667 |
+
margin-top: 12px;
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
/* ---- Selector rail (left) ---- */
|
| 671 |
+
.pm-rail {
|
| 672 |
+
border-radius: var(--radius-sm);
|
| 673 |
+
border: 1px solid var(--card-border);
|
| 674 |
+
background: var(--card-bg);
|
| 675 |
+
backdrop-filter: var(--card-blur);
|
| 676 |
+
-webkit-backdrop-filter: var(--card-blur);
|
| 677 |
+
box-shadow: var(--card-shadow);
|
| 678 |
+
padding: 12px;
|
| 679 |
min-width: 0;
|
| 680 |
}
|
| 681 |
+
.pm-rail-cap {
|
| 682 |
+
font-family: var(--font-display);
|
| 683 |
+
font-weight: 700;
|
| 684 |
+
font-size: 0.78rem;
|
| 685 |
+
letter-spacing: 0.05em;
|
| 686 |
+
text-transform: uppercase;
|
| 687 |
+
color: var(--text-dim);
|
| 688 |
+
margin-bottom: 10px;
|
| 689 |
}
|
| 690 |
+
.pm-rail-list { display: flex; flex-direction: column; gap: 6px; }
|
| 691 |
+
|
| 692 |
+
/* Each selectable row keeps .chip-btn (handler-compatible); override the
|
| 693 |
+
inherited tiny-pill look into a full-width row. */
|
| 694 |
+
.chip-btn.pm-opt {
|
| 695 |
+
display: flex;
|
| 696 |
+
align-items: center;
|
| 697 |
+
gap: 10px;
|
| 698 |
+
width: 100%;
|
| 699 |
+
text-align: left;
|
| 700 |
+
padding: 10px 12px;
|
| 701 |
+
border: 1px solid var(--chip-border);
|
| 702 |
+
background: var(--chip-bg);
|
| 703 |
+
border-radius: var(--radius-sm);
|
| 704 |
+
cursor: pointer;
|
| 705 |
+
position: relative;
|
| 706 |
+
font-size: inherit;
|
| 707 |
+
transition: background 130ms ease, border-color 130ms ease, box-shadow 130ms ease;
|
| 708 |
}
|
| 709 |
+
.chip-btn.pm-opt:hover { background: var(--brand-tint); border-color: var(--brand-ring); transform: none; }
|
| 710 |
+
.chip-btn.pm-opt:focus-visible { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-tint); }
|
| 711 |
|
| 712 |
+
/* Radio-dot indicator */
|
| 713 |
+
.pm-opt-dot {
|
| 714 |
+
flex: 0 0 auto;
|
| 715 |
+
width: 16px; height: 16px;
|
| 716 |
+
border-radius: 50%;
|
| 717 |
+
border: 2px solid var(--text-mute);
|
| 718 |
+
background: transparent;
|
| 719 |
+
display: grid;
|
| 720 |
+
place-items: center; /* centers the check glyph regardless of box metrics */
|
| 721 |
+
transition: border-color 130ms ease, background 130ms ease;
|
| 722 |
}
|
| 723 |
+
|
| 724 |
+
/* Label (condensed display type, like brand titles) */
|
| 725 |
+
.pm-opt-label {
|
| 726 |
flex: 1 1 auto;
|
| 727 |
+
min-width: 0;
|
| 728 |
+
font-family: var(--font-display);
|
| 729 |
+
font-weight: 700;
|
| 730 |
+
font-size: 0.96rem;
|
| 731 |
+
letter-spacing: 0.03em;
|
| 732 |
+
text-transform: uppercase;
|
| 733 |
+
color: var(--text);
|
| 734 |
+
line-height: 1.1;
|
| 735 |
+
word-break: break-word;
|
| 736 |
}
|
| 737 |
|
| 738 |
+
/* "Selected" badge β only on the active row */
|
| 739 |
+
.pm-opt-badge {
|
| 740 |
+
flex: 0 0 auto;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 741 |
display: none;
|
| 742 |
+
font-family: var(--font-display);
|
| 743 |
+
font-weight: 700;
|
| 744 |
+
font-size: 0.62rem;
|
| 745 |
+
letter-spacing: 0.06em;
|
| 746 |
+
text-transform: uppercase;
|
| 747 |
+
color: #fff;
|
| 748 |
+
background: rgba(255,255,255,0.22);
|
| 749 |
+
border-radius: 999px;
|
| 750 |
+
padding: 2px 8px;
|
| 751 |
+
line-height: 1.3;
|
| 752 |
}
|
| 753 |
+
|
| 754 |
+
/* ---- ACTIVE row: unmistakable solid brand fill ---- */
|
| 755 |
+
.chip-btn.pm-opt.active {
|
| 756 |
+
background: var(--brand);
|
| 757 |
+
border-color: var(--brand);
|
| 758 |
+
box-shadow: 0 2px 10px rgba(42,40,157,0.28), inset 0 1px 0 rgba(255,255,255,0.18);
|
| 759 |
+
transform: none;
|
| 760 |
+
}
|
| 761 |
+
.chip-btn.pm-opt.active:hover { background: var(--brand-press); border-color: var(--brand-press); }
|
| 762 |
+
.chip-btn.pm-opt.active .pm-opt-label { color: #fff; }
|
| 763 |
+
.chip-btn.pm-opt.active .pm-opt-badge { display: inline-block; }
|
| 764 |
+
.chip-btn.pm-opt.active .pm-opt-dot { border-color: #fff; background: #fff; }
|
| 765 |
+
.chip-btn.pm-opt.active .pm-opt-dot::after {
|
| 766 |
+
content: "";
|
| 767 |
+
width: 3.5px; height: 7px;
|
| 768 |
+
margin-top: -1px; /* optical lift so the tick sits centred in the circle */
|
| 769 |
+
border: solid var(--brand); border-width: 0 2px 2px 0;
|
| 770 |
+
transform: rotate(45deg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 771 |
}
|
| 772 |
+
.chip-btn.pm-opt.active:focus-visible { box-shadow: 0 0 0 3px var(--brand-ring), 0 2px 10px rgba(42,40,157,0.28); }
|
| 773 |
|
| 774 |
+
.pm-opt-empty {
|
| 775 |
+
padding: 12px;
|
| 776 |
+
border: 1px dashed var(--hairline);
|
| 777 |
+
border-radius: var(--radius-sm);
|
| 778 |
+
font-size: 0.85rem;
|
| 779 |
+
text-align: center;
|
| 780 |
}
|
| 781 |
+
|
| 782 |
+
/* ---- Column 2: Est-vs-HIL throughput as a small bar graph.
|
| 783 |
+
Bars use flex-grow (not % heights) so they scale to whatever height the
|
| 784 |
+
row stretches to, with no dependence on a definite track height. ---- */
|
| 785 |
+
.pm-graph, .pm-acc { display: flex; flex-direction: column; min-width: 0; }
|
| 786 |
+
.pm-bars { flex: 1 1 auto; display: flex; align-items: stretch; justify-content: center; gap: 22px; min-height: 96px; margin-top: 12px; }
|
| 787 |
+
.pm-bar-col { display: flex; flex-direction: column; align-items: center; gap: 7px; flex: 0 0 auto; }
|
| 788 |
+
.pm-bar-val { font-family: var(--font-display); font-weight: 700; font-size: 0.92rem; line-height: 1; color: var(--text); }
|
| 789 |
+
.pm-bar-track { width: 40px; flex: 1 1 auto; min-height: 56px; display: flex; flex-direction: column; }
|
| 790 |
+
.pm-bar-fill { width: 100%; min-height: 4px; border-radius: 6px 6px 2px 2px; }
|
| 791 |
+
.pm-bar-fill.est { background: var(--brand-2); }
|
| 792 |
+
.pm-bar-fill.hil { background: var(--brand); }
|
| 793 |
+
.pm-bar-lbl { font-family: var(--font-display); font-weight: 700; font-size: 0.66rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim); }
|
| 794 |
+
.pm-graph-empty { flex: 1 1 auto; display: grid; place-items: center; min-height: 80px; font-size: 0.85rem; }
|
| 795 |
+
.pm-graph-foot { margin-top: 10px; text-align: center; font-size: 0.7rem; font-weight: 600; color: var(--text-mute); }
|
| 796 |
+
|
| 797 |
+
/* ---- Column 3: Accuracy (HIL-first; "β" until published) ---- */
|
| 798 |
+
.pm-acc-body { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; text-align: center; }
|
| 799 |
+
.pm-acc-num { font-family: var(--font-display); font-weight: 700; font-size: 1.95rem; line-height: 1; color: var(--brand); }
|
| 800 |
+
:root[data-theme="c"] .pm-acc-num { color: #C3C8FF; }
|
| 801 |
+
.pm-acc-num.empty { color: var(--text-mute); font-size: 1.6rem; }
|
| 802 |
+
.pm-acc-sub { font-size: 0.72rem; font-weight: 600; color: var(--text-dim); }
|
| 803 |
+
|
| 804 |
+
/* ---- Dark variant (data-theme="c") β match the established #6670E6 accent ---- */
|
| 805 |
+
:root[data-theme="c"] .chip-btn.pm-opt.active {
|
| 806 |
+
background: #6670E6;
|
| 807 |
+
border-color: #6670E6;
|
| 808 |
+
box-shadow: 0 2px 12px rgba(0,0,0,0.40), inset 0 1px 0 rgba(255,255,255,0.20);
|
| 809 |
}
|
| 810 |
+
:root[data-theme="c"] .chip-btn.pm-opt.active:hover { background: #565FD6; border-color: #565FD6; }
|
| 811 |
+
:root[data-theme="c"] .chip-btn.pm-opt.active .pm-opt-dot::after { border-color: #6670E6; }
|
| 812 |
+
|
| 813 |
+
/* ---- Responsive: selector ABOVE metrics on narrow screens ---- */
|
| 814 |
+
@media (max-width: 760px) {
|
| 815 |
+
.pm-block { grid-template-columns: 1fr; gap: 14px; }
|
| 816 |
+
.pm-rail-list { flex-direction: row; flex-wrap: wrap; }
|
| 817 |
+
.chip-btn.pm-opt { width: auto; flex: 1 1 150px; }
|
| 818 |
}
|
| 819 |
+
|
| 820 |
+
/* Mini chart */
|
| 821 |
+
.mini-chart-wrap { margin-top: 12px; border: 1px solid var(--canvas-border); border-radius: var(--radius-sm); background: var(--canvas-bg); overflow: hidden; position: relative; }
|
| 822 |
+
.mini-chart-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 11px 12px 0; }
|
| 823 |
+
.mini-chart-title { font-family: var(--font-display); font-weight: 700; color: #2C2B45; letter-spacing: 0.02em; }
|
| 824 |
+
.mini-chart-subtle { color: #5b5750; font-weight: 600; font-size: 0.85rem; }
|
| 825 |
+
.mini-chart-wrap canvas { cursor: grab; }
|
| 826 |
+
.mini-chart-wrap canvas:active { cursor: grabbing; }
|
| 827 |
+
|
| 828 |
+
/* Download copy */
|
| 829 |
+
.cmd-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
|
| 830 |
+
.cmd-row pre { flex: 1 1 auto; }
|
| 831 |
+
.copy-btn { appearance: none; border: 1px solid var(--chip-border); background: var(--chip-bg); backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur); border-radius: var(--radius-sm); padding: 9px 12px; cursor: pointer; font-weight: 700; line-height: 1; display: inline-flex; align-items: center; gap: 8px; color: var(--text); white-space: nowrap; transition: background 130ms ease, border-color 130ms ease; }
|
| 832 |
+
.copy-btn:hover { background: var(--brand-tint); border-color: var(--brand); }
|
| 833 |
+
.copy-btn.copied { background: color-mix(in srgb, var(--bc-gguf) 16%, transparent); border-color: color-mix(in srgb, var(--bc-gguf) 45%, transparent); color: var(--bc-gguf); }
|
| 834 |
+
.copy-btn .icon { font-size: 1rem; }
|
| 835 |
+
|
| 836 |
+
/* =====================================================================
|
| 837 |
+
TABLE
|
| 838 |
+
===================================================================== */
|
| 839 |
+
.table-shell { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
|
| 840 |
+
.table-wrap { flex: 1 1 auto; min-height: 0; border: 1px solid var(--card-border); border-radius: var(--radius-sm); overflow: auto; background: var(--card-bg); backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur); }
|
| 841 |
+
table.table { width: 100%; min-width: 720px; border-collapse: collapse; background: transparent; }
|
| 842 |
+
.table th, .table td { padding: 12px 15px; border-bottom: 1px solid var(--hairline); font-size: 0.9rem; color: var(--text); vertical-align: top; text-align: left; }
|
| 843 |
+
/* Header β brand band with a brand-2 accent underline (the signature edge accent) */
|
| 844 |
+
.table th {
|
| 845 |
+
background: var(--table-head-bg); color: var(--table-head-text);
|
| 846 |
+
font-family: var(--font-display); font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; font-size: 0.78rem;
|
| 847 |
+
white-space: nowrap; border-bottom: none; box-shadow: inset 0 -3px 0 var(--brand-2);
|
| 848 |
}
|
| 849 |
+
.table thead th { position: sticky; top: 0; z-index: 3; }
|
| 850 |
+
.table tbody tr { transition: background 130ms ease; }
|
| 851 |
+
/* subtle zebra for cross-row scanning (pinned cell gets the matching tint over its opaque base) */
|
| 852 |
+
.table tbody tr:nth-child(even) td { background: rgba(42,40,157,0.035); }
|
| 853 |
+
.table tbody tr:nth-child(even) .pin { background: linear-gradient(rgba(42,40,157,0.035), rgba(42,40,157,0.035)), var(--panel-bg); }
|
| 854 |
+
.table tbody tr:hover td { background: var(--brand-tint); }
|
| 855 |
+
.table tbody tr:last-child td { border-bottom: none; }
|
| 856 |
+
/* Name reads as the row's title; a left accent bar slides in on hover */
|
| 857 |
+
.table td.cell-name { font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; color: var(--text); white-space: nowrap; }
|
| 858 |
+
/* Publisher logo + model name in the Name cell (mirrors the card's .mc-designer) */
|
| 859 |
+
.tc-name { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
|
| 860 |
+
.tc-name .mc-logo { line-height: 0; }
|
| 861 |
+
.table tbody tr:hover td.cell-name { box-shadow: inset 3px 0 0 var(--brand); }
|
| 862 |
|
| 863 |
+
.pin { position: sticky; left: 0; z-index: 2; background: var(--panel-bg); }
|
| 864 |
+
.table thead .pin { z-index: 4; background: var(--table-head-bg); }
|
| 865 |
+
.table tbody tr:hover .pin { background: var(--card-hover-bg); }
|
| 866 |
+
|
| 867 |
+
.table .badges { flex-direction: column; align-items: flex-start; gap: 6px; }
|
| 868 |
+
.table .badges.badges-row { flex-direction: row; flex-wrap: wrap; }
|
| 869 |
+
.table th.details-col, .table td.details-col { width: 1%; white-space: nowrap; }
|
| 870 |
+
.table td.details-col { vertical-align: middle; }
|
| 871 |
+
|
| 872 |
+
/* Metric mini-table β label left, value right-aligned in display type */
|
| 873 |
+
.cell-metrics { display: grid; gap: 3px; white-space: normal; line-height: 1.2; min-width: 118px; }
|
| 874 |
+
.cell-metrics .row { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: baseline; }
|
| 875 |
+
.cell-metrics .k { font-size: 0.66rem; font-weight: 700; color: var(--text-mute); text-transform: uppercase; letter-spacing: 0.04em; }
|
| 876 |
+
.cell-metrics .v { font-family: var(--font-display); font-weight: 700; color: var(--text); text-align: right; font-size: 0.95rem; line-height: 1; }
|
| 877 |
+
|
| 878 |
+
.mini-btn { appearance: none; border: 1px solid var(--brand-ring); background: var(--brand-tint); color: var(--brand); border-radius: var(--radius-sm); padding: 7px 12px; font-weight: 700; font-size: 0.82rem; cursor: pointer; font-family: var(--font-body); transition: background 130ms ease; }
|
| 879 |
+
:root[data-theme="c"] .mini-btn { color: #C3C8FF; }
|
| 880 |
+
.mini-btn:hover { background: var(--brand); color: #fff; }
|
| 881 |
+
|
| 882 |
+
/* =====================================================================
|
| 883 |
+
MODAL
|
| 884 |
+
===================================================================== */
|
| 885 |
+
.modal { position: fixed; inset: 0; z-index: 10000; display: none; }
|
| 886 |
+
.modal.open { display: block; }
|
| 887 |
+
.modal-backdrop { position: absolute; inset: 0; background: var(--modal-backdrop); backdrop-filter: blur(4px); }
|
| 888 |
+
.modal-panel {
|
| 889 |
+
position: absolute; top: 30px; left: 50%; transform: translateX(-50%);
|
| 890 |
+
width: min(980px, calc(100vw - 28px)); max-height: calc(100vh - 60px); overflow: hidden;
|
| 891 |
+
display: flex; flex-direction: column;
|
| 892 |
+
background: var(--panel-bg); backdrop-filter: var(--card-blur); -webkit-backdrop-filter: var(--card-blur);
|
| 893 |
+
border-radius: var(--radius); border: 1px solid var(--panel-border); box-shadow: 0 40px 90px rgba(0,0,0,0.35), var(--panel-shadow);
|
| 894 |
+
}
|
| 895 |
+
:root[data-theme="a"] .modal-panel { background: #FFFFFF; border-top: 3px solid var(--brand); }
|
| 896 |
+
.modal-head { flex: 0 0 auto; z-index: 5; background: var(--header-bg); backdrop-filter: var(--header-blur); border-bottom: 1px solid var(--hairline); border-radius: var(--radius) var(--radius) 0 0; padding: 15px 18px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
| 897 |
+
.modal-title { font-family: var(--font-display); font-weight: 700; font-size: 1.35rem; color: var(--text); letter-spacing: 0.02em; text-transform: uppercase; }
|
| 898 |
+
.icon-btn { appearance: none; border: 1px solid var(--chip-border); background: var(--chip-bg); border-radius: var(--radius-sm); padding: 8px 11px; cursor: pointer; font-weight: 700; color: var(--text); }
|
| 899 |
+
.icon-btn:hover { background: var(--brand-tint); border-color: var(--brand); }
|
| 900 |
+
.modal-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 16px 18px 20px; }
|
| 901 |
+
|
| 902 |
+
/* =====================================================================
|
| 903 |
+
Scrollbars
|
| 904 |
+
===================================================================== */
|
| 905 |
+
.facets::-webkit-scrollbar, .card-grid::-webkit-scrollbar, .table-wrap::-webkit-scrollbar,
|
| 906 |
+
.carousel-track::-webkit-scrollbar, #sec-overview::-webkit-scrollbar, #sec-explore::-webkit-scrollbar,
|
| 907 |
+
#sec-explore .explore-grid > .card::-webkit-scrollbar,
|
| 908 |
+
.modal-panel::-webkit-scrollbar { width: 10px; height: 9px; }
|
| 909 |
+
::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
|
| 910 |
+
::-webkit-scrollbar-track { background: transparent; }
|
| 911 |
+
|
| 912 |
+
/* =====================================================================
|
| 913 |
+
Responsive
|
| 914 |
+
---------------------------------------------------------------------
|
| 915 |
+
β₯1281px Full layout (tuned for wide / ultrawide screens)
|
| 916 |
+
β€1280px Laptop β tighten padding, narrower rails, shorter chart
|
| 917 |
+
β€1040px Tablet β single-column layouts, catalog filters collapse behind a toggle
|
| 918 |
+
β€680px Phone β switch to natural document scroll, stack everything
|
| 919 |
+
===================================================================== */
|
| 920 |
+
|
| 921 |
+
/* ---------- Laptop: keep the desktop layout but ease the spacing ---------- */
|
| 922 |
+
@media (max-width: 1280px) {
|
| 923 |
+
.section-title { font-size: 1.7rem; }
|
| 924 |
+
.catalog-layout { grid-template-columns: 184px minmax(0, 1fr); }
|
| 925 |
+
.card-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
|
| 926 |
+
.grid.explore-grid { grid-template-columns: minmax(300px, 36%) 1fr; }
|
| 927 |
+
.constellation canvas { height: 400px; }
|
| 928 |
+
.stat-tiles { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
|
| 929 |
+
}
|
| 930 |
+
|
| 931 |
+
/* ---------- Tablet ---------- */
|
| 932 |
+
@media (max-width: 1040px) {
|
| 933 |
+
/* Nav stays inline on the header row (no wrap) right down to the phone breakpoint */
|
| 934 |
+
.topbar-inner { padding: 10px 16px; }
|
| 935 |
.grid.two, .grid.explore-grid { grid-template-columns: 1fr; }
|
| 936 |
+
.field-row.two { grid-template-columns: 1fr 1fr; }
|
| 937 |
+
.summary-grid { grid-template-columns: 1fr; }
|
| 938 |
+
.repo-buttons { justify-items: start; }
|
| 939 |
+
.repo-buttons .link { width: auto; }
|
| 940 |
+
.metric-grid { grid-template-columns: 1fr 1fr; }
|
| 941 |
+
.catalog-layout { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
|
| 942 |
+
.facets { border-right: none; border-bottom: 1px solid var(--hairline); max-height: none; overflow: visible; }
|
| 943 |
+
/* Catalog filters collapse behind the "Filters" toggle β the old always-open
|
| 944 |
+
top strip is removed, leaving only "left rail" (desktop) and "collapsed".
|
| 945 |
+
Scoped to .facets-head so the Explore toggle is unaffected here. */
|
| 946 |
+
.facets-head .filter-toggle { display: flex; width: auto; flex: 1 1 auto; }
|
| 947 |
+
.facets-title { display: none; }
|
| 948 |
+
.facets-body { display: none; }
|
| 949 |
+
.facets-body.open { display: flex; max-height: 50vh; overflow-y: auto; padding-bottom: 2px; }
|
| 950 |
+
/* Overview model constellation β same merge: its "Chart filters" collapse moves
|
| 951 |
+
up here too, so it has only "full" (desktop) and "collapsed" states. */
|
| 952 |
+
#cstlFilterToggle { display: flex; margin-bottom: 12px; }
|
| 953 |
+
.cstl-controls { display: none; margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
|
| 954 |
+
.cstl-controls.open { display: flex; margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--hairline); }
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
/* ---------- Phone: natural document scroll, burger nav, fully stacked ---------- */
|
| 958 |
+
@media (max-width: 680px) {
|
| 959 |
+
/* Release the fixed-viewport lock so the page scrolls as one document */
|
| 960 |
+
html, body { height: auto; }
|
| 961 |
+
body { height: auto; min-height: 100dvh; overflow-y: auto; overflow-x: hidden; }
|
| 962 |
+
.topbar { position: sticky; top: 0; }
|
| 963 |
+
.content { flex: 0 0 auto; height: auto; min-height: 0; overflow: visible; }
|
| 964 |
+
|
| 965 |
+
.section { height: auto; min-height: 0; overflow: visible; }
|
| 966 |
+
#sec-overview.visible, #sec-explore.visible { overflow: visible; }
|
| 967 |
+
|
| 968 |
+
/* Header stays on a single line: brand left, burger right */
|
| 969 |
+
.topbar-inner { flex-wrap: nowrap; padding: 9px 12px; gap: 12px; }
|
| 970 |
+
.brand-icon { height: 19px; }
|
| 971 |
+
.brand-subtitle { display: none; }
|
| 972 |
+
.nav-burger { display: inline-flex; }
|
| 973 |
+
|
| 974 |
+
/* Tabs collapse into a dropdown panel under the header */
|
| 975 |
+
.tabs {
|
| 976 |
+
position: absolute; top: 100%; left: 0; right: 0; margin: 0; z-index: 60;
|
| 977 |
+
flex-direction: column; align-items: stretch; gap: 4px; padding: 8px;
|
| 978 |
+
display: none;
|
| 979 |
+
background: rgba(255,255,255,0.95); backdrop-filter: blur(26px) saturate(165%); -webkit-backdrop-filter: blur(26px) saturate(165%);
|
| 980 |
+
border-bottom: 1px solid var(--header-border); box-shadow: 0 18px 40px rgba(42,40,157,0.20);
|
| 981 |
+
}
|
| 982 |
+
.tabs.open { display: flex; }
|
| 983 |
+
.nav-item { width: 100%; text-align: left; padding: 11px 14px; font-size: 0.96rem; }
|
| 984 |
+
|
| 985 |
+
/* Headings scale down */
|
| 986 |
+
.section-title { font-size: 1.45rem; }
|
| 987 |
+
.card-head-title { font-size: 1.12rem; }
|
| 988 |
+
.carousel-section.featured .carousel-title { font-size: 1.18rem; }
|
| 989 |
+
|
| 990 |
+
/* Overview */
|
| 991 |
+
.stat-tiles { grid-template-columns: 1fr 1fr; }
|
| 992 |
+
.stat-num { font-size: 1.7rem; }
|
| 993 |
+
.cstl-controls .field { min-width: calc(50% - 6px); flex: 1 1 calc(50% - 6px); }
|
| 994 |
+
.constellation canvas { height: 320px; }
|
| 995 |
+
.rc-card { flex-basis: 78vw; }
|
| 996 |
+
|
| 997 |
+
/* Catalog β a wrapping two-up grid that scrolls vertically with the page
|
| 998 |
+
(NOT a single horizontal swipe lane) */
|
| 999 |
+
.toolbar { flex-wrap: wrap; }
|
| 1000 |
+
.card-grid {
|
| 1001 |
+
flex: 0 0 auto; height: auto; min-height: 0;
|
| 1002 |
+
display: grid; grid-template-columns: repeat(2, 1fr);
|
| 1003 |
+
overflow-x: hidden; overflow-y: visible;
|
| 1004 |
+
gap: 10px; padding-bottom: 16px; scroll-snap-type: none;
|
| 1005 |
+
}
|
| 1006 |
+
.model-card { width: auto; scroll-snap-align: none; padding: 10px; gap: 8px; }
|
| 1007 |
+
.mc-monogram { width: 34px; height: 34px; font-size: 0.8rem; }
|
| 1008 |
+
.mc-head { gap: 9px; }
|
| 1009 |
+
.mc-title { font-size: 0.95rem; }
|
| 1010 |
+
.mc-stat { padding: 8px 10px 8px 11px; }
|
| 1011 |
+
.mc-stat-num { font-size: 1.18rem; }
|
| 1012 |
+
/* Table β cards: collapse each row into a stacked card (no horizontal scroll),
|
| 1013 |
+
flowing with the document. Each <td> becomes a labelled space-between row. */
|
| 1014 |
+
.table-view { display: block; flex: 0 0 auto; height: auto; min-height: 0; overflow: visible; padding: 8px 10px 16px; }
|
| 1015 |
+
.table-wrap { max-height: none; overflow: visible; border: none; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
|
| 1016 |
+
table.table { min-width: 0; display: block; width: auto; }
|
| 1017 |
+
.table thead { display: none; }
|
| 1018 |
+
.table tbody { display: flex; flex-direction: column; gap: 12px; }
|
| 1019 |
+
.table tbody tr {
|
| 1020 |
+
position: relative; overflow: hidden; display: block;
|
| 1021 |
+
padding: 15px 16px 13px;
|
| 1022 |
+
border: 1px solid var(--card-border); border-radius: var(--card-radius);
|
| 1023 |
+
background: var(--card-bg); box-shadow: var(--card-shadow);
|
| 1024 |
+
}
|
| 1025 |
+
/* signature top accent (matches .model-card) */
|
| 1026 |
+
.table tbody tr::before {
|
| 1027 |
+
content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
|
| 1028 |
+
background: linear-gradient(90deg, var(--brand), var(--brand-2));
|
| 1029 |
+
transform: scaleX(0.34); transform-origin: left; opacity: 0.85;
|
| 1030 |
+
}
|
| 1031 |
+
/* cancel desktop row tints + sticky pins inside cards */
|
| 1032 |
+
.table tbody tr:hover td, .table tbody tr:nth-child(even) td { background: transparent; }
|
| 1033 |
+
.table .pin { position: static !important; left: auto !important; z-index: auto; background: transparent; }
|
| 1034 |
+
.table tbody tr:hover td.cell-name { box-shadow: none; }
|
| 1035 |
+
.table tbody td {
|
| 1036 |
+
display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
|
| 1037 |
+
width: auto; padding: 8px 0; border-bottom: 1px solid var(--hairline);
|
| 1038 |
+
font-size: 0.88rem; white-space: normal; text-align: right;
|
| 1039 |
+
}
|
| 1040 |
+
.table tbody td::before {
|
| 1041 |
+
content: attr(data-label); flex: 0 0 auto; text-align: left;
|
| 1042 |
+
font-family: var(--font-display); font-weight: 700; font-size: 0.66rem;
|
| 1043 |
+
text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-dim);
|
| 1044 |
+
}
|
| 1045 |
+
.table tbody td:last-child { border-bottom: none; }
|
| 1046 |
+
/* Name β card title (block, larger, no label) */
|
| 1047 |
+
.table tbody td[data-label="Name"] {
|
| 1048 |
+
display: block; text-align: left; padding: 0 0 11px; margin-bottom: 4px;
|
| 1049 |
+
border-bottom: 1px solid var(--hairline); font-size: 1.18rem; white-space: normal;
|
| 1050 |
+
}
|
| 1051 |
+
.table tbody td[data-label="Name"]::before { content: none; }
|
| 1052 |
+
/* Details β full-width button */
|
| 1053 |
+
.table tbody td.details-col { display: block; width: auto; padding: 12px 0 4px; border-bottom: none; }
|
| 1054 |
+
.table tbody td.details-col::before { content: none; }
|
| 1055 |
+
.table tbody td.details-col .mini-btn { width: 100%; }
|
| 1056 |
+
.table .cell-metrics { min-width: 0; }
|
| 1057 |
+
.table .badges, .table .badges.badges-row { flex-direction: row; flex-wrap: wrap; justify-content: flex-end; }
|
| 1058 |
+
|
| 1059 |
+
/* Explore */
|
| 1060 |
+
.field-row.two { grid-template-columns: 1fr; }
|
| 1061 |
+
.metric-grid { grid-template-columns: 1fr; }
|
| 1062 |
+
.model-list { min-height: 220px; }
|
| 1063 |
+
|
| 1064 |
+
/* Collapsible filter clusters β only Explore collapses here now.
|
| 1065 |
+
(Catalog + Overview-constellation filters collapse at β€1040px above.) */
|
| 1066 |
+
.filter-toggle { display: flex; }
|
| 1067 |
+
.explore-filters { display: none; }
|
| 1068 |
+
.explore-filters.open { display: grid; }
|
| 1069 |
+
/* On phone the whole page scrolls, so let the opened filter lists expand fully */
|
| 1070 |
+
.facets-body.open { max-height: none; overflow: visible; }
|
| 1071 |
+
|
| 1072 |
+
/* Modal goes near full-screen */
|
| 1073 |
+
.modal-panel { top: 8px; width: calc(100vw - 16px); max-height: calc(100dvh - 16px); }
|
| 1074 |
+
.modal-title { font-size: 1.15rem; }
|
| 1075 |
+
.modal-body { padding: 14px; }
|
| 1076 |
+
}
|
| 1077 |
+
|
| 1078 |
+
/* Explore: on phone the single "Filters" button reveals #exploreFilters, so
|
| 1079 |
+
force the nested Advanced tier open (no two-step) and hide its desktop
|
| 1080 |
+
sub-toggle. Must come AFTER the block above to win on source order. */
|
| 1081 |
+
@media (max-width: 680px) {
|
| 1082 |
+
.explore-advanced { display: grid; gap: 10px; }
|
| 1083 |
+
.filter-toggle--inline { display: none; }
|
| 1084 |
+
.explore-filters .field-row.two, .explore-advanced .field-row.two { grid-template-columns: 1fr 1fr; }
|
| 1085 |
+
}
|
| 1086 |
+
|
| 1087 |
+
/* ---------- Small phone ---------- */
|
| 1088 |
+
@media (max-width: 380px) {
|
| 1089 |
+
.stat-tiles { grid-template-columns: 1fr; }
|
| 1090 |
+
}
|