tardellirs commited on
Commit
981e257
·
verified ·
1 Parent(s): 6368b66

Model card: restore the v1 Pareto chart until the v2 Full score

Browse files
Files changed (3) hide show
  1. README.md +8 -0
  2. assets/pareto.png +3 -0
  3. assets/plot_pareto.py +158 -0
README.md CHANGED
@@ -73,6 +73,14 @@ newer Crivo models: the training data of [Crivo-400M](https://huggingface.co/tar
73
  as its teacher. Version 1 (board Full 22.21, public 36.39) stays available at revision `7a6c745`; see
74
  [Versions](#versions) for what changed and why.
75
 
 
 
 
 
 
 
 
 
76
  | | |
77
  |---|---|
78
  | Architecture | Ettin / ModernBERT encoder, 22 layers, hidden 768, `[OPT]` readout + MLP scorer |
 
73
  as its teacher. Version 1 (board Full 22.21, public 36.39) stays available at revision `7a6c745`; see
74
  [Versions](#versions) for what changed and why.
75
 
76
+ <p align="center">
77
+ <img src="https://huggingface.co/tardellirs/crivo-150m/resolve/main/assets/pareto.png" width="960"
78
+ alt="Decision Index 0.3, Full score versus served parameters for 147 submissions, coloured by architecture. The Pareto frontier is drawn as a staircase through the frontier models; Crivo-150M version 1 (Full 22.21) is the frontier point at 150M parameters.">
79
+ </p>
80
+ <p align="center"><sub>Board standing of <b>version 1</b> (Full 22.21, on the Pareto frontier at 150M parameters).
81
+ This chart will be updated when the Full score of version 2 is published. Generated from the board's
82
+ <code>data/index.json</code> by <a href="https://huggingface.co/tardellirs/crivo-150m/blob/main/assets/plot_pareto.py"><code>assets/plot_pareto.py</code></a>.</sub></p>
83
+
84
  | | |
85
  |---|---|
86
  | Architecture | Ettin / ModernBERT encoder, 22 layers, hidden 768, `[OPT]` readout + MLP scorer |
assets/pareto.png ADDED

Git LFS Details

  • SHA256: 3ac4150ef015d3c26809aa6b0c1b7e8b8e3c29efa193eb92f84fb32c1ed3814a
  • Pointer size: 131 Bytes
  • Size of remote file: 251 kB
assets/plot_pareto.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Decision Index 0.3 chart (served params x Full) for the Crivo model cards.
3
+
4
+ Frontier models are drawn solid and joined by the staircase (best Full at or below each size); the rest are faded.
5
+ Colors follow the board's architecture palette (multimodalart/jev-decision-index); each architecture
6
+ also gets its own marker shape, because blue and purple are hard to tell apart with colour blindness.
7
+
8
+ curl -sL https://huggingface.co/spaces/multimodalart/jev-decision-index/resolve/main/data/index.json -o index.json
9
+ uv run --no-project --python 3.12 --with matplotlib python plot_pareto.py index.json crivo-150m/assets/pareto.png
10
+ """
11
+ import json
12
+ import sys
13
+
14
+ import matplotlib
15
+ matplotlib.use("Agg")
16
+ import matplotlib.pyplot as plt
17
+ from matplotlib.lines import Line2D
18
+ from matplotlib.ticker import FixedLocator, NullLocator
19
+
20
+ SURFACE, INK, INK2, GRID = "#FBF8F1", "#232323", "#55524B", "#E3DED2"
21
+ HERO, HERO_FILL = "Crivo-150M", "#FFD21E"
22
+ ARCH = { # technique -> (label, colour, marker)
23
+ "autoregressive": ("autoregressive", "#3B7CF6", "o"),
24
+ "encoder": ("encoder", "#3E8E5E", "D"),
25
+ "GLi family": ("GLi family", "#FF9D00", "^"),
26
+ "diffusion": ("diffusion", "#A855F7", "s"),
27
+ }
28
+ XMAX = 4.2e10 # just past the largest submission (~36B)
29
+ LEAD_UNTIL = 7.5e8 # nothing below this size scores higher than Crivo-150M (checked in main)
30
+
31
+ # labels: name -> (text, offset in points)
32
+ LABELS = {
33
+ "Bekko System One v0 17M": ("Bekko 17M", (6, -13)),
34
+ "Bekko System One v0 68M": ("Bekko 68M", (-9, 3)),
35
+ "tasksource Decider nano (150M)": ("tasksource nano", (-10, 3)),
36
+ "Dinah-0": ("Dinah-0", (10, -3)),
37
+ "Supersonic Labs Julia 1": ("Julia-1", (-10, -1)),
38
+ "Bekko System One v0 400M": ("Bekko 400M", (-10, 3)),
39
+ "vLLM-SR d3-edge (0.6B)": ("vLLM-SR d3-edge 0.6B", (-10, 3)),
40
+ "jiwo 0.8B v2": ("jiwo 0.8B", (-10, 3)),
41
+ "vLLM-SR d3-lite (0.8B)": ("vLLM-SR d3-lite 0.8B", (-10, 3)),
42
+ "LiquidAI d1-3B": ("LiquidAI d1-3B", (8, -10)),
43
+ "vLLM-SR d3 (27B)": ("vLLM-SR d3 27B", (-10, 3)),
44
+ }
45
+ # labels placed at (x, y) in data units with a leader line: name -> (text, xy, ha)
46
+ PLACED = {
47
+ "LiquidAI d1-omni-600M": ("LiquidAI d1-omni 0.6B", (9.5e8, 1.4), "left"),
48
+ "Together Tev1 Qwen3.5-0.8B": ("Together Tev1 0.8B", (1.6e9, 9.0), "left"),
49
+ "Cloudflare clef": ("Cloudflare\nClef 28B", (1.35e10, 33.0), "left"),
50
+ "Fastino GLiDE no-thinking (28B)": ("Fastino GLiDE 28B", (1.6e10, 64.5), "right"),
51
+ }
52
+ SIZE_LABEL = {1e7: "10M", 3e7: "30M", 1e8: "100M", 3e8: "300M", 1e9: "1B", 3e9: "3B", 1e10: "10B",
53
+ 3e10: "30B", 1e11: "100B"}
54
+
55
+
56
+ def load(src):
57
+ d = json.load(open(src))
58
+ rows = []
59
+ for m in d["models"]:
60
+ v, meta = m.get("v03") or {}, m.get("meta") or {}
61
+ if v.get("v") is not None and meta.get("served_params"):
62
+ rows.append({"p": meta["served_params"], "v": v["v"], "name": v["name"],
63
+ "arch": meta.get("technique") if meta.get("technique") in ARCH else "autoregressive"})
64
+ return d, rows
65
+
66
+
67
+ def frontier(rows):
68
+ out, best = [], -1.0
69
+ for r in sorted(rows, key=lambda r: (r["p"], -r["v"])):
70
+ if r["v"] > best:
71
+ best = r["v"]
72
+ out.append(r)
73
+ return out
74
+
75
+
76
+ def style(ax, xlim, ylim, ticks):
77
+ ax.set_facecolor(SURFACE)
78
+ ax.set_xscale("log")
79
+ ax.set_xlim(*xlim)
80
+ ax.set_ylim(*ylim)
81
+ ax.xaxis.set_major_locator(FixedLocator(ticks))
82
+ ax.xaxis.set_minor_locator(NullLocator())
83
+ ax.set_xticklabels([SIZE_LABEL[t] for t in ticks])
84
+ ax.grid(True, color=GRID, lw=0.8, zorder=0)
85
+ for s in ("top", "right"):
86
+ ax.spines[s].set_visible(False)
87
+ for s in ("left", "bottom"):
88
+ ax.spines[s].set_color(GRID)
89
+ ax.tick_params(colors=INK2, length=0, labelsize=9)
90
+ ax.set_xlabel("Served parameters (log scale)", color=INK2, fontsize=9.5)
91
+
92
+
93
+ def main(src, out):
94
+ d, rows = load(src)
95
+ front = frontier(rows)
96
+ hero = next(r for r in rows if r["name"] == HERO)
97
+ above = [r for r in rows if r["p"] < LEAD_UNTIL and r["v"] > hero["v"]]
98
+ assert not above, above
99
+
100
+ plt.rcParams.update({"font.family": "DejaVu Sans"})
101
+ fig, ax = plt.subplots(figsize=(13, 7.6), dpi=200)
102
+ fig.patch.set_facecolor(SURFACE)
103
+ style(ax, (1.2e7, XMAX), (-2.5, 72), [3e7, 1e8, 3e8, 1e9, 3e9, 1e10, 3e10])
104
+ ax.set_ylabel("Full score (0–100)", color=INK2, fontsize=10)
105
+
106
+ # Pareto frontier as the board draws it: a line through the frontier models, the rest faded
107
+ fx, fy = [], [] # staircase: best Full at or below each size
108
+ for i, r in enumerate(front):
109
+ if i:
110
+ fx.append(r["p"]); fy.append(front[i - 1]["v"])
111
+ fx.append(r["p"]); fy.append(r["v"])
112
+ fx.append(XMAX); fy.append(front[-1]["v"])
113
+ ax.plot(fx, fy, color=INK, lw=2, zorder=4, solid_joinstyle="miter")
114
+ on = {r["name"] for r in front}
115
+ for key, (_, color, marker) in ARCH.items():
116
+ for faded in (True, False):
117
+ pts = [r for r in rows if r["arch"] == key and r["name"] != HERO and (r["name"] not in on) == faded]
118
+ ax.scatter([r["p"] for r in pts], [r["v"] for r in pts], s=55 if faded else 85, color=color,
119
+ marker=marker, edgecolors=INK, linewidths=0.6 if faded else 1.2,
120
+ alpha=0.3 if faded else 1, zorder=3 if faded else 5)
121
+ ax.scatter([hero["p"]], [hero["v"]], s=420, color=HERO_FILL, marker="D", edgecolors=INK, linewidths=2,
122
+ zorder=6)
123
+ ax.annotate(f"Crivo-150M\nFull {hero['v']:.2f}", (hero["p"], hero["v"]), xytext=(-4, 26),
124
+ textcoords="offset points", ha="center", va="bottom", fontsize=13, fontweight="bold",
125
+ color=INK, zorder=7)
126
+
127
+ for r in rows:
128
+ if r["name"] in LABELS:
129
+ text, (dx, dy) = LABELS[r["name"]]
130
+ ax.annotate(text, (r["p"], r["v"]), xytext=(dx, dy), textcoords="offset points",
131
+ ha="left" if dx > 0 else "right", va="center", fontsize=8.5, color=INK2, zorder=5)
132
+ if r["name"] in PLACED:
133
+ text, xy, ha = PLACED[r["name"]]
134
+ ax.annotate(text, (r["p"], r["v"]), xytext=xy, textcoords="data", ha=ha, va="center",
135
+ fontsize=8.5, color=INK2, zorder=5,
136
+ arrowprops=dict(arrowstyle="-", color=INK2, lw=0.7, shrinkA=2, shrinkB=5))
137
+ missing = (set(LABELS) | set(PLACED)) - {r["name"] for r in rows}
138
+ assert not missing, missing
139
+
140
+ handles = [Line2D([], [], ls="", marker=m, markersize=8, markerfacecolor=c, markeredgecolor=INK,
141
+ markeredgewidth=0.7, label=lab) for lab, c, m in ARCH.values()]
142
+ handles.append(Line2D([], [], ls="", marker="D", markersize=11, markerfacecolor=HERO_FILL,
143
+ markeredgecolor=INK, markeredgewidth=1.6, label=HERO))
144
+ handles.append(Line2D([], [], color=INK, lw=2, label="Pareto frontier (no smaller model scores higher)"))
145
+ ax.legend(handles=handles, loc="upper left", frameon=False, fontsize=9.5, labelcolor=INK2,
146
+ borderaxespad=0.8)
147
+
148
+ fig.suptitle("Decision Index 0.3 · Full score vs. model size", x=0.01, ha="left", fontsize=16,
149
+ fontweight="bold", color=INK)
150
+ fig.text(0.01, 0.915, f"{len(rows)} submissions with a known size · board snapshot {d['generated_utc'][:10]} · "
151
+ "Full = 20% public + 50% private same-skill + 30% private new-domain tasks",
152
+ fontsize=9.5, color=INK2)
153
+ fig.tight_layout(rect=(0, 0, 1, 0.91))
154
+ fig.savefig(out, facecolor=SURFACE)
155
+
156
+
157
+ if __name__ == "__main__":
158
+ main(*sys.argv[1:])