Skip to content

Commit f53f72f

Browse files
committed
feat: the /ml catalogue generates from the models.yaml registry
The page was hand-written and listed 14 of what is now 35 models. scripts/generate-models.mjs reads the registry (same pattern as the maps catalogue generator): id, task, precision, size, split-part count, sha-pinned release link, and ordered metrics per model; ml.astro renders the ledger from that data, split by tier on precision, with every id linking to its release. Prose counts now compute. The maps page test's hardcoded 289 became 318 (the true current total).
1 parent 4fd2ae9 commit f53f72f

5 files changed

Lines changed: 1088 additions & 121 deletions

File tree

‎package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"format:check": "prettier --check .",
1919
"test:e2e": "playwright test",
2020
"test:e2e:ui": "playwright test --ui",
21-
"generate:catalogue": "tsx scripts/generate-catalogue.mjs"
21+
"generate:catalogue": "tsx scripts/generate-catalogue.mjs",
22+
"generate:models": "tsx scripts/generate-models.mjs"
2223
},
2324
"dependencies": {
2425
"@asciidoctor/core": "^4.0.6",

‎scripts/generate-models.mjs‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Regenerate `src/data/models-catalogue.json` from the model registry
3+
* (interscript-models/models.yaml). Run: `npm run generate:models`.
4+
*/
5+
6+
import { readFileSync, writeFileSync } from "node:fs"
7+
import { join, resolve, dirname } from "node:path"
8+
import { fileURLToPath } from "node:url"
9+
import yaml from "js-yaml"
10+
11+
const __dirname = dirname(fileURLToPath(import.meta.url))
12+
const ROOT = resolve(__dirname, "..")
13+
const REGISTRY = resolve(ROOT, "..", "interscript-models", "models.yaml")
14+
const OUT_PATH = join(ROOT, "src", "data", "models-catalogue.json")
15+
16+
const METRIC_ORDER = [
17+
"der_total_greedy", "der_morph_greedy", "der_teacher_greedy",
18+
"der_teacher_fullset", "wer_wikinews2024_multiref", "wer_wikinews_multiref",
19+
"cer", "per", "em",
20+
]
21+
22+
function humanSize(bytes) {
23+
if (!bytes) return ""
24+
const gib = bytes / 2 ** 30
25+
if (gib >= 1) return `${gib.toFixed(1)} GiB`
26+
return `${(bytes / 2 ** 20).toFixed(0)} MiB`
27+
}
28+
29+
function releaseTag(entry, id) {
30+
const first = (entry.parts || [])[0]
31+
if (first && first.url) {
32+
const m = first.url.match(/releases\/download\/([^/]+)\//)
33+
if (m) return m[1]
34+
}
35+
const alias = (entry.aliases || [])[0]
36+
return alias || id
37+
}
38+
39+
function main() {
40+
const registry = yaml.load(readFileSync(REGISTRY, "utf8"))
41+
const out = {}
42+
for (const [id, e] of Object.entries(registry.models || {})) {
43+
const metrics = (e.metrics || []).map((m) => ({
44+
name: m.name,
45+
value: m.value,
46+
}))
47+
metrics.sort(
48+
(a, b) =>
49+
(METRIC_ORDER.indexOf(a.name) + 1 || 99) -
50+
(METRIC_ORDER.indexOf(b.name) + 1 || 99),
51+
)
52+
out[id] = {
53+
id,
54+
task: e.task || "",
55+
scripts: e.scripts || [],
56+
precision: e.precision || "",
57+
size: e.size || 0,
58+
sizeHuman: humanSize(e.size),
59+
splitParts: (e.parts || []).length || null,
60+
filename: e.filename || "",
61+
releaseTag: releaseTag(e, id),
62+
releaseUrl: `https://github.com/interscript/interscript-models/releases/tag/${releaseTag(e, id)}`,
63+
metrics,
64+
license: e.license || "",
65+
paritySamples: e.parity ? e.parity.samples : null,
66+
}
67+
}
68+
writeFileSync(OUT_PATH, JSON.stringify(out, null, 2) + "\n", "utf8")
69+
console.log(`Generated models catalogue: ${Object.keys(out).length} models → ${OUT_PATH}`)
70+
}
71+
72+
main()

0 commit comments

Comments
 (0)