David Pomerenke
commited on
Commit
·
f18ff7d
1
Parent(s):
698d104
Improve Observable setup
Browse files- observablehq.config.js +1 -1
- src/chart.md +0 -85
- src/{list.md → compare-ais.md} +2 -8
- src/compare-languages.md +20 -0
- src/components/language-chart.js +68 -0
- src/components/timeline.js +0 -16
- src/index.md +11 -69
- src/methodology.md +12 -0
- src/observable.png +0 -0
observablehq.config.js
CHANGED
@@ -17,7 +17,7 @@ export default {
|
|
17 |
// ],
|
18 |
|
19 |
// Content to add to the head of the page, e.g. for a favicon:
|
20 |
-
head: '<link rel="icon" href="
|
21 |
|
22 |
// The path to the source root.
|
23 |
root: "src",
|
|
|
17 |
// ],
|
18 |
|
19 |
// Content to add to the head of the page, e.g. for a favicon:
|
20 |
+
head: '<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22 fill=%22black%22>🌍</text></svg>">',
|
21 |
|
22 |
// The path to the source root.
|
23 |
root: "src",
|
src/chart.md
DELETED
@@ -1,85 +0,0 @@
|
|
1 |
-
---
|
2 |
-
theme: dashboard
|
3 |
-
title: AI Language Monitor
|
4 |
-
toc: false
|
5 |
-
head: <link rel="icon"
|
6 |
-
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22 fill=%22black%22>🌍</text></svg>">
|
7 |
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
8 |
-
<!--<link rel="stylesheet" href="styles.css">-->
|
9 |
-
<script src="https://cdn.tailwindcss.com"></script>
|
10 |
-
---
|
11 |
-
|
12 |
-
# AI Language Monitor
|
13 |
-
|
14 |
-
```js
|
15 |
-
const data = FileAttachment("data/languagebench.json").json();
|
16 |
-
```
|
17 |
-
|
18 |
-
```js
|
19 |
-
const scoreKey = "bleu"
|
20 |
-
const scoreName = "BLEU Score"
|
21 |
-
|
22 |
-
// Format captions
|
23 |
-
const formatScore = (score) => score > 0 ? score.toFixed(2) : "No benchmark available!"
|
24 |
-
const formatTitle = d => (d.language_name + "\n" + parseInt(d.speakers / 1_000_00) / 10 + "M speakers\n" + scoreName + ": " + formatScore(d[scoreKey]))
|
25 |
-
|
26 |
-
// Create summary plot
|
27 |
-
const chart = Plot.plot({
|
28 |
-
width: 600,
|
29 |
-
height: 400,
|
30 |
-
marginBottom: 100,
|
31 |
-
x: { label: "Number of speakers", axis: null },
|
32 |
-
y: { label: `${scoreName} (average across models)` },
|
33 |
-
// color: { scheme: "BrBG" },
|
34 |
-
marks: [
|
35 |
-
Plot.rectY(data, Plot.stackX({
|
36 |
-
x: "speakers",
|
37 |
-
order: scoreKey,
|
38 |
-
reverse: true,
|
39 |
-
y2: scoreKey, // y2 to avoid stacking by y
|
40 |
-
title: formatTitle,
|
41 |
-
tip: true,
|
42 |
-
fill: d => d[scoreKey] > 0 ? "black" : "pink"
|
43 |
-
})),
|
44 |
-
Plot.rectY(data, Plot.pointerX(Plot.stackX({
|
45 |
-
x: "speakers",
|
46 |
-
order: scoreKey,
|
47 |
-
reverse: true,
|
48 |
-
y2: scoreKey, // y2 to avoid stacking by y
|
49 |
-
fill: "grey",
|
50 |
-
}))),
|
51 |
-
Plot.text(data, Plot.stackX({
|
52 |
-
x: "speakers",
|
53 |
-
y2: scoreKey,
|
54 |
-
order: scoreKey,
|
55 |
-
reverse: true,
|
56 |
-
text: "language_name",
|
57 |
-
frameAnchor: "bottom",
|
58 |
-
textAnchor: "end",
|
59 |
-
dy: 10,
|
60 |
-
rotate: 270,
|
61 |
-
opacity: (d) => d.speakers > 50_000_000 ? 1 : 0,
|
62 |
-
}))
|
63 |
-
]
|
64 |
-
});
|
65 |
-
display(chart);
|
66 |
-
```
|
67 |
-
|
68 |
-
<style>
|
69 |
-
body {
|
70 |
-
margin: 0 auto;
|
71 |
-
padding: 20px;
|
72 |
-
font-family: sans-serif;
|
73 |
-
}
|
74 |
-
|
75 |
-
.language-header {
|
76 |
-
margin-bottom: 10px;
|
77 |
-
}
|
78 |
-
|
79 |
-
.speaker-count {
|
80 |
-
font-size: 0.8em;
|
81 |
-
color: #666;
|
82 |
-
font-weight: normal;
|
83 |
-
margin: 0;
|
84 |
-
}
|
85 |
-
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/{list.md → compare-ais.md}
RENAMED
@@ -1,15 +1,9 @@
|
|
1 |
---
|
2 |
theme: dashboard
|
3 |
-
title:
|
4 |
-
toc: false
|
5 |
-
head: <link rel="icon"
|
6 |
-
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22 fill=%22black%22>🌍</text></svg>">
|
7 |
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
8 |
-
<!--<link rel="stylesheet" href="styles.css">-->
|
9 |
-
<script src="https://cdn.tailwindcss.com"></script>
|
10 |
---
|
11 |
|
12 |
-
# AI
|
13 |
|
14 |
```js
|
15 |
const data = FileAttachment("data/languagebench.json").json();
|
|
|
1 |
---
|
2 |
theme: dashboard
|
3 |
+
title: Compare AI models
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
---
|
5 |
|
6 |
+
# Compare AI models
|
7 |
|
8 |
```js
|
9 |
const data = FileAttachment("data/languagebench.json").json();
|
src/compare-languages.md
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
theme: dashboard
|
3 |
+
title: Compare languages
|
4 |
+
---
|
5 |
+
|
6 |
+
# Compare languages
|
7 |
+
|
8 |
+
```js
|
9 |
+
import { languageChart } from "./components/language-chart.js";
|
10 |
+
|
11 |
+
const data = FileAttachment("data/languagebench.json").json();
|
12 |
+
```
|
13 |
+
|
14 |
+
```js
|
15 |
+
const scoreKey = "bleu"
|
16 |
+
const scoreName = "BLEU Score"
|
17 |
+
|
18 |
+
// Create summary plot
|
19 |
+
display(languageChart(data, {width: 1000, height: 400, scoreKey: scoreKey, scoreName: scoreName}))
|
20 |
+
```
|
src/components/language-chart.js
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as Plot from "npm:@observablehq/plot";
|
2 |
+
|
3 |
+
export function languageChart(
|
4 |
+
languageData,
|
5 |
+
{ width, height, scoreKey, scoreName } = {}
|
6 |
+
) {
|
7 |
+
// Format captions
|
8 |
+
const formatScore = (score) =>
|
9 |
+
score > 0 ? score.toFixed(2) : "No benchmark available!";
|
10 |
+
const formatTitle = (d) =>
|
11 |
+
d.language_name +
|
12 |
+
"\n" +
|
13 |
+
parseInt(d.speakers / 1_000_00) / 10 +
|
14 |
+
"M speakers\n" +
|
15 |
+
scoreName +
|
16 |
+
": " +
|
17 |
+
formatScore(d[scoreKey]);
|
18 |
+
|
19 |
+
return Plot.plot({
|
20 |
+
width: width,
|
21 |
+
height: height,
|
22 |
+
marginBottom: 100,
|
23 |
+
x: { label: "Number of speakers", axis: null },
|
24 |
+
y: { label: `${scoreName} (average across models)` },
|
25 |
+
// color: { scheme: "BrBG" },
|
26 |
+
marks: [
|
27 |
+
Plot.rectY(
|
28 |
+
languageData,
|
29 |
+
Plot.stackX({
|
30 |
+
x: "speakers",
|
31 |
+
order: scoreKey,
|
32 |
+
reverse: true,
|
33 |
+
y2: scoreKey, // y2 to avoid stacking by y
|
34 |
+
title: formatTitle,
|
35 |
+
tip: true,
|
36 |
+
fill: (d) => (d[scoreKey] > 0 ? "black" : "pink"),
|
37 |
+
})
|
38 |
+
),
|
39 |
+
Plot.rectY(
|
40 |
+
languageData,
|
41 |
+
Plot.pointerX(
|
42 |
+
Plot.stackX({
|
43 |
+
x: "speakers",
|
44 |
+
order: scoreKey,
|
45 |
+
reverse: true,
|
46 |
+
y2: scoreKey, // y2 to avoid stacking by y
|
47 |
+
fill: "grey",
|
48 |
+
})
|
49 |
+
)
|
50 |
+
),
|
51 |
+
Plot.text(
|
52 |
+
languageData,
|
53 |
+
Plot.stackX({
|
54 |
+
x: "speakers",
|
55 |
+
y2: scoreKey,
|
56 |
+
order: scoreKey,
|
57 |
+
reverse: true,
|
58 |
+
text: "language_name",
|
59 |
+
frameAnchor: "bottom",
|
60 |
+
textAnchor: "end",
|
61 |
+
dy: 10,
|
62 |
+
rotate: 270,
|
63 |
+
opacity: (d) => (d.speakers > 50_000_000 ? 1 : 0),
|
64 |
+
})
|
65 |
+
),
|
66 |
+
],
|
67 |
+
});
|
68 |
+
}
|
src/components/timeline.js
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
import * as Plot from "npm:@observablehq/plot";
|
2 |
-
|
3 |
-
export function timeline(events, {width, height} = {}) {
|
4 |
-
return Plot.plot({
|
5 |
-
width,
|
6 |
-
height,
|
7 |
-
marginTop: 30,
|
8 |
-
x: {nice: true, label: null, tickFormat: ""},
|
9 |
-
y: {axis: null},
|
10 |
-
marks: [
|
11 |
-
Plot.ruleX(events, {x: "year", y: "y", markerEnd: "dot", strokeWidth: 2.5}),
|
12 |
-
Plot.ruleY([0]),
|
13 |
-
Plot.text(events, {x: "year", y: "y", text: "name", lineAnchor: "bottom", dy: -10, lineWidth: 10, fontSize: 12})
|
14 |
-
]
|
15 |
-
});
|
16 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/index.md
CHANGED
@@ -4,66 +4,24 @@ toc: false
|
|
4 |
|
5 |
<div class="hero">
|
6 |
<h1>AI Language Monitor</h1>
|
7 |
-
<h2>
|
8 |
-
<a href="https://observablehq.com/framework/getting-started">Get started<span style="display: inline-block; margin-left: 0.25rem;">↗︎</span></a>
|
9 |
</div>
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
resize((width) => Plot.plot({
|
14 |
-
title: "Your awesomeness over time 🚀",
|
15 |
-
subtitle: "Up and to the right!",
|
16 |
-
width,
|
17 |
-
y: {grid: true, label: "Awesomeness"},
|
18 |
-
marks: [
|
19 |
-
Plot.ruleY([0]),
|
20 |
-
Plot.lineY(aapl, {x: "Date", y: "Close", tip: true})
|
21 |
-
]
|
22 |
-
}))
|
23 |
-
}</div>
|
24 |
-
<div class="card">${
|
25 |
-
resize((width) => Plot.plot({
|
26 |
-
title: "How big are penguins, anyway? 🐧",
|
27 |
-
width,
|
28 |
-
grid: true,
|
29 |
-
x: {label: "Body mass (g)"},
|
30 |
-
y: {label: "Flipper length (mm)"},
|
31 |
-
color: {legend: true},
|
32 |
-
marks: [
|
33 |
-
Plot.linearRegressionY(penguins, {x: "body_mass_g", y: "flipper_length_mm", stroke: "species"}),
|
34 |
-
Plot.dot(penguins, {x: "body_mass_g", y: "flipper_length_mm", stroke: "species", tip: true})
|
35 |
-
]
|
36 |
-
}))
|
37 |
-
}</div>
|
38 |
-
</div>
|
39 |
|
40 |
-
|
|
|
41 |
|
42 |
-
## Next steps
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
<div class="grid grid-cols-4">
|
47 |
-
<div class="card">
|
48 |
-
Chart your own data using <a href="https://observablehq.com/framework/lib/plot"><code>Plot</code></a> and <a href="https://observablehq.com/framework/files"><code>FileAttachment</code></a>. Make it responsive using <a href="https://observablehq.com/framework/javascript#resize(render)"><code>resize</code></a>.
|
49 |
-
</div>
|
50 |
-
<div class="card">
|
51 |
-
Create a <a href="https://observablehq.com/framework/project-structure">new page</a> by adding a Markdown file (<code>whatever.md</code>) to the <code>src</code> folder.
|
52 |
-
</div>
|
53 |
-
<div class="card">
|
54 |
-
Add a drop-down menu using <a href="https://observablehq.com/framework/inputs/select"><code>Inputs.select</code></a> and use it to filter the data shown in a chart.
|
55 |
-
</div>
|
56 |
-
<div class="card">
|
57 |
-
Write a <a href="https://observablehq.com/framework/loaders">data loader</a> that queries a local database or API, generating a data snapshot on build.
|
58 |
-
</div>
|
59 |
-
<div class="card">
|
60 |
-
Import a <a href="https://observablehq.com/framework/imports">recommended library</a> from npm, such as <a href="https://observablehq.com/framework/lib/leaflet">Leaflet</a>, <a href="https://observablehq.com/framework/lib/dot">GraphViz</a>, <a href="https://observablehq.com/framework/lib/tex">TeX</a>, or <a href="https://observablehq.com/framework/lib/duckdb">DuckDB</a>.
|
61 |
-
</div>
|
62 |
<div class="card">
|
63 |
-
|
|
|
64 |
</div>
|
65 |
<div class="card">
|
66 |
-
|
|
|
67 |
</div>
|
68 |
</div>
|
69 |
|
@@ -83,7 +41,7 @@ Here are some ideas of things you could try…
|
|
83 |
margin: 1rem 0;
|
84 |
padding: 1rem 0;
|
85 |
max-width: none;
|
86 |
-
font-size:
|
87 |
font-weight: 900;
|
88 |
line-height: 1;
|
89 |
background: linear-gradient(30deg, var(--theme-foreground-focus), currentColor);
|
@@ -92,20 +50,4 @@ Here are some ideas of things you could try…
|
|
92 |
background-clip: text;
|
93 |
}
|
94 |
|
95 |
-
.hero h2 {
|
96 |
-
margin: 0;
|
97 |
-
max-width: 34em;
|
98 |
-
font-size: 20px;
|
99 |
-
font-style: initial;
|
100 |
-
font-weight: 500;
|
101 |
-
line-height: 1.5;
|
102 |
-
color: var(--theme-foreground-muted);
|
103 |
-
}
|
104 |
-
|
105 |
-
@media (min-width: 640px) {
|
106 |
-
.hero h1 {
|
107 |
-
font-size: 90px;
|
108 |
-
}
|
109 |
-
}
|
110 |
-
|
111 |
</style>
|
|
|
4 |
|
5 |
<div class="hero">
|
6 |
<h1>AI Language Monitor</h1>
|
7 |
+
<h2>Benchmarking all big AI models on all benchmarkable languages.</h2>
|
|
|
8 |
</div>
|
9 |
|
10 |
+
```js
|
11 |
+
import { languageChart } from "./components/language-chart.js";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
+
const data = FileAttachment("data/languagebench.json").json();
|
14 |
+
```
|
15 |
|
|
|
16 |
|
17 |
+
<div class="grid grid-cols-2" style="grid-auto-rows: 504px;">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
<div class="card">
|
19 |
+
<h2 class="hero">Compare languages</h2>
|
20 |
+
${resize((width) => languageChart(data, {width: 1000, height: 400, scoreKey: "bleu", scoreName: "BLEU Score"}))}
|
21 |
</div>
|
22 |
<div class="card">
|
23 |
+
<h2 class="hero">Compare AI models</h2>
|
24 |
+
...
|
25 |
</div>
|
26 |
</div>
|
27 |
|
|
|
41 |
margin: 1rem 0;
|
42 |
padding: 1rem 0;
|
43 |
max-width: none;
|
44 |
+
font-size: 90px;
|
45 |
font-weight: 900;
|
46 |
line-height: 1;
|
47 |
background: linear-gradient(30deg, var(--theme-foreground-focus), currentColor);
|
|
|
50 |
background-clip: text;
|
51 |
}
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
</style>
|
src/methodology.md
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Methodology
|
3 |
+
---
|
4 |
+
|
5 |
+
# Methodology
|
6 |
+
|
7 |
+
Sources:
|
8 |
+
|
9 |
+
1. For AI models: [OpenRouter](https://openrouter.ai/)
|
10 |
+
2. For language benchmarks: [FLORES+](https://github.com/openlanguagedata/flores)
|
11 |
+
3. For language statistics: [Wikidata](https://gist.github.com/unhammer/3e8f2e0f79972bf5008a4c970081502d), [Ethnologue](https://www.ethnologue.com/browse/names/)
|
12 |
+
|
src/observable.png
DELETED
Binary file (394 Bytes)
|
|