pmarquees commited on
Commit
338bb9c
·
verified ·
1 Parent(s): 5e2f29a

Upload 11 files

Browse files
README.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: mlx
3
+ tags:
4
+ - mlx
5
+ - model-routing
6
+ - synthetic-data
7
+ ---
8
+
9
+ # Succinct Router 14M
10
+
11
+ A 14M-parameter decoder-only routing model trained from random initialization. It predicts an
12
+ independent pass probability for each of these candidate configurations:
13
+
14
+ - `gpt-5.6-luna-none`
15
+ - `gpt-5.6-terra-low`
16
+ - `gpt-5.6-sol-medium`
17
+
18
+ This model does **not** answer prompts. It selects the cheapest candidate configuration expected to
19
+ pass a calibrated quality threshold.
20
+
21
+ ## Evaluation
22
+
23
+ ```json
24
+ {
25
+ "exact_route_accuracy": 0.9508599508599509,
26
+ "unsafe_downroute_rate": 0.005528255528255528,
27
+ "selected_model_pass_rate": 0.9944717444717445,
28
+ "abstention_rate": 0.0,
29
+ "savings_vs_always_large": 0.8486732186732187
30
+ }
31
+ ```
32
+
33
+ ## Run with MLX
34
+
35
+ ```bash
36
+ pip install "mlx>=0.32,<0.33" tokenizers
37
+ python route_mlx.py --model-dir . --prompt "Extract the invoice number from INV-4821."
38
+ ```
39
+
40
+ The result contains calibrated pass probabilities and the selected candidate configuration. If no
41
+ candidate clears the threshold, `abstained_to_largest` is true and the route falls back to the
42
+ largest configuration.
43
+
44
+ ## Limitations
45
+
46
+ Training and evaluation data are synthetic and mechanically graded. The artifact is a learning
47
+ prototype, not a production-ready router. Validate it on anonymized real traffic before making
48
+ product or cost claims. MLX runtime parity and latency must be measured on Apple Silicon.
calibration.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": "1",
3
+ "model_ids": [
4
+ "gpt-5.6-luna-none",
5
+ "gpt-5.6-terra-low",
6
+ "gpt-5.6-sol-medium"
7
+ ],
8
+ "temperatures": [
9
+ 1.0598043203353882,
10
+ 1.106358528137207,
11
+ 0.3136223554611206
12
+ ],
13
+ "selection_threshold": 0.58,
14
+ "constraints": {
15
+ "max_unsafe_downroute_rate": 0.005,
16
+ "min_selected_model_pass_rate": 0.99,
17
+ "satisfied": true
18
+ },
19
+ "validation_route_metrics": {
20
+ "exact_route_accuracy": 0.9509283819628647,
21
+ "unsafe_downroute_rate": 0.004641909814323607,
22
+ "selected_model_pass_rate": 0.9953580901856764,
23
+ "abstention_rate": 0.0,
24
+ "savings_vs_always_large": 0.8416445623342175
25
+ },
26
+ "uncalibrated": {
27
+ "pass_vector_accuracy": 0.9244031830238727,
28
+ "pass_bit_accuracy": 0.9748010610079576,
29
+ "macro_f1": 0.985090243264452,
30
+ "brier_score": 0.01777769201095797,
31
+ "expected_calibration_error": 0.018437407725585803
32
+ },
33
+ "calibrated": {
34
+ "pass_vector_accuracy": 0.9244031830238727,
35
+ "pass_bit_accuracy": 0.9748010610079576,
36
+ "macro_f1": 0.985090243264452,
37
+ "brier_score": 0.017453370615839958,
38
+ "expected_calibration_error": 0.01830040662266169
39
+ }
40
+ }
config.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": "1",
3
+ "architecture": "succinct-router-decoder-v1",
4
+ "model": {
5
+ "vocab_size": 8192,
6
+ "max_sequence_length": 1024,
7
+ "layers": 6,
8
+ "model_width": 384,
9
+ "attention_heads": 6,
10
+ "ffn_width": 1024,
11
+ "dropout": 0.1,
12
+ "candidate_count": 3
13
+ },
14
+ "route_state": "final_<ROUTE>_token",
15
+ "tied_lm_head": true
16
+ }
example_inputs.jsonl ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {"example_id": "sha256:5db7b3e355519960ac61e93ac9f7cd537f5010bb5142e8d2f0b85d9e801162e5", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 492, 352, 11, 351, 11, 133, 612, 159, 141, 13, 94, 94, 560, 11, 859, 530, 605, 13, 332, 700, 526, 13, 1036, 238, 540, 664, 13, 686, 608, 702, 99, 973, 59, 974, 29, 4], "reference_pass_logits": [7.015040397644043, 6.347684383392334, 6.796907901763916], "reference_scores": [0.989065408706665, 0.9848109483718872, 0.990003764629364]}
2
+ {"example_id": "sha256:780d0b0600848b763ea1d247395a6abc9295344d2a44d8cd7ba33641927bec67", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 492, 352, 11, 351, 11, 133, 612, 159, 141, 13, 94, 94, 560, 11, 859, 530, 605, 13, 332, 700, 526, 13, 1036, 238, 540, 664, 13, 686, 608, 702, 99, 973, 59, 974, 29, 4], "reference_pass_logits": [7.015040397644043, 6.347684383392334, 6.796907901763916], "reference_scores": [0.989065408706665, 0.9848109483718872, 0.990003764629364]}
3
+ {"example_id": "sha256:2f773ba7a80b8d601866a7d93b6ea025b2fe8dfc9140365dac1e8e60ab9e26d1", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 814, 180, 617, 133, 240, 158, 148, 595, 651, 345, 704, 683, 537, 59, 270, 11, 639, 644, 267, 158, 110, 571, 6, 348, 116, 483, 629, 238, 13, 712, 24, 349, 234, 107, 110, 678, 59, 270, 181, 110, 345, 107, 148, 270, 59, 144, 107, 110, 340, 641, 148, 234, 107, 110, 445, 59, 270, 181, 110, 345, 107, 148, 270, 59, 144, 107, 110, 340, 181, 110, 618, 107, 110, 340, 642, 94, 94, 558, 434, 12, 1216, 820, 25, 295, 682, 491, 541, 13, 4], "reference_pass_logits": [6.926111698150635, 6.366804122924805, 6.842347621917725], "reference_scores": [0.99000084400177, 0.9857044219970703, 0.9898501634597778]}
4
+ {"example_id": "sha256:2c7baa36710166560457211f804dd37cf02b40470e395dda9a0c64c72b528a91", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 814, 180, 617, 133, 240, 158, 148, 595, 651, 345, 704, 683, 537, 59, 270, 11, 639, 644, 267, 158, 110, 571, 6, 348, 116, 483, 629, 238, 13, 712, 24, 349, 234, 107, 110, 678, 59, 270, 181, 110, 345, 107, 148, 270, 59, 144, 107, 110, 340, 641, 148, 234, 107, 110, 445, 59, 270, 181, 110, 345, 107, 148, 270, 59, 144, 107, 110, 340, 181, 110, 618, 107, 110, 340, 642, 94, 94, 558, 434, 12, 1216, 820, 25, 295, 682, 491, 541, 13, 4], "reference_pass_logits": [6.926111698150635, 6.366804122924805, 6.842347621917725], "reference_scores": [0.99000084400177, 0.9857044219970703, 0.9898501634597778]}
5
+ {"example_id": "sha256:1746c9cf5738c6f562730b79c8a48454e0457b259ee27e32fb1ac9b0b8eba4f9", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 166, 125, 464, 459, 699, 548, 677, 717, 706, 159, 148, 436, 107, 481, 456, 671, 684, 819, 11, 551, 99, 554, 7, 654, 11, 755, 551, 333, 7, 834, 548, 125, 991, 992, 13, 670, 24, 349, 284, 107, 1114, 13, 1062, 11, 110, 286, 107, 335, 285, 148, 284, 107, 1095, 13, 17, 11, 110, 286, 107, 288, 285, 148, 284, 107, 1150, 13, 1049, 11, 110, 286, 107, 288, 285, 148, 284, 107, 1156, 13, 1009, 11, 110, 286, 107, 230, 457, 4], "reference_pass_logits": [-7.627079963684082, 2.626823663711548, 4.990095615386963], "reference_scores": [0.018578819930553436, 0.9573246240615845, 0.9830689430236816]}
6
+ {"example_id": "sha256:40396bbb4a9130ac5fdeb93980af7a9f98f12406d55c20b9c48a05ad6e65ece7", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 833, 506, 464, 459, 699, 548, 677, 717, 706, 159, 148, 436, 107, 481, 456, 671, 684, 819, 11, 551, 99, 554, 7, 654, 11, 755, 551, 333, 7, 834, 548, 506, 991, 992, 13, 670, 24, 349, 284, 107, 1114, 13, 1062, 11, 110, 286, 107, 335, 285, 148, 284, 107, 1095, 13, 17, 11, 110, 286, 107, 288, 285, 148, 284, 107, 1150, 13, 1049, 11, 110, 286, 107, 288, 285, 148, 284, 107, 1156, 13, 1009, 11, 110, 286, 107, 230, 457, 4], "reference_pass_logits": [-7.622464656829834, 2.636568307876587, 4.985684394836426], "reference_scores": [0.018651440739631653, 0.9573564529418945, 0.9829824566841125]}
7
+ {"example_id": "sha256:62fafb8ee1842978bd6c2b7a324561b09a2b546db5c40264b20d33c6fa2de220", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 817, 125, 715, 315, 342, 59, 144, 133, 714, 459, 59, 633, 13, 177, 141, 271, 13, 94, 94, 132, 568, 107, 148, 144, 107, 110, 691, 12, 1221, 865, 273, 110, 688, 107, 110, 695, 181, 110, 436, 59, 574, 107, 1120, 13, 1067, 87, 4], "reference_pass_logits": [6.730648040771484, 6.451633453369141, 6.800724506378174], "reference_scores": [0.9886912107467651, 0.9871037602424622, 0.9892838597297668]}
8
+ {"example_id": "sha256:3c9e6ec5cf888091fd117958d1f87455b125ac6985f38d2adfa72fcd66815b50", "input_ids": [2, 26, 200, 28, 94, 219, 125, 222, 158, 13, 177, 180, 220, 141, 221, 133, 188, 215, 11, 217, 11, 115, 168, 223, 13, 214, 198, 115, 218, 224, 159, 201, 199, 13, 94, 94, 26, 211, 28, 94, 817, 506, 715, 315, 342, 59, 144, 133, 714, 459, 59, 633, 13, 240, 141, 271, 13, 94, 94, 132, 568, 107, 148, 144, 107, 110, 691, 12, 1221, 865, 273, 110, 688, 107, 110, 695, 181, 110, 436, 59, 574, 107, 1120, 13, 1067, 87, 4], "reference_pass_logits": [6.713947296142578, 6.455345153808594, 6.808040618896484], "reference_scores": [0.9886158108711243, 0.9869857430458069, 0.9892330169677734]}
labels.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "candidate_model_config_ids": [
3
+ "gpt-5.6-luna-none",
4
+ "gpt-5.6-terra-low",
5
+ "gpt-5.6-sol-medium"
6
+ ]
7
+ }
manifest.json ADDED
@@ -0,0 +1,391 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": "1",
3
+ "format": "succinct-router-mlx-v1",
4
+ "linux_validation": {
5
+ "tensor_names_shapes_dtypes": "passed",
6
+ "tokenizer_round_trip": "passed",
7
+ "reference_pytorch_logits": 8
8
+ },
9
+ "mlx_runtime_validation": {
10
+ "status": "passed",
11
+ "device": "Device(cpu, 0)",
12
+ "examples": 8,
13
+ "max_abs_pass_logit_error": 3.814697265625e-06,
14
+ "max_abs_score_error": 5.960464477539063e-08,
15
+ "tolerance": 0.0001
16
+ },
17
+ "apple_silicon_metal_latency_validation": "required",
18
+ "weights": {
19
+ "tensor_count": 48,
20
+ "sha256": "35e54bfcffe5ade95e32bee903c708ca30554170acb9c7b82dc7db6e3d4eebe4",
21
+ "bytes": 55084128,
22
+ "tied_weight": {
23
+ "lm_head.weight": "embedding.weight"
24
+ },
25
+ "tensors": {
26
+ "blocks.0.attention.output.weight": {
27
+ "shape": [
28
+ 384,
29
+ 384
30
+ ],
31
+ "dtype": "float32"
32
+ },
33
+ "blocks.0.attention.qkv.weight": {
34
+ "shape": [
35
+ 1152,
36
+ 384
37
+ ],
38
+ "dtype": "float32"
39
+ },
40
+ "blocks.0.attention_norm.weight": {
41
+ "shape": [
42
+ 384
43
+ ],
44
+ "dtype": "float32"
45
+ },
46
+ "blocks.0.ffn.down.weight": {
47
+ "shape": [
48
+ 384,
49
+ 1024
50
+ ],
51
+ "dtype": "float32"
52
+ },
53
+ "blocks.0.ffn.gate.weight": {
54
+ "shape": [
55
+ 1024,
56
+ 384
57
+ ],
58
+ "dtype": "float32"
59
+ },
60
+ "blocks.0.ffn.up.weight": {
61
+ "shape": [
62
+ 1024,
63
+ 384
64
+ ],
65
+ "dtype": "float32"
66
+ },
67
+ "blocks.0.ffn_norm.weight": {
68
+ "shape": [
69
+ 384
70
+ ],
71
+ "dtype": "float32"
72
+ },
73
+ "blocks.1.attention.output.weight": {
74
+ "shape": [
75
+ 384,
76
+ 384
77
+ ],
78
+ "dtype": "float32"
79
+ },
80
+ "blocks.1.attention.qkv.weight": {
81
+ "shape": [
82
+ 1152,
83
+ 384
84
+ ],
85
+ "dtype": "float32"
86
+ },
87
+ "blocks.1.attention_norm.weight": {
88
+ "shape": [
89
+ 384
90
+ ],
91
+ "dtype": "float32"
92
+ },
93
+ "blocks.1.ffn.down.weight": {
94
+ "shape": [
95
+ 384,
96
+ 1024
97
+ ],
98
+ "dtype": "float32"
99
+ },
100
+ "blocks.1.ffn.gate.weight": {
101
+ "shape": [
102
+ 1024,
103
+ 384
104
+ ],
105
+ "dtype": "float32"
106
+ },
107
+ "blocks.1.ffn.up.weight": {
108
+ "shape": [
109
+ 1024,
110
+ 384
111
+ ],
112
+ "dtype": "float32"
113
+ },
114
+ "blocks.1.ffn_norm.weight": {
115
+ "shape": [
116
+ 384
117
+ ],
118
+ "dtype": "float32"
119
+ },
120
+ "blocks.2.attention.output.weight": {
121
+ "shape": [
122
+ 384,
123
+ 384
124
+ ],
125
+ "dtype": "float32"
126
+ },
127
+ "blocks.2.attention.qkv.weight": {
128
+ "shape": [
129
+ 1152,
130
+ 384
131
+ ],
132
+ "dtype": "float32"
133
+ },
134
+ "blocks.2.attention_norm.weight": {
135
+ "shape": [
136
+ 384
137
+ ],
138
+ "dtype": "float32"
139
+ },
140
+ "blocks.2.ffn.down.weight": {
141
+ "shape": [
142
+ 384,
143
+ 1024
144
+ ],
145
+ "dtype": "float32"
146
+ },
147
+ "blocks.2.ffn.gate.weight": {
148
+ "shape": [
149
+ 1024,
150
+ 384
151
+ ],
152
+ "dtype": "float32"
153
+ },
154
+ "blocks.2.ffn.up.weight": {
155
+ "shape": [
156
+ 1024,
157
+ 384
158
+ ],
159
+ "dtype": "float32"
160
+ },
161
+ "blocks.2.ffn_norm.weight": {
162
+ "shape": [
163
+ 384
164
+ ],
165
+ "dtype": "float32"
166
+ },
167
+ "blocks.3.attention.output.weight": {
168
+ "shape": [
169
+ 384,
170
+ 384
171
+ ],
172
+ "dtype": "float32"
173
+ },
174
+ "blocks.3.attention.qkv.weight": {
175
+ "shape": [
176
+ 1152,
177
+ 384
178
+ ],
179
+ "dtype": "float32"
180
+ },
181
+ "blocks.3.attention_norm.weight": {
182
+ "shape": [
183
+ 384
184
+ ],
185
+ "dtype": "float32"
186
+ },
187
+ "blocks.3.ffn.down.weight": {
188
+ "shape": [
189
+ 384,
190
+ 1024
191
+ ],
192
+ "dtype": "float32"
193
+ },
194
+ "blocks.3.ffn.gate.weight": {
195
+ "shape": [
196
+ 1024,
197
+ 384
198
+ ],
199
+ "dtype": "float32"
200
+ },
201
+ "blocks.3.ffn.up.weight": {
202
+ "shape": [
203
+ 1024,
204
+ 384
205
+ ],
206
+ "dtype": "float32"
207
+ },
208
+ "blocks.3.ffn_norm.weight": {
209
+ "shape": [
210
+ 384
211
+ ],
212
+ "dtype": "float32"
213
+ },
214
+ "blocks.4.attention.output.weight": {
215
+ "shape": [
216
+ 384,
217
+ 384
218
+ ],
219
+ "dtype": "float32"
220
+ },
221
+ "blocks.4.attention.qkv.weight": {
222
+ "shape": [
223
+ 1152,
224
+ 384
225
+ ],
226
+ "dtype": "float32"
227
+ },
228
+ "blocks.4.attention_norm.weight": {
229
+ "shape": [
230
+ 384
231
+ ],
232
+ "dtype": "float32"
233
+ },
234
+ "blocks.4.ffn.down.weight": {
235
+ "shape": [
236
+ 384,
237
+ 1024
238
+ ],
239
+ "dtype": "float32"
240
+ },
241
+ "blocks.4.ffn.gate.weight": {
242
+ "shape": [
243
+ 1024,
244
+ 384
245
+ ],
246
+ "dtype": "float32"
247
+ },
248
+ "blocks.4.ffn.up.weight": {
249
+ "shape": [
250
+ 1024,
251
+ 384
252
+ ],
253
+ "dtype": "float32"
254
+ },
255
+ "blocks.4.ffn_norm.weight": {
256
+ "shape": [
257
+ 384
258
+ ],
259
+ "dtype": "float32"
260
+ },
261
+ "blocks.5.attention.output.weight": {
262
+ "shape": [
263
+ 384,
264
+ 384
265
+ ],
266
+ "dtype": "float32"
267
+ },
268
+ "blocks.5.attention.qkv.weight": {
269
+ "shape": [
270
+ 1152,
271
+ 384
272
+ ],
273
+ "dtype": "float32"
274
+ },
275
+ "blocks.5.attention_norm.weight": {
276
+ "shape": [
277
+ 384
278
+ ],
279
+ "dtype": "float32"
280
+ },
281
+ "blocks.5.ffn.down.weight": {
282
+ "shape": [
283
+ 384,
284
+ 1024
285
+ ],
286
+ "dtype": "float32"
287
+ },
288
+ "blocks.5.ffn.gate.weight": {
289
+ "shape": [
290
+ 1024,
291
+ 384
292
+ ],
293
+ "dtype": "float32"
294
+ },
295
+ "blocks.5.ffn.up.weight": {
296
+ "shape": [
297
+ 1024,
298
+ 384
299
+ ],
300
+ "dtype": "float32"
301
+ },
302
+ "blocks.5.ffn_norm.weight": {
303
+ "shape": [
304
+ 384
305
+ ],
306
+ "dtype": "float32"
307
+ },
308
+ "embedding.weight": {
309
+ "shape": [
310
+ 8192,
311
+ 384
312
+ ],
313
+ "dtype": "float32"
314
+ },
315
+ "norm.weight": {
316
+ "shape": [
317
+ 384
318
+ ],
319
+ "dtype": "float32"
320
+ },
321
+ "pass_head.bias": {
322
+ "shape": [
323
+ 3
324
+ ],
325
+ "dtype": "float32"
326
+ },
327
+ "pass_head.weight": {
328
+ "shape": [
329
+ 3,
330
+ 384
331
+ ],
332
+ "dtype": "float32"
333
+ },
334
+ "score_head.bias": {
335
+ "shape": [
336
+ 3
337
+ ],
338
+ "dtype": "float32"
339
+ },
340
+ "score_head.weight": {
341
+ "shape": [
342
+ 3,
343
+ 384
344
+ ],
345
+ "dtype": "float32"
346
+ }
347
+ }
348
+ },
349
+ "files": {
350
+ "README.md": {
351
+ "bytes": 1397,
352
+ "sha256": "a1c485e0e037508e1ea8b7fe6c6422d24ed1ddaa8c60579ba552eeae4a673c29"
353
+ },
354
+ "calibration.json": {
355
+ "bytes": 1139,
356
+ "sha256": "416b2d6d5d609608c405a615646cab6e7ee9022d24586b9245053a75e78daf74"
357
+ },
358
+ "config.json": {
359
+ "bytes": 350,
360
+ "sha256": "68c3fd9f8ae9c8376cfdbba58acb642c76645c145705f6bb7e68e86c3de4367a"
361
+ },
362
+ "example_inputs.jsonl": {
363
+ "bytes": 6124,
364
+ "sha256": "223879c190c301466279ddd177fd46af91e448b6b8e1be44a4aa89c2ccc43ca0"
365
+ },
366
+ "labels.json": {
367
+ "bytes": 117,
368
+ "sha256": "c4ea84d5fcde04d423647df6843a07c21ee680ec95983ac485370f07697d495a"
369
+ },
370
+ "mlx_model.py": {
371
+ "bytes": 5486,
372
+ "sha256": "5fbb97e004f7c9e613ae94144f3d04966d64d1a2a0bbf152664296876fd28901"
373
+ },
374
+ "model.safetensors": {
375
+ "bytes": 55084128,
376
+ "sha256": "35e54bfcffe5ade95e32bee903c708ca30554170acb9c7b82dc7db6e3d4eebe4"
377
+ },
378
+ "route_mlx.py": {
379
+ "bytes": 3265,
380
+ "sha256": "20b7520c89c876d9ae2e964bf49679294a1f50e67567538f719c8107db9a4d6c"
381
+ },
382
+ "tokenizer.json": {
383
+ "bytes": 532269,
384
+ "sha256": "f417f5abf0de1c4a475620c4b16b487834115555688d379b29202c4edc5d7481"
385
+ },
386
+ "tokenizer_config.json": {
387
+ "bytes": 183,
388
+ "sha256": "568172f0cc44b6d1d080d53807dce5537a0e58cdbe7fb9d7e6678f97c1f3641c"
389
+ }
390
+ }
391
+ }
mlx_model.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ try:
8
+ import mlx.core as mx
9
+ import mlx.nn as nn
10
+ except ImportError: # Linux export validation intentionally has no MLX runtime.
11
+ mx = None
12
+ nn = None
13
+
14
+
15
+ if nn is not None and mx is not None:
16
+
17
+ class RMSNorm(nn.Module):
18
+ def __init__(self, dimension: int, epsilon: float = 1e-6) -> None:
19
+ super().__init__()
20
+ self.weight = mx.ones((dimension,))
21
+ self.epsilon = epsilon
22
+
23
+ def __call__(self, values: Any) -> Any:
24
+ normalized = values * mx.rsqrt(
25
+ mx.mean(mx.square(values), axis=-1, keepdims=True) + self.epsilon
26
+ )
27
+ return normalized * self.weight
28
+
29
+ def _rotate_half(values: Any) -> Any:
30
+ first, second = mx.split(values, 2, axis=-1)
31
+ return mx.concatenate((-second, first), axis=-1)
32
+
33
+ def apply_rope(query: Any, key: Any) -> tuple[Any, Any]:
34
+ sequence_length = query.shape[-2]
35
+ dimension = query.shape[-1]
36
+ positions = mx.arange(sequence_length, dtype=mx.float32)
37
+ frequencies = 1.0 / (10000 ** (mx.arange(0, dimension, 2, dtype=mx.float32) / dimension))
38
+ angles = positions[:, None] * frequencies[None, :]
39
+ angles = mx.concatenate((angles, angles), axis=-1)[None, None, :, :]
40
+ cosine = mx.cos(angles)
41
+ sine = mx.sin(angles)
42
+ return query * cosine + _rotate_half(query) * sine, key * cosine + _rotate_half(key) * sine
43
+
44
+ class CausalSelfAttention(nn.Module):
45
+ def __init__(self, config: dict[str, Any]) -> None:
46
+ super().__init__()
47
+ self.heads = int(config["attention_heads"])
48
+ self.head_dimension = int(config["model_width"]) // self.heads
49
+ width = int(config["model_width"])
50
+ self.qkv = nn.Linear(width, 3 * width, bias=False)
51
+ self.output = nn.Linear(width, width, bias=False)
52
+
53
+ def __call__(self, values: Any) -> Any:
54
+ batch, sequence, width = values.shape
55
+ qkv = self.qkv(values).reshape(batch, sequence, 3, self.heads, self.head_dimension)
56
+ qkv = qkv.transpose(2, 0, 3, 1, 4)
57
+ query, key, value = qkv[0], qkv[1], qkv[2]
58
+ query, key = apply_rope(query, key)
59
+ mask = nn.MultiHeadAttention.create_additive_causal_mask(sequence)
60
+ attended = mx.fast.scaled_dot_product_attention(
61
+ query,
62
+ key,
63
+ value,
64
+ scale=self.head_dimension**-0.5,
65
+ mask=mask,
66
+ )
67
+ return self.output(attended.transpose(0, 2, 1, 3).reshape(batch, sequence, width))
68
+
69
+ class SwiGLU(nn.Module):
70
+ def __init__(self, config: dict[str, Any]) -> None:
71
+ super().__init__()
72
+ width = int(config["model_width"])
73
+ ffn_width = int(config["ffn_width"])
74
+ self.gate = nn.Linear(width, ffn_width, bias=False)
75
+ self.up = nn.Linear(width, ffn_width, bias=False)
76
+ self.down = nn.Linear(ffn_width, width, bias=False)
77
+
78
+ def __call__(self, values: Any) -> Any:
79
+ return self.down(nn.silu(self.gate(values)) * self.up(values))
80
+
81
+ class TransformerBlock(nn.Module):
82
+ def __init__(self, config: dict[str, Any]) -> None:
83
+ super().__init__()
84
+ width = int(config["model_width"])
85
+ self.attention_norm = RMSNorm(width)
86
+ self.attention = CausalSelfAttention(config)
87
+ self.ffn_norm = RMSNorm(width)
88
+ self.ffn = SwiGLU(config)
89
+
90
+ def __call__(self, values: Any) -> Any:
91
+ values = values + self.attention(self.attention_norm(values))
92
+ return values + self.ffn(self.ffn_norm(values))
93
+
94
+ class TransformerRouterMLX(nn.Module):
95
+ def __init__(self, config: dict[str, Any]) -> None:
96
+ super().__init__()
97
+ width = int(config["model_width"])
98
+ self.config = config
99
+ self.embedding = nn.Embedding(int(config["vocab_size"]), width)
100
+ self.blocks = [TransformerBlock(config) for _ in range(int(config["layers"]))]
101
+ self.norm = RMSNorm(width)
102
+ self.pass_head = nn.Linear(width, int(config["candidate_count"]))
103
+ self.score_head = nn.Linear(width, int(config["candidate_count"]))
104
+
105
+ def __call__(self, input_ids: Any) -> dict[str, Any]:
106
+ hidden = self.embedding(input_ids)
107
+ for block in self.blocks:
108
+ hidden = block(hidden)
109
+ hidden = self.norm(hidden)
110
+ route_state = hidden[:, -1]
111
+ return {
112
+ "pass_logits": self.pass_head(route_state),
113
+ "scores": mx.sigmoid(self.score_head(route_state)),
114
+ }
115
+
116
+ def load_mlx_router(directory: str | Path) -> Any:
117
+ root = Path(directory)
118
+ config = json.loads((root / "config.json").read_text(encoding="utf-8"))["model"]
119
+ model = TransformerRouterMLX(config)
120
+ weights = mx.load(str(root / "model.safetensors"))
121
+ model.load_weights(list(weights.items()), strict=True)
122
+ mx.eval(model.parameters())
123
+ return model
124
+
125
+ else:
126
+
127
+ class TransformerRouterMLX: # type: ignore[no-redef]
128
+ def __init__(self, config: dict[str, Any]) -> None:
129
+ raise RuntimeError("MLX requires macOS on Apple Silicon")
130
+
131
+ def load_mlx_router(directory: str | Path) -> Any:
132
+ raise RuntimeError("MLX requires macOS on Apple Silicon")
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:35e54bfcffe5ade95e32bee903c708ca30554170acb9c7b82dc7db6e3d4eebe4
3
+ size 55084128
route_mlx.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import mlx.core as mx
9
+ from mlx_model import load_mlx_router
10
+ from tokenizers import Tokenizer
11
+
12
+
13
+ def _encode_prompt(
14
+ tokenizer: Tokenizer,
15
+ prompt: str,
16
+ *,
17
+ system: str | None,
18
+ max_length: int,
19
+ ) -> list[int]:
20
+ text = f"<user>\n{prompt}" if system is None else f"<system>\n{system}\n\n<user>\n{prompt}"
21
+ bos_id = tokenizer.token_to_id("<BOS>")
22
+ route_id = tokenizer.token_to_id("<ROUTE>")
23
+ head_tail_id = tokenizer.token_to_id("<HEAD_TAIL>")
24
+ if bos_id is None or route_id is None or head_tail_id is None:
25
+ raise ValueError("Tokenizer is missing required routing tokens")
26
+ body = tokenizer.encode(text, add_special_tokens=False).ids
27
+ available = max_length - 2
28
+ if len(body) > available:
29
+ head_length = (available - 1 + 1) // 2
30
+ tail_length = available - 1 - head_length
31
+ body = body[:head_length] + [head_tail_id] + (body[-tail_length:] if tail_length else [])
32
+ return [bos_id, *body, route_id]
33
+
34
+
35
+ def route_prompt(
36
+ model_dir: str | Path,
37
+ prompt: str,
38
+ *,
39
+ system: str | None = None,
40
+ ) -> dict[str, Any]:
41
+ root = Path(model_dir)
42
+ config = json.loads((root / "config.json").read_text(encoding="utf-8"))
43
+ calibration = json.loads((root / "calibration.json").read_text(encoding="utf-8"))
44
+ labels = json.loads((root / "labels.json").read_text(encoding="utf-8"))[
45
+ "candidate_model_config_ids"
46
+ ]
47
+ tokenizer = Tokenizer.from_file(str(root / "tokenizer.json"))
48
+ input_ids = _encode_prompt(
49
+ tokenizer,
50
+ prompt,
51
+ system=system,
52
+ max_length=int(config["model"]["max_sequence_length"]),
53
+ )
54
+ model = load_mlx_router(root)
55
+ prediction = model(mx.array([input_ids]))
56
+ temperatures = mx.array(calibration["temperatures"])
57
+ probabilities = mx.sigmoid(prediction["pass_logits"][0] / temperatures)
58
+ mx.eval(probabilities, prediction["scores"])
59
+ pass_probabilities = probabilities.tolist()
60
+ threshold = float(calibration["selection_threshold"])
61
+ selected_index = next(
62
+ (index for index, probability in enumerate(pass_probabilities) if probability >= threshold),
63
+ None,
64
+ )
65
+ abstained = selected_index is None
66
+ fallback_index = len(labels) - 1
67
+ route_index = fallback_index if abstained else selected_index
68
+ return {
69
+ "route_config_id": labels[route_index],
70
+ "abstained_to_largest": abstained,
71
+ "selection_threshold": threshold,
72
+ "pass_probabilities": dict(zip(labels, pass_probabilities, strict=True)),
73
+ "predicted_scores": dict(zip(labels, prediction["scores"][0].tolist(), strict=True)),
74
+ "input_tokens": len(input_ids),
75
+ }
76
+
77
+
78
+ def main() -> None:
79
+ parser = argparse.ArgumentParser(description="Route one prompt with the exported MLX model")
80
+ parser.add_argument("--model-dir", default=".")
81
+ parser.add_argument("--prompt", required=True)
82
+ parser.add_argument("--system")
83
+ args = parser.parse_args()
84
+ print(
85
+ json.dumps(
86
+ route_prompt(args.model_dir, args.prompt, system=args.system),
87
+ indent=2,
88
+ sort_keys=True,
89
+ )
90
+ )
91
+
92
+
93
+ if __name__ == "__main__":
94
+ main()
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 8192,
3
+ "model_vocab_size": 8192,
4
+ "special_tokens": {
5
+ "<PAD>": 0,
6
+ "<UNK>": 1,
7
+ "<BOS>": 2,
8
+ "<EOS>": 3,
9
+ "<ROUTE>": 4,
10
+ "<HEAD_TAIL>": 5
11
+ }
12
+ }