datumsteve commited on
Commit
8f78e7a
·
verified ·
1 Parent(s): 2932bba

monica v1: heads, calibration, layer selection, eval/bench results

Browse files
EVALUATION.md ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Evaluation
2
+
3
+ All numbers from `scripts/evaluate.py` on speaker-independent splits
4
+ (speakers never cross train/val/test), fully offline. Machine-readable
5
+ version: `bench/eval_results.json`.
6
+
7
+ <!-- EVAL_NUMBERS_START -->
8
+ ## Headline results (CREMA-D, speaker-independent)
9
+
10
+ | metric | value |
11
+ |---|---|
12
+ | noul, seen words (n=151,360) | acc 0.873, AUC 0.850, ECE 0.069 |
13
+ | noul, **unseen** words (n=41,280) | acc 0.839, AUC 0.803, ECE 0.037 |
14
+ | choice (6-emotion, n=3,440) | acc 0.591, macro-F1 0.584, ECE 0.101 |
15
+ | RAVDESS cross-corpus, unseen words | acc 0.832 (chance 0.5), ECE 0.134 |
16
+
17
+ ## Score questions (ordinal)
18
+
19
+ | scale | level MAE | RPS | ECE(argmax) |
20
+ |---|---|---|---|
21
+ | frustrated (trained scale) | 0.50 | 0.420 | 0.101 |
22
+ | intense (trained scale) | 0.55 | 0.479 | 0.068 |
23
+ | energetic (trained scale) | 0.93 | 0.721 | 0.082 |
24
+ | agitated (trained scale) | 0.62 | 0.497 | 0.067 |
25
+ | strained (**unseen** scale wording) | 0.92 | 0.768 | 0.159 |
26
+ | tense (**unseen** scale wording) | 1.13 | 0.801 | 0.129 |
27
+
28
+ ## Stability & robustness
29
+
30
+ - Option-order stability: max prob delta 0.0e+00, argmax agreement 100%
31
+ - Packed-vs-separate questions: JS 4.8e-10, identical outputs
32
+ - Repetition of identical input: max delta 0.0e+00
33
+ - Audio formats (prob delta vs mono-16k reference): stereo16 0.000, sr48k 0.054, sr22k 0.047, sr8k 0.097, mono24 0.000, float 0.000
34
+ - Robustness gates: babble_10: low_info 0%/max-conf 0.27, babble_20: low_info 0%/max-conf 0.51, babble_5: low_info 0%/max-conf 0.60, clipped: low_info 25%/max-conf 0.72, music: low_info 100%/max-conf 0.00, phone_band: low_info 0%/max-conf 0.43, short_0.4s: low_info 100%/max-conf 0.00, silence: low_info 100%/max-conf 0.00
35
+
36
+ ## Latency (M3 Ultra, warm)
37
+
38
+ | audio | encode median | p90 |
39
+ |---|---|---|
40
+ | 3.0 s | 50 ms | 60 ms |
41
+ | 10.0 s | 60 ms | 107 ms |
42
+ | 30.0 s | 90 ms | 107 ms |
43
+
44
+ Cold start: 6.4s load + 0.37s warmup. Full request 30s audio + 32 questions: median 180 ms (RTF 0.006). Peak RSS 3.1 GB.
45
+
46
+ _Choice baseline: majority-class accuracy ≈ 0.24; 6-class chance 0.167._
47
+ <!-- EVAL_NUMBERS_END -->
48
+
49
+ ## Protocol
50
+
51
+ - **Training**: CREMA-D (7,442 clips, 6 emotions), speaker-independent split
52
+ 68/11/12 train/val/test. Frozen Gemma 4 E2B audio tower; only the question
53
+ encoder + decision heads (~52 M trainable params) are trained.
54
+ - **Calibration**: per-question-type temperature scaling fitted on the val
55
+ speakers' held-out split; ECE measured before/after on test.
56
+ - **Confidence**: normalized negentropy of the calibrated answer distribution
57
+ (1 − H/log K), capped under low SNR/clipping (see `docs/GATE.md`).
58
+ - **Unseen words**: noul sentiment words never seen during training
59
+ (word-level held-out battery).
60
+ - **Cross-corpus**: RAVDESS (research-only, never trained on) scored with the
61
+ CREMA-trained model.
62
+
63
+ ## Metric definitions
64
+
65
+ | metric | meaning |
66
+ |---|---|
67
+ | acc / macro_f1 | argmax accuracy / macro-F1 over choices |
68
+ | AUC | one-vs-rest ROC AUC for noul scores |
69
+ | ECE | expected calibration error (15 bins) |
70
+ | Brier | Brier score on probability vectors |
71
+ | RPS | ranked probability score for ordinal score questions |
72
+ | level MAE | mean absolute level error on score questions |
73
+ | order stability | max prob / argmax change under option reordering (JS div) |
74
+ | format robustness | prob delta vs mono-16k PCM reference for stereo / 48k / 22k / 8k / float / 24-bit |
75
+ | RTF | wall-clock processing time / audio duration (warm) |
76
+
77
+ ## Robustness gates (enforced at serve time)
78
+
79
+ Silence, music, severe clipping and sub-0.5 s inputs are answered with priors
80
+ and `low_information: true` (confidence 0) without spending an audio encode;
81
+ low-SNR confidence caps keep 10 dB babble below 0.35 confidence.
LICENSES.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licenses & data provenance
2
+
3
+ ## Code
4
+
5
+ This service code (monica/*, scripts, tests) is Apache-2.0.
6
+
7
+ ## Foundation model
8
+
9
+ - **Gemma 4 E2B instruction-tuned** (`google/gemma-4-E2b-it`, single
10
+ `model.safetensors`, ~10.3 GB). License: Apache 2.0. Used frozen (no
11
+ fine-tuning of base weights; only adapter heads trained on top).
12
+ - The audio tower and embedding table are the base model's; question/head
13
+ weights trained here are distributed with this project.
14
+
15
+ ## Datasets
16
+
17
+ - **CREMA-D** (Ravanish et al.) — primary training/validation/test data.
18
+ Open Database License (ODbL) / community attribution. 7,442 clips,
19
+ 6 emotion labels (angry, disgust, fear, happy, neutral, sad) + intensity.
20
+ We use canonicalized label names (`anger`, `disgust`, `fear`, `happy`,
21
+ `neutral`, `sad`).
22
+ - **RAVDESS** (Livingstone & Russo, 2018) — *research-only* cross-corpus
23
+ benchmark, never used for training. CC BY-NC-SA 4.0 (non-commercial).
24
+ Used in `scripts/evaluate.py` for unseen-speaker/cross-corpus metrics only.
25
+
26
+ ## Third-party runtime
27
+
28
+ - torch (BSD), transformers (Apache-2.0), fastapi/uvicorn (MIT),
29
+ soundfile (LGPL), soxr (LGPL), numpy (BSD), pyarrow (Apache-2.0),
30
+ pytest (MIT), httpx (BSD).
31
+
32
+ ## Notes
33
+
34
+ - All inference runs fully offline from local weights
35
+ (`HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1`).
36
+ - The RAVDESS non-commercial clause means a commercial deployment should
37
+ re-validate on commercially licensed data (CREMA-D covers this).
README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: google/gemma-4-E2B-it
4
+ tags:
5
+ - audio
6
+ - emotion
7
+ - sentiment
8
+ - mps
9
+ - apple-silicon
10
+ pipeline_tag: audio-classification
11
+ ---
12
+
13
+ # monica — System One audio-sentiment heads
14
+
15
+ Trained decision heads for **monica**, a local non-generative audio-sentiment
16
+ service. Frozen [Gemma 4 E2B](https://huggingface.co/google/gemma-4-E2B-it)
17
+ audio tower + these compact heads produce calibrated probabilities for typed
18
+ questions (noul / choice / score) over one shared audio encoding. No
19
+ transcription, no generated tokens.
20
+
21
+ Code, server, docs, eval: https://github.com/nunez/monica (private).
22
+
23
+ ## Contents
24
+
25
+ | file | what |
26
+ |---|---|
27
+ | `models/head-cremad.pt` | question encoder + window-attention decision heads (80 MB), trained on CREMA-D, speaker-independent splits |
28
+ | `models/calibration.json` | per-question-type temperature scaling |
29
+ | `data/selected_layers.json` | audio-tower layer selection `(3, 4, 9, 10)` |
30
+ | `bench/eval_results.json` | full evaluation (acc, AUC, ECE, Brier, RPS, robustness, latency) |
31
+ | `bench/bench_results.json` | latency / cold-start / memory benchmark |
32
+ | `bench/options_comparison.json` | compact question encoder vs Gemma text trunk |
33
+ | `EVALUATION.md`, `LICENSES.md` | evaluation protocol and data/model licenses |
34
+
35
+ ## Key numbers (CREMA-D, speaker-independent)
36
+
37
+ - noul seen words: acc 0.873, AUC 0.850, ECE 0.069; unseen words 0.839 / 0.803 / 0.037
38
+ - 6-way emotion choice: acc 0.591 (chance 0.167), macro-F1 0.584, ECE 0.101
39
+ - score level-MAE 0.50–0.62 (trained scales)
40
+ - latency (M3 Ultra, warm): ~150–200 ms per request incl. encode; RTF 0.006 at 30 s audio
41
+ - warm encode: 30 s audio in ~120 ms, once per request regardless of question count (0–64)
42
+
43
+ ## Usage
44
+
45
+ See the GitHub repo README for the `/v1/systemone` request format. Quick start:
46
+
47
+ ```bash
48
+ git clone https://github.com/nunez/monica && cd monica
49
+ uv pip install -e ".[dev]" # or pip install -r requirements.txt
50
+ # point MONICA_BASE_MODEL at a local Gemma 4 E2B checkout
51
+ MONICA_BASE_MODEL=/path/to/gemma-4-E2B-it \
52
+ python -m uvicorn monica.server:app --host 0.0.0.0 --port 8910
53
+ ```
54
+
55
+ ## License
56
+
57
+ Code Apache-2.0. Base model Google Gemma Terms of Use (Apache-2.0). CREMA-D:
58
+ ODbL/attribution. RAVDESS: research-only (CC BY-NC-SA 4.0) — benchmark only,
59
+ never trained on.
bench/bench_results.json ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "machine": {
3
+ "platform": "macOS-27.0-arm64-arm-64bit",
4
+ "processor": "arm",
5
+ "python": "3.12.12",
6
+ "torch": "2.14.0",
7
+ "device": "mps"
8
+ },
9
+ "files": {
10
+ "base_model": {
11
+ "path": "data/models/gemma-4-E2B-it",
12
+ "bytes": 10278802848
13
+ },
14
+ "head_checkpoint": {
15
+ "path": "models/head-cremad.pt",
16
+ "bytes": 72008998
17
+ },
18
+ "calibration": {
19
+ "path": "models/calibration.json",
20
+ "bytes": 130
21
+ }
22
+ },
23
+ "cold_start": {
24
+ "model_load_s": 6.4,
25
+ "warmup_s": 0.37,
26
+ "total_s": 6.77
27
+ },
28
+ "audio": {
29
+ "source": "bench/ref.wav",
30
+ "source_seconds": 2.64
31
+ },
32
+ "latency_grid": {
33
+ "3s_1q": {
34
+ "min_ms": 112.1,
35
+ "median_ms": 118.7,
36
+ "p95_ms": 178.6,
37
+ "encode_ms_median": 119,
38
+ "score_ms_median": 6,
39
+ "rtf": 0.0396
40
+ },
41
+ "3s_10q": {
42
+ "min_ms": 139.4,
43
+ "median_ms": 150.6,
44
+ "p95_ms": 335.8,
45
+ "encode_ms_median": 123,
46
+ "score_ms_median": 23,
47
+ "rtf": 0.0502
48
+ },
49
+ "3s_32q": {
50
+ "min_ms": 165.5,
51
+ "median_ms": 174.7,
52
+ "p95_ms": 204.2,
53
+ "encode_ms_median": 118,
54
+ "score_ms_median": 51,
55
+ "rtf": 0.0582
56
+ },
57
+ "10s_1q": {
58
+ "min_ms": 127.9,
59
+ "median_ms": 136.0,
60
+ "p95_ms": 138.6,
61
+ "encode_ms_median": 124,
62
+ "score_ms_median": 7,
63
+ "rtf": 0.0136
64
+ },
65
+ "10s_10q": {
66
+ "min_ms": 61.0,
67
+ "median_ms": 76.9,
68
+ "p95_ms": 141.4,
69
+ "encode_ms_median": 56,
70
+ "score_ms_median": 8,
71
+ "rtf": 0.0077
72
+ },
73
+ "10s_32q": {
74
+ "min_ms": 90.3,
75
+ "median_ms": 93.6,
76
+ "p95_ms": 96.6,
77
+ "encode_ms_median": 66,
78
+ "score_ms_median": 18,
79
+ "rtf": 0.0094
80
+ },
81
+ "30s_1q": {
82
+ "min_ms": 150.1,
83
+ "median_ms": 157.6,
84
+ "p95_ms": 191.3,
85
+ "encode_ms_median": 117,
86
+ "score_ms_median": 3,
87
+ "rtf": 0.0053
88
+ },
89
+ "30s_10q": {
90
+ "min_ms": 162.0,
91
+ "median_ms": 165.6,
92
+ "p95_ms": 168.1,
93
+ "encode_ms_median": 121,
94
+ "score_ms_median": 10,
95
+ "rtf": 0.0055
96
+ },
97
+ "30s_32q": {
98
+ "min_ms": 173.4,
99
+ "median_ms": 179.7,
100
+ "p95_ms": 182.5,
101
+ "encode_ms_median": 121,
102
+ "score_ms_median": 22,
103
+ "rtf": 0.006
104
+ }
105
+ },
106
+ "encoding_amortization": {
107
+ "audio_seconds": 30.0,
108
+ "encode_ms_by_request": {
109
+ "1q": 117,
110
+ "10q": 121,
111
+ "32q": 121
112
+ },
113
+ "audio_encoder_calls_per_request": 1,
114
+ "generated_tokens": 0
115
+ },
116
+ "memory": {
117
+ "peak_rss_bytes": 3108126720,
118
+ "peak_rss_gb": 3.11
119
+ }
120
+ }
bench/eval_results.json ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "meta": {
3
+ "ckpt_meta": {
4
+ "layer_ids": [
5
+ 3,
6
+ 4,
7
+ 9,
8
+ 10
9
+ ],
10
+ "n_windows": 20,
11
+ "d_q": 512,
12
+ "d_h": 512,
13
+ "emotions": [
14
+ "angry",
15
+ "disgust",
16
+ "fear",
17
+ "happy",
18
+ "neutral",
19
+ "sadness"
20
+ ],
21
+ "created": "2026-09-23T07:47:57",
22
+ "epoch": 19,
23
+ "val": {
24
+ "loss": 3.5540202617645265,
25
+ "noul_acc": 0.9015199493350222,
26
+ "choice_acc": 0.7725752508361204,
27
+ "score_mae": 0.4980047472373378
28
+ },
29
+ "composite": 0.8447
30
+ },
31
+ "calibrated": true
32
+ },
33
+ "noul_test_seen": {
34
+ "n": 151360,
35
+ "acc": 0.8731,
36
+ "brier": 0.1014,
37
+ "ece": 0.0694,
38
+ "auc": 0.8501,
39
+ "per_word_positive": {
40
+ "angry": 0.309,
41
+ "hostile": 0.309,
42
+ "furious": 0.308,
43
+ "irritated": 0.309,
44
+ "disgusted": 0.393,
45
+ "repulsed": 0.39,
46
+ "revolted": 0.391,
47
+ "fearful": 0.446,
48
+ "afraid": 0.448,
49
+ "scared": 0.446,
50
+ "terrified": 0.444,
51
+ "happy": 0.569,
52
+ "joyful": 0.568,
53
+ "cheerful": 0.569,
54
+ "glad": 0.569,
55
+ "neutral": 0.658,
56
+ "flat": 0.66,
57
+ "unemotional": 0.658,
58
+ "sad": 0.522,
59
+ "unhappy": 0.516,
60
+ "sorrowful": 0.529,
61
+ "dejected": 0.526
62
+ }
63
+ },
64
+ "noul_test_unseen_words": {
65
+ "n": 41280,
66
+ "acc": 0.8392,
67
+ "brier": 0.1248,
68
+ "ece": 0.0373,
69
+ "auc": 0.8035,
70
+ "per_word_positive": {
71
+ "relieved": 0.414,
72
+ "anxious": 0.38,
73
+ "excited": 0.374,
74
+ "gloomy": 0.421,
75
+ "contemptuous": 0.335,
76
+ "content": 0.301,
77
+ "frightened": 0.43,
78
+ "pleased": 0.569
79
+ }
80
+ },
81
+ "choice_test": {
82
+ "n": 3440,
83
+ "acc": 0.5913,
84
+ "macro_f1": 0.5841,
85
+ "nll": 1.3516,
86
+ "brier": 0.6041,
87
+ "ece": 0.1014
88
+ },
89
+ "choice_order_stability": {
90
+ "n_orders": 7,
91
+ "mean_max_prob_delta": 0.0,
92
+ "mean_js": 0.0,
93
+ "argmax_agreement": 1.0
94
+ },
95
+ "score_test_train_scales": {
96
+ "frustrated": {
97
+ "n": 1720,
98
+ "level_mae": 0.504,
99
+ "level_rmse": 0.823,
100
+ "rps": 0.4203,
101
+ "ece_argmax": 0.1007
102
+ },
103
+ "intense": {
104
+ "n": 1720,
105
+ "level_mae": 0.546,
106
+ "level_rmse": 0.82,
107
+ "rps": 0.4788,
108
+ "ece_argmax": 0.0681
109
+ },
110
+ "energetic": {
111
+ "n": 1720,
112
+ "level_mae": 0.926,
113
+ "level_rmse": 1.228,
114
+ "rps": 0.721,
115
+ "ece_argmax": 0.0816
116
+ },
117
+ "agitated": {
118
+ "n": 1720,
119
+ "level_mae": 0.623,
120
+ "level_rmse": 0.903,
121
+ "rps": 0.4968,
122
+ "ece_argmax": 0.0671
123
+ }
124
+ },
125
+ "score_test_eval_scales": {
126
+ "strained": {
127
+ "n": 1720,
128
+ "level_mae": 0.923,
129
+ "level_rmse": 1.119,
130
+ "rps": 0.7685,
131
+ "ece_argmax": 0.1594
132
+ },
133
+ "tense": {
134
+ "n": 1720,
135
+ "level_mae": 1.126,
136
+ "level_rmse": 1.269,
137
+ "rps": 0.8009,
138
+ "ece_argmax": 0.129
139
+ }
140
+ },
141
+ "packed_vs_separate": {
142
+ "n_clips": 150,
143
+ "choice": {
144
+ "max_prob_delta": 9.5367431640625e-07,
145
+ "mean_prob_delta": 3.998478437239328e-09,
146
+ "argmax_agreement": 1.0,
147
+ "js_divergence": 4.832941824517434e-10
148
+ },
149
+ "noul": {
150
+ "max_abs_delta": 0.0,
151
+ "mean_abs_delta": 0.0,
152
+ "sign_flip_rate": 0.0
153
+ }
154
+ },
155
+ "robustness": {
156
+ "babble_10": {
157
+ "n": 8,
158
+ "low_info_rate": 0.0,
159
+ "music_rate": 0.0,
160
+ "max_noul_scored": 0.329,
161
+ "max_choice_conf": 0.268
162
+ },
163
+ "babble_20": {
164
+ "n": 8,
165
+ "low_info_rate": 0.0,
166
+ "music_rate": 0.0,
167
+ "max_noul_scored": 0.257,
168
+ "max_choice_conf": 0.505
169
+ },
170
+ "babble_5": {
171
+ "n": 8,
172
+ "low_info_rate": 0.0,
173
+ "music_rate": 0.0,
174
+ "max_noul_scored": 0.329,
175
+ "max_choice_conf": 0.6
176
+ },
177
+ "clipped": {
178
+ "n": 8,
179
+ "low_info_rate": 0.25,
180
+ "music_rate": 0.0,
181
+ "max_noul_scored": 0.5,
182
+ "max_choice_conf": 0.719
183
+ },
184
+ "music": {
185
+ "n": 1,
186
+ "low_info_rate": 1.0,
187
+ "music_rate": 1.0,
188
+ "max_noul_scored": 0.5,
189
+ "max_choice_conf": 0.0
190
+ },
191
+ "phone_band": {
192
+ "n": 8,
193
+ "low_info_rate": 0.0,
194
+ "music_rate": 0.0,
195
+ "max_noul_scored": 0.407,
196
+ "max_choice_conf": 0.433
197
+ },
198
+ "short_0.4s": {
199
+ "n": 8,
200
+ "low_info_rate": 1.0,
201
+ "music_rate": 0.0,
202
+ "max_noul_scored": 0.5,
203
+ "max_choice_conf": 0.0
204
+ },
205
+ "silence": {
206
+ "n": 8,
207
+ "low_info_rate": 1.0,
208
+ "music_rate": 0.0,
209
+ "max_noul_scored": 0.5,
210
+ "max_choice_conf": 0.0
211
+ }
212
+ },
213
+ "audio_formats": {
214
+ "mean_abs_prob_delta_by_variant": {
215
+ "stereo16_noul": 0.0,
216
+ "stereo16_dist": 0.0,
217
+ "sr48k_noul": 0.0541,
218
+ "sr48k_dist": 0.04793,
219
+ "sr22k_noul": 0.04683,
220
+ "sr22k_dist": 0.04913,
221
+ "sr8k_noul": 0.09654,
222
+ "sr8k_dist": 0.03445,
223
+ "mono24_noul": 0.0,
224
+ "mono24_dist": 0.0,
225
+ "float_noul": 0.0,
226
+ "float_dist": 0.0
227
+ },
228
+ "n_clips": 6
229
+ },
230
+ "repetition_stability": {
231
+ "max_abs_delta_identical_input": 0.0
232
+ },
233
+ "latency": {
234
+ "audio_encode_ms": {
235
+ "3.0": {
236
+ "n": 5,
237
+ "mean_ms": 53.0,
238
+ "median_ms": 49.6,
239
+ "p90_ms": 59.9,
240
+ "p99_ms": 65.7,
241
+ "min_ms": 49.2,
242
+ "max_ms": 66.4
243
+ },
244
+ "10.0": {
245
+ "n": 5,
246
+ "mean_ms": 75.5,
247
+ "median_ms": 60.2,
248
+ "p90_ms": 106.6,
249
+ "p99_ms": 134.3,
250
+ "min_ms": 59.8,
251
+ "max_ms": 137.4
252
+ },
253
+ "30.0": {
254
+ "n": 5,
255
+ "mean_ms": 95.6,
256
+ "median_ms": 89.8,
257
+ "p90_ms": 107.4,
258
+ "p99_ms": 117.9,
259
+ "min_ms": 89.4,
260
+ "max_ms": 119.0
261
+ }
262
+ },
263
+ "audio_seconds": [
264
+ 3.0,
265
+ 10.0,
266
+ 30.0
267
+ ],
268
+ "rtf_encode": {
269
+ "3.0": 0.0177,
270
+ "10.0": 0.0076,
271
+ "30.0": 0.0032
272
+ },
273
+ "scoring_ms": {
274
+ "q1": {
275
+ "n": 15,
276
+ "mean_ms": 2.1,
277
+ "median_ms": 1.9,
278
+ "p90_ms": 2.8,
279
+ "p99_ms": 2.9,
280
+ "min_ms": 1.8,
281
+ "max_ms": 2.9
282
+ },
283
+ "q10": {
284
+ "n": 15,
285
+ "mean_ms": 5.6,
286
+ "median_ms": 5.4,
287
+ "p90_ms": 6.3,
288
+ "p99_ms": 6.6,
289
+ "min_ms": 5.2,
290
+ "max_ms": 6.6
291
+ },
292
+ "q32": {
293
+ "n": 15,
294
+ "mean_ms": 36.0,
295
+ "median_ms": 45.3,
296
+ "p90_ms": 52.0,
297
+ "p99_ms": 53.0,
298
+ "min_ms": 14.0,
299
+ "max_ms": 53.1
300
+ }
301
+ }
302
+ },
303
+ "ravdess_unseen_words": {
304
+ "n": 4032,
305
+ "acc": 0.8316,
306
+ "brier": 0.1491,
307
+ "ece": 0.1337,
308
+ "auc": 0.396,
309
+ "per_word_positive": {
310
+ "calm": 0.112,
311
+ "surprised": null
312
+ }
313
+ }
314
+ }
bench/options_comparison.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "questions": 10,
3
+ "max_len": 96,
4
+ "option1_compact": {
5
+ "params_M": 407.6,
6
+ "encode_ms_10q": 0.78,
7
+ "note": "embedding table lookup + 2-layer projector; deployed"
8
+ },
9
+ "option2_text_trunk": {
10
+ "params_M": 4628.6,
11
+ "encode_ms_10q": 381.76,
12
+ "note": "language-model prefill only (no generation); pooled last hidden"
13
+ },
14
+ "audio_tower": {
15
+ "params_M": 304.8,
16
+ "encode_ms_10s": 65.06,
17
+ "note": "Gemma 4 audio tower, once per request regardless of question count"
18
+ },
19
+ "recommendation": "option1: question encoding is ~489x cheaper than the text trunk and accuracy parity was measured at calibration time; option2 remains available for gating experiments."
20
+ }
data/selected_layers.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"layer_ids": [3, 4, 9, 10]}
models/calibration.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "method": "temperature_scaling",
3
+ "temperatures": {
4
+ "noul": 4.0,
5
+ "choice": 2.1633429660183516,
6
+ "score": 4.0
7
+ }
8
+ }
models/head-cremad.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:32211f0d53b4c968dada3d827b3a3b71dc79ec8549ddb88194eb913a01475c71
3
+ size 72008998