NathanRoll commited on
Commit
debfb0d
·
verified ·
1 Parent(s): 14ab744

Remove retired benchmark material

Browse files
README.md CHANGED
@@ -105,36 +105,6 @@ Orukeet improves 25 of 27 complete LibriSpeech/FLEURS splits and 36 of 47 accent
105
 
106
  [All 74 paired WER/CER scores and edit counts](docs/current-checkpoint-benchmarks.md) · [Methods](docs/technical-report.md) · [Technical report](orukeet-technical-report.pdf)
107
 
108
- <!-- orukeet-open-asr-20260918:start -->
109
- ## Open ASR public English evaluation, September 18, 2026
110
-
111
- **Submission withdrawn September 19, 2026 (UTC).** [Open ASR PR #221](https://github.com/huggingface/open_asr_leaderboard/pull/221) is closed. The leaderboard submission has been withdrawn; the checkpoint, code, research results, and exposure disclosures remain available as historical research artifacts.
112
-
113
- The released r3 checkpoint was evaluated on all eight current public English Open ASR datasets using the official NeMo H200 container. Mean WER is **4.49%**, with aggregate throughput **5545.68 RTFx**. These are self-reported public-set results; the leaderboard submission is withdrawn and no official inclusion is claimed.
114
-
115
- **Training exposure:** r3 trained on all 2,939 LibriSpeech test-other recordings for three passes and used that split for selection. Monsoon English also informed earlier training-partition selection. The aggregate includes these datasets and is not a held-out generalization estimate. [Training and benchmark exposure](https://huggingface.co/oruk/orukeet/blob/main/evaluation/open_asr_20260918/training-disclosure.md).
116
-
117
- | Dataset | WER (%) | H200 RTFx |
118
- |:--|--:|--:|
119
- | AMI-Cleaned | 8.68 | 3741.22 |
120
- | Earnings22-Cleaned-AA | 5.74 | 2982.17 |
121
- | GigaSpeech-Cleaned | 7.48 | 5346.49 |
122
- | LibriSpeech test-clean | 1.47 | 4180.11 |
123
- | LibriSpeech test-other (trained on) | 2.84 | 4159.42 |
124
- | SPGISpeech | 3.38 | 6419.21 |
125
- | Monsoon English (prior selection exposure) | 3.84 | 4835.62 |
126
- | VoxPopuli-Cleaned-AA | 2.46 | 2488.16 |
127
- | **Public-eight aggregate** | **4.49** | **5545.68** |
128
-
129
- The run uses H200, NeMo 2.7.2, Torch 2.8.0, BF16, batch size 128, and the same greedy-batch TDT decoder with `max_symbols=10` across all datasets. Timing covers the complete transcription pass after up to four warmup batches, with CUDA synchronization. RTFx is total evaluated audio divided by total measured transcription time; it excludes model/data acquisition and warmup. Batch size follows the existing Parakeet profile; exhaustive throughput optimization is not claimed.
130
-
131
- All 74,443 eligible inputs from 74,544 source records are retained. The official reference rule excludes 90 AMI and 11 GigaSpeech records; Earnings22's 341 chunks are merged into six full calls for scoring. The exact official normalizer and compound-aware `kaldialign==0.12.0` scorer are used. The mean averages the eight two-decimal dataset WERs. The earlier CPU FP32 comparison remains a separate run.
132
-
133
- [Complete metrics and execution hashes](https://huggingface.co/oruk/orukeet/blob/main/evaluation/open_asr_20260918/public-eight-h200-results.json) · [Pinned reproduction code](https://huggingface.co/spaces/oruk/open-asr-leaderboard-orukeet/tree/171ab5e79454cc3772a8700479cb150cfe4cc84f)
134
-
135
- Monsoon currently lacks a registered Hub metric task. Its score is retained in the complete report and eight-dataset aggregate; the active Hub submission YAML has been removed.
136
- <!-- orukeet-open-asr-20260918:end -->
137
-
138
  ## sherpa-onnx inference
139
 
140
  The [ONNX INT8 archive](https://huggingface.co/oruk/orukeet/resolve/55a984d46f68323301837194ce647c702f55facc/onnx/sherpa-onnx-orukeet-v0.1.0-int8.tar.bz2) uses the standard Parakeet TDT v3 layout: `encoder.int8.onnx`, `decoder.int8.onnx`, `joiner.int8.onnx` and `tokens.txt`. It also includes the BPE vocabulary, weight license and attribution. Gabor filters are ordinary convolution weights; the model uses sherpa-onnx's existing offline transducer loader.
 
105
 
106
  [All 74 paired WER/CER scores and edit counts](docs/current-checkpoint-benchmarks.md) · [Methods](docs/technical-report.md) · [Technical report](orukeet-technical-report.pdf)
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  ## sherpa-onnx inference
109
 
110
  The [ONNX INT8 archive](https://huggingface.co/oruk/orukeet/resolve/55a984d46f68323301837194ce647c702f55facc/onnx/sherpa-onnx-orukeet-v0.1.0-int8.tar.bz2) uses the standard Parakeet TDT v3 layout: `encoder.int8.onnx`, `decoder.int8.onnx`, `joiner.int8.onnx` and `tokens.txt`. It also includes the BPE vocabulary, weight license and attribution. Gabor filters are ordinary convolution weights; the model uses sherpa-onnx's existing offline transducer loader.
evaluation/open_asr_20260918/official-scorer-output.txt DELETED
@@ -1,34 +0,0 @@
1
- Filtering models by id: oruk/orukeet
2
- ********************************************************************************
3
- Results per dataset:
4
- ********************************************************************************
5
- oruk/orukeet | ArtificialAnalysis-Earnings22-Cleaned-AA-chunked__test: WER = 5.74 %, RTFx = 2982.17
6
- oruk/orukeet | VoiceArena-Monsoon_en_IN_test__test: WER = 3.84 %, RTFx = 4835.62
7
- oruk/orukeet | hf-audio-open-asr-leaderboard_ami_cleaned_test: WER = 8.68 %, RTFx = 3741.22
8
- oruk/orukeet | hf-audio-open-asr-leaderboard_gigaspeech_cleaned_test: WER = 7.48 %, RTFx = 5346.49
9
- oruk/orukeet | hf-audio-open-asr-leaderboard_librispeech_test.clean: WER = 1.47 %, RTFx = 4180.11
10
- oruk/orukeet | hf-audio-open-asr-leaderboard_librispeech_test.other: WER = 2.84 %, RTFx = 4159.42
11
- oruk/orukeet | hf-audio-open-asr-leaderboard_spgispeech_test: WER = 3.38 %, RTFx = 6419.21
12
- oruk/orukeet | hf-audio-open-asr-leaderboard_voxpopuli_cleaned_aa_test: WER = 2.46 %, RTFx = 2488.16
13
-
14
- ********************************************************************************
15
- Composite Results:
16
- ********************************************************************************
17
- oruk/orukeet: WER = 4.49 %
18
- oruk/orukeet: RTFx = 5545.68
19
- ********************************************************************************
20
-
21
- ********************************************************************************
22
- CSV Summary (Public):
23
- ********************************************************************************
24
- avg WER (oruk/orukeet) = 4.49
25
- model,RTFx,License,Size (B),# Languages,Encoder,Decoder,AMI-Cleaned WER,Earnings22-Cleaned-AA-chunked WER,Gigaspeech-Cleaned WER,LS Clean WER,LS Other WER,SPGISpeech WER,Voice-Arena-Moonsoon WER,Voxpopuli-Cleaned-AA WER,AMI-Cleaned RTFx,Earnings22-Cleaned-AA-chunked RTFx,Gigaspeech-Cleaned RTFx,LS Clean RTFx,LS Other RTFx,SPGISpeech RTFx,Voice-Arena-Moonsoon RTFx,Voxpopuli-Cleaned-AA RTFx
26
- oruk/orukeet,5545.68,,,,,,8.68,5.74,7.48,1.47,2.84,3.38,3.84,2.46,3741.2159,2982.1706,5346.4904,4180.1148,4159.4244,6419.2142,4835.625,2488.1643
27
- ********************************************************************************
28
-
29
- ********************************************************************************
30
- CSV Summary (Extra):
31
- ********************************************************************************
32
- model,AMI WER,Earnings22 WER,Gigaspeech WER,Voxpopuli WER
33
- oruk/orukeet,,,,
34
- ********************************************************************************
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/open_asr_20260918/public-eight-h200-results.json DELETED
@@ -1,1530 +0,0 @@
1
- {
2
- "schema_version": 1,
3
- "complete_public_eight_metrics": true,
4
- "complete_per_dataset_hub_task_coverage": false,
5
- "missing_registered_tasks": [
6
- "voicearena_monsoon_en_in"
7
- ],
8
- "model": {
9
- "model_id": "oruk/orukeet",
10
- "parameter_count": 627008134,
11
- "size_billions": 0.627008134,
12
- "supported_language_count": 25,
13
- "evaluated_languages": [
14
- "en"
15
- ],
16
- "license": "cc-by-sa-4.0",
17
- "encoder": "FastConformer",
18
- "decoder": "Token-and-Duration Transducer (TDT)",
19
- "checkpoint_file": "orukeet-v0.1.0.nemo",
20
- "checkpoint_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
21
- "parameter_scope": "total parameters, not trainable parameters only",
22
- "known_exposure": [
23
- "All 2939 LibriSpeech test-other recordings used for r3 training and selection.",
24
- "Monsoon English informed earlier training-partition selection.",
25
- "Other inherited training exposure is incompletely verified."
26
- ]
27
- },
28
- "evaluation_date": "2026-09-18",
29
- "aggregate": {
30
- "mean_wer_percent": 4.49,
31
- "mean_of_two_decimal_dataset_wer": 4.48625,
32
- "rtfx": 5545.68,
33
- "rtfx_unrounded": 5545.67879726494,
34
- "audio_seconds": 588203.26,
35
- "transcription_seconds": 106.06515117501839
36
- },
37
- "datasets": {
38
- "ami_cleaned": {
39
- "wer": 8.68,
40
- "audio_length": 28727.5903125,
41
- "inference_time": 7.678677501156925,
42
- "rtfx": 3741.2159,
43
- "ins": 1873,
44
- "del": 2187,
45
- "sub": 3085
46
- },
47
- "earnings22_cleaned_aa_chunked": {
48
- "wer": 5.74,
49
- "audio_length": 6900.9376250000005,
50
- "inference_time": 2.3140653409063816,
51
- "rtfx": 2982.1706,
52
- "ins": 101,
53
- "del": 237,
54
- "sub": 545
55
- },
56
- "gigaspeech_cleaned": {
57
- "wer": 7.48,
58
- "audio_length": 126515.196,
59
- "inference_time": 23.663223169045523,
60
- "rtfx": 5346.4904,
61
- "ins": 8004,
62
- "del": 4624,
63
- "sub": 17079
64
- },
65
- "librispeech_test_clean": {
66
- "wer": 1.47,
67
- "audio_length": 19452.480625,
68
- "inference_time": 4.653575702803209,
69
- "rtfx": 4180.1148,
70
- "ins": 72,
71
- "del": 65,
72
- "sub": 640
73
- },
74
- "librispeech_test_other": {
75
- "wer": 2.84,
76
- "audio_length": 19229.570125,
77
- "inference_time": 4.6231324940454215,
78
- "rtfx": 4159.4244,
79
- "ins": 132,
80
- "del": 102,
81
- "sub": 1265
82
- },
83
- "spgispeech": {
84
- "wer": 3.38,
85
- "audio_length": 360007.4995,
86
- "inference_time": 56.082798800896846,
87
- "rtfx": 6419.2142,
88
- "ins": 17251,
89
- "del": 2741,
90
- "sub": 12728
91
- },
92
- "voicearena_monsoon_en_in": {
93
- "wer": 3.84,
94
- "audio_length": 20247.6074375,
95
- "inference_time": 4.187174894148484,
96
- "rtfx": 4835.625,
97
- "ins": 481,
98
- "del": 299,
99
- "sub": 1095
100
- },
101
- "voxpopuli_cleaned_aa": {
102
- "wer": 2.46,
103
- "audio_length": 7122.378375,
104
- "inference_time": 2.8625032720156014,
105
- "rtfx": 2488.1643,
106
- "ins": 99,
107
- "del": 147,
108
- "sub": 191
109
- }
110
- },
111
- "runs": {
112
- "ami_cleaned": {
113
- "completion_sha256": "867369d9353d5006fb9219b0cb870bd7591383d54a862a4fd843657301610b31",
114
- "manifest_sha256": "79c7419a85acda2054114234299ff7574efcf3cb0693d40e1c7bd5a6e69d416b",
115
- "run_sha256": "823d21dbdd15fa3cd20c3fd002f2ba42bef6b0a0e8ee1d31382fc54099d13246",
116
- "inputs_sha256": "e50554e60ce197c9c6d96a4efb86768d58c48e1bb50a57c05bce7780dcd3f28b",
117
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
118
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
119
- "dataset": {
120
- "dataset_path": "hf-audio/open-asr-leaderboard",
121
- "dataset": "ami_cleaned",
122
- "split": "test",
123
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
124
- "parent_dataset_revision": null
125
- },
126
- "counts": {
127
- "source_count": 7805,
128
- "eligible_count": 7715,
129
- "prediction_count": 7715
130
- },
131
- "runtime": {
132
- "gpu_name": "NVIDIA H200",
133
- "device": "cuda:0",
134
- "dtype": "torch.bfloat16",
135
- "batch_size": 128,
136
- "num_workers": 1,
137
- "packages": {
138
- "torch": "2.8.0+cu128",
139
- "nemo_toolkit": "2.7.2",
140
- "datasets": "5.0.0",
141
- "torchcodec": "0.6.0+cu128",
142
- "soundfile": "0.14.0",
143
- "numpy": "2.4.6",
144
- "huggingface_hub": "0.36.2"
145
- },
146
- "decoding": {
147
- "model_type": "tdt",
148
- "strategy": "greedy_batch",
149
- "compute_hypothesis_token_set": false,
150
- "preserve_alignments": null,
151
- "tdt_include_token_duration": null,
152
- "confidence_cfg": {
153
- "preserve_frame_confidence": false,
154
- "preserve_token_confidence": false,
155
- "preserve_word_confidence": false,
156
- "exclude_blank": true,
157
- "aggregation": "min",
158
- "tdt_include_duration": false,
159
- "method_cfg": {
160
- "name": "entropy",
161
- "entropy_type": "tsallis",
162
- "alpha": 0.33,
163
- "entropy_norm": "exp",
164
- "temperature": "DEPRECATED"
165
- }
166
- },
167
- "fused_batch_size": null,
168
- "compute_timestamps": null,
169
- "compute_langs": false,
170
- "word_seperator": " ",
171
- "segment_seperators": [
172
- ".",
173
- "!",
174
- "?"
175
- ],
176
- "segment_gap_threshold": null,
177
- "rnnt_timestamp_type": "all",
178
- "greedy": {
179
- "max_symbols_per_step": 10,
180
- "preserve_alignments": false,
181
- "preserve_frame_confidence": false,
182
- "tdt_include_token_duration": false,
183
- "tdt_include_duration_confidence": false,
184
- "confidence_method_cfg": {
185
- "name": "entropy",
186
- "entropy_type": "tsallis",
187
- "alpha": 0.33,
188
- "entropy_norm": "exp",
189
- "temperature": "DEPRECATED"
190
- },
191
- "loop_labels": true,
192
- "use_cuda_graph_decoder": true,
193
- "ngram_lm_model": null,
194
- "ngram_lm_alpha": 0.0,
195
- "boosting_tree": {
196
- "model_path": null,
197
- "key_phrases_file": null,
198
- "key_phrases_list": null,
199
- "key_phrase_items_list": null,
200
- "context_score": 1.0,
201
- "depth_scaling": 2.0,
202
- "unk_score": 0.0,
203
- "final_eos_score": 1.0,
204
- "score_per_phrase": 0.0,
205
- "source_lang": "en",
206
- "use_triton": true,
207
- "uniform_weights": false,
208
- "use_bpe_dropout": false,
209
- "num_of_transcriptions": 5,
210
- "bpe_alpha": 0.3
211
- },
212
- "boosting_tree_alpha": 0.0,
213
- "enable_per_stream_biasing": false,
214
- "max_symbols": 10
215
- },
216
- "beam": {
217
- "beam_size": 2,
218
- "search_type": "default",
219
- "score_norm": true,
220
- "return_best_hypothesis": false,
221
- "tsd_max_sym_exp_per_step": 50,
222
- "alsd_max_target_len": 2.0,
223
- "nsc_max_timesteps_expansion": 1,
224
- "nsc_prefix_alpha": 1,
225
- "maes_num_steps": 2,
226
- "maes_prefix_alpha": 1,
227
- "maes_expansion_gamma": 2.3,
228
- "maes_expansion_beta": 2,
229
- "language_model": null,
230
- "softmax_temperature": 1.0,
231
- "preserve_alignments": false,
232
- "ngram_lm_model": null,
233
- "ngram_lm_alpha": 0.0,
234
- "boosting_tree": {
235
- "model_path": null,
236
- "key_phrases_file": null,
237
- "key_phrases_list": null,
238
- "key_phrase_items_list": null,
239
- "context_score": 1.0,
240
- "depth_scaling": 2.0,
241
- "unk_score": 0.0,
242
- "final_eos_score": 1.0,
243
- "score_per_phrase": 0.0,
244
- "source_lang": "en",
245
- "use_triton": true,
246
- "uniform_weights": false,
247
- "use_bpe_dropout": false,
248
- "num_of_transcriptions": 5,
249
- "bpe_alpha": 0.3
250
- },
251
- "boosting_tree_alpha": 0.0,
252
- "hat_subtract_ilm": false,
253
- "hat_ilm_weight": 0.0,
254
- "max_symbols_per_step": 10,
255
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
256
- "pruning_mode": "LATE",
257
- "allow_cuda_graphs": true,
258
- "tsd_max_sym_exp": 50
259
- },
260
- "temperature": 1.0,
261
- "durations": [
262
- 0,
263
- 1,
264
- 2,
265
- 3,
266
- 4
267
- ],
268
- "big_blank_durations": []
269
- },
270
- "parameter_dtypes": [
271
- "torch.bfloat16"
272
- ],
273
- "parameter_devices": [
274
- "cuda:0"
275
- ],
276
- "warmup_batches": 4,
277
- "cuda_synchronized": true,
278
- "clock": "time.perf_counter",
279
- "segmentation": "unchanged source clips; no added chunking or truncation"
280
- },
281
- "timing": {
282
- "audio_seconds": 28727.5903125,
283
- "transcription_seconds": 7.678677501156926,
284
- "rtfx_unrounded": 3741.2158940353584,
285
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
286
- }
287
- },
288
- "earnings22_cleaned_aa_chunked": {
289
- "completion_sha256": "09fe168223cb28d0f57fc7d33d660e7a23769dbb2e6f00e20010fe25364c1125",
290
- "manifest_sha256": "6d5361d4b3946158906882ff454050ed31b2ec7e3458044a7a06ed4acd938229",
291
- "run_sha256": "d09c8781619a5a6d279bc5900a29e5825308298ec0e8b23c517558e969936a67",
292
- "inputs_sha256": "2ef1afa2dab81292b15a4c2e43fcded0ae925009f795e50136cbf86fafbd657e",
293
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
294
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
295
- "dataset": {
296
- "dataset_path": "ArtificialAnalysis/Earnings22-Cleaned-AA-chunked",
297
- "dataset": "",
298
- "split": "test",
299
- "dataset_revision": "27f7d0056d593231974a752ce03c1e965da69b3f",
300
- "parent_dataset_revision": "5999936ee3d8d3cde160e3c65a8cc6ff5b7c5276"
301
- },
302
- "counts": {
303
- "source_count": 341,
304
- "eligible_count": 341,
305
- "prediction_count": 341
306
- },
307
- "runtime": {
308
- "gpu_name": "NVIDIA H200",
309
- "device": "cuda:0",
310
- "dtype": "torch.bfloat16",
311
- "batch_size": 128,
312
- "num_workers": 1,
313
- "packages": {
314
- "torch": "2.8.0+cu128",
315
- "nemo_toolkit": "2.7.2",
316
- "datasets": "5.0.0",
317
- "torchcodec": "0.6.0+cu128",
318
- "soundfile": "0.14.0",
319
- "numpy": "2.4.6",
320
- "huggingface_hub": "0.36.2"
321
- },
322
- "decoding": {
323
- "model_type": "tdt",
324
- "strategy": "greedy_batch",
325
- "compute_hypothesis_token_set": false,
326
- "preserve_alignments": null,
327
- "tdt_include_token_duration": null,
328
- "confidence_cfg": {
329
- "preserve_frame_confidence": false,
330
- "preserve_token_confidence": false,
331
- "preserve_word_confidence": false,
332
- "exclude_blank": true,
333
- "aggregation": "min",
334
- "tdt_include_duration": false,
335
- "method_cfg": {
336
- "name": "entropy",
337
- "entropy_type": "tsallis",
338
- "alpha": 0.33,
339
- "entropy_norm": "exp",
340
- "temperature": "DEPRECATED"
341
- }
342
- },
343
- "fused_batch_size": null,
344
- "compute_timestamps": null,
345
- "compute_langs": false,
346
- "word_seperator": " ",
347
- "segment_seperators": [
348
- ".",
349
- "!",
350
- "?"
351
- ],
352
- "segment_gap_threshold": null,
353
- "rnnt_timestamp_type": "all",
354
- "greedy": {
355
- "max_symbols_per_step": 10,
356
- "preserve_alignments": false,
357
- "preserve_frame_confidence": false,
358
- "tdt_include_token_duration": false,
359
- "tdt_include_duration_confidence": false,
360
- "confidence_method_cfg": {
361
- "name": "entropy",
362
- "entropy_type": "tsallis",
363
- "alpha": 0.33,
364
- "entropy_norm": "exp",
365
- "temperature": "DEPRECATED"
366
- },
367
- "loop_labels": true,
368
- "use_cuda_graph_decoder": true,
369
- "ngram_lm_model": null,
370
- "ngram_lm_alpha": 0.0,
371
- "boosting_tree": {
372
- "model_path": null,
373
- "key_phrases_file": null,
374
- "key_phrases_list": null,
375
- "key_phrase_items_list": null,
376
- "context_score": 1.0,
377
- "depth_scaling": 2.0,
378
- "unk_score": 0.0,
379
- "final_eos_score": 1.0,
380
- "score_per_phrase": 0.0,
381
- "source_lang": "en",
382
- "use_triton": true,
383
- "uniform_weights": false,
384
- "use_bpe_dropout": false,
385
- "num_of_transcriptions": 5,
386
- "bpe_alpha": 0.3
387
- },
388
- "boosting_tree_alpha": 0.0,
389
- "enable_per_stream_biasing": false,
390
- "max_symbols": 10
391
- },
392
- "beam": {
393
- "beam_size": 2,
394
- "search_type": "default",
395
- "score_norm": true,
396
- "return_best_hypothesis": false,
397
- "tsd_max_sym_exp_per_step": 50,
398
- "alsd_max_target_len": 2.0,
399
- "nsc_max_timesteps_expansion": 1,
400
- "nsc_prefix_alpha": 1,
401
- "maes_num_steps": 2,
402
- "maes_prefix_alpha": 1,
403
- "maes_expansion_gamma": 2.3,
404
- "maes_expansion_beta": 2,
405
- "language_model": null,
406
- "softmax_temperature": 1.0,
407
- "preserve_alignments": false,
408
- "ngram_lm_model": null,
409
- "ngram_lm_alpha": 0.0,
410
- "boosting_tree": {
411
- "model_path": null,
412
- "key_phrases_file": null,
413
- "key_phrases_list": null,
414
- "key_phrase_items_list": null,
415
- "context_score": 1.0,
416
- "depth_scaling": 2.0,
417
- "unk_score": 0.0,
418
- "final_eos_score": 1.0,
419
- "score_per_phrase": 0.0,
420
- "source_lang": "en",
421
- "use_triton": true,
422
- "uniform_weights": false,
423
- "use_bpe_dropout": false,
424
- "num_of_transcriptions": 5,
425
- "bpe_alpha": 0.3
426
- },
427
- "boosting_tree_alpha": 0.0,
428
- "hat_subtract_ilm": false,
429
- "hat_ilm_weight": 0.0,
430
- "max_symbols_per_step": 10,
431
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
432
- "pruning_mode": "LATE",
433
- "allow_cuda_graphs": true,
434
- "tsd_max_sym_exp": 50
435
- },
436
- "temperature": 1.0,
437
- "durations": [
438
- 0,
439
- 1,
440
- 2,
441
- 3,
442
- 4
443
- ],
444
- "big_blank_durations": []
445
- },
446
- "parameter_dtypes": [
447
- "torch.bfloat16"
448
- ],
449
- "parameter_devices": [
450
- "cuda:0"
451
- ],
452
- "warmup_batches": 4,
453
- "cuda_synchronized": true,
454
- "clock": "time.perf_counter",
455
- "segmentation": "unchanged source clips; no added chunking or truncation"
456
- },
457
- "timing": {
458
- "audio_seconds": 6900.937625,
459
- "transcription_seconds": 2.3140653409063816,
460
- "rtfx_unrounded": 2982.1705995116868,
461
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
462
- }
463
- },
464
- "gigaspeech_cleaned": {
465
- "completion_sha256": "49e46bcdd03efe2eb8398417a6427ebb34babec98a17b8f30990fb676757b128",
466
- "manifest_sha256": "b2904a6c1e25d4146ec46f416f6837ee6b751d8d2f5b412bd8f0e990357f6c6c",
467
- "run_sha256": "e9ac3a765118471602ef13709383dae3ba4f316c083bc3f231cc8b37d4cbaa99",
468
- "inputs_sha256": "91a933d2a4128e506f7f7faec4c0a218b804fd3d1298d775092729e9520ff6b3",
469
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
470
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
471
- "dataset": {
472
- "dataset_path": "hf-audio/open-asr-leaderboard",
473
- "dataset": "gigaspeech_cleaned",
474
- "split": "test",
475
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
476
- "parent_dataset_revision": null
477
- },
478
- "counts": {
479
- "source_count": 18768,
480
- "eligible_count": 18757,
481
- "prediction_count": 18757
482
- },
483
- "runtime": {
484
- "gpu_name": "NVIDIA H200",
485
- "device": "cuda:0",
486
- "dtype": "torch.bfloat16",
487
- "batch_size": 128,
488
- "num_workers": 1,
489
- "packages": {
490
- "torch": "2.8.0+cu128",
491
- "nemo_toolkit": "2.7.2",
492
- "datasets": "5.0.0",
493
- "torchcodec": "0.6.0+cu128",
494
- "soundfile": "0.14.0",
495
- "numpy": "2.4.6",
496
- "huggingface_hub": "0.36.2"
497
- },
498
- "decoding": {
499
- "model_type": "tdt",
500
- "strategy": "greedy_batch",
501
- "compute_hypothesis_token_set": false,
502
- "preserve_alignments": null,
503
- "tdt_include_token_duration": null,
504
- "confidence_cfg": {
505
- "preserve_frame_confidence": false,
506
- "preserve_token_confidence": false,
507
- "preserve_word_confidence": false,
508
- "exclude_blank": true,
509
- "aggregation": "min",
510
- "tdt_include_duration": false,
511
- "method_cfg": {
512
- "name": "entropy",
513
- "entropy_type": "tsallis",
514
- "alpha": 0.33,
515
- "entropy_norm": "exp",
516
- "temperature": "DEPRECATED"
517
- }
518
- },
519
- "fused_batch_size": null,
520
- "compute_timestamps": null,
521
- "compute_langs": false,
522
- "word_seperator": " ",
523
- "segment_seperators": [
524
- ".",
525
- "!",
526
- "?"
527
- ],
528
- "segment_gap_threshold": null,
529
- "rnnt_timestamp_type": "all",
530
- "greedy": {
531
- "max_symbols_per_step": 10,
532
- "preserve_alignments": false,
533
- "preserve_frame_confidence": false,
534
- "tdt_include_token_duration": false,
535
- "tdt_include_duration_confidence": false,
536
- "confidence_method_cfg": {
537
- "name": "entropy",
538
- "entropy_type": "tsallis",
539
- "alpha": 0.33,
540
- "entropy_norm": "exp",
541
- "temperature": "DEPRECATED"
542
- },
543
- "loop_labels": true,
544
- "use_cuda_graph_decoder": true,
545
- "ngram_lm_model": null,
546
- "ngram_lm_alpha": 0.0,
547
- "boosting_tree": {
548
- "model_path": null,
549
- "key_phrases_file": null,
550
- "key_phrases_list": null,
551
- "key_phrase_items_list": null,
552
- "context_score": 1.0,
553
- "depth_scaling": 2.0,
554
- "unk_score": 0.0,
555
- "final_eos_score": 1.0,
556
- "score_per_phrase": 0.0,
557
- "source_lang": "en",
558
- "use_triton": true,
559
- "uniform_weights": false,
560
- "use_bpe_dropout": false,
561
- "num_of_transcriptions": 5,
562
- "bpe_alpha": 0.3
563
- },
564
- "boosting_tree_alpha": 0.0,
565
- "enable_per_stream_biasing": false,
566
- "max_symbols": 10
567
- },
568
- "beam": {
569
- "beam_size": 2,
570
- "search_type": "default",
571
- "score_norm": true,
572
- "return_best_hypothesis": false,
573
- "tsd_max_sym_exp_per_step": 50,
574
- "alsd_max_target_len": 2.0,
575
- "nsc_max_timesteps_expansion": 1,
576
- "nsc_prefix_alpha": 1,
577
- "maes_num_steps": 2,
578
- "maes_prefix_alpha": 1,
579
- "maes_expansion_gamma": 2.3,
580
- "maes_expansion_beta": 2,
581
- "language_model": null,
582
- "softmax_temperature": 1.0,
583
- "preserve_alignments": false,
584
- "ngram_lm_model": null,
585
- "ngram_lm_alpha": 0.0,
586
- "boosting_tree": {
587
- "model_path": null,
588
- "key_phrases_file": null,
589
- "key_phrases_list": null,
590
- "key_phrase_items_list": null,
591
- "context_score": 1.0,
592
- "depth_scaling": 2.0,
593
- "unk_score": 0.0,
594
- "final_eos_score": 1.0,
595
- "score_per_phrase": 0.0,
596
- "source_lang": "en",
597
- "use_triton": true,
598
- "uniform_weights": false,
599
- "use_bpe_dropout": false,
600
- "num_of_transcriptions": 5,
601
- "bpe_alpha": 0.3
602
- },
603
- "boosting_tree_alpha": 0.0,
604
- "hat_subtract_ilm": false,
605
- "hat_ilm_weight": 0.0,
606
- "max_symbols_per_step": 10,
607
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
608
- "pruning_mode": "LATE",
609
- "allow_cuda_graphs": true,
610
- "tsd_max_sym_exp": 50
611
- },
612
- "temperature": 1.0,
613
- "durations": [
614
- 0,
615
- 1,
616
- 2,
617
- 3,
618
- 4
619
- ],
620
- "big_blank_durations": []
621
- },
622
- "parameter_dtypes": [
623
- "torch.bfloat16"
624
- ],
625
- "parameter_devices": [
626
- "cuda:0"
627
- ],
628
- "warmup_batches": 4,
629
- "cuda_synchronized": true,
630
- "clock": "time.perf_counter",
631
- "segmentation": "unchanged source clips; no added chunking or truncation"
632
- },
633
- "timing": {
634
- "audio_seconds": 126515.196,
635
- "transcription_seconds": 23.663223169045523,
636
- "rtfx_unrounded": 5346.490420861086,
637
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
638
- }
639
- },
640
- "librispeech_test_clean": {
641
- "completion_sha256": "454e79fc47aeac5e5c3f20a0e333abb63aef21bab587d52fb881ed1b132c3ad6",
642
- "manifest_sha256": "ef41dea7fd36011ea044679c1d5f5dd419fd2660a86408db1265f72f381ba8d0",
643
- "run_sha256": "035e817cb45c3b2ff60a0501196871ec830e192b0706352376980bf5cf586952",
644
- "inputs_sha256": "d3d9dc61b5ac17c6c66f66e0da3d25c15acbbc36fb69ee4fd0cd60ee1ddd4c6b",
645
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
646
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
647
- "dataset": {
648
- "dataset_path": "hf-audio/open-asr-leaderboard",
649
- "dataset": "librispeech",
650
- "split": "test.clean",
651
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
652
- "parent_dataset_revision": null
653
- },
654
- "counts": {
655
- "source_count": 2620,
656
- "eligible_count": 2620,
657
- "prediction_count": 2620
658
- },
659
- "runtime": {
660
- "gpu_name": "NVIDIA H200",
661
- "device": "cuda:0",
662
- "dtype": "torch.bfloat16",
663
- "batch_size": 128,
664
- "num_workers": 1,
665
- "packages": {
666
- "torch": "2.8.0+cu128",
667
- "nemo_toolkit": "2.7.2",
668
- "datasets": "5.0.0",
669
- "torchcodec": "0.6.0+cu128",
670
- "soundfile": "0.14.0",
671
- "numpy": "2.4.6",
672
- "huggingface_hub": "0.36.2"
673
- },
674
- "decoding": {
675
- "model_type": "tdt",
676
- "strategy": "greedy_batch",
677
- "compute_hypothesis_token_set": false,
678
- "preserve_alignments": null,
679
- "tdt_include_token_duration": null,
680
- "confidence_cfg": {
681
- "preserve_frame_confidence": false,
682
- "preserve_token_confidence": false,
683
- "preserve_word_confidence": false,
684
- "exclude_blank": true,
685
- "aggregation": "min",
686
- "tdt_include_duration": false,
687
- "method_cfg": {
688
- "name": "entropy",
689
- "entropy_type": "tsallis",
690
- "alpha": 0.33,
691
- "entropy_norm": "exp",
692
- "temperature": "DEPRECATED"
693
- }
694
- },
695
- "fused_batch_size": null,
696
- "compute_timestamps": null,
697
- "compute_langs": false,
698
- "word_seperator": " ",
699
- "segment_seperators": [
700
- ".",
701
- "!",
702
- "?"
703
- ],
704
- "segment_gap_threshold": null,
705
- "rnnt_timestamp_type": "all",
706
- "greedy": {
707
- "max_symbols_per_step": 10,
708
- "preserve_alignments": false,
709
- "preserve_frame_confidence": false,
710
- "tdt_include_token_duration": false,
711
- "tdt_include_duration_confidence": false,
712
- "confidence_method_cfg": {
713
- "name": "entropy",
714
- "entropy_type": "tsallis",
715
- "alpha": 0.33,
716
- "entropy_norm": "exp",
717
- "temperature": "DEPRECATED"
718
- },
719
- "loop_labels": true,
720
- "use_cuda_graph_decoder": true,
721
- "ngram_lm_model": null,
722
- "ngram_lm_alpha": 0.0,
723
- "boosting_tree": {
724
- "model_path": null,
725
- "key_phrases_file": null,
726
- "key_phrases_list": null,
727
- "key_phrase_items_list": null,
728
- "context_score": 1.0,
729
- "depth_scaling": 2.0,
730
- "unk_score": 0.0,
731
- "final_eos_score": 1.0,
732
- "score_per_phrase": 0.0,
733
- "source_lang": "en",
734
- "use_triton": true,
735
- "uniform_weights": false,
736
- "use_bpe_dropout": false,
737
- "num_of_transcriptions": 5,
738
- "bpe_alpha": 0.3
739
- },
740
- "boosting_tree_alpha": 0.0,
741
- "enable_per_stream_biasing": false,
742
- "max_symbols": 10
743
- },
744
- "beam": {
745
- "beam_size": 2,
746
- "search_type": "default",
747
- "score_norm": true,
748
- "return_best_hypothesis": false,
749
- "tsd_max_sym_exp_per_step": 50,
750
- "alsd_max_target_len": 2.0,
751
- "nsc_max_timesteps_expansion": 1,
752
- "nsc_prefix_alpha": 1,
753
- "maes_num_steps": 2,
754
- "maes_prefix_alpha": 1,
755
- "maes_expansion_gamma": 2.3,
756
- "maes_expansion_beta": 2,
757
- "language_model": null,
758
- "softmax_temperature": 1.0,
759
- "preserve_alignments": false,
760
- "ngram_lm_model": null,
761
- "ngram_lm_alpha": 0.0,
762
- "boosting_tree": {
763
- "model_path": null,
764
- "key_phrases_file": null,
765
- "key_phrases_list": null,
766
- "key_phrase_items_list": null,
767
- "context_score": 1.0,
768
- "depth_scaling": 2.0,
769
- "unk_score": 0.0,
770
- "final_eos_score": 1.0,
771
- "score_per_phrase": 0.0,
772
- "source_lang": "en",
773
- "use_triton": true,
774
- "uniform_weights": false,
775
- "use_bpe_dropout": false,
776
- "num_of_transcriptions": 5,
777
- "bpe_alpha": 0.3
778
- },
779
- "boosting_tree_alpha": 0.0,
780
- "hat_subtract_ilm": false,
781
- "hat_ilm_weight": 0.0,
782
- "max_symbols_per_step": 10,
783
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
784
- "pruning_mode": "LATE",
785
- "allow_cuda_graphs": true,
786
- "tsd_max_sym_exp": 50
787
- },
788
- "temperature": 1.0,
789
- "durations": [
790
- 0,
791
- 1,
792
- 2,
793
- 3,
794
- 4
795
- ],
796
- "big_blank_durations": []
797
- },
798
- "parameter_dtypes": [
799
- "torch.bfloat16"
800
- ],
801
- "parameter_devices": [
802
- "cuda:0"
803
- ],
804
- "warmup_batches": 4,
805
- "cuda_synchronized": true,
806
- "clock": "time.perf_counter",
807
- "segmentation": "unchanged source clips; no added chunking or truncation"
808
- },
809
- "timing": {
810
- "audio_seconds": 19452.480625,
811
- "transcription_seconds": 4.653575702803209,
812
- "rtfx_unrounded": 4180.114790715076,
813
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
814
- }
815
- },
816
- "librispeech_test_other": {
817
- "completion_sha256": "b996b7eddeacb73cb4bd4574098a79cac229697b2d5f517fc8984cb4276bf484",
818
- "manifest_sha256": "0358a449ca0adbd031371a8c342189b67330d3ec66f8dbb8ca898829521c215e",
819
- "run_sha256": "4c5ecfb0c6ce492a92634607b786e9292b5c43df654d9bf13b27f91b3aa2391f",
820
- "inputs_sha256": "c695e3fea3f000b019ed0a7a5bea10a3036f0f4952927887174f0f1466337c63",
821
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
822
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
823
- "dataset": {
824
- "dataset_path": "hf-audio/open-asr-leaderboard",
825
- "dataset": "librispeech",
826
- "split": "test.other",
827
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
828
- "parent_dataset_revision": null
829
- },
830
- "counts": {
831
- "source_count": 2939,
832
- "eligible_count": 2939,
833
- "prediction_count": 2939
834
- },
835
- "runtime": {
836
- "gpu_name": "NVIDIA H200",
837
- "device": "cuda:0",
838
- "dtype": "torch.bfloat16",
839
- "batch_size": 128,
840
- "num_workers": 1,
841
- "packages": {
842
- "torch": "2.8.0+cu128",
843
- "nemo_toolkit": "2.7.2",
844
- "datasets": "5.0.0",
845
- "torchcodec": "0.6.0+cu128",
846
- "soundfile": "0.14.0",
847
- "numpy": "2.4.6",
848
- "huggingface_hub": "0.36.2"
849
- },
850
- "decoding": {
851
- "model_type": "tdt",
852
- "strategy": "greedy_batch",
853
- "compute_hypothesis_token_set": false,
854
- "preserve_alignments": null,
855
- "tdt_include_token_duration": null,
856
- "confidence_cfg": {
857
- "preserve_frame_confidence": false,
858
- "preserve_token_confidence": false,
859
- "preserve_word_confidence": false,
860
- "exclude_blank": true,
861
- "aggregation": "min",
862
- "tdt_include_duration": false,
863
- "method_cfg": {
864
- "name": "entropy",
865
- "entropy_type": "tsallis",
866
- "alpha": 0.33,
867
- "entropy_norm": "exp",
868
- "temperature": "DEPRECATED"
869
- }
870
- },
871
- "fused_batch_size": null,
872
- "compute_timestamps": null,
873
- "compute_langs": false,
874
- "word_seperator": " ",
875
- "segment_seperators": [
876
- ".",
877
- "!",
878
- "?"
879
- ],
880
- "segment_gap_threshold": null,
881
- "rnnt_timestamp_type": "all",
882
- "greedy": {
883
- "max_symbols_per_step": 10,
884
- "preserve_alignments": false,
885
- "preserve_frame_confidence": false,
886
- "tdt_include_token_duration": false,
887
- "tdt_include_duration_confidence": false,
888
- "confidence_method_cfg": {
889
- "name": "entropy",
890
- "entropy_type": "tsallis",
891
- "alpha": 0.33,
892
- "entropy_norm": "exp",
893
- "temperature": "DEPRECATED"
894
- },
895
- "loop_labels": true,
896
- "use_cuda_graph_decoder": true,
897
- "ngram_lm_model": null,
898
- "ngram_lm_alpha": 0.0,
899
- "boosting_tree": {
900
- "model_path": null,
901
- "key_phrases_file": null,
902
- "key_phrases_list": null,
903
- "key_phrase_items_list": null,
904
- "context_score": 1.0,
905
- "depth_scaling": 2.0,
906
- "unk_score": 0.0,
907
- "final_eos_score": 1.0,
908
- "score_per_phrase": 0.0,
909
- "source_lang": "en",
910
- "use_triton": true,
911
- "uniform_weights": false,
912
- "use_bpe_dropout": false,
913
- "num_of_transcriptions": 5,
914
- "bpe_alpha": 0.3
915
- },
916
- "boosting_tree_alpha": 0.0,
917
- "enable_per_stream_biasing": false,
918
- "max_symbols": 10
919
- },
920
- "beam": {
921
- "beam_size": 2,
922
- "search_type": "default",
923
- "score_norm": true,
924
- "return_best_hypothesis": false,
925
- "tsd_max_sym_exp_per_step": 50,
926
- "alsd_max_target_len": 2.0,
927
- "nsc_max_timesteps_expansion": 1,
928
- "nsc_prefix_alpha": 1,
929
- "maes_num_steps": 2,
930
- "maes_prefix_alpha": 1,
931
- "maes_expansion_gamma": 2.3,
932
- "maes_expansion_beta": 2,
933
- "language_model": null,
934
- "softmax_temperature": 1.0,
935
- "preserve_alignments": false,
936
- "ngram_lm_model": null,
937
- "ngram_lm_alpha": 0.0,
938
- "boosting_tree": {
939
- "model_path": null,
940
- "key_phrases_file": null,
941
- "key_phrases_list": null,
942
- "key_phrase_items_list": null,
943
- "context_score": 1.0,
944
- "depth_scaling": 2.0,
945
- "unk_score": 0.0,
946
- "final_eos_score": 1.0,
947
- "score_per_phrase": 0.0,
948
- "source_lang": "en",
949
- "use_triton": true,
950
- "uniform_weights": false,
951
- "use_bpe_dropout": false,
952
- "num_of_transcriptions": 5,
953
- "bpe_alpha": 0.3
954
- },
955
- "boosting_tree_alpha": 0.0,
956
- "hat_subtract_ilm": false,
957
- "hat_ilm_weight": 0.0,
958
- "max_symbols_per_step": 10,
959
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
960
- "pruning_mode": "LATE",
961
- "allow_cuda_graphs": true,
962
- "tsd_max_sym_exp": 50
963
- },
964
- "temperature": 1.0,
965
- "durations": [
966
- 0,
967
- 1,
968
- 2,
969
- 3,
970
- 4
971
- ],
972
- "big_blank_durations": []
973
- },
974
- "parameter_dtypes": [
975
- "torch.bfloat16"
976
- ],
977
- "parameter_devices": [
978
- "cuda:0"
979
- ],
980
- "warmup_batches": 4,
981
- "cuda_synchronized": true,
982
- "clock": "time.perf_counter",
983
- "segmentation": "unchanged source clips; no added chunking or truncation"
984
- },
985
- "timing": {
986
- "audio_seconds": 19229.570125,
987
- "transcription_seconds": 4.6231324940454215,
988
- "rtfx_unrounded": 4159.424405371816,
989
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
990
- }
991
- },
992
- "spgispeech": {
993
- "completion_sha256": "1e24a2e56d62cb37ea9b5d320aed0a536f83924fdaf7d6bcca7f3441f8c0f370",
994
- "manifest_sha256": "04cee652d2ec9734bbf22918f6d848a3e812465e09e3dd5e4d49f373e189f4e3",
995
- "run_sha256": "014659bc814f3b8a61e234d65fdeeb0ce0095ff23d9a267f933ec02309870963",
996
- "inputs_sha256": "7a60c54feeedfe78479c1f2782948dd902374e3fda3d7a1082e16cea20191ca2",
997
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
998
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
999
- "dataset": {
1000
- "dataset_path": "hf-audio/open-asr-leaderboard",
1001
- "dataset": "spgispeech",
1002
- "split": "test",
1003
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
1004
- "parent_dataset_revision": null
1005
- },
1006
- "counts": {
1007
- "source_count": 39341,
1008
- "eligible_count": 39341,
1009
- "prediction_count": 39341
1010
- },
1011
- "runtime": {
1012
- "gpu_name": "NVIDIA H200",
1013
- "device": "cuda:0",
1014
- "dtype": "torch.bfloat16",
1015
- "batch_size": 128,
1016
- "num_workers": 1,
1017
- "packages": {
1018
- "torch": "2.8.0+cu128",
1019
- "nemo_toolkit": "2.7.2",
1020
- "datasets": "5.0.0",
1021
- "torchcodec": "0.6.0+cu128",
1022
- "soundfile": "0.14.0",
1023
- "numpy": "2.4.6",
1024
- "huggingface_hub": "0.36.2"
1025
- },
1026
- "decoding": {
1027
- "model_type": "tdt",
1028
- "strategy": "greedy_batch",
1029
- "compute_hypothesis_token_set": false,
1030
- "preserve_alignments": null,
1031
- "tdt_include_token_duration": null,
1032
- "confidence_cfg": {
1033
- "preserve_frame_confidence": false,
1034
- "preserve_token_confidence": false,
1035
- "preserve_word_confidence": false,
1036
- "exclude_blank": true,
1037
- "aggregation": "min",
1038
- "tdt_include_duration": false,
1039
- "method_cfg": {
1040
- "name": "entropy",
1041
- "entropy_type": "tsallis",
1042
- "alpha": 0.33,
1043
- "entropy_norm": "exp",
1044
- "temperature": "DEPRECATED"
1045
- }
1046
- },
1047
- "fused_batch_size": null,
1048
- "compute_timestamps": null,
1049
- "compute_langs": false,
1050
- "word_seperator": " ",
1051
- "segment_seperators": [
1052
- ".",
1053
- "!",
1054
- "?"
1055
- ],
1056
- "segment_gap_threshold": null,
1057
- "rnnt_timestamp_type": "all",
1058
- "greedy": {
1059
- "max_symbols_per_step": 10,
1060
- "preserve_alignments": false,
1061
- "preserve_frame_confidence": false,
1062
- "tdt_include_token_duration": false,
1063
- "tdt_include_duration_confidence": false,
1064
- "confidence_method_cfg": {
1065
- "name": "entropy",
1066
- "entropy_type": "tsallis",
1067
- "alpha": 0.33,
1068
- "entropy_norm": "exp",
1069
- "temperature": "DEPRECATED"
1070
- },
1071
- "loop_labels": true,
1072
- "use_cuda_graph_decoder": true,
1073
- "ngram_lm_model": null,
1074
- "ngram_lm_alpha": 0.0,
1075
- "boosting_tree": {
1076
- "model_path": null,
1077
- "key_phrases_file": null,
1078
- "key_phrases_list": null,
1079
- "key_phrase_items_list": null,
1080
- "context_score": 1.0,
1081
- "depth_scaling": 2.0,
1082
- "unk_score": 0.0,
1083
- "final_eos_score": 1.0,
1084
- "score_per_phrase": 0.0,
1085
- "source_lang": "en",
1086
- "use_triton": true,
1087
- "uniform_weights": false,
1088
- "use_bpe_dropout": false,
1089
- "num_of_transcriptions": 5,
1090
- "bpe_alpha": 0.3
1091
- },
1092
- "boosting_tree_alpha": 0.0,
1093
- "enable_per_stream_biasing": false,
1094
- "max_symbols": 10
1095
- },
1096
- "beam": {
1097
- "beam_size": 2,
1098
- "search_type": "default",
1099
- "score_norm": true,
1100
- "return_best_hypothesis": false,
1101
- "tsd_max_sym_exp_per_step": 50,
1102
- "alsd_max_target_len": 2.0,
1103
- "nsc_max_timesteps_expansion": 1,
1104
- "nsc_prefix_alpha": 1,
1105
- "maes_num_steps": 2,
1106
- "maes_prefix_alpha": 1,
1107
- "maes_expansion_gamma": 2.3,
1108
- "maes_expansion_beta": 2,
1109
- "language_model": null,
1110
- "softmax_temperature": 1.0,
1111
- "preserve_alignments": false,
1112
- "ngram_lm_model": null,
1113
- "ngram_lm_alpha": 0.0,
1114
- "boosting_tree": {
1115
- "model_path": null,
1116
- "key_phrases_file": null,
1117
- "key_phrases_list": null,
1118
- "key_phrase_items_list": null,
1119
- "context_score": 1.0,
1120
- "depth_scaling": 2.0,
1121
- "unk_score": 0.0,
1122
- "final_eos_score": 1.0,
1123
- "score_per_phrase": 0.0,
1124
- "source_lang": "en",
1125
- "use_triton": true,
1126
- "uniform_weights": false,
1127
- "use_bpe_dropout": false,
1128
- "num_of_transcriptions": 5,
1129
- "bpe_alpha": 0.3
1130
- },
1131
- "boosting_tree_alpha": 0.0,
1132
- "hat_subtract_ilm": false,
1133
- "hat_ilm_weight": 0.0,
1134
- "max_symbols_per_step": 10,
1135
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
1136
- "pruning_mode": "LATE",
1137
- "allow_cuda_graphs": true,
1138
- "tsd_max_sym_exp": 50
1139
- },
1140
- "temperature": 1.0,
1141
- "durations": [
1142
- 0,
1143
- 1,
1144
- 2,
1145
- 3,
1146
- 4
1147
- ],
1148
- "big_blank_durations": []
1149
- },
1150
- "parameter_dtypes": [
1151
- "torch.bfloat16"
1152
- ],
1153
- "parameter_devices": [
1154
- "cuda:0"
1155
- ],
1156
- "warmup_batches": 4,
1157
- "cuda_synchronized": true,
1158
- "clock": "time.perf_counter",
1159
- "segmentation": "unchanged source clips; no added chunking or truncation"
1160
- },
1161
- "timing": {
1162
- "audio_seconds": 360007.4995,
1163
- "transcription_seconds": 56.08279880089685,
1164
- "rtfx_unrounded": 6419.214218928084,
1165
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
1166
- }
1167
- },
1168
- "voicearena_monsoon_en_in": {
1169
- "completion_sha256": "cd6b3b08c5a98e5c9c981305790c7c862a3f808575fa53c6c1129e2fb815d756",
1170
- "manifest_sha256": "c4d6afde9f6506cfa313d99b9c3019368c88c947ef05e95240fcc780c7f1b34b",
1171
- "run_sha256": "13fe7db18c2c944c0def9456fedd5b6adff6c2e5ed15c06dbcf80ba1143e7e42",
1172
- "inputs_sha256": "13845efbda33d013912cc7ffeba467c7a763fbb4ab17fb45770d26256414f512",
1173
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
1174
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
1175
- "dataset": {
1176
- "dataset_path": "VoiceArena/Monsoon_en_IN_test",
1177
- "dataset": "",
1178
- "split": "test",
1179
- "dataset_revision": "bc1da7b42ef6e2853123c97bf6d22067e4802d11",
1180
- "parent_dataset_revision": null
1181
- },
1182
- "counts": {
1183
- "source_count": 2102,
1184
- "eligible_count": 2102,
1185
- "prediction_count": 2102
1186
- },
1187
- "runtime": {
1188
- "gpu_name": "NVIDIA H200",
1189
- "device": "cuda:0",
1190
- "dtype": "torch.bfloat16",
1191
- "batch_size": 128,
1192
- "num_workers": 1,
1193
- "packages": {
1194
- "torch": "2.8.0+cu128",
1195
- "nemo_toolkit": "2.7.2",
1196
- "datasets": "5.0.0",
1197
- "torchcodec": "0.6.0+cu128",
1198
- "soundfile": "0.14.0",
1199
- "numpy": "2.4.6",
1200
- "huggingface_hub": "0.36.2"
1201
- },
1202
- "decoding": {
1203
- "model_type": "tdt",
1204
- "strategy": "greedy_batch",
1205
- "compute_hypothesis_token_set": false,
1206
- "preserve_alignments": null,
1207
- "tdt_include_token_duration": null,
1208
- "confidence_cfg": {
1209
- "preserve_frame_confidence": false,
1210
- "preserve_token_confidence": false,
1211
- "preserve_word_confidence": false,
1212
- "exclude_blank": true,
1213
- "aggregation": "min",
1214
- "tdt_include_duration": false,
1215
- "method_cfg": {
1216
- "name": "entropy",
1217
- "entropy_type": "tsallis",
1218
- "alpha": 0.33,
1219
- "entropy_norm": "exp",
1220
- "temperature": "DEPRECATED"
1221
- }
1222
- },
1223
- "fused_batch_size": null,
1224
- "compute_timestamps": null,
1225
- "compute_langs": false,
1226
- "word_seperator": " ",
1227
- "segment_seperators": [
1228
- ".",
1229
- "!",
1230
- "?"
1231
- ],
1232
- "segment_gap_threshold": null,
1233
- "rnnt_timestamp_type": "all",
1234
- "greedy": {
1235
- "max_symbols_per_step": 10,
1236
- "preserve_alignments": false,
1237
- "preserve_frame_confidence": false,
1238
- "tdt_include_token_duration": false,
1239
- "tdt_include_duration_confidence": false,
1240
- "confidence_method_cfg": {
1241
- "name": "entropy",
1242
- "entropy_type": "tsallis",
1243
- "alpha": 0.33,
1244
- "entropy_norm": "exp",
1245
- "temperature": "DEPRECATED"
1246
- },
1247
- "loop_labels": true,
1248
- "use_cuda_graph_decoder": true,
1249
- "ngram_lm_model": null,
1250
- "ngram_lm_alpha": 0.0,
1251
- "boosting_tree": {
1252
- "model_path": null,
1253
- "key_phrases_file": null,
1254
- "key_phrases_list": null,
1255
- "key_phrase_items_list": null,
1256
- "context_score": 1.0,
1257
- "depth_scaling": 2.0,
1258
- "unk_score": 0.0,
1259
- "final_eos_score": 1.0,
1260
- "score_per_phrase": 0.0,
1261
- "source_lang": "en",
1262
- "use_triton": true,
1263
- "uniform_weights": false,
1264
- "use_bpe_dropout": false,
1265
- "num_of_transcriptions": 5,
1266
- "bpe_alpha": 0.3
1267
- },
1268
- "boosting_tree_alpha": 0.0,
1269
- "enable_per_stream_biasing": false,
1270
- "max_symbols": 10
1271
- },
1272
- "beam": {
1273
- "beam_size": 2,
1274
- "search_type": "default",
1275
- "score_norm": true,
1276
- "return_best_hypothesis": false,
1277
- "tsd_max_sym_exp_per_step": 50,
1278
- "alsd_max_target_len": 2.0,
1279
- "nsc_max_timesteps_expansion": 1,
1280
- "nsc_prefix_alpha": 1,
1281
- "maes_num_steps": 2,
1282
- "maes_prefix_alpha": 1,
1283
- "maes_expansion_gamma": 2.3,
1284
- "maes_expansion_beta": 2,
1285
- "language_model": null,
1286
- "softmax_temperature": 1.0,
1287
- "preserve_alignments": false,
1288
- "ngram_lm_model": null,
1289
- "ngram_lm_alpha": 0.0,
1290
- "boosting_tree": {
1291
- "model_path": null,
1292
- "key_phrases_file": null,
1293
- "key_phrases_list": null,
1294
- "key_phrase_items_list": null,
1295
- "context_score": 1.0,
1296
- "depth_scaling": 2.0,
1297
- "unk_score": 0.0,
1298
- "final_eos_score": 1.0,
1299
- "score_per_phrase": 0.0,
1300
- "source_lang": "en",
1301
- "use_triton": true,
1302
- "uniform_weights": false,
1303
- "use_bpe_dropout": false,
1304
- "num_of_transcriptions": 5,
1305
- "bpe_alpha": 0.3
1306
- },
1307
- "boosting_tree_alpha": 0.0,
1308
- "hat_subtract_ilm": false,
1309
- "hat_ilm_weight": 0.0,
1310
- "max_symbols_per_step": 10,
1311
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
1312
- "pruning_mode": "LATE",
1313
- "allow_cuda_graphs": true,
1314
- "tsd_max_sym_exp": 50
1315
- },
1316
- "temperature": 1.0,
1317
- "durations": [
1318
- 0,
1319
- 1,
1320
- 2,
1321
- 3,
1322
- 4
1323
- ],
1324
- "big_blank_durations": []
1325
- },
1326
- "parameter_dtypes": [
1327
- "torch.bfloat16"
1328
- ],
1329
- "parameter_devices": [
1330
- "cuda:0"
1331
- ],
1332
- "warmup_batches": 4,
1333
- "cuda_synchronized": true,
1334
- "clock": "time.perf_counter",
1335
- "segmentation": "unchanged source clips; no added chunking or truncation"
1336
- },
1337
- "timing": {
1338
- "audio_seconds": 20247.6074375,
1339
- "transcription_seconds": 4.187174894148484,
1340
- "rtfx_unrounded": 4835.624961784075,
1341
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
1342
- }
1343
- },
1344
- "voxpopuli_cleaned_aa": {
1345
- "completion_sha256": "92805a8d186411aeb61b1591222be24878c95669fa80bc52335ce95f1ad960b7",
1346
- "manifest_sha256": "4ea41ceff0db011f6b5caa45825a5613489a4043f1c95c7b1e2a0b7c63009519",
1347
- "run_sha256": "2f6ab7c29a8f5912e020444aefee81beec6239f926ed4a3185bc8528a0fdea2c",
1348
- "inputs_sha256": "98255266f2e023d8bb891e76c17b67494a4c3a9a6b1bdaff848739992f9cc078",
1349
- "model_revision": "555136b50265a132d4cea0d35560c26fc4f657ab",
1350
- "model_sha256": "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56",
1351
- "dataset": {
1352
- "dataset_path": "hf-audio/open-asr-leaderboard",
1353
- "dataset": "voxpopuli_cleaned_aa",
1354
- "split": "test",
1355
- "dataset_revision": "b6bdcd0beb34f8975dc659796176d88f43aff502",
1356
- "parent_dataset_revision": null
1357
- },
1358
- "counts": {
1359
- "source_count": 628,
1360
- "eligible_count": 628,
1361
- "prediction_count": 628
1362
- },
1363
- "runtime": {
1364
- "gpu_name": "NVIDIA H200",
1365
- "device": "cuda:0",
1366
- "dtype": "torch.bfloat16",
1367
- "batch_size": 128,
1368
- "num_workers": 1,
1369
- "packages": {
1370
- "torch": "2.8.0+cu128",
1371
- "nemo_toolkit": "2.7.2",
1372
- "datasets": "5.0.0",
1373
- "torchcodec": "0.6.0+cu128",
1374
- "soundfile": "0.14.0",
1375
- "numpy": "2.4.6",
1376
- "huggingface_hub": "0.36.2"
1377
- },
1378
- "decoding": {
1379
- "model_type": "tdt",
1380
- "strategy": "greedy_batch",
1381
- "compute_hypothesis_token_set": false,
1382
- "preserve_alignments": null,
1383
- "tdt_include_token_duration": null,
1384
- "confidence_cfg": {
1385
- "preserve_frame_confidence": false,
1386
- "preserve_token_confidence": false,
1387
- "preserve_word_confidence": false,
1388
- "exclude_blank": true,
1389
- "aggregation": "min",
1390
- "tdt_include_duration": false,
1391
- "method_cfg": {
1392
- "name": "entropy",
1393
- "entropy_type": "tsallis",
1394
- "alpha": 0.33,
1395
- "entropy_norm": "exp",
1396
- "temperature": "DEPRECATED"
1397
- }
1398
- },
1399
- "fused_batch_size": null,
1400
- "compute_timestamps": null,
1401
- "compute_langs": false,
1402
- "word_seperator": " ",
1403
- "segment_seperators": [
1404
- ".",
1405
- "!",
1406
- "?"
1407
- ],
1408
- "segment_gap_threshold": null,
1409
- "rnnt_timestamp_type": "all",
1410
- "greedy": {
1411
- "max_symbols_per_step": 10,
1412
- "preserve_alignments": false,
1413
- "preserve_frame_confidence": false,
1414
- "tdt_include_token_duration": false,
1415
- "tdt_include_duration_confidence": false,
1416
- "confidence_method_cfg": {
1417
- "name": "entropy",
1418
- "entropy_type": "tsallis",
1419
- "alpha": 0.33,
1420
- "entropy_norm": "exp",
1421
- "temperature": "DEPRECATED"
1422
- },
1423
- "loop_labels": true,
1424
- "use_cuda_graph_decoder": true,
1425
- "ngram_lm_model": null,
1426
- "ngram_lm_alpha": 0.0,
1427
- "boosting_tree": {
1428
- "model_path": null,
1429
- "key_phrases_file": null,
1430
- "key_phrases_list": null,
1431
- "key_phrase_items_list": null,
1432
- "context_score": 1.0,
1433
- "depth_scaling": 2.0,
1434
- "unk_score": 0.0,
1435
- "final_eos_score": 1.0,
1436
- "score_per_phrase": 0.0,
1437
- "source_lang": "en",
1438
- "use_triton": true,
1439
- "uniform_weights": false,
1440
- "use_bpe_dropout": false,
1441
- "num_of_transcriptions": 5,
1442
- "bpe_alpha": 0.3
1443
- },
1444
- "boosting_tree_alpha": 0.0,
1445
- "enable_per_stream_biasing": false,
1446
- "max_symbols": 10
1447
- },
1448
- "beam": {
1449
- "beam_size": 2,
1450
- "search_type": "default",
1451
- "score_norm": true,
1452
- "return_best_hypothesis": false,
1453
- "tsd_max_sym_exp_per_step": 50,
1454
- "alsd_max_target_len": 2.0,
1455
- "nsc_max_timesteps_expansion": 1,
1456
- "nsc_prefix_alpha": 1,
1457
- "maes_num_steps": 2,
1458
- "maes_prefix_alpha": 1,
1459
- "maes_expansion_gamma": 2.3,
1460
- "maes_expansion_beta": 2,
1461
- "language_model": null,
1462
- "softmax_temperature": 1.0,
1463
- "preserve_alignments": false,
1464
- "ngram_lm_model": null,
1465
- "ngram_lm_alpha": 0.0,
1466
- "boosting_tree": {
1467
- "model_path": null,
1468
- "key_phrases_file": null,
1469
- "key_phrases_list": null,
1470
- "key_phrase_items_list": null,
1471
- "context_score": 1.0,
1472
- "depth_scaling": 2.0,
1473
- "unk_score": 0.0,
1474
- "final_eos_score": 1.0,
1475
- "score_per_phrase": 0.0,
1476
- "source_lang": "en",
1477
- "use_triton": true,
1478
- "uniform_weights": false,
1479
- "use_bpe_dropout": false,
1480
- "num_of_transcriptions": 5,
1481
- "bpe_alpha": 0.3
1482
- },
1483
- "boosting_tree_alpha": 0.0,
1484
- "hat_subtract_ilm": false,
1485
- "hat_ilm_weight": 0.0,
1486
- "max_symbols_per_step": 10,
1487
- "blank_lm_score_mode": "LM_WEIGHTED_FULL",
1488
- "pruning_mode": "LATE",
1489
- "allow_cuda_graphs": true,
1490
- "tsd_max_sym_exp": 50
1491
- },
1492
- "temperature": 1.0,
1493
- "durations": [
1494
- 0,
1495
- 1,
1496
- 2,
1497
- 3,
1498
- 4
1499
- ],
1500
- "big_blank_durations": []
1501
- },
1502
- "parameter_dtypes": [
1503
- "torch.bfloat16"
1504
- ],
1505
- "parameter_devices": [
1506
- "cuda:0"
1507
- ],
1508
- "warmup_batches": 4,
1509
- "cuda_synchronized": true,
1510
- "clock": "time.perf_counter",
1511
- "segmentation": "unchanged source clips; no added chunking or truncation"
1512
- },
1513
- "timing": {
1514
- "audio_seconds": 7122.378375,
1515
- "transcription_seconds": 2.8625032720156014,
1516
- "rtfx_unrounded": 2488.1642737773545,
1517
- "timing_scope": "full transcribe pass including file loading and decoding; four-batch warmup excluded; CUDA synchronized"
1518
- }
1519
- }
1520
- },
1521
- "source_url": "https://huggingface.co/oruk/orukeet/blob/main/evaluation/open_asr_20260918/public-eight-h200-results.json",
1522
- "prepared_by_sha256": "600b58ad29df47ef1bbc833b25d99c6dd4fff3ed40cbf1ad002efa467cab0b33",
1523
- "bundle_sha256": "0cb403d1553052f0396770be499558cdd2a0d88dd29e73481121b54f715af5cd",
1524
- "task_map_sha256": "27d565b719a9f98e5cfd58e185404d3c129329ebfc5b73cb3de0399ee6a34137",
1525
- "hub_yaml": {
1526
- "path": ".eval_results/open_asr_leaderboard.yaml",
1527
- "sha256": "b2aa8144405d83c39278ff022e6eb16193a0b769d11b2775b52253db815d25e7"
1528
- },
1529
- "known_exposure": "LibriSpeech test-other was used for r3 training and selection. Monsoon English informed prior training-partition selection. Remaining inherited exposure is incompletely verified."
1530
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/open_asr_20260918/public-eight-h200-results.md DELETED
@@ -1,16 +0,0 @@
1
- | Dataset | WER (%) | H200 RTFx |
2
- |:--|--:|--:|
3
- | ami_cleaned | 8.68 | 3741.22 |
4
- | earnings22_cleaned_aa_chunked | 5.74 | 2982.17 |
5
- | gigaspeech_cleaned | 7.48 | 5346.49 |
6
- | librispeech_test_clean | 1.47 | 4180.11 |
7
- | librispeech_test_other | 2.84 | 4159.42 |
8
- | spgispeech | 3.38 | 6419.21 |
9
- | voicearena_monsoon_en_in | 3.84 | 4835.62 |
10
- | voxpopuli_cleaned_aa | 2.46 | 2488.16 |
11
- | **Public-eight aggregate** | **4.49** | **5545.68** |
12
-
13
- LibriSpeech test-other was used for r3 training and selection. Monsoon English informed prior training-partition selection. Remaining inherited exposure is incompletely verified.
14
-
15
- Monsoon has no registered Hub metric task. All eight results are retained above; no task ID is invented.
16
- RTFx aggregate is total audio divided by total measured inference time, not an arithmetic mean of per-dataset RTFx.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/open_asr_20260918/training-disclosure.md DELETED
@@ -1,15 +0,0 @@
1
- # Orukeet r3: training and benchmark exposure
2
-
3
- This disclosure applies to [Orukeet](https://huggingface.co/oruk/orukeet), native NeMo artifact `orukeet-v0.1.0.nemo` at revision `555136b50265a132d4cea0d35560c26fc4f657ab`. Its SHA-256 is `031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56`.
4
-
5
- **LibriSpeech test-other was used directly for training and model selection.** The released r3 checkpoint trained on all 2,939 recordings for three passes, totaling 8,817 training presentations. The same split informed candidate selection. Its reported WER is therefore a result on exposed data, not a held-out generalization estimate. Exact source-ID and decoded-waveform matching confirmed all 2,939 records against the current evaluation partition.
6
-
7
- **The preceding FT-4035 continuation used 223,452 records across 24 complete selected partitions, totaling 371.47 hours for one pass.** The previously reported 6,118 examples were a sampled follow-up fit diagnostic; they were not the full training population. Those partitions comprised EuroSpeech Bulgarian, Greek and Italian; 17 English GigaSpeechBench domains; Golos crowd Russian; Lesbos Greek; and NST Danish and Swedish. These names describe that continuation stage, not a complete accounting of upstream Parakeet or earlier Orukeet training.
8
-
9
- **Voice Arena Monsoon English has prior evaluation and selection exposure.** All 2,102 records from the same source revision used in the current benchmark participated in the earlier evaluation that informed selection of FT-4035 training partitions. Monsoon itself was not among the 24 partitions directly trained on in that continuation. LibriSpeech test-clean was also evaluated earlier; evaluation alone is not presented as proof of direct training or of an additional selection decision.
10
-
11
- An audit of the retained FT-4035 source and training waveform fingerprints found no exact whole-waveform matches to the eight current public partitions. This limited comparison does not rule out inherited exposure, partial overlap, different segmentation or transformations of the same recording. GigaSpeechBench domain training and GigaSpeech-Cleaned evaluation are distinct source definitions; their similar names do not establish exact overlap or independence.
12
-
13
- The local eight-dataset mean includes test-other. A separately reported seven-dataset sensitivity omits that split, but still includes Monsoon selection exposure and does not certify the remaining audio as unseen. We have not selected a new subset retrospectively.
14
-
15
- We ask the leaderboard maintainers how this known exposure should be represented and whether they require a different checkpoint for inclusion. We do not assume that disclosure guarantees acceptance or that the published guidelines automatically exclude this model.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/CURRENT.md DELETED
@@ -1,30 +0,0 @@
1
- # Paired evaluation for the r3 technical report
2
-
3
- The report is bound to Orukeet NeMo SHA-256 `031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56` and stock Parakeet SHA-256 `3cbdc85877e668ca7b82d0d56770eb1fac76691f55d6b97545e8d61ca588d10d`.
4
-
5
- Two manifests are evaluated independently with `run.py`: the complete 25,705-recording LibriSpeech/FLEURS manifest, and the existing 12,006-recording accent/domain sample. Both models are decoded afresh. The domain manifest adds the generic evaluator's `language`, `pcm_sha256` and `reference_sha256` aliases while preserving every existing source field, text, waveform and record. Its source manifest remains immutable.
6
-
7
- `run.py` records an initial diagnostic score. `rescore.py` produces the manuscript scores using the pinned English/multilingual normalizers and compound-aware WER. `audit_predictions.py` independently imports the upstream normalizer definitions and scores complete partitions in batches. The report builder accepts only those audited scores.
8
-
9
- ```sh
10
- python evaluation/standard_asr/rescore.py \
11
- --private-records /path/to/private-records \
12
- --evidence evidence/standard-asr-r3-20260908
13
- python evaluation/standard_asr/audit_predictions.py \
14
- --private-records /path/to/private-records \
15
- --evidence evidence/standard-asr-r3-20260908 \
16
- --upstream-root /path/to/pinned-scoring-source
17
- ```
18
-
19
- Repeat with `evidence/domains-r3-20260908` and its corresponding records. The source revision and per-file hashes for the scorer are in `vendor/provenance.json`. All normalizer dependencies are recorded in each final `comparison.json`.
20
-
21
- Without private audio or transcripts, reproduce every reported score and build the PDF:
22
-
23
- ```sh
24
- python evaluation/standard_asr/build_current_report.py
25
- python scripts/build_neurips_report.py
26
- ```
27
-
28
- Pooled WER divides summed edit counts by summed reference-word counts. FLEURS pooling includes all 25 languages, including English; the 25-language macro gives each language equal weight. Non-English compound alignment can change the reference-word denominator separately for each model. Win counts compare full-precision per-partition WERs. The two evaluation samples are never merged into one pooled headline.
29
-
30
- Test-other was used for the final adaptation and checkpoint selection. The domain sample contains 6,118 recordings from the preceding adaptation and retains previously audited Greek/Italian EuroSpeech transcript spans. No recordings are dropped. Numeric evidence is transcript-free; full manifests and hypotheses are archived in the private model repository.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/README.md CHANGED
@@ -1,39 +1,5 @@
1
- # LibriSpeech and FLEURS comparison
2
 
3
- This evaluation compares the released Orukeet FT-4035 NeMo checkpoint with NVIDIA Parakeet TDT 0.6B v3 on both complete LibriSpeech test partitions and all 25 supported FLEURS test languages. The [score table](../../docs/standard-asr-benchmarks.md) reports WER and CER for each partition and both models.
4
 
5
- The runner uses identical mono 16 kHz audio, FP32 weights, BF16 CUDA autocast and matched greedy-batch TDT decoding. It retains every record and every empty hypothesis. Final scoring uses the pinned English and multilingual normalizers in [vendor/](vendor/). English normalization standardizes spelling, names and numbers. Multilingual normalization retains diacritics, expands digits by language and aligns compound boundaries; WER uses compound-aware edit distance. CER uses normalized strings before boundary alignment, including spaces. Corpus rates pool integer edit counts; language macros weight their specified languages equally.
6
-
7
- Place the original LibriSpeech `test-clean` audio and `.trans.txt` files under `data/goal_v2_sources/libri/LibriSpeech/test-clean`, `test-other` under `data/librispeech/LibriSpeech/test-other`, and original FLEURS test FLAC files under `data/fleurs/<language>/test`, relative to `AUDIO_ROOT`. Use the recorded NeMo environment from the preceding source-model comparison. FLEURS references are fetched from the immutable dataset revision recorded in `prepare.py`; the scripts record reference-file and decoded-audio hashes.
8
-
9
- ```sh
10
- python evaluation/standard_asr/prepare.py --audio-root "$AUDIO_ROOT" --output /tmp/orukeet-standard/prepared
11
- python evaluation/standard_asr/run.py \
12
- --manifest /tmp/orukeet-standard/prepared/manifest.jsonl \
13
- --parakeet /path/to/parakeet-tdt-0.6b-v3.nemo \
14
- --orukeet /path/to/orukeet-v0.1.0rc1.nemo \
15
- --metric-code evaluation/unseen \
16
- --output /tmp/orukeet-standard/evaluation
17
- ```
18
-
19
- The runner verifies both checkpoint hashes before inference. Resume accepts only predictions with matching checkpoint, manifest, runner and normalizer hashes. A decoded-audio hash check precedes inference. Out-of-memory recovery recursively reduces the batch size; it does not omit or shorten recordings.
20
-
21
- The inference runner also emits diagnostic counts under the preceding evaluation's normalizer. Preserve these as `inference-comparison.json` and `inference-numeric-evidence.jsonl.gz` in the evidence directory. Place the unchanged `manifest.jsonl`, `parakeet.jsonl` and `orukeet.jsonl` in a private records directory, then generate the final scores:
22
-
23
- ```sh
24
- python -m pip install -r evaluation/standard_asr/requirements-score.txt
25
- python evaluation/standard_asr/rescore.py --private-records /path/to/private-records --evidence /path/to/evidence
26
- python evaluation/standard_asr/audit_predictions.py --private-records /path/to/private-records --evidence /path/to/evidence
27
- ```
28
-
29
- The scoring implementation is pinned to [source revision 48219c6](https://github.com/huggingface/open_asr_leaderboard/tree/48219c6028db0517d704600d92f31edfc96e8c23/normalizer). [Provenance](vendor/provenance.json) records source and vendored hashes, exact extracted definitions and the Apache-2.0 license. Compound alignment can change the reference word count separately for each model; all resulting denominators are retained. Scoring changes never alter predictions or checkpoint identities. For the release audit, pass `--upstream-root /path/to/pinned-source` to `audit_predictions.py`; it independently loads the original normalization definitions and verifies all 54 model/partition WERs with full-partition batch scoring.
30
-
31
- `comparison.json` holds full-precision corpus results and checkpoint identities. `numeric-evidence.jsonl.gz` contains transcript-free per-record edit counts. `preparation.json` records the complete test membership and source revisions. To reproduce the release tables from the included counts:
32
-
33
- ```sh
34
- python evaluation/standard_asr/build_materials.py
35
- python scripts/build_neurips_report.py
36
- python evaluation/standard_asr/build_materials.py --verify-pdf
37
- ```
38
-
39
- Corpus sources: [LibriSpeech](https://www.openslr.org/12) and [FLEURS](https://arxiv.org/abs/2205.12446). Dataset audio and reference transcripts are obtained from the original providers; the release evidence contains counts and hashes.
 
1
+ # LibriSpeech and FLEURS evaluation
2
 
3
+ The complete source-model evaluation and reproduction code is maintained in the [Orukeet source repository](https://github.com/Oruk-AI/orukeet/tree/main/evaluation/standard_asr).
4
 
5
+ The [released-checkpoint score tables](../../docs/current-checkpoint-benchmarks.md), [methods](../../docs/technical-report.md), and recorded evaluation evidence remain available in this model repository.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/audit_predictions.py DELETED
@@ -1,104 +0,0 @@
1
- """Re-score the private hypotheses and compare every record with release counts."""
2
- import argparse
3
- import gzip
4
- import hashlib
5
- import json
6
- from pathlib import Path
7
- import sys
8
- import ast
9
- from collections import defaultdict
10
- from difflib import SequenceMatcher
11
- import importlib.util
12
- import re
13
- import num2words
14
- from kaldialign import batch_error_rate
15
-
16
- ROOT = Path(__file__).resolve().parents[2]
17
- from scoring import counts
18
-
19
-
20
- def sha(path):
21
- return hashlib.sha256(path.read_bytes()).hexdigest()
22
-
23
-
24
- def main():
25
- p=argparse.ArgumentParser()
26
- p.add_argument('--private-records',type=Path,required=True)
27
- p.add_argument('--evidence',type=Path,default=ROOT/'evidence/standard-asr-20260908')
28
- p.add_argument('--upstream-root',type=Path)
29
- a=p.parse_args()
30
- result=json.loads((a.evidence/'comparison.json').read_text())
31
- manifest=a.private_records/'manifest.jsonl'
32
- assert sha(manifest)==result['manifest_sha256']
33
- rows=[json.loads(line) for line in manifest.open()]
34
- numeric={}
35
- with gzip.open(a.evidence/'numeric-evidence.jsonl.gz','rt') as stream:
36
- for line in stream:
37
- row=json.loads(line)
38
- assert row['record_sha256'] not in numeric
39
- numeric[row['record_sha256']]=row
40
- assert len(numeric)==len(rows)==result['rows']
41
- empty={}
42
- paired=defaultdict(lambda: [[], []])
43
- for model in ['parakeet','orukeet']:
44
- path=a.private_records/(model+'.jsonl')
45
- assert sha(path)==result['prediction_sha256'][model]
46
- records=[json.loads(line) for line in path.open()]
47
- predictions={r['uid']:r for r in records}
48
- assert len(predictions)==len(records)==len(rows)
49
- empty[model]=0
50
- for row in rows:
51
- prediction=predictions[row['uid']]
52
- assert prediction['model_sha256']==result['models'][model]
53
- assert prediction['manifest_sha256']==result['manifest_sha256']
54
- values=counts(row['text'],prediction['prediction'],row['language'])
55
- expected=numeric[hashlib.sha256(row['uid'].encode()).hexdigest()]
56
- assert expected['split']==row['split']
57
- for metric in ['errors','words','char_errors','chars','utterance_error']:
58
- assert values[metric]==expected['counts'][model][metric],(row['uid'],model,metric)
59
- empty[model]+=not bool(prediction['prediction'].strip())
60
- paired[(row['split'], model)][0].append(row['text'])
61
- paired[(row['split'], model)][1].append(prediction['prediction'])
62
- audit=dict(status='passed',publication_authorized=False,records=len(rows),paired_predictions=2*len(rows),
63
- models=result['models'],empty_hypotheses=empty,
64
- checks=['Every private hypothesis re-scored locally','All reference and prediction hashes match',
65
- 'Every WER/CER numerator and denominator matches released counts'],
66
- inputs_sha256={name:sha(a.evidence/name) for name in ['comparison.json','numeric-evidence.jsonl.gz']},
67
- manifest_sha256=result['manifest_sha256'],prediction_sha256=result['prediction_sha256'],
68
- script_sha256=sha(Path(__file__)))
69
- if a.upstream_root:
70
- provenance=json.loads((ROOT/'evaluation/standard_asr/vendor/provenance.json').read_text())
71
- for name,digest in provenance['upstream_sha256'].items():
72
- assert sha(a.upstream_root/name)==digest,name
73
- # Load upstream normalizers independently of the release's vendored package.
74
- init=a.upstream_root/'normalizer/__init__.py'
75
- spec=importlib.util.spec_from_file_location('upstream_text',init,
76
- submodule_search_locations=[str(init.parent)])
77
- module=importlib.util.module_from_spec(spec);sys.modules[spec.name]=module
78
- spec.loader.exec_module(module)
79
- namespace=dict(BasicMultilingualTextNormalizer=module.BasicMultilingualTextNormalizer,
80
- re=re,num2words=num2words,FILLER_WORDS={},SequenceMatcher=SequenceMatcher)
81
- for filename,name in [('data_utils.py','MultilingualNormalizer'),
82
- ('eval_utils.py','normalize_compound_pairs')]:
83
- tree=ast.parse((init.parent/filename).read_text())
84
- definition=next(n for n in tree.body if isinstance(n,(ast.ClassDef,ast.FunctionDef)) and n.name==name)
85
- exec(compile(ast.Module(body=[definition],type_ignores=[]),filename,'exec'),namespace)
86
- english=module.EnglishTextNormalizer()
87
- multilingual=namespace['MultilingualNormalizer'](remove_diacritics=False)
88
- for (split,model),(refs,hyps) in paired.items():
89
- lang=result['sets'][split]['language']
90
- normalize=english if lang=='en' else lambda text:multilingual(text,lang=lang)
91
- refs,hyps=list(map(normalize,refs)),list(map(normalize,hyps))
92
- if lang!='en':refs,hyps=namespace['normalize_compound_pairs'](refs,hyps)
93
- batch=batch_error_rate([tuple(r.split()) for r in refs],[tuple(h.split()) for h in hyps],merge_compounds=True)
94
- target=result['sets'][split]['models'][model]
95
- assert batch['total']==target['errors'] and batch['ref_len']==target['words']
96
- assert abs(100*batch['err_rate']-target['wer'])<1e-12
97
- audit['upstream_scoring_verified']=dict(revision=provenance['revision'],model_partition_pairs=len(paired),
98
- check=f'Unmodified upstream normalizer definitions and full-partition batch scoring reproduce all {len(paired)} paired WERs.')
99
- audit['checks'].append(f'All {len(paired)} model/partition WERs match independent upstream batch scoring')
100
- (a.evidence/'hypotheses-audit.json').write_text(json.dumps(audit,indent=2)+'\n')
101
- print(json.dumps(audit))
102
-
103
-
104
- if __name__=='__main__':main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/build_current_report.py DELETED
@@ -1,179 +0,0 @@
1
- """Bind the short report to one checkpoint and reproduce every aggregate from counts."""
2
- from collections import Counter, defaultdict
3
- import csv
4
- import gzip
5
- import hashlib
6
- import json
7
- from pathlib import Path
8
- import subprocess
9
- import sys
10
- import unicodedata
11
-
12
- ROOT = Path(__file__).resolve().parents[2]
13
- LANGUAGES = dict(bg='Bulgarian', cs='Czech', da='Danish', de='German', el='Greek', en='English',
14
- es='Spanish', et='Estonian', fi='Finnish', fr='French', hr='Croatian', hu='Hungarian',
15
- it='Italian', lt='Lithuanian', lv='Latvian', mt='Maltese', nl='Dutch', pl='Polish',
16
- pt='Portuguese', ro='Romanian', ru='Russian', sk='Slovak', sl='Slovenian', sv='Swedish', uk='Ukrainian')
17
- MODEL = '031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56'
18
- BASE = '3cbdc85877e668ca7b82d0d56770eb1fac76691f55d6b97545e8d61ca588d10d'
19
- MODELS = ['parakeet', 'orukeet']
20
- COUNTS = ['errors','words','substitutions','deletions','insertions','chars','char_errors','utterance_error']
21
-
22
- def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest()
23
- def read(path): return json.loads(path.read_text())
24
- def write(path, value): path.write_text(json.dumps(value,indent=2,ensure_ascii=False)+'\n')
25
-
26
- def validate(folder, nrows, nsets):
27
- d=ROOT/'evidence'/folder; result=read(d/'comparison.json');audit=read(d/'hypotheses-audit.json')
28
- assert result['status']=='complete' and result['rows']==nrows and len(result['sets'])==nsets
29
- assert result['models']==dict(parakeet=BASE,orukeet=MODEL)
30
- assert result['timings']['parakeet']['rows']==result['timings']['orukeet']['rows']==nrows
31
- assert audit['status']=='passed' and audit['models']==result['models']
32
- assert audit['upstream_scoring_verified']['model_partition_pairs']==2*nsets
33
- assert result['numeric_evidence_sha256']==sha(d/'numeric-evidence.jsonl.gz')
34
- for name,digest in result['scoring']['code_sha256'].items(): assert sha(ROOT/name)==digest,name
35
- for name,digest in audit['inputs_sha256'].items(): assert sha(d/name)==digest,name
36
- seen=set();counts=defaultdict(Counter);sizes=Counter()
37
- with gzip.open(d/'numeric-evidence.jsonl.gz','rt') as f:
38
- for line in f:
39
- row=json.loads(line);uid=row['record_sha256'];assert uid not in seen;seen.add(uid)
40
- sizes[row['split']]+=1
41
- for model in MODELS:
42
- c=row['counts'][model];assert c['errors']==c['substitutions']+c['deletions']+c['insertions']
43
- counts[(row['split'],model)].update({k:c[k] for k in COUNTS})
44
- assert len(seen)==nrows
45
- for split,spec in result['sets'].items():
46
- assert sizes[split]==spec['rows']
47
- for model in MODELS:
48
- c=counts[(split,model)];reported=spec['models'][model]
49
- assert all(reported[k]==v for k,v in c.items())
50
- for metric,num,den in [('wer','errors','words'),('cer','char_errors','chars')]:
51
- assert abs(reported[metric]-100*c[num]/c[den])<1e-12
52
- return result
53
-
54
- def pool(result, splits):
55
- members=[result['sets'][s] for s in splits];models={}
56
- for model in MODELS:
57
- c=Counter()
58
- for spec in members: c.update({k:spec['models'][model][k] for k in COUNTS})
59
- models[model]=dict(c,wer=100*c['errors']/c['words'],cer=100*c['char_errors']/c['chars'])
60
- wins=sum(s['models']['orukeet']['wer']<s['models']['parakeet']['wer'] for s in members)
61
- ties=sum(s['models']['orukeet']['wer']==s['models']['parakeet']['wer'] for s in members)
62
- return dict(splits=list(splits),rows=sum(s['rows'] for s in members),models=models,wins=wins,ties=ties,
63
- losses=len(members)-wins-ties,relative_wer_reduction_percent=100*(1-models['orukeet']['wer']/models['parakeet']['wer']))
64
-
65
- def label(split):
66
- if split.startswith('librispeech_'):return 'LibriSpeech '+split.removeprefix('librispeech_').replace('_','-')
67
- if split.startswith('fleurs_'):return 'FLEURS '+LANGUAGES[split.rsplit('_',1)[1]]
68
- gsb=dict(agr='agriculture',ait='AI',art='arts',bio='biology',chn='Chinese accent',ecm='economics',
69
- eng='engineering',ent='entertainment',fin='finance',hum='humanities',ind='Indian accent',jpn='Japanese accent',law='law',
70
- med='medicine',mil='military',phl='Filipino accent',sct='Scottish accent',sgp='Singaporean accent')
71
- if split.startswith('gigaspeechbench_'):return 'GSB '+gsb[split.split('_')[1]]
72
- if split.startswith('eurospeech_'):return 'EuroSpeech '+split.rsplit('_',1)[1].upper()
73
- if split.startswith('voxpopuli_'):return 'VoxPopuli '+split.rsplit('_',1)[1].upper()
74
- return dict(golos_crowd_ru='Golos crowd RU',golos_farfield_ru='Golos far-field RU',
75
- nst_da_da='NST Danish',nst_sv_sv='NST Swedish',monsoon_en_in='Monsoon India',lesbos_el='Lesbos Greek')[split]
76
-
77
- def wer_tex(spec,model):
78
- value=f"{spec['models'][model]['wer']:.2f}"
79
- other=MODELS[1-MODELS.index(model)]
80
- if spec['models'][model]['wer']<spec['models'][other]['wer']:value=r'\textbf{'+value+'}'
81
- return value
82
-
83
- def main():
84
- standard=validate('standard-asr-r3-20260908',25705,27)
85
- domains=validate('domains-r3-20260908',12006,47)
86
- expected={'librispeech_test_clean','librispeech_test_other'}|{'fleurs_'+l for l in LANGUAGES}
87
- assert set(standard['sets'])==expected
88
- assert all(s['rows']==(230 if name=='lesbos_el' else 256) for name,s in domains['sets'].items())
89
- freeze=read(ROOT/'evidence/librispeech-ft-20260908/r3/export-audit.json')
90
- assert freeze['status']=='pass' and freeze['candidate_sha256']==MODEL
91
- assert freeze['frozen_gabor_rows_exact']==12288 and freeze['gabor_values_match_parent_and_original_functions']
92
- summaries={'fleurs':pool(standard,sorted(s for s in expected if s.startswith('fleurs_'))),
93
- 'standard':pool(standard,sorted(expected)),
94
- 'domains':pool(domains,sorted(domains['sets'])),
95
- 'domain_english':pool(domains,sorted(s for s,v in domains['sets'].items() if v['language']=='en'))}
96
- assert summaries['fleurs']['rows']==20146 and summaries['domain_english']['rows']==5120
97
- macros={}
98
- for prefix,source,split in [('LibriClean',standard,'librispeech_test_clean'),('LibriOther',standard,'librispeech_test_other'),('FleursEnglish',standard,'fleurs_en')]:
99
- for model in MODELS:macros[prefix+model.title()+'WER']=f"{source['sets'][split]['models'][model]['wer']:.2f}"
100
- for prefix,key in [('FleursPooled','fleurs'),('DomainPooled','domains'),('DomainEnglish','domain_english')]:
101
- for model in MODELS:macros[prefix+model.title()+'WER']=f"{summaries[key]['models'][model]['wer']:.2f}"
102
- for model in MODELS:
103
- macros['FleursMacro'+model.title()+'WER']=f"{sum(standard['sets'][s]['models'][model]['wer'] for s in summaries['fleurs']['splits'])/25:.2f}"
104
- for name,key in [('FleursWins','fleurs'),('StandardWins','standard'),('DomainWins','domains'),('DomainEnglishWins','domain_english')]:macros[name]=str(summaries[key]['wins'])
105
- assert set(standard['sets']).isdisjoint(domains['sets'])
106
- macros['TestedWins']=str(summaries['standard']['wins']+summaries['domains']['wins'])
107
- macros['TestedSplits']=str(len(standard['sets'])+len(domains['sets']))
108
- macros['FleursPooledReduction']=f"{summaries['fleurs']['relative_wer_reduction_percent']:.1f}"
109
- (ROOT/'report/current-benchmark-values.tex').write_text('% Generated from audited r3 edit counts.\n'+''.join('\\newcommand{\\'+k+'}{'+v+'}\n' for k,v in macros.items()))
110
- order=['librispeech_test_clean','librispeech_test_other']+sorted((s for s in expected if s.startswith('fleurs_')),key=label)
111
- table=[r'\begin{table}[!ht]',r'\centering',r'\caption{Complete LibriSpeech and FLEURS test partitions. WER and CER are percentages; bold identifies lower WER. The pooled FLEURS row sums errors and reference words over all 25 languages, including English. The macro row weights languages equally.}',r'\label{tab:current-standard}',r'\small',r'\setlength{\tabcolsep}{5pt}',r'\renewcommand{\arraystretch}{1.02}',r'\begin{tabular}{lrrrrr}',r'\toprule',r'Benchmark & Clips & \multicolumn{2}{c}{Parakeet} & \multicolumn{2}{c}{Orukeet}\\',r' & & WER & CER & WER & CER\\',r'\midrule']
112
- table_rows=[]
113
- for split in order:
114
- spec=standard['sets'][split];table_rows.append((label(split),spec))
115
- table_rows.append(('FLEURS pooled',summaries['fleurs']))
116
- macro=dict(rows=20146,models={m:{metric:sum(standard['sets'][s]['models'][m][metric] for s in summaries['fleurs']['splits'])/25 for metric in ['wer','cer']} for m in MODELS})
117
- table_rows.append(('FLEURS language macro',macro))
118
- for name,spec in table_rows:
119
- if name=='FLEURS pooled':table.append(r'\midrule')
120
- values=[wer_tex(spec,m)+' & '+f"{spec['models'][m]['cer']:.2f}" for m in MODELS]
121
- table.append(name+' & '+f"{spec['rows']:,}"+' & '+' & '.join(values)+r'\\')
122
- if name=='LibriSpeech test-other':table.append(r'\midrule')
123
- table += [r'\bottomrule',r'\end{tabular}',r'\end{table}']
124
- (ROOT/'report/current-standard-table.tex').write_text('\n'.join(table)+'\n')
125
- domain_order=sorted(domains['sets'],key=label)
126
- table=[r'\begin{table}[!p]',r'\centering',r'\caption{WER (\%) on the fixed accent and domain sample. Each partition contains 256 recordings, except Lesbos (230). GSB denotes GigaSpeechBench; two-letter suffixes identify languages. Bold identifies lower WER. Both models use the same decoding and scoring protocol as Table~\ref{tab:current-standard}.}',r'\label{tab:current-domains}',r'\small']
127
- for idx,subset in enumerate([domain_order[:24],domain_order[24:]]):
128
- table += [r'\begin{minipage}[t]{0.49\linewidth}',r'\vspace{0pt}',r'\centering',r'\setlength{\tabcolsep}{3pt}',r'\renewcommand{\arraystretch}{1.10}',r'\begin{tabular}{lrr}',r'\toprule',r'Partition & Parakeet & Orukeet\\',r'\midrule']
129
- for split in subset:
130
- spec=domains['sets'][split]
131
- table.append(label(split)+' & '+' & '.join(wer_tex(spec,m) for m in MODELS)+r'\\')
132
- table += [r'\bottomrule',r'\end{tabular}',r'\end{minipage}'+(r'\hfill%' if idx==0 else '')]
133
- table += [r'\par\vspace{12pt}',r'\begin{tabular}{lrrr}',r'\toprule',r'Pooled comparison & Clips & Parakeet & Orukeet\\',r'\midrule']
134
- for name,key in [('All 47 partitions','domains'),('All 20 English partitions','domain_english')]:
135
- spec=summaries[key];table.append(name+' & '+f"{spec['rows']:,}"+' & '+' & '.join(wer_tex(spec,m) for m in MODELS)+r'\\')
136
- table += [r'\bottomrule',r'\end{tabular}',r'\end{table}']
137
- (ROOT/'report/current-domains-table.tex').write_text('\n'.join(table)+'\n')
138
- md=['# Orukeet r3: paired recognition scores','',f'All Orukeet scores refer to NeMo SHA-256 `{MODEL}`. Parakeet is `{BASE}`. Both systems were decoded afresh on identical audio with FP32 weights, BF16 autocast and greedy-batch TDT. Lower WER is better.','',
139
- 'Pooled WER is 100 times total substitutions, deletions and insertions divided by total normalized reference words. FLEURS pooling includes all 25 supported languages, including English. It is not an average of language WERs. Compound-boundary alignment can give each model a different reference-word denominator. CER uses normalized strings before compound alignment.','',
140
- 'LibriSpeech test-other was used for final adaptation and checkpoint selection. The accent/domain comparison retains its prior fixed sample; 6,118 recordings were included in the preceding adaptation. Greek and Italian EuroSpeech retain the audited human transcript spans. No records are dropped from either comparison.','']
141
- for title,source,order,folder in [('Complete read-speech partitions',standard,order,'standard-asr-r3-20260908'),('Accent and domain sample',domains,domain_order,'domains-r3-20260908')]:
142
- md += ['## '+title,'','| Partition | Clips | Parakeet WER / CER | Orukeet WER / CER |','|:--|--:|--:|--:|']
143
- with (ROOT/'evidence'/folder/'scores.csv').open('w',newline='') as f:
144
- writer=csv.writer(f);writer.writerow(['split','clips','hours']+[m+'_'+k for m in MODELS for k in ['wer','cer','errors','words']])
145
- for s in order:
146
- spec=source['sets'][s];md.append('| '+label(s)+' | '+str(spec['rows'])+' | '+' | '.join(f"{spec['models'][m]['wer']:.2f} / {spec['models'][m]['cer']:.2f}" for m in MODELS)+' |')
147
- writer.writerow([s,spec['rows'],spec['hours']]+[spec['models'][m][k] for m in MODELS for k in ['wer','cer','errors','words']])
148
- md += ['',f'[Full precision](../evidence/{folder}/scores.csv) · [Counts](../evidence/{folder}/numeric-evidence.jsonl.gz) · [Independent scoring audit](../evidence/{folder}/hypotheses-audit.json)','']
149
- md += ['## Pooled comparisons','','| Comparison | Clips | Parakeet errors / words | WER | Orukeet errors / words | WER | Wins / partitions |','|:--|--:|--:|--:|--:|--:|--:|']
150
- for name,key in [('FLEURS, 25 languages','fleurs'),('Accents/domains, 25 languages','domains'),('Accents/domains, English','domain_english')]:
151
- spec=summaries[key];md.append('| '+name+' | '+str(spec['rows'])+' | '+' | '.join(f"{spec['models'][m]['errors']:,} / {spec['models'][m]['words']:,} | {spec['models'][m]['wer']:.2f}" for m in MODELS)+f" | {spec['wins']} / {len(spec['splits'])} |")
152
- (ROOT/'docs/current-checkpoint-benchmarks.md').write_text('\n'.join(md)+'\n')
153
- receipt=dict(status='passed',publication_authorized=False,models=standard['models'],summaries=summaries,
154
- checks=['Fresh matched decoding of both checkpoints','All 74 paired split results recomputed from per-record counts','Pooled WER recomputed from summed errors and reference words','Independent upstream scoring matches all 148 model/partition pairs'],
155
- inputs_sha256={str(p.relative_to(ROOT)):sha(p) for folder in ['standard-asr-r3-20260908','domains-r3-20260908'] for p in [ROOT/'evidence'/folder/f for f in ['comparison.json','hypotheses-audit.json','numeric-evidence.jsonl.gz']]})
156
- if '--verify-pdf' in sys.argv:
157
- text=unicodedata.normalize('NFKC',subprocess.check_output(['pdftotext','-layout',str(ROOT/'output/pdf/orukeet-technical-report.pdf'),'-'],text=True))
158
- lines=[' '.join(l.split()) for l in text.splitlines()]
159
- for name,spec in table_rows:
160
- target=' '.join([name,f"{spec['rows']:,}"]+[f"{spec['models'][m][metric]:.2f}" for m in MODELS for metric in ['wer','cer']])
161
- assert target in lines,target
162
- for s in domain_order:
163
- spec=domains['sets'][s];target=' '.join([label(s)]+[f"{spec['models'][m]['wer']:.2f}" for m in MODELS])
164
- assert any(target in line for line in lines),target
165
- abstract=text.split('Abstract',1)[1].split('A fixed structure',1)[0]
166
- assert all(macros[k] in abstract for k in ['FleursPooledParakeetWER','FleursPooledOrukeetWER','LibriCleanParakeetWER','LibriCleanOrukeetWER','LibriOtherParakeetWER','LibriOtherOrukeetWER','FleursEnglishParakeetWER','FleursEnglishOrukeetWER'])
167
- assert 'leaderboard' not in text.lower() and 'gabormer' not in text.lower()
168
- # Ignore line-break hyphenation when checking the rendered claim and setup.
169
- compact_abstract=''.join(abstract.split()).replace('-','')
170
- assert '031c8ddab484' in text
171
- for phrase in ['Final adaptation and checkpoint selection use LibriSpeech test-other.',
172
- f"Orukeet outperforms Parakeet on {macros['TestedWins']} out of {macros['TestedSplits']} tested splits"]:
173
- assert ''.join(phrase.split()).replace('-','') in compact_abstract,phrase
174
- receipt['checks'].append('Rendered abstract and all 74 benchmark rows match the current checkpoint evidence')
175
- receipt['pdf_sha256']=sha(ROOT/'output/pdf/orukeet-technical-report.pdf')
176
- write(ROOT/'report/current-benchmark-validation.json',receipt)
177
- print(json.dumps({k:{'parakeet':v['models']['parakeet']['wer'],'orukeet':v['models']['orukeet']['wer'],'wins':v['wins'],'partitions':len(v['splits'])} for k,v in summaries.items()}))
178
-
179
- if __name__=='__main__':main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/build_materials.py DELETED
@@ -1,149 +0,0 @@
1
- """Reproduce complete-test scores from edit counts and generate report tables."""
2
- from collections import Counter, defaultdict
3
- import csv
4
- import gzip
5
- import hashlib
6
- import json
7
- import math
8
- from pathlib import Path
9
- import subprocess
10
- import sys
11
-
12
- ROOT = Path(__file__).resolve().parents[2]
13
- OUT = ROOT / 'evidence/standard-asr-20260908'
14
- LANGUAGES = dict(bg='Bulgarian', cs='Czech', da='Danish', de='German', el='Greek', en='English',
15
- es='Spanish', et='Estonian', fi='Finnish', fr='French', hr='Croatian', hu='Hungarian',
16
- it='Italian', lt='Lithuanian', lv='Latvian', mt='Maltese', nl='Dutch', pl='Polish',
17
- pt='Portuguese', ro='Romanian', ru='Russian', sk='Slovak', sl='Slovenian',
18
- sv='Swedish', uk='Ukrainian')
19
-
20
-
21
- def sha(path):
22
- return hashlib.sha256(path.read_bytes()).hexdigest()
23
-
24
-
25
- def main():
26
- source = json.loads((OUT/'comparison.json').read_text())
27
- prep = json.loads((OUT/'preparation.json').read_text())
28
- assert source['status'] == 'complete' and prep['status'] == 'prepared'
29
- canonical = json.loads((ROOT/'release/model-stages.json').read_text())['canonical']['source_sha256']
30
- assert source['models']['orukeet'] == canonical
31
- assert source['models']['parakeet'] == '3cbdc85877e668ca7b82d0d56770eb1fac76691f55d6b97545e8d61ca588d10d'
32
- assert source['manifest_sha256'] == prep['manifest_sha256']
33
- assert source['script_sha256'] == sha(ROOT/'evaluation/standard_asr/run.py')
34
- assert prep['script_sha256'] == sha(ROOT/'evaluation/standard_asr/prepare.py')
35
- assert source['normalizer_sha256'] == sha(ROOT/'evaluation/unseen/metrics.py')
36
- assert source['numeric_evidence_sha256'] == sha(OUT/'numeric-evidence.jsonl.gz')
37
- for name, digest in source['scoring']['code_sha256'].items():
38
- assert sha(ROOT/name) == digest, name
39
- audit = json.loads((OUT/'hypotheses-audit.json').read_text())
40
- assert audit['status'] == 'passed' and audit['models'] == source['models']
41
- assert audit['upstream_scoring_verified']['model_partition_pairs'] == 54
42
- assert audit['script_sha256'] == sha(ROOT/'evaluation/standard_asr/audit_predictions.py')
43
- for name, digest in audit['inputs_sha256'].items():
44
- assert sha(OUT/name) == digest, name
45
- expected = {f'fleurs_{lang}' for lang in LANGUAGES} | {'librispeech_test_clean','librispeech_test_other'}
46
- assert set(source['sets']) == set(prep['sources']) == expected
47
- totals, sizes, durations, seen = defaultdict(Counter), Counter(), Counter(), set()
48
- with gzip.open(OUT/'numeric-evidence.jsonl.gz', 'rt') as stream:
49
- for line in stream:
50
- row = json.loads(line)
51
- assert row['record_sha256'] not in seen
52
- seen.add(row['record_sha256'])
53
- sizes[row['split']] += 1
54
- durations[row['split']] += row['duration']
55
- for model in ['parakeet','orukeet']:
56
- c = row['counts'][model]
57
- assert c['errors'] == c['substitutions'] + c['deletions'] + c['insertions']
58
- totals[(row['split'], model)].update(c)
59
- assert row['counts']['parakeet']['chars'] == row['counts']['orukeet']['chars']
60
- assert len(seen) == source['rows'] == prep['rows']
61
- for split, spec in source['sets'].items():
62
- assert sizes[split] == spec['rows'] == prep['sources'][split]['rows']
63
- assert math.isclose(durations[split]/3600, spec['hours'], abs_tol=1e-8)
64
- for model in source['models']:
65
- c = totals[(split, model)]
66
- assert all(spec['models'][model][k] == v for k,v in c.items())
67
- assert math.isclose(spec['models'][model]['wer'], 100*c['errors']/c['words'], abs_tol=1e-12)
68
- assert math.isclose(spec['models'][model]['cer'], 100*c['char_errors']/c['chars'], abs_tol=1e-12)
69
- summaries = {}
70
- for name, languages in [('fleurs_five', 'de es fr it pt'.split()), ('fleurs_all', list(LANGUAGES))]:
71
- members = [source['sets'][f'fleurs_{lang}'] for lang in languages]
72
- summaries[name] = dict(languages=languages, rows=sum(s['rows'] for s in members),
73
- models={model:{metric:sum(s['models'][model][metric] for s in members)/len(members)
74
- for metric in ['wer','cer']} for model in source['models']})
75
- order = ['librispeech_test_clean','librispeech_test_other'] + [f'fleurs_{k}' for k in sorted(LANGUAGES,key=LANGUAGES.get)]
76
- names = {'librispeech_test_clean':'LibriSpeech test-clean', 'librispeech_test_other':'LibriSpeech test-other',
77
- **{f'fleurs_{k}':'FLEURS '+v for k,v in LANGUAGES.items()}}
78
- rows = [dict(split=s, label=names[s], **source['sets'][s]) for s in order]
79
- macros = {}
80
- for name, split in [('LibriClean','librispeech_test_clean'),('LibriOther','librispeech_test_other'),('FleursEnglish','fleurs_en')]:
81
- for model, prefix in [('parakeet','Parakeet'),('orukeet','Orukeet')]:
82
- macros[name+prefix+'WER'] = f"{source['sets'][split]['models'][model]['wer']:.2f}"
83
- for name, key in [('FleursFive','fleurs_five'),('FleursAll','fleurs_all')]:
84
- for model, prefix in [('parakeet','Parakeet'),('orukeet','Orukeet')]:
85
- macros[name+prefix+'WER'] = f"{summaries[key]['models'][model]['wer']:.2f}"
86
- macros['StandardTestRows'] = f"{source['rows']:,}"
87
- macros['FleursTestRows'] = f"{summaries['fleurs_all']['rows']:,}"
88
- (ROOT/'report/standard-benchmark-values.tex').write_text('% Generated from complete-test edit counts.\n'+''.join(
89
- '\\newcommand{\\'+key+'}{'+value+'}\n' for key,value in macros.items()))
90
- table = [r'\begin{table}[!ht]',r'\centering',
91
- r'\caption{Complete LibriSpeech and FLEURS test partitions. Both models use matched NeMo greedy decoding; WER and CER are percentages. Macro rows weight languages equally. Lower is better.}',
92
- r'\label{tab:standard-benchmarks}',r'\small',r'\setlength{\tabcolsep}{5pt}',
93
- r'\renewcommand{\arraystretch}{1.05}',r'\begin{tabular}{lrrrrr}',r'\toprule',
94
- r'Benchmark & Clips & \multicolumn{2}{c}{Parakeet} & \multicolumn{2}{c}{Orukeet}\\',
95
- r' & & WER & CER & WER & CER\\',r'\midrule']
96
- md = ['| Benchmark | Clips | Parakeet WER / CER | Orukeet WER / CER |','|:--|--:|--:|--:|']
97
- for row in rows:
98
- values = [f"{row['models'][model][metric]:.2f}" for model in ['parakeet','orukeet'] for metric in ['wer','cer']]
99
- table.append(row['label']+' & '+f"{row['rows']:,}"+' & '+' & '.join(values)+r'\\')
100
- md.append('| '+row['label']+' | '+f"{row['rows']:,}"+' | '+values[0]+' / '+values[1]+' | '+values[2]+' / '+values[3]+' |')
101
- if row['split'] == 'librispeech_test_other': table.append(r'\midrule')
102
- table.append(r'\midrule')
103
- for key, label in [('fleurs_five','FLEURS five-language macro'),('fleurs_all','FLEURS 25-language macro')]:
104
- row=summaries[key]
105
- values=[f"{row['models'][model][metric]:.2f}" for model in ['parakeet','orukeet'] for metric in ['wer','cer']]
106
- table.append(label+' & '+f"{row['rows']:,}"+' & '+' & '.join(values)+r'\\')
107
- md.append('| '+label+' | '+f"{row['rows']:,}"+' | '+values[0]+' / '+values[1]+' | '+values[2]+' / '+values[3]+' |')
108
- table += [r'\bottomrule',r'\end{tabular}',r'\end{table}']
109
- (ROOT/'report/standard-benchmark-table.tex').write_text('\n'.join(table)+'\n')
110
- with (OUT/'scores.csv').open('w',newline='') as stream:
111
- writer=csv.writer(stream);writer.writerow(['split','clips','hours','parakeet_wer','parakeet_cer','orukeet_wer','orukeet_cer'])
112
- for row in rows:writer.writerow([row['split'],row['rows'],row['hours']]+[row['models'][m][x] for m in ['parakeet','orukeet'] for x in ['wer','cer']])
113
- method = ('Both checkpoints use identical mono 16 kHz audio, NeMo greedy-batch TDT decoding, FP32 weights and BF16 CUDA autocast. '
114
- 'English uses the pinned English text normalizer. Multilingual normalization retains diacritics and expands numbers by language. '
115
- 'WER aligns compound boundaries, then uses compound-aware edit distance; CER measures normalized strings before boundary alignment. '
116
- 'WER and CER pool integer edit counts and reference lengths within each test partition. Every test record is retained, including empty hypotheses. '
117
- 'The five-language FLEURS macro averages German, Spanish, French, Italian and Portuguese; the 25-language macro includes every supported language.')
118
- doc = '# LibriSpeech and FLEURS benchmarks\n\n'+method+'\n\n'+'\n'.join(md)+'\n\n'+(
119
- '[Evaluation and reproduction](../evaluation/standard_asr/README.md) · '
120
- '[Full-precision scores](../evidence/standard-asr-20260908/scores.csv) · '
121
- '[Per-record edit counts](../evidence/standard-asr-20260908/numeric-evidence.jsonl.gz)\n')
122
- (ROOT/'docs/standard-asr-benchmarks.md').write_text(doc)
123
- receipt = dict(status='passed', publication_authorized=False, rows=len(seen), splits=len(rows),
124
- model_sha256=canonical, summaries=summaries, checks=['Unique complete test membership','All paired integer counts','WER and CER recomputation','Pinned checkpoint and source hashes'],
125
- inputs_sha256={name:sha(OUT/name) for name in ['comparison.json','preparation.json','numeric-evidence.jsonl.gz','hypotheses-audit.json']},
126
- outputs_sha256={name:sha(ROOT/name) for name in ['report/standard-benchmark-values.tex','report/standard-benchmark-table.tex','docs/standard-asr-benchmarks.md','evidence/standard-asr-20260908/scores.csv']})
127
- if '--verify-pdf' in sys.argv:
128
- text=subprocess.check_output(['pdftotext','-layout',str(ROOT/'output/pdf/orukeet-technical-report.pdf'),'-'],text=True)
129
- lines={' '.join(line.split()) for line in text.splitlines()}
130
- for row in rows:
131
- values=[f"{row['models'][model][metric]:.2f}" for model in ['parakeet','orukeet'] for metric in ['wer','cer']]
132
- assert ' '.join([row['label'],f"{row['rows']:,}"]+values) in lines, row['split']
133
- normalized_lines={line.replace('\ufb01','fi') for line in lines}
134
- for key,label in [('fleurs_five','FLEURS five-language macro'),('fleurs_all','FLEURS 25-language macro')]:
135
- summary=summaries[key]
136
- values=[f"{summary['models'][model][metric]:.2f}" for model in ['parakeet','orukeet'] for metric in ['wer','cer']]
137
- assert ' '.join([label,f"{summary['rows']:,}"]+values) in normalized_lines,key
138
- import re
139
- abstract=re.split(r'\n\s*1\s+Introduction',text.split('Abstract',1)[1],maxsplit=1)[0]
140
- assert 'Open ASR' not in text and 'leaderboard' not in text.lower()
141
- for key in ['LibriClean','LibriOther','FleursEnglish','FleursFive']:
142
- assert macros[key+'ParakeetWER'] in abstract and macros[key+'OrukeetWER'] in abstract
143
- receipt['checks'].append('Rendered abstract and all 27 test table rows match measurements')
144
- (OUT/'materials-validation.json').write_text(json.dumps(receipt,indent=2)+'\n')
145
- print(json.dumps({k:v for k,v in receipt.items() if k not in ['inputs_sha256','outputs_sha256','summaries']}))
146
-
147
-
148
- if __name__ == '__main__':
149
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/prepare.py DELETED
@@ -1,99 +0,0 @@
1
- """Pair pinned FLEURS references and official LibriSpeech transcripts with audio."""
2
- import argparse
3
- from concurrent.futures import ThreadPoolExecutor
4
- import hashlib
5
- import json
6
- from pathlib import Path
7
-
8
- FLEURS_REPO = 'hf-audio/open-asr-leaderboard-multilingual-datasets'
9
- FLEURS_REVISION = 'b791fc9151221e5b7e59c6c2dfa4dee09dda3cb7'
10
- LANGUAGES = 'bg cs da de el en es et fi fr hr hu it lt lv mt nl pl pt ro ru sk sl sv uk'.split()
11
-
12
-
13
- def sha(path):
14
- return hashlib.sha256(path.read_bytes()).hexdigest()
15
-
16
-
17
- def main():
18
- p = argparse.ArgumentParser()
19
- p.add_argument('--audio-root', type=Path, required=True)
20
- p.add_argument('--output', type=Path, required=True)
21
- a = p.parse_args()
22
- import numpy as np
23
- import soundfile as sf
24
- import pyarrow.parquet as pq
25
- from huggingface_hub import HfFileSystem
26
- a.output.mkdir(parents=True, exist_ok=True)
27
-
28
- def fleurs(language):
29
- path = f'datasets/{FLEURS_REPO}@{FLEURS_REVISION}/data/fleurs/{language}_test.parquet'
30
- target = a.output / f'fleurs-{language}-references.json'
31
- if target.exists():
32
- return json.loads(target.read_text())
33
- with HfFileSystem().open(path, 'rb', block_size=1024*1024) as stream:
34
- parquet = pq.ParquetFile(stream)
35
- records = parquet.read(columns=['file_name', 'duration', 'text']).to_pylist()
36
- assert len(records) == parquet.metadata.num_rows
37
- target.write_text(json.dumps(records, ensure_ascii=False) + '\n')
38
- print('REFERENCES', language, len(records), flush=True)
39
- return records
40
-
41
- with ThreadPoolExecutor(max_workers=6) as pool:
42
- reference_sets = dict(zip(LANGUAGES, pool.map(fleurs, LANGUAGES)))
43
- rows, sources = [], {}
44
-
45
- def add(split, language, uid, path, text, duration=None):
46
- assert path.is_file(), path
47
- audio, rate = sf.read(path, dtype='float32')
48
- assert rate == 16000 and audio.ndim == 1 and np.isfinite(audio).all()
49
- seconds = len(audio) / rate
50
- if duration is not None:
51
- assert abs(seconds - duration) < 0.002, (path, seconds, duration)
52
- rows.append(dict(uid=uid, split=split, language=language, text=text,
53
- audio_filepath=str(path), duration=seconds,
54
- pcm_sha256=hashlib.sha256(audio.astype('<f4').tobytes()).hexdigest(),
55
- reference_sha256=hashlib.sha256(text.encode()).hexdigest()))
56
-
57
- for language, records in reference_sets.items():
58
- split = f'fleurs_{language}'
59
- assert len(records) == len({r['file_name'] for r in records})
60
- for row in records:
61
- path = a.audio_root / 'data/fleurs' / language / 'test' / (Path(row['file_name']).stem + '.flac')
62
- add(split, language, split+':'+Path(row['file_name']).stem, path, row['text'], row['duration'])
63
- sources[split] = dict(repository=FLEURS_REPO, revision=FLEURS_REVISION,
64
- path=f'data/fleurs/{language}_test.parquet', rows=len(records),
65
- reference_file_sha256=sha(a.output/f'fleurs-{language}-references.json'))
66
-
67
- for split, folder, expected in [
68
- ('librispeech_test_clean', 'data/goal_v2_sources/libri/LibriSpeech/test-clean', 2620),
69
- ('librispeech_test_other', 'data/librispeech/LibriSpeech/test-other', 2939),
70
- ]:
71
- transcripts = sorted((a.audio_root / folder).rglob('*.trans.txt'))
72
- count = 0
73
- for transcript in transcripts:
74
- for line in transcript.read_text().splitlines():
75
- uid, text = line.split(' ', 1)
76
- add(split, 'en', split+':'+uid, transcript.parent/(uid+'.flac'), text)
77
- count += 1
78
- assert count == expected, (split, count)
79
- sources[split] = dict(source='Official LibriSpeech test partition and original .trans.txt transcripts',
80
- rows=count, transcript_files_sha256={str(x.relative_to(a.audio_root)):sha(x) for x in transcripts})
81
- rows.sort(key=lambda r: (r['split'], r['uid']))
82
- assert len(rows) == len({r['uid'] for r in rows})
83
- manifest = a.output/'manifest.jsonl'
84
- with manifest.open('w') as stream:
85
- for row in rows:
86
- stream.write(json.dumps(row, ensure_ascii=False)+'\n')
87
- receipt = dict(status='prepared', publication_authorized=False, rows=len(rows), splits=len(sources),
88
- selection='Complete published test partitions; all records retained, no selection by model output.',
89
- sources=sources, manifest_sha256=sha(manifest), script_sha256=sha(Path(__file__)),
90
- hours=sum(r['duration'] for r in rows)/3600,
91
- audio='Existing mono 16 kHz FLAC files, decoded float32 PCM hashes checked before inference.',
92
- abstract_comparisons=['librispeech_test_clean','librispeech_test_other','fleurs_en'],
93
- additional_abstract_summary='Equal-language macro over de, es, fr, it, pt FLEURS test partitions')
94
- (a.output/'preparation.json').write_text(json.dumps(receipt, indent=2)+'\n')
95
- print('PREPARED', len(rows), receipt['hours'], flush=True)
96
-
97
-
98
- if __name__ == '__main__':
99
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/requirements-score.txt DELETED
@@ -1,4 +0,0 @@
1
- kaldialign==0.12.0
2
- num2words==0.5.14
3
- rapidfuzz==3.14.6
4
- regex==2026.9.3
 
 
 
 
 
evaluation/standard_asr/rescore.py DELETED
@@ -1,70 +0,0 @@
1
- """Score fixed private transcripts with pinned compound-aware normalization."""
2
- import argparse
3
- from collections import Counter, defaultdict
4
- import gzip
5
- import hashlib
6
- from importlib.metadata import version
7
- import json
8
- from pathlib import Path
9
- from scoring import counts
10
-
11
- ROOT = Path(__file__).resolve().parents[2]
12
-
13
-
14
- def sha(path):
15
- return hashlib.sha256(path.read_bytes()).hexdigest()
16
-
17
-
18
- def main():
19
- parser = argparse.ArgumentParser()
20
- parser.add_argument('--private-records', type=Path, required=True)
21
- parser.add_argument('--evidence', type=Path, default=ROOT/'evidence/standard-asr-20260908')
22
- a = parser.parse_args()
23
- source = json.loads((a.evidence/'inference-comparison.json').read_text())
24
- assert sha(a.private_records/'manifest.jsonl') == source['manifest_sha256']
25
- rows = [json.loads(line) for line in (a.private_records/'manifest.jsonl').open()]
26
- predictions = {}
27
- for model in source['models']:
28
- path = a.private_records/(model+'.jsonl')
29
- assert sha(path) == source['prediction_sha256'][model]
30
- records = [json.loads(line) for line in path.open()]
31
- predictions[model] = {r['uid']:r['prediction'] for r in records}
32
- assert len(records) == len(predictions[model]) == len(rows)
33
- totals, seen = defaultdict(Counter), set()
34
- with gzip.open(a.evidence/'numeric-evidence.jsonl.gz', 'wt') as stream:
35
- for row in rows:
36
- assert row['uid'] not in seen
37
- seen.add(row['uid'])
38
- values = {model:counts(row['text'], predictions[model][row['uid']], row['language'])
39
- for model in source['models']}
40
- for model, value in values.items():
41
- totals[(row['split'], model)].update(value)
42
- stream.write(json.dumps(dict(record_sha256=hashlib.sha256(row['uid'].encode()).hexdigest(),
43
- split=row['split'], language=row['language'],
44
- duration=row['duration'], counts=values))+'\n')
45
- assert len(seen) == source['rows']
46
- for split, spec in source['sets'].items():
47
- spec['models'] = {model:dict(totals[(split,model)],
48
- wer=100*totals[(split,model)]['errors']/totals[(split,model)]['words'],
49
- cer=100*totals[(split,model)]['char_errors']/totals[(split,model)]['chars'])
50
- for model in source['models']}
51
- paths = [Path(__file__), ROOT/'evaluation/standard_asr/scoring.py']
52
- paths += [p for p in (ROOT/'evaluation/standard_asr/vendor').iterdir() if p.is_file()]
53
- source['scoring'] = dict(
54
- protocol='Pinned English and multilingual normalization; compound-aware WER',
55
- dependencies={name:version(name) for name in ['kaldialign','num2words','regex','rapidfuzz']},
56
- code_sha256={p.relative_to(ROOT).as_posix():sha(p) for p in paths},
57
- reference_word_counts='Non-English word-boundary alignment may change reference token counts separately for each model.',
58
- cer='Character distance before compound alignment, including normalized spaces.',
59
- inference_comparison_sha256=sha(a.evidence/'inference-comparison.json'))
60
- source['normalizers'] = dict(en='Pinned EnglishTextNormalizer with spelling/name/compound maps',
61
- other='Pinned MultilingualNormalizer; diacritics retained; language-specific numbers; compound-boundary alignment')
62
- source['numeric_evidence_sha256'] = sha(a.evidence/'numeric-evidence.jsonl.gz')
63
- (a.evidence/'comparison.json').write_text(json.dumps(source,indent=2,ensure_ascii=False)+'\n')
64
- for split in ['librispeech_test_clean','librispeech_test_other','fleurs_en','fleurs_de','fleurs_es','fleurs_fr','fleurs_it','fleurs_pt']:
65
- if split in source['sets']:
66
- print(split,{m:round(v['wer'],3) for m,v in source['sets'][split]['models'].items()})
67
-
68
-
69
- if __name__ == '__main__':
70
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/run.py DELETED
@@ -1,158 +0,0 @@
1
- """Compare two fixed NeMo checkpoints on complete LibriSpeech and FLEURS tests.
2
-
3
- Input is a JSONL manifest with uid, split, language, text, audio_filepath,
4
- duration, and pcm_sha256. Every record is decoded by both checkpoints; empty
5
- hypotheses remain in the score. Resume verifies model, manifest and code hashes.
6
- """
7
- import argparse
8
- from collections import Counter, defaultdict
9
- import gc
10
- import gzip
11
- import hashlib
12
- import json
13
- from pathlib import Path
14
- import sys
15
- import time
16
-
17
-
18
- def sha(path):
19
- h = hashlib.sha256()
20
- with open(path, 'rb') as stream:
21
- for block in iter(lambda: stream.read(1 << 20), b''):
22
- h.update(block)
23
- return h.hexdigest()
24
-
25
-
26
- def write(path, value):
27
- tmp = path.with_suffix('.tmp')
28
- tmp.write_text(json.dumps(value, indent=2, ensure_ascii=False) + '\n')
29
- tmp.replace(path)
30
-
31
-
32
- def main():
33
- p = argparse.ArgumentParser()
34
- p.add_argument('--manifest', type=Path, required=True)
35
- p.add_argument('--parakeet', type=Path, required=True)
36
- p.add_argument('--orukeet', type=Path, required=True)
37
- p.add_argument('--parakeet-sha256', default='3cbdc85877e668ca7b82d0d56770eb1fac76691f55d6b97545e8d61ca588d10d')
38
- p.add_argument('--orukeet-sha256', default='0ccfefcd1894871cb0850bd3c464adf5397752840de2a76d1d2d075c4141a945')
39
- p.add_argument('--metric-code', type=Path, required=True)
40
- p.add_argument('--output', type=Path, required=True)
41
- a = p.parse_args()
42
- import numpy as np
43
- import soundfile as sf
44
- import torch
45
- from omegaconf import OmegaConf
46
- from nemo.collections.asr.models import ASRModel
47
- from nemo.utils import logging
48
- sys.path.insert(0, str(a.metric_code))
49
- from metrics import counts, normalize, ENGLISH
50
-
51
- logging.set_verbosity(logging.ERROR)
52
- torch.set_num_threads(8)
53
- torch.manual_seed(20260908)
54
- np.random.seed(20260908)
55
- torch.backends.cuda.matmul.allow_tf32 = False
56
- torch.backends.cudnn.allow_tf32 = True
57
- a.output.mkdir(parents=True, exist_ok=True)
58
- rows = [json.loads(line) for line in a.manifest.open()]
59
- assert len(rows) == len({r['uid'] for r in rows})
60
- rows.sort(key=lambda r: (r['duration'], r['uid']))
61
- identities = dict(manifest_sha256=sha(a.manifest), script_sha256=sha(__file__),
62
- normalizer_sha256=sha(a.metric_code / 'metrics.py'))
63
- for row in rows:
64
- audio, rate = sf.read(row['audio_filepath'], dtype='float32')
65
- assert rate == 16000 and audio.ndim == 1
66
- assert abs(len(audio) / rate - row['duration']) < 1 / rate
67
- assert hashlib.sha256(audio.astype('<f4').tobytes()).hexdigest() == row['pcm_sha256']
68
- print('AUDIO_VERIFIED', len(rows), flush=True)
69
- decoding, predictions, timings, models = None, {}, {}, {}
70
- for label, path in [('parakeet', a.parakeet), ('orukeet', a.orukeet)]:
71
- identity = dict(identities, model_sha256=sha(path))
72
- assert identity['model_sha256'] == getattr(a, label + '_sha256')
73
- models[label] = identity['model_sha256']
74
- target = a.output / (label + '.jsonl')
75
- prior = [json.loads(line) for line in target.open()] if target.exists() else []
76
- assert len(prior) == len({r['uid'] for r in prior})
77
- for record in prior:
78
- assert all(record[k] == v for k, v in identity.items())
79
- done = {r['uid']: r for r in prior}
80
- assert set(done) <= {r['uid'] for r in rows}
81
- pending = [r for r in rows if r['uid'] not in done]
82
- if pending:
83
- model = ASRModel.restore_from(str(path), map_location='cuda').eval()
84
- model.freeze()
85
- config = OmegaConf.to_container(model.cfg.decoding, resolve=True)
86
- assert config['strategy'] == 'greedy_batch' and config['greedy']['max_symbols'] == 10
87
- if decoding is None:
88
- decoding = config
89
- write(a.output / 'decoding.json', config)
90
- assert config == decoding
91
- model.change_decoding_strategy(OmegaConf.create(config))
92
- started = time.monotonic()
93
-
94
- def infer(batch):
95
- try:
96
- with torch.inference_mode(), torch.autocast('cuda', dtype=torch.bfloat16):
97
- hypotheses = model.transcribe([r['audio_filepath'] for r in batch],
98
- batch_size=16, num_workers=4, verbose=False)
99
- assert len(hypotheses) == len(batch)
100
- return [h.text if hasattr(h, 'text') else str(h) for h in hypotheses]
101
- except torch.cuda.OutOfMemoryError:
102
- torch.cuda.empty_cache()
103
- gc.collect()
104
- if len(batch) == 1:
105
- raise
106
- mid = len(batch) // 2
107
- return infer(batch[:mid]) + infer(batch[mid:])
108
-
109
- with target.open('a') as stream:
110
- for offset in range(0, len(pending), 256):
111
- batch = pending[offset:offset + 256]
112
- for row, text in zip(batch, infer(batch)):
113
- record = dict(uid=row['uid'], prediction=text, **identity)
114
- done[row['uid']] = record
115
- stream.write(json.dumps(record, ensure_ascii=False) + '\n')
116
- stream.flush()
117
- print('EVAL', label, len(done), '/', len(rows), flush=True)
118
- torch.cuda.synchronize()
119
- timings[label] = dict(seconds=time.monotonic() - started, rows=len(pending))
120
- del model
121
- gc.collect()
122
- torch.cuda.empty_cache()
123
- predictions[label] = done
124
- assert len(done) == len(rows)
125
- totals, sizes, durations = defaultdict(lambda: defaultdict(Counter)), Counter(), Counter()
126
- with gzip.open(a.output / 'numeric-evidence.jsonl.gz', 'wt') as stream:
127
- for row in rows:
128
- split = row['split']
129
- sizes[split] += 1
130
- durations[split] += row['duration']
131
- normalizer = ENGLISH if row['language'] == 'en' else normalize
132
- values = {label: counts(row['text'], predictions[label][row['uid']]['prediction'], normalizer)
133
- for label in predictions}
134
- for label, count in values.items():
135
- totals[split][label].update(count)
136
- stream.write(json.dumps(dict(record_sha256=hashlib.sha256(row['uid'].encode()).hexdigest(),
137
- split=split, language=row['language'],
138
- duration=row['duration'], counts=values)) + '\n')
139
- sets = {}
140
- for split in sorted(sizes):
141
- sets[split] = dict(rows=sizes[split], hours=durations[split] / 3600,
142
- language=next(r['language'] for r in rows if r['split'] == split),
143
- models={label: dict(c, wer=100*c['errors']/c['words'],
144
- cer=100*c['char_errors']/c['chars'])
145
- for label, c in totals[split].items()})
146
- result = dict(status='complete', publication_authorized=False, rows=len(rows), sets=sets,
147
- models=models, **identities, decoding=json.loads((a.output/'decoding.json').read_text()),
148
- precision='FP32 weights, BF16 CUDA autocast, TF32 matrix multiplication disabled',
149
- normalizers={'en':'Whisper EnglishTextNormalizer', 'other':'Recorded multilingual normalizer'},
150
- empty_output_handling='Every manifest record is scored; empty hypotheses remain.',
151
- timings=timings, prediction_sha256={k:sha(a.output/(k+'.jsonl')) for k in models},
152
- numeric_evidence_sha256=sha(a.output/'numeric-evidence.jsonl.gz'))
153
- write(a.output / 'comparison.json', result)
154
- print('COMPLETE', len(rows), flush=True)
155
-
156
-
157
- if __name__ == '__main__':
158
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/scoring.py DELETED
@@ -1,27 +0,0 @@
1
- """Pinned English/multilingual normalization and compound-aware WER."""
2
- from kaldialign import batch_error_rate
3
- from rapidfuzz.distance import Levenshtein
4
- from vendor.normalizer import EnglishTextNormalizer
5
- from vendor.multilingual import MultilingualNormalizer, normalize_compound_pairs
6
-
7
- ENGLISH = EnglishTextNormalizer()
8
- MULTILINGUAL = MultilingualNormalizer(remove_diacritics=False)
9
-
10
-
11
- def normalized_pair(reference, prediction, language):
12
- normalizer = ENGLISH if language == 'en' else lambda text: MULTILINGUAL(text, lang=language)
13
- return normalizer(reference), normalizer(prediction)
14
-
15
-
16
- def counts(reference, prediction, language):
17
- ref, hyp = normalized_pair(reference, prediction, language)
18
- # CER uses the normalized strings before pair-dependent word-boundary changes.
19
- chars, char_errors = len(ref), Levenshtein.distance(ref, hyp)
20
- if language != 'en':
21
- refs, hyps = normalize_compound_pairs([ref], [hyp])
22
- ref, hyp = refs[0], hyps[0]
23
- result = batch_error_rate([tuple(ref.split())], [tuple(hyp.split())], merge_compounds=True)
24
- return dict(words=len(ref.split()), errors=result['ins'] + result['del'] + result['sub'],
25
- substitutions=result['sub'], deletions=result['del'], insertions=result['ins'],
26
- chars=chars, char_errors=char_errors,
27
- utterance_error=int(bool(result['ins'] + result['del'] + result['sub'])))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/vendor/LICENSE DELETED
@@ -1,201 +0,0 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright [2024] [The HuggingFace Inc. team]
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/vendor/__init__.py DELETED
@@ -1 +0,0 @@
1
- """Pinned text-scoring dependencies; see provenance.json and LICENSE."""
 
 
evaluation/standard_asr/vendor/english_abbreviations.py DELETED
@@ -1,1934 +0,0 @@
1
- english_spelling_normalizer = {
2
- "ok": "okay",
3
- "kay": "okay",
4
- "etcetera": "etc",
5
- "accessorise": "accessorize",
6
- "accessorised": "accessorized",
7
- "accessorises": "accessorizes",
8
- "accessorising": "accessorizing",
9
- "acclimatisation": "acclimatization",
10
- "acclimatise": "acclimatize",
11
- "acclimatised": "acclimatized",
12
- "acclimatises": "acclimatizes",
13
- "acclimatising": "acclimatizing",
14
- "accoutrements": "accouterments",
15
- "aeon": "eon",
16
- "aeons": "eons",
17
- "aerogramme": "aerogram",
18
- "aerogrammes": "aerograms",
19
- "aeroplane": "airplane",
20
- "aeroplanes": "airplanes",
21
- "aesthete": "esthete",
22
- "aesthetes": "esthetes",
23
- "aesthetic": "esthetic",
24
- "aesthetically": "esthetically",
25
- "aesthetics": "esthetics",
26
- "aetiology": "etiology",
27
- "ageing": "aging",
28
- "aggrandisement": "aggrandizement",
29
- "agonise": "agonize",
30
- "agonised": "agonized",
31
- "agonises": "agonizes",
32
- "agonising": "agonizing",
33
- "agonisingly": "agonizingly",
34
- "almanack": "almanac",
35
- "almanacks": "almanacs",
36
- "aluminium": "aluminum",
37
- "amortisable": "amortizable",
38
- "amortisation": "amortization",
39
- "amortisations": "amortizations",
40
- "amortise": "amortize",
41
- "amortised": "amortized",
42
- "amortises": "amortizes",
43
- "amortising": "amortizing",
44
- "amphitheatre": "amphitheater",
45
- "amphitheatres": "amphitheaters",
46
- "anaemia": "anemia",
47
- "anaemic": "anemic",
48
- "anaesthesia": "anesthesia",
49
- "anaesthetic": "anesthetic",
50
- "anaesthetics": "anesthetics",
51
- "anaesthetise": "anesthetize",
52
- "anaesthetised": "anesthetized",
53
- "anaesthetises": "anesthetizes",
54
- "anaesthetising": "anesthetizing",
55
- "anaesthetist": "anesthetist",
56
- "anaesthetists": "anesthetists",
57
- "anaesthetize": "anesthetize",
58
- "anaesthetized": "anesthetized",
59
- "anaesthetizes": "anesthetizes",
60
- "anaesthetizing": "anesthetizing",
61
- "analogue": "analog",
62
- "analogues": "analogs",
63
- "analyse": "analyze",
64
- "analysed": "analyzed",
65
- "analyses": "analyzes",
66
- "analysing": "analyzing",
67
- "anglicise": "anglicize",
68
- "anglicised": "anglicized",
69
- "anglicises": "anglicizes",
70
- "anglicising": "anglicizing",
71
- "annualised": "annualized",
72
- "antagonise": "antagonize",
73
- "antagonised": "antagonized",
74
- "antagonises": "antagonizes",
75
- "antagonising": "antagonizing",
76
- "apologise": "apologize",
77
- "apologised": "apologized",
78
- "apologises": "apologizes",
79
- "apologising": "apologizing",
80
- "appal": "appall",
81
- "appals": "appalls",
82
- "appetiser": "appetizer",
83
- "appetisers": "appetizers",
84
- "appetising": "appetizing",
85
- "appetisingly": "appetizingly",
86
- "arbour": "arbor",
87
- "arbours": "arbors",
88
- "archaeologically": "archeologically",
89
- "archaeologist": "archeologist",
90
- "archaeologists": "archeologists",
91
- "archaeology": "archeology",
92
- "archaeological": "archeological",
93
- "ardour": "ardor",
94
- "armour": "armor",
95
- "armoured": "armored",
96
- "armourer": "armorer",
97
- "armourers": "armorers",
98
- "armouries": "armories",
99
- "armoury": "armory",
100
- "artefact": "artifact",
101
- "artefacts": "artifacts",
102
- "authorise": "authorize",
103
- "authorised": "authorized",
104
- "authorises": "authorizes",
105
- "authorising": "authorizing",
106
- "axe": "ax",
107
- "backpedalled": "backpedaled",
108
- "backpedalling": "backpedaling",
109
- "bannister": "banister",
110
- "bannisters": "banisters",
111
- "baptise": "baptize",
112
- "baptised": "baptized",
113
- "baptises": "baptizes",
114
- "baptising": "baptizing",
115
- "bastardise": "bastardize",
116
- "bastardised": "bastardized",
117
- "bastardises": "bastardizes",
118
- "bastardising": "bastardizing",
119
- "battleax": "battleaxe",
120
- "baulk": "balk",
121
- "baulked": "balked",
122
- "baulking": "balking",
123
- "baulks": "balks",
124
- "bedevilled": "bedeviled",
125
- "bedevilling": "bedeviling",
126
- "behaviour": "behavior",
127
- "behavioural": "behavioral",
128
- "behaviourism": "behaviorism",
129
- "behaviourist": "behaviorist",
130
- "behaviourists": "behaviorists",
131
- "behaviours": "behaviors",
132
- "behove": "behoove",
133
- "behoved": "behooved",
134
- "behoves": "behooves",
135
- "bejewelled": "bejeweled",
136
- "belabour": "belabor",
137
- "belaboured": "belabored",
138
- "belabouring": "belaboring",
139
- "belabours": "belabors",
140
- "bevelled": "beveled",
141
- "bevvies": "bevies",
142
- "bevvy": "bevy",
143
- "biassed": "biased",
144
- "biassing": "biasing",
145
- "bingeing": "binging",
146
- "bougainvillaea": "bougainvillea",
147
- "bougainvillaeas": "bougainvilleas",
148
- "bowdlerise": "bowdlerize",
149
- "bowdlerised": "bowdlerized",
150
- "bowdlerises": "bowdlerizes",
151
- "bowdlerising": "bowdlerizing",
152
- "breathalyse": "breathalyze",
153
- "breathalysed": "breathalyzed",
154
- "breathalyser": "breathalyzer",
155
- "breathalysers": "breathalyzers",
156
- "breathalyses": "breathalyzes",
157
- "breathalysing": "breathalyzing",
158
- "brutalise": "brutalize",
159
- "brutalised": "brutalized",
160
- "brutalises": "brutalizes",
161
- "brutalising": "brutalizing",
162
- "busses": "buses",
163
- "bussing": "busing",
164
- "caesarean": "cesarean",
165
- "caesareans": "cesareans",
166
- "calibre": "caliber",
167
- "calibres": "calibers",
168
- "calliper": "caliper",
169
- "callipers": "calipers",
170
- "callisthenics": "calisthenics",
171
- "canalise": "canalize",
172
- "canalised": "canalized",
173
- "canalises": "canalizes",
174
- "canalising": "canalizing",
175
- "cancellation": "cancelation",
176
- "cancellations": "cancelations",
177
- "cancelled": "canceled",
178
- "cancelling": "canceling",
179
- "candour": "candor",
180
- "cannibalise": "cannibalize",
181
- "cannibalised": "cannibalized",
182
- "cannibalises": "cannibalizes",
183
- "cannibalising": "cannibalizing",
184
- "canonise": "canonize",
185
- "canonised": "canonized",
186
- "canonises": "canonizes",
187
- "canonising": "canonizing",
188
- "capitalise": "capitalize",
189
- "capitalised": "capitalized",
190
- "capitalises": "capitalizes",
191
- "capitalising": "capitalizing",
192
- "caramelise": "caramelize",
193
- "caramelised": "caramelized",
194
- "caramelises": "caramelizes",
195
- "caramelising": "caramelizing",
196
- "carbonise": "carbonize",
197
- "carbonised": "carbonized",
198
- "carbonises": "carbonizes",
199
- "carbonising": "carbonizing",
200
- "carolled": "caroled",
201
- "carolling": "caroling",
202
- "catalogue": "catalog",
203
- "catalogued": "cataloged",
204
- "catalogues": "catalogs",
205
- "cataloguing": "cataloging",
206
- "catalyse": "catalyze",
207
- "catalysed": "catalyzed",
208
- "catalyses": "catalyzes",
209
- "catalysing": "catalyzing",
210
- "categorise": "categorize",
211
- "categorised": "categorized",
212
- "categorises": "categorizes",
213
- "categorising": "categorizing",
214
- "cauterise": "cauterize",
215
- "cauterised": "cauterized",
216
- "cauterises": "cauterizes",
217
- "cauterising": "cauterizing",
218
- "cavilled": "caviled",
219
- "cavilling": "caviling",
220
- "centigramme": "centigram",
221
- "centigrammes": "centigrams",
222
- "centilitre": "centiliter",
223
- "centilitres": "centiliters",
224
- "centimetre": "centimeter",
225
- "centimetres": "centimeters",
226
- "centralise": "centralize",
227
- "centralised": "centralized",
228
- "centralises": "centralizes",
229
- "centralising": "centralizing",
230
- "centre": "center",
231
- "centred": "centered",
232
- "centrefold": "centerfold",
233
- "centrefolds": "centerfolds",
234
- "centrepiece": "centerpiece",
235
- "centrepieces": "centerpieces",
236
- "centres": "centers",
237
- "channelled": "channeled",
238
- "channelling": "channeling",
239
- "characterise": "characterize",
240
- "characterised": "characterized",
241
- "characterises": "characterizes",
242
- "characterising": "characterizing",
243
- "cheque": "check",
244
- "chequebook": "checkbook",
245
- "chequebooks": "checkbooks",
246
- "chequered": "checkered",
247
- "cheques": "checks",
248
- "chilli": "chili",
249
- "chimaera": "chimera",
250
- "chimaeras": "chimeras",
251
- "chiselled": "chiseled",
252
- "chiselling": "chiseling",
253
- "circularise": "circularize",
254
- "circularised": "circularized",
255
- "circularises": "circularizes",
256
- "circularising": "circularizing",
257
- "civilise": "civilize",
258
- "civilised": "civilized",
259
- "civilises": "civilizes",
260
- "civilising": "civilizing",
261
- "clamour": "clamor",
262
- "clamoured": "clamored",
263
- "clamouring": "clamoring",
264
- "clamours": "clamors",
265
- "clangour": "clangor",
266
- "clarinettist": "clarinetist",
267
- "clarinettists": "clarinetists",
268
- "collectivise": "collectivize",
269
- "collectivised": "collectivized",
270
- "collectivises": "collectivizes",
271
- "collectivising": "collectivizing",
272
- "colonisation": "colonization",
273
- "colonise": "colonize",
274
- "colonised": "colonized",
275
- "coloniser": "colonizer",
276
- "colonisers": "colonizers",
277
- "colonises": "colonizes",
278
- "colonising": "colonizing",
279
- "colour": "color",
280
- "colourant": "colorant",
281
- "colourants": "colorants",
282
- "coloured": "colored",
283
- "coloureds": "coloreds",
284
- "colourful": "colorful",
285
- "colourfully": "colorfully",
286
- "colouring": "coloring",
287
- "colourize": "colorize",
288
- "colourized": "colorized",
289
- "colourizes": "colorizes",
290
- "colourizing": "colorizing",
291
- "colourless": "colorless",
292
- "colours": "colors",
293
- "commercialise": "commercialize",
294
- "commercialised": "commercialized",
295
- "commercialises": "commercializes",
296
- "commercialising": "commercializing",
297
- "compartmentalise": "compartmentalize",
298
- "compartmentalised": "compartmentalized",
299
- "compartmentalises": "compartmentalizes",
300
- "compartmentalising": "compartmentalizing",
301
- "computerise": "computerize",
302
- "computerised": "computerized",
303
- "computerises": "computerizes",
304
- "computerising": "computerizing",
305
- "conceptualise": "conceptualize",
306
- "conceptualised": "conceptualized",
307
- "conceptualises": "conceptualizes",
308
- "conceptualising": "conceptualizing",
309
- "connexion": "connection",
310
- "connexions": "connections",
311
- "contextualise": "contextualize",
312
- "contextualised": "contextualized",
313
- "contextualises": "contextualizes",
314
- "contextualising": "contextualizing",
315
- "cosier": "cozier",
316
- "cosies": "cozies",
317
- "cosiest": "coziest",
318
- "cosily": "cozily",
319
- "cosiness": "coziness",
320
- "cosy": "cozy",
321
- "councillor": "councilor",
322
- "councillors": "councilors",
323
- "counselled": "counseled",
324
- "counselling": "counseling",
325
- "counsellor": "counselor",
326
- "counsellors": "counselors",
327
- "crenelated": "crenellated",
328
- "criminalise": "criminalize",
329
- "criminalised": "criminalized",
330
- "criminalises": "criminalizes",
331
- "criminalising": "criminalizing",
332
- "criticise": "criticize",
333
- "criticised": "criticized",
334
- "criticises": "criticizes",
335
- "criticising": "criticizing",
336
- "crueller": "crueler",
337
- "cruellest": "cruelest",
338
- "crystallisation": "crystallization",
339
- "crystallise": "crystallize",
340
- "crystallised": "crystallized",
341
- "crystallises": "crystallizes",
342
- "crystallising": "crystallizing",
343
- "cudgelled": "cudgeled",
344
- "cudgelling": "cudgeling",
345
- "customise": "customize",
346
- "customised": "customized",
347
- "customises": "customizes",
348
- "customising": "customizing",
349
- "cypher": "cipher",
350
- "cyphers": "ciphers",
351
- "decentralisation": "decentralization",
352
- "decentralise": "decentralize",
353
- "decentralised": "decentralized",
354
- "decentralises": "decentralizes",
355
- "decentralising": "decentralizing",
356
- "decriminalisation": "decriminalization",
357
- "decriminalise": "decriminalize",
358
- "decriminalised": "decriminalized",
359
- "decriminalises": "decriminalizes",
360
- "decriminalising": "decriminalizing",
361
- "defence": "defense",
362
- "defenceless": "defenseless",
363
- "defences": "defenses",
364
- "dehumanisation": "dehumanization",
365
- "dehumanise": "dehumanize",
366
- "dehumanised": "dehumanized",
367
- "dehumanises": "dehumanizes",
368
- "dehumanising": "dehumanizing",
369
- "demeanour": "demeanor",
370
- "demilitarisation": "demilitarization",
371
- "demilitarise": "demilitarize",
372
- "demilitarised": "demilitarized",
373
- "demilitarises": "demilitarizes",
374
- "demilitarising": "demilitarizing",
375
- "demobilisation": "demobilization",
376
- "demobilise": "demobilize",
377
- "demobilised": "demobilized",
378
- "demobilises": "demobilizes",
379
- "demobilising": "demobilizing",
380
- "democratisation": "democratization",
381
- "democratise": "democratize",
382
- "democratised": "democratized",
383
- "democratises": "democratizes",
384
- "democratising": "democratizing",
385
- "demonise": "demonize",
386
- "demonised": "demonized",
387
- "demonises": "demonizes",
388
- "demonising": "demonizing",
389
- "demoralisation": "demoralization",
390
- "demoralise": "demoralize",
391
- "demoralised": "demoralized",
392
- "demoralises": "demoralizes",
393
- "demoralising": "demoralizing",
394
- "denationalisation": "denationalization",
395
- "denationalise": "denationalize",
396
- "denationalised": "denationalized",
397
- "denationalises": "denationalizes",
398
- "denationalising": "denationalizing",
399
- "deodorise": "deodorize",
400
- "deodorised": "deodorized",
401
- "deodorises": "deodorizes",
402
- "deodorising": "deodorizing",
403
- "depersonalise": "depersonalize",
404
- "depersonalised": "depersonalized",
405
- "depersonalises": "depersonalizes",
406
- "depersonalising": "depersonalizing",
407
- "deputise": "deputize",
408
- "deputised": "deputized",
409
- "deputises": "deputizes",
410
- "deputising": "deputizing",
411
- "desensitisation": "desensitization",
412
- "desensitise": "desensitize",
413
- "desensitised": "desensitized",
414
- "desensitises": "desensitizes",
415
- "desensitising": "desensitizing",
416
- "destabilisation": "destabilization",
417
- "destabilise": "destabilize",
418
- "destabilised": "destabilized",
419
- "destabilises": "destabilizes",
420
- "destabilising": "destabilizing",
421
- "dialled": "dialed",
422
- "dialling": "dialing",
423
- "dialogue": "dialog",
424
- "dialogues": "dialogs",
425
- "diarrhoea": "diarrhea",
426
- "digitise": "digitize",
427
- "digitised": "digitized",
428
- "digitises": "digitizes",
429
- "digitising": "digitizing",
430
- "disc": "disk",
431
- "discolour": "discolor",
432
- "discoloured": "discolored",
433
- "discolouring": "discoloring",
434
- "discolours": "discolors",
435
- "discs": "disks",
436
- "disembowelled": "disemboweled",
437
- "disembowelling": "disemboweling",
438
- "disfavour": "disfavor",
439
- "dishevelled": "disheveled",
440
- "dishonour": "dishonor",
441
- "dishonourable": "dishonorable",
442
- "dishonourably": "dishonorably",
443
- "dishonoured": "dishonored",
444
- "dishonouring": "dishonoring",
445
- "dishonours": "dishonors",
446
- "disorganisation": "disorganization",
447
- "disorganised": "disorganized",
448
- "distil": "distill",
449
- "distils": "distills",
450
- "dramatisation": "dramatization",
451
- "dramatisations": "dramatizations",
452
- "dramatise": "dramatize",
453
- "dramatised": "dramatized",
454
- "dramatises": "dramatizes",
455
- "dramatising": "dramatizing",
456
- "draught": "draft",
457
- "draughtboard": "draftboard",
458
- "draughtboards": "draftboards",
459
- "draughtier": "draftier",
460
- "draughtiest": "draftiest",
461
- "draughts": "drafts",
462
- "draughtsman": "draftsman",
463
- "draughtsmanship": "draftsmanship",
464
- "draughtsmen": "draftsmen",
465
- "draughtswoman": "draftswoman",
466
- "draughtswomen": "draftswomen",
467
- "draughty": "drafty",
468
- "drivelled": "driveled",
469
- "drivelling": "driveling",
470
- "duelled": "dueled",
471
- "duelling": "dueling",
472
- "economise": "economize",
473
- "economised": "economized",
474
- "economises": "economizes",
475
- "economising": "economizing",
476
- "editorialise": "editorialize",
477
- "editorialised": "editorialized",
478
- "editorialises": "editorializes",
479
- "editorialising": "editorializing",
480
- "edoema": "edema",
481
- "empathise": "empathize",
482
- "empathised": "empathized",
483
- "empathises": "empathizes",
484
- "empathising": "empathizing",
485
- "emphasise": "emphasize",
486
- "emphasised": "emphasized",
487
- "emphasises": "emphasizes",
488
- "emphasising": "emphasizing",
489
- "enamelled": "enameled",
490
- "enamelling": "enameling",
491
- "enamoured": "enamored",
492
- "encyclopaedia": "encyclopedia",
493
- "encyclopaedias": "encyclopedias",
494
- "encyclopaedic": "encyclopedic",
495
- "endeavour": "endeavor",
496
- "endeavoured": "endeavored",
497
- "endeavouring": "endeavoring",
498
- "endeavours": "endeavors",
499
- "energise": "energize",
500
- "energised": "energized",
501
- "energises": "energizes",
502
- "energising": "energizing",
503
- "enrol": "enroll",
504
- "enrols": "enrolls",
505
- "enthral": "enthrall",
506
- "enthrals": "enthralls",
507
- "epaulette": "epaulet",
508
- "epaulettes": "epaulets",
509
- "epicentre": "epicenter",
510
- "epicentres": "epicenters",
511
- "epilogue": "epilog",
512
- "epilogues": "epilogs",
513
- "epitomise": "epitomize",
514
- "epitomised": "epitomized",
515
- "epitomises": "epitomizes",
516
- "epitomising": "epitomizing",
517
- "equalisation": "equalization",
518
- "equalise": "equalize",
519
- "equalised": "equalized",
520
- "equaliser": "equalizer",
521
- "equalisers": "equalizers",
522
- "equalises": "equalizes",
523
- "equalising": "equalizing",
524
- "eulogise": "eulogize",
525
- "eulogised": "eulogized",
526
- "eulogises": "eulogizes",
527
- "eulogising": "eulogizing",
528
- "evangelise": "evangelize",
529
- "evangelised": "evangelized",
530
- "evangelises": "evangelizes",
531
- "evangelising": "evangelizing",
532
- "exorcise": "exorcize",
533
- "exorcised": "exorcized",
534
- "exorcises": "exorcizes",
535
- "exorcising": "exorcizing",
536
- "extemporisation": "extemporization",
537
- "extemporise": "extemporize",
538
- "extemporised": "extemporized",
539
- "extemporises": "extemporizes",
540
- "extemporising": "extemporizing",
541
- "externalisation": "externalization",
542
- "externalisations": "externalizations",
543
- "externalise": "externalize",
544
- "externalised": "externalized",
545
- "externalises": "externalizes",
546
- "externalising": "externalizing",
547
- "factorise": "factorize",
548
- "factorised": "factorized",
549
- "factorises": "factorizes",
550
- "factorising": "factorizing",
551
- "faecal": "fecal",
552
- "faeces": "feces",
553
- "familiarisation": "familiarization",
554
- "familiarise": "familiarize",
555
- "familiarised": "familiarized",
556
- "familiarises": "familiarizes",
557
- "familiarising": "familiarizing",
558
- "fantasise": "fantasize",
559
- "fantasised": "fantasized",
560
- "fantasises": "fantasizes",
561
- "fantasising": "fantasizing",
562
- "favour": "favor",
563
- "favourable": "favorable",
564
- "favourably": "favorably",
565
- "favoured": "favored",
566
- "favouring": "favoring",
567
- "favourite": "favorite",
568
- "favourites": "favorites",
569
- "favouritism": "favoritism",
570
- "favours": "favors",
571
- "feminise": "feminize",
572
- "feminised": "feminized",
573
- "feminises": "feminizes",
574
- "feminising": "feminizing",
575
- "fertilisation": "fertilization",
576
- "fertilise": "fertilize",
577
- "fertilised": "fertilized",
578
- "fertiliser": "fertilizer",
579
- "fertilisers": "fertilizers",
580
- "fertilises": "fertilizes",
581
- "fertilising": "fertilizing",
582
- "fervour": "fervor",
583
- "fibre": "fiber",
584
- "fibreglass": "fiberglass",
585
- "fibres": "fibers",
586
- "fictionalisation": "fictionalization",
587
- "fictionalisations": "fictionalizations",
588
- "fictionalise": "fictionalize",
589
- "fictionalised": "fictionalized",
590
- "fictionalises": "fictionalizes",
591
- "fictionalising": "fictionalizing",
592
- "fillet": "filet",
593
- "filleted": "fileted",
594
- "filleting": "fileting",
595
- "fillets": "filets",
596
- "finalisation": "finalization",
597
- "finalise": "finalize",
598
- "finalised": "finalized",
599
- "finalises": "finalizes",
600
- "finalising": "finalizing",
601
- "flautist": "flutist",
602
- "flautists": "flutists",
603
- "flavour": "flavor",
604
- "flavoured": "flavored",
605
- "flavouring": "flavoring",
606
- "flavourings": "flavorings",
607
- "flavourless": "flavorless",
608
- "flavours": "flavors",
609
- "flavoursome": "flavorsome",
610
- "flyer": "flier",
611
- "foetal": "fetal",
612
- "foetid": "fetid",
613
- "foetus": "fetus",
614
- "foetuses": "fetuses",
615
- "formalisation": "formalization",
616
- "formalise": "formalize",
617
- "formalised": "formalized",
618
- "formalises": "formalizes",
619
- "formalising": "formalizing",
620
- "fossilisation": "fossilization",
621
- "fossilise": "fossilize",
622
- "fossilised": "fossilized",
623
- "fossilises": "fossilizes",
624
- "fossilising": "fossilizing",
625
- "fraternisation": "fraternization",
626
- "fraternise": "fraternize",
627
- "fraternised": "fraternized",
628
- "fraternises": "fraternizes",
629
- "fraternising": "fraternizing",
630
- "fulfil": "fulfill",
631
- "fulfilment": "fulfillment",
632
- "fulfils": "fulfills",
633
- "funnelled": "funneled",
634
- "funnelling": "funneling",
635
- "gage": "gauge",
636
- "gaged": "gauged",
637
- "gages": "gauges",
638
- "gaging": "gauging",
639
- "galvanise": "galvanize",
640
- "galvanised": "galvanized",
641
- "galvanises": "galvanizes",
642
- "galvanising": "galvanizing",
643
- "gambolled": "gamboled",
644
- "gambolling": "gamboling",
645
- "gaol": "jail",
646
- "gaolbird": "jailbird",
647
- "gaolbirds": "jailbirds",
648
- "gaolbreak": "jailbreak",
649
- "gaolbreaks": "jailbreaks",
650
- "gaoled": "jailed",
651
- "gaoler": "jailer",
652
- "gaolers": "jailers",
653
- "gaoling": "jailing",
654
- "gaols": "jails",
655
- "gasses": "gases",
656
- "generalisation": "generalization",
657
- "generalisations": "generalizations",
658
- "generalise": "generalize",
659
- "generalised": "generalized",
660
- "generalises": "generalizes",
661
- "generalising": "generalizing",
662
- "ghettoise": "ghettoize",
663
- "ghettoised": "ghettoized",
664
- "ghettoises": "ghettoizes",
665
- "ghettoising": "ghettoizing",
666
- "gipsies": "gypsies",
667
- "glamor": "glamour",
668
- "glamorise": "glamorize",
669
- "glamorised": "glamorized",
670
- "glamorises": "glamorizes",
671
- "glamorising": "glamorizing",
672
- "globalisation": "globalization",
673
- "globalise": "globalize",
674
- "globalised": "globalized",
675
- "globalises": "globalizes",
676
- "globalising": "globalizing",
677
- "glueing": "gluing",
678
- "goitre": "goiter",
679
- "goitres": "goiters",
680
- "gonorrhoea": "gonorrhea",
681
- "gramme": "gram",
682
- "grammes": "grams",
683
- "gravelled": "graveled",
684
- "grey": "gray",
685
- "greyed": "grayed",
686
- "greying": "graying",
687
- "greyish": "grayish",
688
- "greyness": "grayness",
689
- "greys": "grays",
690
- "grovelled": "groveled",
691
- "grovelling": "groveling",
692
- "groyne": "groin",
693
- "groynes": "groins",
694
- "gruelling": "grueling",
695
- "gruellingly": "gruelingly",
696
- "gryphon": "griffin",
697
- "gryphons": "griffins",
698
- "gynaecological": "gynecological",
699
- "gynaecologist": "gynecologist",
700
- "gynaecologists": "gynecologists",
701
- "gynaecology": "gynecology",
702
- "haematological": "hematological",
703
- "haematologist": "hematologist",
704
- "haematologists": "hematologists",
705
- "haematology": "hematology",
706
- "haemoglobin": "hemoglobin",
707
- "haemophilia": "hemophilia",
708
- "haemophiliac": "hemophiliac",
709
- "haemophiliacs": "hemophiliacs",
710
- "haemorrhage": "hemorrhage",
711
- "haemorrhaged": "hemorrhaged",
712
- "haemorrhages": "hemorrhages",
713
- "haemorrhaging": "hemorrhaging",
714
- "haemorrhoids": "hemorrhoids",
715
- "harbour": "harbor",
716
- "harboured": "harbored",
717
- "harbouring": "harboring",
718
- "harbours": "harbors",
719
- "harmonisation": "harmonization",
720
- "harmonise": "harmonize",
721
- "harmonised": "harmonized",
722
- "harmonises": "harmonizes",
723
- "harmonising": "harmonizing",
724
- "homoeopath": "homeopath",
725
- "homoeopathic": "homeopathic",
726
- "homoeopaths": "homeopaths",
727
- "homoeopathy": "homeopathy",
728
- "homogenise": "homogenize",
729
- "homogenised": "homogenized",
730
- "homogenises": "homogenizes",
731
- "homogenising": "homogenizing",
732
- "honour": "honor",
733
- "honourable": "honorable",
734
- "honourably": "honorably",
735
- "honoured": "honored",
736
- "honouring": "honoring",
737
- "honours": "honors",
738
- "hospitalisation": "hospitalization",
739
- "hospitalise": "hospitalize",
740
- "hospitalised": "hospitalized",
741
- "hospitalises": "hospitalizes",
742
- "hospitalising": "hospitalizing",
743
- "humanise": "humanize",
744
- "humanised": "humanized",
745
- "humanises": "humanizes",
746
- "humanising": "humanizing",
747
- "humour": "humor",
748
- "humoured": "humored",
749
- "humouring": "humoring",
750
- "humourless": "humorless",
751
- "humours": "humors",
752
- "hybridise": "hybridize",
753
- "hybridised": "hybridized",
754
- "hybridises": "hybridizes",
755
- "hybridising": "hybridizing",
756
- "hypnotise": "hypnotize",
757
- "hypnotised": "hypnotized",
758
- "hypnotises": "hypnotizes",
759
- "hypnotising": "hypnotizing",
760
- "hypothesise": "hypothesize",
761
- "hypothesised": "hypothesized",
762
- "hypothesises": "hypothesizes",
763
- "hypothesising": "hypothesizing",
764
- "idealisation": "idealization",
765
- "idealise": "idealize",
766
- "idealised": "idealized",
767
- "idealises": "idealizes",
768
- "idealising": "idealizing",
769
- "idolise": "idolize",
770
- "idolised": "idolized",
771
- "idolises": "idolizes",
772
- "idolising": "idolizing",
773
- "immobilisation": "immobilization",
774
- "immobilise": "immobilize",
775
- "immobilised": "immobilized",
776
- "immobiliser": "immobilizer",
777
- "immobilisers": "immobilizers",
778
- "immobilises": "immobilizes",
779
- "immobilising": "immobilizing",
780
- "immortalise": "immortalize",
781
- "immortalised": "immortalized",
782
- "immortalises": "immortalizes",
783
- "immortalising": "immortalizing",
784
- "immunisation": "immunization",
785
- "immunise": "immunize",
786
- "immunised": "immunized",
787
- "immunises": "immunizes",
788
- "immunising": "immunizing",
789
- "impanelled": "impaneled",
790
- "impanelling": "impaneling",
791
- "imperilled": "imperiled",
792
- "imperilling": "imperiling",
793
- "individualise": "individualize",
794
- "individualised": "individualized",
795
- "individualises": "individualizes",
796
- "individualising": "individualizing",
797
- "industrialise": "industrialize",
798
- "industrialised": "industrialized",
799
- "industrialises": "industrializes",
800
- "industrialising": "industrializing",
801
- "inflexion": "inflection",
802
- "inflexions": "inflections",
803
- "initialise": "initialize",
804
- "initialised": "initialized",
805
- "initialises": "initializes",
806
- "initialising": "initializing",
807
- "initialled": "initialed",
808
- "initialling": "initialing",
809
- "instal": "install",
810
- "instalment": "installment",
811
- "instalments": "installments",
812
- "instals": "installs",
813
- "instil": "instill",
814
- "instils": "instills",
815
- "institutionalisation": "institutionalization",
816
- "institutionalise": "institutionalize",
817
- "institutionalised": "institutionalized",
818
- "institutionalises": "institutionalizes",
819
- "institutionalising": "institutionalizing",
820
- "intellectualise": "intellectualize",
821
- "intellectualised": "intellectualized",
822
- "intellectualises": "intellectualizes",
823
- "intellectualising": "intellectualizing",
824
- "internalisation": "internalization",
825
- "internalise": "internalize",
826
- "internalised": "internalized",
827
- "internalises": "internalizes",
828
- "internalising": "internalizing",
829
- "internationalisation": "internationalization",
830
- "internationalise": "internationalize",
831
- "internationalised": "internationalized",
832
- "internationalises": "internationalizes",
833
- "internationalising": "internationalizing",
834
- "ionisation": "ionization",
835
- "ionise": "ionize",
836
- "ionised": "ionized",
837
- "ioniser": "ionizer",
838
- "ionisers": "ionizers",
839
- "ionises": "ionizes",
840
- "ionising": "ionizing",
841
- "italicise": "italicize",
842
- "italicised": "italicized",
843
- "italicises": "italicizes",
844
- "italicising": "italicizing",
845
- "itemise": "itemize",
846
- "itemised": "itemized",
847
- "itemises": "itemizes",
848
- "itemising": "itemizing",
849
- "jeopardise": "jeopardize",
850
- "jeopardised": "jeopardized",
851
- "jeopardises": "jeopardizes",
852
- "jeopardising": "jeopardizing",
853
- "jewelled": "jeweled",
854
- "jeweller": "jeweler",
855
- "jewellers": "jewelers",
856
- "jewellery": "jewelry",
857
- "judgement": "judgment",
858
- "kilogramme": "kilogram",
859
- "kilogrammes": "kilograms",
860
- "kilometre": "kilometer",
861
- "kilometres": "kilometers",
862
- "labelled": "labeled",
863
- "labelling": "labeling",
864
- "labour": "labor",
865
- "laboured": "labored",
866
- "labourer": "laborer",
867
- "labourers": "laborers",
868
- "labouring": "laboring",
869
- "labours": "labors",
870
- "lacklustre": "lackluster",
871
- "legalisation": "legalization",
872
- "legalise": "legalize",
873
- "legalised": "legalized",
874
- "legalises": "legalizes",
875
- "legalising": "legalizing",
876
- "legitimise": "legitimize",
877
- "legitimised": "legitimized",
878
- "legitimises": "legitimizes",
879
- "legitimising": "legitimizing",
880
- "leukaemia": "leukemia",
881
- "levelled": "leveled",
882
- "leveller": "leveler",
883
- "levellers": "levelers",
884
- "levelling": "leveling",
885
- "libelled": "libeled",
886
- "libelling": "libeling",
887
- "libellous": "libelous",
888
- "liberalisation": "liberalization",
889
- "liberalise": "liberalize",
890
- "liberalised": "liberalized",
891
- "liberalises": "liberalizes",
892
- "liberalising": "liberalizing",
893
- "licence": "license",
894
- "licenced": "licensed",
895
- "licences": "licenses",
896
- "licencing": "licensing",
897
- "likeable": "likable",
898
- "lionisation": "lionization",
899
- "lionise": "lionize",
900
- "lionised": "lionized",
901
- "lionises": "lionizes",
902
- "lionising": "lionizing",
903
- "liquidise": "liquidize",
904
- "liquidised": "liquidized",
905
- "liquidiser": "liquidizer",
906
- "liquidisers": "liquidizers",
907
- "liquidises": "liquidizes",
908
- "liquidising": "liquidizing",
909
- "litre": "liter",
910
- "litres": "liters",
911
- "localise": "localize",
912
- "localised": "localized",
913
- "localises": "localizes",
914
- "localising": "localizing",
915
- "louvre": "louver",
916
- "louvred": "louvered",
917
- "louvres": "louvers",
918
- "lustre": "luster",
919
- "magnetise": "magnetize",
920
- "magnetised": "magnetized",
921
- "magnetises": "magnetizes",
922
- "magnetising": "magnetizing",
923
- "manoeuvrability": "maneuverability",
924
- "manoeuvrable": "maneuverable",
925
- "manoeuvre": "maneuver",
926
- "manoeuvred": "maneuvered",
927
- "manoeuvres": "maneuvers",
928
- "manoeuvring": "maneuvering",
929
- "manoeuvrings": "maneuverings",
930
- "marginalisation": "marginalization",
931
- "marginalise": "marginalize",
932
- "marginalised": "marginalized",
933
- "marginalises": "marginalizes",
934
- "marginalising": "marginalizing",
935
- "marshalled": "marshaled",
936
- "marshalling": "marshaling",
937
- "marvelled": "marveled",
938
- "marvelling": "marveling",
939
- "marvellous": "marvelous",
940
- "marvellously": "marvelously",
941
- "materialisation": "materialization",
942
- "materialise": "materialize",
943
- "materialised": "materialized",
944
- "materialises": "materializes",
945
- "materialising": "materializing",
946
- "maximisation": "maximization",
947
- "maximise": "maximize",
948
- "maximised": "maximized",
949
- "maximises": "maximizes",
950
- "maximising": "maximizing",
951
- "meagre": "meager",
952
- "mechanisation": "mechanization",
953
- "mechanise": "mechanize",
954
- "mechanised": "mechanized",
955
- "mechanises": "mechanizes",
956
- "mechanising": "mechanizing",
957
- "mediaeval": "medieval",
958
- "memorialise": "memorialize",
959
- "memorialised": "memorialized",
960
- "memorialises": "memorializes",
961
- "memorialising": "memorializing",
962
- "memorise": "memorize",
963
- "memorised": "memorized",
964
- "memorises": "memorizes",
965
- "memorising": "memorizing",
966
- "mesmerise": "mesmerize",
967
- "mesmerised": "mesmerized",
968
- "mesmerises": "mesmerizes",
969
- "mesmerising": "mesmerizing",
970
- "metabolise": "metabolize",
971
- "metabolised": "metabolized",
972
- "metabolises": "metabolizes",
973
- "metabolising": "metabolizing",
974
- "metre": "meter",
975
- "metres": "meters",
976
- "mhm": "hmm",
977
- "micrometre": "micrometer",
978
- "micrometres": "micrometers",
979
- "militarise": "militarize",
980
- "militarised": "militarized",
981
- "militarises": "militarizes",
982
- "militarising": "militarizing",
983
- "milligramme": "milligram",
984
- "milligrammes": "milligrams",
985
- "millilitre": "milliliter",
986
- "millilitres": "milliliters",
987
- "millimetre": "millimeter",
988
- "millimetres": "millimeters",
989
- "miniaturisation": "miniaturization",
990
- "miniaturise": "miniaturize",
991
- "miniaturised": "miniaturized",
992
- "miniaturises": "miniaturizes",
993
- "miniaturising": "miniaturizing",
994
- "minibusses": "minibuses",
995
- "minimise": "minimize",
996
- "minimised": "minimized",
997
- "minimises": "minimizes",
998
- "minimising": "minimizing",
999
- "misbehaviour": "misbehavior",
1000
- "misdemeanour": "misdemeanor",
1001
- "misdemeanours": "misdemeanors",
1002
- "misspelt": "misspelled",
1003
- "mitre": "miter",
1004
- "mitres": "miters",
1005
- "mm": "hmm",
1006
- "mmm": "hmm",
1007
- "mobilisation": "mobilization",
1008
- "mobilise": "mobilize",
1009
- "mobilised": "mobilized",
1010
- "mobilises": "mobilizes",
1011
- "mobilising": "mobilizing",
1012
- "modelled": "modeled",
1013
- "modeller": "modeler",
1014
- "modellers": "modelers",
1015
- "modelling": "modeling",
1016
- "modernise": "modernize",
1017
- "modernised": "modernized",
1018
- "modernises": "modernizes",
1019
- "modernising": "modernizing",
1020
- "moisturise": "moisturize",
1021
- "moisturised": "moisturized",
1022
- "moisturiser": "moisturizer",
1023
- "moisturisers": "moisturizers",
1024
- "moisturises": "moisturizes",
1025
- "moisturising": "moisturizing",
1026
- "monologue": "monolog",
1027
- "monologues": "monologs",
1028
- "monopolisation": "monopolization",
1029
- "monopolise": "monopolize",
1030
- "monopolised": "monopolized",
1031
- "monopolises": "monopolizes",
1032
- "monopolising": "monopolizing",
1033
- "moralise": "moralize",
1034
- "moralised": "moralized",
1035
- "moralises": "moralizes",
1036
- "moralising": "moralizing",
1037
- "motorised": "motorized",
1038
- "mould": "mold",
1039
- "moulded": "molded",
1040
- "moulder": "molder",
1041
- "mouldered": "moldered",
1042
- "mouldering": "moldering",
1043
- "moulders": "molders",
1044
- "mouldier": "moldier",
1045
- "mouldiest": "moldiest",
1046
- "moulding": "molding",
1047
- "mouldings": "moldings",
1048
- "moulds": "molds",
1049
- "mouldy": "moldy",
1050
- "moult": "molt",
1051
- "moulted": "molted",
1052
- "moulting": "molting",
1053
- "moults": "molts",
1054
- "moustache": "mustache",
1055
- "moustached": "mustached",
1056
- "moustaches": "mustaches",
1057
- "moustachioed": "mustachioed",
1058
- "multicoloured": "multicolored",
1059
- "nationalisation": "nationalization",
1060
- "nationalisations": "nationalizations",
1061
- "nationalise": "nationalize",
1062
- "nationalised": "nationalized",
1063
- "nationalises": "nationalizes",
1064
- "nationalising": "nationalizing",
1065
- "naturalisation": "naturalization",
1066
- "naturalise": "naturalize",
1067
- "naturalised": "naturalized",
1068
- "naturalises": "naturalizes",
1069
- "naturalising": "naturalizing",
1070
- "neighbour": "neighbor",
1071
- "neighbourhood": "neighborhood",
1072
- "neighbourhoods": "neighborhoods",
1073
- "neighbouring": "neighboring",
1074
- "neighbourliness": "neighborliness",
1075
- "neighbourly": "neighborly",
1076
- "neighbours": "neighbors",
1077
- "neutralisation": "neutralization",
1078
- "neutralise": "neutralize",
1079
- "neutralised": "neutralized",
1080
- "neutralises": "neutralizes",
1081
- "neutralising": "neutralizing",
1082
- "normalisation": "normalization",
1083
- "normalise": "normalize",
1084
- "normalised": "normalized",
1085
- "normalises": "normalizes",
1086
- "normalising": "normalizing",
1087
- "odour": "odor",
1088
- "odourless": "odorless",
1089
- "odours": "odors",
1090
- "oesophagus": "esophagus",
1091
- "oesophaguses": "esophaguses",
1092
- "oestrogen": "estrogen",
1093
- "offence": "offense",
1094
- "offences": "offenses",
1095
- "omelette": "omelet",
1096
- "omelettes": "omelets",
1097
- "optimise": "optimize",
1098
- "optimised": "optimized",
1099
- "optimises": "optimizes",
1100
- "optimising": "optimizing",
1101
- "organisation": "organization",
1102
- "organisational": "organizational",
1103
- "organisations": "organizations",
1104
- "organise": "organize",
1105
- "organised": "organized",
1106
- "organiser": "organizer",
1107
- "organisers": "organizers",
1108
- "organises": "organizes",
1109
- "organising": "organizing",
1110
- "orthopaedic": "orthopedic",
1111
- "orthopaedics": "orthopedics",
1112
- "ostracise": "ostracize",
1113
- "ostracised": "ostracized",
1114
- "ostracises": "ostracizes",
1115
- "ostracising": "ostracizing",
1116
- "outmanoeuvre": "outmaneuver",
1117
- "outmanoeuvred": "outmaneuvered",
1118
- "outmanoeuvres": "outmaneuvers",
1119
- "outmanoeuvring": "outmaneuvering",
1120
- "overemphasise": "overemphasize",
1121
- "overemphasised": "overemphasized",
1122
- "overemphasises": "overemphasizes",
1123
- "overemphasising": "overemphasizing",
1124
- "oxidisation": "oxidization",
1125
- "oxidise": "oxidize",
1126
- "oxidised": "oxidized",
1127
- "oxidises": "oxidizes",
1128
- "oxidising": "oxidizing",
1129
- "paederast": "pederast",
1130
- "paederasts": "pederasts",
1131
- "paediatric": "pediatric",
1132
- "paediatrician": "pediatrician",
1133
- "paediatricians": "pediatricians",
1134
- "paediatrics": "pediatrics",
1135
- "paedophile": "pedophile",
1136
- "paedophiles": "pedophiles",
1137
- "paedophilia": "pedophilia",
1138
- "palaeolithic": "paleolithic",
1139
- "palaeontologist": "paleontologist",
1140
- "palaeontologists": "paleontologists",
1141
- "palaeontology": "paleontology",
1142
- "panelled": "paneled",
1143
- "panelling": "paneling",
1144
- "panellist": "panelist",
1145
- "panellists": "panelists",
1146
- "paralyse": "paralyze",
1147
- "paralysed": "paralyzed",
1148
- "paralyses": "paralyzes",
1149
- "paralysing": "paralyzing",
1150
- "parcelled": "parceled",
1151
- "parcelling": "parceling",
1152
- "parlour": "parlor",
1153
- "parlours": "parlors",
1154
- "particularise": "particularize",
1155
- "particularised": "particularized",
1156
- "particularises": "particularizes",
1157
- "particularising": "particularizing",
1158
- "passivisation": "passivization",
1159
- "passivise": "passivize",
1160
- "passivised": "passivized",
1161
- "passivises": "passivizes",
1162
- "passivising": "passivizing",
1163
- "pasteurisation": "pasteurization",
1164
- "pasteurise": "pasteurize",
1165
- "pasteurised": "pasteurized",
1166
- "pasteurises": "pasteurizes",
1167
- "pasteurising": "pasteurizing",
1168
- "patronise": "patronize",
1169
- "patronised": "patronized",
1170
- "patronises": "patronizes",
1171
- "patronising": "patronizing",
1172
- "patronisingly": "patronizingly",
1173
- "pedalled": "pedaled",
1174
- "pedalling": "pedaling",
1175
- "pedestrianisation": "pedestrianization",
1176
- "pedestrianise": "pedestrianize",
1177
- "pedestrianised": "pedestrianized",
1178
- "pedestrianises": "pedestrianizes",
1179
- "pedestrianising": "pedestrianizing",
1180
- "penalise": "penalize",
1181
- "penalised": "penalized",
1182
- "penalises": "penalizes",
1183
- "penalising": "penalizing",
1184
- "pencilled": "penciled",
1185
- "pencilling": "penciling",
1186
- "personalise": "personalize",
1187
- "personalised": "personalized",
1188
- "personalises": "personalizes",
1189
- "personalising": "personalizing",
1190
- "pharmacopoeia": "pharmacopeia",
1191
- "pharmacopoeias": "pharmacopeias",
1192
- "philosophise": "philosophize",
1193
- "philosophised": "philosophized",
1194
- "philosophises": "philosophizes",
1195
- "philosophising": "philosophizing",
1196
- "philtre": "filter",
1197
- "philtres": "filters",
1198
- "phoney": "phony",
1199
- "plagiarise": "plagiarize",
1200
- "plagiarised": "plagiarized",
1201
- "plagiarises": "plagiarizes",
1202
- "plagiarising": "plagiarizing",
1203
- "plough": "plow",
1204
- "ploughed": "plowed",
1205
- "ploughing": "plowing",
1206
- "ploughman": "plowman",
1207
- "ploughmen": "plowmen",
1208
- "ploughs": "plows",
1209
- "ploughshare": "plowshare",
1210
- "ploughshares": "plowshares",
1211
- "polarisation": "polarization",
1212
- "polarise": "polarize",
1213
- "polarised": "polarized",
1214
- "polarises": "polarizes",
1215
- "polarising": "polarizing",
1216
- "politicisation": "politicization",
1217
- "politicise": "politicize",
1218
- "politicised": "politicized",
1219
- "politicises": "politicizes",
1220
- "politicising": "politicizing",
1221
- "popularisation": "popularization",
1222
- "popularise": "popularize",
1223
- "popularised": "popularized",
1224
- "popularises": "popularizes",
1225
- "popularising": "popularizing",
1226
- "pouffe": "pouf",
1227
- "pouffes": "poufs",
1228
- "practise": "practice",
1229
- "practised": "practiced",
1230
- "practises": "practices",
1231
- "practising": "practicing",
1232
- "praesidium": "presidium",
1233
- "praesidiums": "presidiums",
1234
- "pressurisation": "pressurization",
1235
- "pressurise": "pressurize",
1236
- "pressurised": "pressurized",
1237
- "pressurises": "pressurizes",
1238
- "pressurising": "pressurizing",
1239
- "pretence": "pretense",
1240
- "pretences": "pretenses",
1241
- "primaeval": "primeval",
1242
- "prioritisation": "prioritization",
1243
- "prioritise": "prioritize",
1244
- "prioritised": "prioritized",
1245
- "prioritises": "prioritizes",
1246
- "prioritising": "prioritizing",
1247
- "privatisation": "privatization",
1248
- "privatisations": "privatizations",
1249
- "privatise": "privatize",
1250
- "privatised": "privatized",
1251
- "privatises": "privatizes",
1252
- "privatising": "privatizing",
1253
- "professionalisation": "professionalization",
1254
- "professionalise": "professionalize",
1255
- "professionalised": "professionalized",
1256
- "professionalises": "professionalizes",
1257
- "professionalising": "professionalizing",
1258
- "programme": "program",
1259
- "programmes": "programs",
1260
- "prologue": "prolog",
1261
- "prologues": "prologs",
1262
- "propagandise": "propagandize",
1263
- "propagandised": "propagandized",
1264
- "propagandises": "propagandizes",
1265
- "propagandising": "propagandizing",
1266
- "proselytise": "proselytize",
1267
- "proselytised": "proselytized",
1268
- "proselytiser": "proselytizer",
1269
- "proselytisers": "proselytizers",
1270
- "proselytises": "proselytizes",
1271
- "proselytising": "proselytizing",
1272
- "psychoanalyse": "psychoanalyze",
1273
- "psychoanalysed": "psychoanalyzed",
1274
- "psychoanalyses": "psychoanalyzes",
1275
- "psychoanalysing": "psychoanalyzing",
1276
- "publicise": "publicize",
1277
- "publicised": "publicized",
1278
- "publicises": "publicizes",
1279
- "publicising": "publicizing",
1280
- "pulverisation": "pulverization",
1281
- "pulverise": "pulverize",
1282
- "pulverised": "pulverized",
1283
- "pulverises": "pulverizes",
1284
- "pulverising": "pulverizing",
1285
- "pummelled": "pummeled",
1286
- "pummelling": "pummeling",
1287
- "pyjama": "pajama",
1288
- "pyjamas": "pajamas",
1289
- "pzazz": "pizzazz",
1290
- "quarrelled": "quarreled",
1291
- "quarrelling": "quarreling",
1292
- "radicalise": "radicalize",
1293
- "radicalised": "radicalized",
1294
- "radicalises": "radicalizes",
1295
- "radicalising": "radicalizing",
1296
- "rancour": "rancor",
1297
- "randomise": "randomize",
1298
- "randomised": "randomized",
1299
- "randomises": "randomizes",
1300
- "randomising": "randomizing",
1301
- "rationalisation": "rationalization",
1302
- "rationalisations": "rationalizations",
1303
- "rationalise": "rationalize",
1304
- "rationalised": "rationalized",
1305
- "rationalises": "rationalizes",
1306
- "rationalising": "rationalizing",
1307
- "ravelled": "raveled",
1308
- "ravelling": "raveling",
1309
- "realisable": "realizable",
1310
- "realisation": "realization",
1311
- "realisations": "realizations",
1312
- "realise": "realize",
1313
- "realised": "realized",
1314
- "realises": "realizes",
1315
- "realising": "realizing",
1316
- "recognisable": "recognizable",
1317
- "recognisably": "recognizably",
1318
- "recognisance": "recognizance",
1319
- "recognise": "recognize",
1320
- "recognised": "recognized",
1321
- "recognises": "recognizes",
1322
- "recognising": "recognizing",
1323
- "reconnoitre": "reconnoiter",
1324
- "reconnoitred": "reconnoitered",
1325
- "reconnoitres": "reconnoiters",
1326
- "reconnoitring": "reconnoitering",
1327
- "refuelled": "refueled",
1328
- "refuelling": "refueling",
1329
- "regularisation": "regularization",
1330
- "regularise": "regularize",
1331
- "regularised": "regularized",
1332
- "regularises": "regularizes",
1333
- "regularising": "regularizing",
1334
- "remodelled": "remodeled",
1335
- "remodelling": "remodeling",
1336
- "remould": "remold",
1337
- "remoulded": "remolded",
1338
- "remoulding": "remolding",
1339
- "remoulds": "remolds",
1340
- "reorganisation": "reorganization",
1341
- "reorganisations": "reorganizations",
1342
- "reorganise": "reorganize",
1343
- "reorganised": "reorganized",
1344
- "reorganises": "reorganizes",
1345
- "reorganising": "reorganizing",
1346
- "revelled": "reveled",
1347
- "reveller": "reveler",
1348
- "revellers": "revelers",
1349
- "revelling": "reveling",
1350
- "revitalise": "revitalize",
1351
- "revitalised": "revitalized",
1352
- "revitalises": "revitalizes",
1353
- "revitalising": "revitalizing",
1354
- "revolutionise": "revolutionize",
1355
- "revolutionised": "revolutionized",
1356
- "revolutionises": "revolutionizes",
1357
- "revolutionising": "revolutionizing",
1358
- "rhapsodise": "rhapsodize",
1359
- "rhapsodised": "rhapsodized",
1360
- "rhapsodises": "rhapsodizes",
1361
- "rhapsodising": "rhapsodizing",
1362
- "rigour": "rigor",
1363
- "rigours": "rigors",
1364
- "ritualised": "ritualized",
1365
- "rivalled": "rivaled",
1366
- "rivalling": "rivaling",
1367
- "romanticise": "romanticize",
1368
- "romanticised": "romanticized",
1369
- "romanticises": "romanticizes",
1370
- "romanticising": "romanticizing",
1371
- "rumour": "rumor",
1372
- "rumoured": "rumored",
1373
- "rumours": "rumors",
1374
- "sabre": "saber",
1375
- "sabres": "sabers",
1376
- "saltpetre": "saltpeter",
1377
- "sanitise": "sanitize",
1378
- "sanitised": "sanitized",
1379
- "sanitises": "sanitizes",
1380
- "sanitising": "sanitizing",
1381
- "satirise": "satirize",
1382
- "satirised": "satirized",
1383
- "satirises": "satirizes",
1384
- "satirising": "satirizing",
1385
- "saviour": "savior",
1386
- "saviours": "saviors",
1387
- "savour": "savor",
1388
- "savoured": "savored",
1389
- "savouries": "savories",
1390
- "savouring": "savoring",
1391
- "savours": "savors",
1392
- "savoury": "savory",
1393
- "scandalise": "scandalize",
1394
- "scandalised": "scandalized",
1395
- "scandalises": "scandalizes",
1396
- "scandalising": "scandalizing",
1397
- "sceptic": "skeptic",
1398
- "sceptical": "skeptical",
1399
- "sceptically": "skeptically",
1400
- "scepticism": "skepticism",
1401
- "sceptics": "skeptics",
1402
- "sceptre": "scepter",
1403
- "sceptres": "scepters",
1404
- "scrutinise": "scrutinize",
1405
- "scrutinised": "scrutinized",
1406
- "scrutinises": "scrutinizes",
1407
- "scrutinising": "scrutinizing",
1408
- "secularisation": "secularization",
1409
- "secularise": "secularize",
1410
- "secularised": "secularized",
1411
- "secularises": "secularizes",
1412
- "secularising": "secularizing",
1413
- "sensationalise": "sensationalize",
1414
- "sensationalised": "sensationalized",
1415
- "sensationalises": "sensationalizes",
1416
- "sensationalising": "sensationalizing",
1417
- "sensitise": "sensitize",
1418
- "sensitised": "sensitized",
1419
- "sensitises": "sensitizes",
1420
- "sensitising": "sensitizing",
1421
- "sentimentalise": "sentimentalize",
1422
- "sentimentalised": "sentimentalized",
1423
- "sentimentalises": "sentimentalizes",
1424
- "sentimentalising": "sentimentalizing",
1425
- "sepulchre": "sepulcher",
1426
- "sepulchres": "sepulchers",
1427
- "serialisation": "serialization",
1428
- "serialisations": "serializations",
1429
- "serialise": "serialize",
1430
- "serialised": "serialized",
1431
- "serialises": "serializes",
1432
- "serialising": "serializing",
1433
- "sermonise": "sermonize",
1434
- "sermonised": "sermonized",
1435
- "sermonises": "sermonizes",
1436
- "sermonising": "sermonizing",
1437
- "sheikh": "sheik",
1438
- "shovelled": "shoveled",
1439
- "shovelling": "shoveling",
1440
- "shrivelled": "shriveled",
1441
- "shrivelling": "shriveling",
1442
- "signalise": "signalize",
1443
- "signalised": "signalized",
1444
- "signalises": "signalizes",
1445
- "signalising": "signalizing",
1446
- "signalled": "signaled",
1447
- "signalling": "signaling",
1448
- "smoulder": "smolder",
1449
- "smouldered": "smoldered",
1450
- "smouldering": "smoldering",
1451
- "smoulders": "smolders",
1452
- "snivelled": "sniveled",
1453
- "snivelling": "sniveling",
1454
- "snorkelled": "snorkeled",
1455
- "snorkelling": "snorkeling",
1456
- "snowplough": "snowplow",
1457
- "snowploughs": "snowplows",
1458
- "socialisation": "socialization",
1459
- "socialise": "socialize",
1460
- "socialised": "socialized",
1461
- "socialises": "socializes",
1462
- "socialising": "socializing",
1463
- "sodomise": "sodomize",
1464
- "sodomised": "sodomized",
1465
- "sodomises": "sodomizes",
1466
- "sodomising": "sodomizing",
1467
- "solemnise": "solemnize",
1468
- "solemnised": "solemnized",
1469
- "solemnises": "solemnizes",
1470
- "solemnising": "solemnizing",
1471
- "sombre": "somber",
1472
- "specialisation": "specialization",
1473
- "specialisations": "specializations",
1474
- "specialise": "specialize",
1475
- "specialised": "specialized",
1476
- "specialises": "specializes",
1477
- "specialising": "specializing",
1478
- "spectre": "specter",
1479
- "spectres": "specters",
1480
- "spiralled": "spiraled",
1481
- "spiralling": "spiraling",
1482
- "splendour": "splendor",
1483
- "splendours": "splendors",
1484
- "squirrelled": "squirreled",
1485
- "squirrelling": "squirreling",
1486
- "stabilisation": "stabilization",
1487
- "stabilise": "stabilize",
1488
- "stabilised": "stabilized",
1489
- "stabiliser": "stabilizer",
1490
- "stabilisers": "stabilizers",
1491
- "stabilises": "stabilizes",
1492
- "stabilising": "stabilizing",
1493
- "standardisation": "standardization",
1494
- "standardise": "standardize",
1495
- "standardised": "standardized",
1496
- "standardises": "standardizes",
1497
- "standardising": "standardizing",
1498
- "stencilled": "stenciled",
1499
- "stencilling": "stenciling",
1500
- "sterilisation": "sterilization",
1501
- "sterilisations": "sterilizations",
1502
- "sterilise": "sterilize",
1503
- "sterilised": "sterilized",
1504
- "steriliser": "sterilizer",
1505
- "sterilisers": "sterilizers",
1506
- "sterilises": "sterilizes",
1507
- "sterilising": "sterilizing",
1508
- "stigmatisation": "stigmatization",
1509
- "stigmatise": "stigmatize",
1510
- "stigmatised": "stigmatized",
1511
- "stigmatises": "stigmatizes",
1512
- "stigmatising": "stigmatizing",
1513
- "storey": "story",
1514
- "storeys": "stories",
1515
- "subsidisation": "subsidization",
1516
- "subsidise": "subsidize",
1517
- "subsidised": "subsidized",
1518
- "subsidiser": "subsidizer",
1519
- "subsidisers": "subsidizers",
1520
- "subsidises": "subsidizes",
1521
- "subsidising": "subsidizing",
1522
- "succour": "succor",
1523
- "succoured": "succored",
1524
- "succouring": "succoring",
1525
- "succours": "succors",
1526
- "sulphate": "sulfate",
1527
- "sulphates": "sulfates",
1528
- "sulphide": "sulfide",
1529
- "sulphides": "sulfides",
1530
- "sulphur": "sulfur",
1531
- "sulphurous": "sulfurous",
1532
- "summarise": "summarize",
1533
- "summarised": "summarized",
1534
- "summarises": "summarizes",
1535
- "summarising": "summarizing",
1536
- "swivelled": "swiveled",
1537
- "swivelling": "swiveling",
1538
- "symbolise": "symbolize",
1539
- "symbolised": "symbolized",
1540
- "symbolises": "symbolizes",
1541
- "symbolising": "symbolizing",
1542
- "sympathise": "sympathize",
1543
- "sympathised": "sympathized",
1544
- "sympathiser": "sympathizer",
1545
- "sympathisers": "sympathizers",
1546
- "sympathises": "sympathizes",
1547
- "sympathising": "sympathizing",
1548
- "synchronisation": "synchronization",
1549
- "synchronise": "synchronize",
1550
- "synchronised": "synchronized",
1551
- "synchronises": "synchronizes",
1552
- "synchronising": "synchronizing",
1553
- "synthesise": "synthesize",
1554
- "synthesised": "synthesized",
1555
- "synthesiser": "synthesizer",
1556
- "synthesisers": "synthesizers",
1557
- "synthesises": "synthesizes",
1558
- "synthesising": "synthesizing",
1559
- "syphon": "siphon",
1560
- "syphoned": "siphoned",
1561
- "syphoning": "siphoning",
1562
- "syphons": "siphons",
1563
- "systematisation": "systematization",
1564
- "systematise": "systematize",
1565
- "systematised": "systematized",
1566
- "systematises": "systematizes",
1567
- "systematising": "systematizing",
1568
- "tantalise": "tantalize",
1569
- "tantalised": "tantalized",
1570
- "tantalises": "tantalizes",
1571
- "tantalising": "tantalizing",
1572
- "tantalisingly": "tantalizingly",
1573
- "tasselled": "tasseled",
1574
- "technicolour": "technicolor",
1575
- "temporise": "temporize",
1576
- "temporised": "temporized",
1577
- "temporises": "temporizes",
1578
- "temporising": "temporizing",
1579
- "tenderise": "tenderize",
1580
- "tenderised": "tenderized",
1581
- "tenderises": "tenderizes",
1582
- "tenderising": "tenderizing",
1583
- "terrorise": "terrorize",
1584
- "terrorised": "terrorized",
1585
- "terrorises": "terrorizes",
1586
- "terrorising": "terrorizing",
1587
- "theatre": "theater",
1588
- "theatregoer": "theatergoer",
1589
- "theatregoers": "theatergoers",
1590
- "theatres": "theaters",
1591
- "theorise": "theorize",
1592
- "theorised": "theorized",
1593
- "theorises": "theorizes",
1594
- "theorising": "theorizing",
1595
- "tonne": "ton",
1596
- "tonnes": "tons",
1597
- "towelled": "toweled",
1598
- "towelling": "toweling",
1599
- "toxaemia": "toxemia",
1600
- "tranquillise": "tranquilize",
1601
- "tranquillised": "tranquilized",
1602
- "tranquilliser": "tranquilizer",
1603
- "tranquillisers": "tranquilizers",
1604
- "tranquillises": "tranquilizes",
1605
- "tranquillising": "tranquilizing",
1606
- "tranquillity": "tranquility",
1607
- "tranquillize": "tranquilize",
1608
- "tranquillized": "tranquilized",
1609
- "tranquillizer": "tranquilizer",
1610
- "tranquillizers": "tranquilizers",
1611
- "tranquillizes": "tranquilizes",
1612
- "tranquillizing": "tranquilizing",
1613
- "tranquilly": "tranquility",
1614
- "transistorised": "transistorized",
1615
- "traumatise": "traumatize",
1616
- "traumatised": "traumatized",
1617
- "traumatises": "traumatizes",
1618
- "traumatising": "traumatizing",
1619
- "travelled": "traveled",
1620
- "traveller": "traveler",
1621
- "travellers": "travelers",
1622
- "travelling": "traveling",
1623
- "travelogue": "travelog",
1624
- "travelogues": "travelogs",
1625
- "trialled": "trialed",
1626
- "trialling": "trialing",
1627
- "tricolour": "tricolor",
1628
- "tricolours": "tricolors",
1629
- "trivialise": "trivialize",
1630
- "trivialised": "trivialized",
1631
- "trivialises": "trivializes",
1632
- "trivialising": "trivializing",
1633
- "tumour": "tumor",
1634
- "tumours": "tumors",
1635
- "tunnelled": "tunneled",
1636
- "tunnelling": "tunneling",
1637
- "tyrannise": "tyrannize",
1638
- "tyrannised": "tyrannized",
1639
- "tyrannises": "tyrannizes",
1640
- "tyrannising": "tyrannizing",
1641
- "tyre": "tire",
1642
- "tyres": "tires",
1643
- "unauthorised": "unauthorized",
1644
- "uncivilised": "uncivilized",
1645
- "underutilised": "underutilized",
1646
- "unequalled": "unequaled",
1647
- "unfavourable": "unfavorable",
1648
- "unfavourably": "unfavorably",
1649
- "unionisation": "unionization",
1650
- "unionise": "unionize",
1651
- "unionised": "unionized",
1652
- "unionises": "unionizes",
1653
- "unionising": "unionizing",
1654
- "unorganised": "unorganized",
1655
- "unravelled": "unraveled",
1656
- "unravelling": "unraveling",
1657
- "unrecognisable": "unrecognizable",
1658
- "unrecognised": "unrecognized",
1659
- "unrivalled": "unrivaled",
1660
- "unsavoury": "unsavory",
1661
- "untrammelled": "untrammeled",
1662
- "urbanisation": "urbanization",
1663
- "urbanise": "urbanize",
1664
- "urbanised": "urbanized",
1665
- "urbanises": "urbanizes",
1666
- "urbanising": "urbanizing",
1667
- "utilisable": "utilizable",
1668
- "utilisation": "utilization",
1669
- "utilise": "utilize",
1670
- "utilised": "utilized",
1671
- "utilises": "utilizes",
1672
- "utilising": "utilizing",
1673
- "valour": "valor",
1674
- "vandalise": "vandalize",
1675
- "vandalised": "vandalized",
1676
- "vandalises": "vandalizes",
1677
- "vandalising": "vandalizing",
1678
- "vaporisation": "vaporization",
1679
- "vaporise": "vaporize",
1680
- "vaporised": "vaporized",
1681
- "vaporises": "vaporizes",
1682
- "vaporising": "vaporizing",
1683
- "vapour": "vapor",
1684
- "vapours": "vapors",
1685
- "verbalise": "verbalize",
1686
- "verbalised": "verbalized",
1687
- "verbalises": "verbalizes",
1688
- "verbalising": "verbalizing",
1689
- "victimisation": "victimization",
1690
- "victimise": "victimize",
1691
- "victimised": "victimized",
1692
- "victimises": "victimizes",
1693
- "victimising": "victimizing",
1694
- "videodisc": "videodisk",
1695
- "videodiscs": "videodisks",
1696
- "vigour": "vigor",
1697
- "visualisation": "visualization",
1698
- "visualisations": "visualizations",
1699
- "visualise": "visualize",
1700
- "visualised": "visualized",
1701
- "visualises": "visualizes",
1702
- "visualising": "visualizing",
1703
- "vocalisation": "vocalization",
1704
- "vocalisations": "vocalizations",
1705
- "vocalise": "vocalize",
1706
- "vocalised": "vocalized",
1707
- "vocalises": "vocalizes",
1708
- "vocalising": "vocalizing",
1709
- "vulcanised": "vulcanized",
1710
- "vulgarisation": "vulgarization",
1711
- "vulgarise": "vulgarize",
1712
- "vulgarised": "vulgarized",
1713
- "vulgarises": "vulgarizes",
1714
- "vulgarising": "vulgarizing",
1715
- "waggon": "wagon",
1716
- "waggons": "wagons",
1717
- "watercolour": "watercolor",
1718
- "watercolours": "watercolors",
1719
- "weaselled": "weaseled",
1720
- "weaselling": "weaseling",
1721
- "westernisation": "westernization",
1722
- "westernise": "westernize",
1723
- "westernised": "westernized",
1724
- "westernises": "westernizes",
1725
- "westernising": "westernizing",
1726
- "womanise": "womanize",
1727
- "womanised": "womanized",
1728
- "womaniser": "womanizer",
1729
- "womanisers": "womanizers",
1730
- "womanises": "womanizes",
1731
- "womanising": "womanizing",
1732
- "woollen": "woolen",
1733
- "woollens": "woolens",
1734
- "woollies": "woolies",
1735
- "woolly": "wooly",
1736
- "worshipped": "worshiped",
1737
- "worshipper": "worshiper",
1738
- "worshipping": "worshiping",
1739
- "yodelled": "yodeled",
1740
- "yodelling": "yodeling",
1741
- "yoghourt": "yogurt",
1742
- "yoghourts": "yogurts",
1743
- "yoghurt": "yogurt",
1744
- "yoghurts": "yogurts"
1745
- }
1746
-
1747
-
1748
- english_name_normalizer = {
1749
- # ── Double-letter variants ──────────────────────────────────────────────
1750
- "alan": "allen",
1751
- "allan": "allen",
1752
- "bridgette": "bridget",
1753
- "charly": "charlie",
1754
- "charley": "charlie",
1755
- "garry": "gary",
1756
- "gregg": "greg",
1757
- "jacky": "jackie",
1758
- "joann": "joanne",
1759
- "joane": "joanne",
1760
- "kellye": "kelly",
1761
- "kelli": "kelly",
1762
- "kelley": "kelly",
1763
- "lilly": "lily",
1764
- "micheal": "michael",
1765
- "michele": "michelle",
1766
- "mollie": "molly",
1767
- "phillip": "philip",
1768
- "sallie": "sally",
1769
- "stacey": "stacy",
1770
- "stacie": "stacy",
1771
- "tracey": "tracy",
1772
- "tracie": "tracy",
1773
- "bret": "brett",
1774
- "carrol": "carol",
1775
- "carole": "carol",
1776
- "carroll": "carol",
1777
- "allison": "alison",
1778
- "alyson": "alison",
1779
- "russel": "russell",
1780
- "douglass": "douglas",
1781
- "dominick": "dominic",
1782
- "robb": "rob",
1783
- # ── Chr/Kr variants ─────────────────────────────────────────────────────
1784
- "kris": "chris",
1785
- "kristopher": "christopher",
1786
- "cristopher": "christopher",
1787
- "kristina": "christina",
1788
- "kristen": "kristin",
1789
- # ── C/K variants ────────────────────────────────────────────────────────
1790
- "karl": "carl",
1791
- "kathy": "cathy",
1792
- "katherine": "catherine",
1793
- "kathryn": "catherine",
1794
- "catharine": "catherine",
1795
- "erik": "eric",
1796
- "erick": "eric",
1797
- "caren": "karen",
1798
- "caryn": "karen",
1799
- "karin": "karen",
1800
- "katelyn": "caitlin",
1801
- "kaitlyn": "caitlin",
1802
- "kaitlin": "caitlin",
1803
- "nikole": "nicole",
1804
- "veronika": "veronica",
1805
- "viktor": "victor",
1806
- "viktoria": "victoria",
1807
- "kevan": "kevin",
1808
- "patrik": "patrick",
1809
- "frederik": "frederick",
1810
- "fredrick": "frederick",
1811
- "lukas": "lucas",
1812
- # ── Silent letters / alternate spellings ───────────────────────────────
1813
- "ann": "anne",
1814
- "jon": "john",
1815
- "johnathan": "jonathan",
1816
- "jonathon": "jonathan",
1817
- "sara": "sarah",
1818
- "mathew": "matthew",
1819
- "nicolas": "nicholas",
1820
- "rachael": "rachel",
1821
- "rebekah": "rebecca",
1822
- "devorah": "deborah",
1823
- "theresa": "teresa",
1824
- "suzanne": "susanne",
1825
- "antony": "anthony",
1826
- "martyn": "martin",
1827
- "denis": "dennis",
1828
- "laurence": "lawrence",
1829
- "tomas": "thomas",
1830
- "tobey": "toby",
1831
- # ── Mac/Mc extensions ───────────────────────────────────────────────────
1832
- "macarthur": "mcarthur",
1833
- "macartney": "mccartney",
1834
- "macarthy": "mccarthy",
1835
- "maccarthy": "mccarthy",
1836
- "macdonald": "mcdonald",
1837
- "mackay": "mckay",
1838
- "mackenzie": "mckenzie",
1839
- "macleod": "mcleod",
1840
- "maclean": "mclean",
1841
- "macmillan": "mcmillan",
1842
- "macintosh": "mcintosh",
1843
- "macintyre": "mcintyre",
1844
- "macnamara": "mcnamara",
1845
- "macgowan": "mcgowan",
1846
- # ── International ─────────────────────────────────
1847
- "mohamad": "mohammed",
1848
- "mohamed": "mohammed",
1849
- "mohammad": "mohammed",
1850
- "muhammad": "mohammed",
1851
- "muhamad": "mohammed",
1852
- "muhammed": "mohammed",
1853
- "mouhamed": "mohammed",
1854
- "mouhamad": "mohammed",
1855
- "mahomet": "mohammed",
1856
- "fatimah": "fatima",
1857
- "yusuf": "yousef",
1858
- "yusef": "yousef",
1859
- "myriam": "miriam",
1860
- "rajeev": "rajiv",
1861
- # ── Miscellaneous homophones ────────────────────────────────────────────
1862
- "alphonso": "alfonso",
1863
- "bryan": "brian",
1864
- "geoffrey": "jeffrey",
1865
- "jeffery": "jeffrey",
1866
- "geoff": "jeff",
1867
- "neal": "neil",
1868
- "shaun": "sean",
1869
- "shawn": "sean",
1870
- "shayne": "shane",
1871
- "stephen": "steven",
1872
- "toni": "tony",
1873
- "leigh": "lee",
1874
- "lewis": "louis",
1875
- "marc": "mark",
1876
- "meghan": "megan",
1877
- "nathalie": "natalie",
1878
- "robyn": "robin",
1879
- "rodger": "roger",
1880
- "linsey": "lindsay",
1881
- "lindsey": "lindsay",
1882
- "zackary": "zachary",
1883
- "zachery": "zachary",
1884
- "zak": "zach",
1885
- "sheri": "sherry",
1886
- "cheri": "sherry",
1887
- "sherrie": "sherry",
1888
- "terri": "terry",
1889
- "lori": "laurie",
1890
- "jaime": "jamie",
1891
- "jayson": "jason",
1892
- "lesley": "leslie",
1893
- "lynda": "linda",
1894
- "lynne": "lynn",
1895
- "gayle": "gail",
1896
- "rhonda": "ronda",
1897
- "yvonne": "ivonne",
1898
- "stewart": "stuart",
1899
- "walther": "walter",
1900
- "symon": "simon",
1901
- "collin": "colin",
1902
- "dillon": "dylan",
1903
- "aron": "aaron",
1904
- "artur": "arthur",
1905
- "henri": "henry",
1906
- "josef": "joseph",
1907
- "pieter": "peter",
1908
- }
1909
-
1910
-
1911
- # Regex-based multi-word → single-token mappings, plus spellings that vary too
1912
- # freely to enumerate in english_spelling_normalizer (e.g. elongations).
1913
- # Applied after symbol removal, so hyphens/punctuation are already stripped.
1914
- # Keys are used with re.sub; values are the replacement strings.
1915
- english_compound_normalizer = {
1916
- r"\bet\s+cetera\b": "etc",
1917
- r"\bal\s+right\b": "alright",
1918
- r"\ball\s+right\b": "alright",
1919
- r"\bhow\s+ever\b": "however",
1920
- r"\bwi\s+fi\b": "wifi",
1921
- r"\bhi\s+fi\b": "hifi",
1922
- r"\blo\s+fi\b": "lofi",
1923
- r"\bsci\s+fi\b": "scifi",
1924
- r"\be\s+mail\b": "email",
1925
- r"\be\s+book\b": "ebook",
1926
- r"\be\s+commerce\b": "ecommerce",
1927
- r"\bx\s+ray\b": "xray",
1928
- r"\bt\s+shirt\b": "tshirt",
1929
- r"\ba\s+m\b": "am",
1930
- r"\bp\s+m\b": "pm",
1931
- r"\bo\s+k\b": "okay",
1932
- r"\bo+h+\b": "oh",
1933
- r"\booo+\b": "oh",
1934
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/vendor/multilingual.py DELETED
@@ -1,94 +0,0 @@
1
- # Adapted from Hugging Face text scoring, Apache-2.0; see provenance.json.
2
- # Only dependency imports and unrelated data-loading/scoring code were removed.
3
- import re
4
- from difflib import SequenceMatcher
5
- import num2words
6
- from .normalizer import BasicMultilingualTextNormalizer
7
- FILLER_WORDS = {}
8
-
9
- class MultilingualNormalizer(BasicMultilingualTextNormalizer):
10
- """BasicMultilingualTextNormalizer with optional number normalization.
11
-
12
- Call with just text for standard normalization (backward-compatible).
13
- Pass lang= to also convert digits to words via num2words and remove
14
- language-specific filler words (see FILLER_WORDS).
15
- """
16
-
17
- def __init__(self, remove_diacritics: bool = True):
18
- super().__init__(remove_diacritics)
19
- # Pre-compile filler patterns. Each filler word is passed through the
20
- # base normalization itself, so the pattern matches the normalized
21
- # text exactly (base normalization may strip punctuation such as "…"
22
- # or combining marks). Longest-first so that multi-word and longer
23
- # variants match before their prefixes. Matched on whitespace
24
- # boundaries ((?<!\S) / (?!\S)) rather than \b, which is unreliable
25
- # next to combining marks.
26
- self._filler_patterns = {}
27
- base_normalize = super().__call__
28
- for lang, words in FILLER_WORDS.items():
29
- normalized_words = {base_normalize(w) for w in words}
30
- normalized_words.discard("")
31
- self._filler_patterns[lang] = re.compile(
32
- r"(?<!\S)(?:"
33
- + "|".join(re.escape(w) for w in sorted(normalized_words, key=len, reverse=True))
34
- + r")(?!\S)"
35
- )
36
-
37
- def _remove_fillers(self, text, lang):
38
- pattern = self._filler_patterns.get(lang)
39
- if pattern is None:
40
- return text
41
- text = pattern.sub("", text)
42
- return re.sub(r"\s+", " ", text).strip()
43
-
44
- def _normalize_numbers(self, text, lang):
45
- # Join space-separated thousand groups (e.g. "10 000" -> "10000")
46
- text = re.sub(r"(\d)\s+(\d{3})\b", r"\1\2", text)
47
-
48
- # Convert remaining digit sequences to words
49
- def _replace(m):
50
- try:
51
- return num2words.num2words(int(m.group()), lang=lang)
52
- except Exception:
53
- return m.group()
54
-
55
- return re.sub(r"\d+", _replace, text)
56
-
57
- def __call__(self, s, lang=None):
58
- s = super().__call__(s)
59
- if lang is not None:
60
- s = self._remove_fillers(s, lang)
61
- s = self._normalize_numbers(s, lang)
62
- return s
63
-
64
- def normalize_compound_pairs(refs, preds):
65
- """Align compound word boundaries between ref/pred pairs.
66
-
67
- When a mismatch region has identical characters ignoring whitespace,
68
- normalize both sides to the joined form.
69
- """
70
- new_refs, new_preds = [], []
71
- for ref_text, pred_text in zip(refs, preds):
72
- ref_words = ref_text.split()
73
- pred_words = pred_text.split()
74
-
75
- sm = SequenceMatcher(None, ref_words, pred_words)
76
- new_rw, new_pw = [], []
77
-
78
- for tag, i1, i2, j1, j2 in sm.get_opcodes():
79
- if tag == "equal":
80
- new_rw.extend(ref_words[i1:i2])
81
- new_pw.extend(pred_words[j1:j2])
82
- else:
83
- rc = "".join(ref_words[i1:i2])
84
- pc = "".join(pred_words[j1:j2])
85
- if rc == pc:
86
- new_rw.append(rc)
87
- new_pw.append(pc)
88
- else:
89
- new_rw.extend(ref_words[i1:i2])
90
- new_pw.extend(pred_words[j1:j2])
91
-
92
- new_refs.append(" ".join(new_rw))
93
- new_preds.append(" ".join(new_pw))
94
- return new_refs, new_preds
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/vendor/normalizer.py DELETED
@@ -1,753 +0,0 @@
1
- # Copyright 2022 The OpenAI team and The HuggingFace Team. All rights reserved.
2
- # Most of the code is copy pasted from the original whisper repository
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- import re
17
- import unicodedata
18
- from fractions import Fraction
19
- from typing import Iterator, List, Match, Optional, Union
20
- from .english_abbreviations import english_name_normalizer, english_spelling_normalizer, english_compound_normalizer
21
-
22
- import regex
23
-
24
-
25
- # non-ASCII letters that are not separated by "NFKD" normalization
26
- ADDITIONAL_DIACRITICS = {
27
- "œ": "oe",
28
- "Œ": "OE",
29
- "ø": "o",
30
- "Ø": "O",
31
- "æ": "ae",
32
- "Æ": "AE",
33
- "ß": "ss",
34
- "ẞ": "SS",
35
- "đ": "d",
36
- "Đ": "D",
37
- "ð": "d",
38
- "Ð": "D",
39
- "þ": "th",
40
- "Þ": "th",
41
- "ł": "l",
42
- "Ł": "L",
43
- }
44
-
45
-
46
- def remove_symbols_and_diacritics(s: str, keep=""):
47
- """
48
- Replace any other markers, symbols, and punctuations with a space, and drop any diacritics (category 'Mn' and some
49
- manual mappings)
50
- """
51
-
52
- def replace_character(char):
53
- if char in keep:
54
- return char
55
- elif char in ADDITIONAL_DIACRITICS:
56
- return ADDITIONAL_DIACRITICS[char]
57
-
58
- elif unicodedata.category(char) == "Mn":
59
- return ""
60
-
61
- elif unicodedata.category(char)[0] in "MSP":
62
- return " "
63
-
64
- return char
65
-
66
- return "".join(replace_character(c) for c in unicodedata.normalize("NFKD", s))
67
-
68
-
69
- def remove_symbols(s: str):
70
- """
71
- Replace any other markers, symbols, punctuations with a space, keeping diacritics
72
- """
73
- return "".join(" " if unicodedata.category(c)[0] in "MSP" else c for c in unicodedata.normalize("NFKC", s))
74
-
75
-
76
- def remove_symbols_keep_marks(s: str):
77
- """
78
- Replace symbols and punctuation with a space, keeping combining marks.
79
-
80
- Unlike `remove_symbols`, combining marks (category 'M') are preserved. This
81
- is required for scripts like Devanagari, where vowel signs (matras) and the
82
- virama are combining marks that are integral to words.
83
- """
84
- return "".join(" " if unicodedata.category(c)[0] in "SP" else c for c in unicodedata.normalize("NFKC", s))
85
-
86
-
87
- class BasicTextNormalizer:
88
- def __init__(self, remove_diacritics: bool = False, split_letters: bool = False):
89
- self.clean = remove_symbols_and_diacritics if remove_diacritics else remove_symbols
90
- self.split_letters = split_letters
91
-
92
- def __call__(self, s: str):
93
- s = s.lower()
94
- s = re.sub(r"[<\[][^>\]]*[>\]]", "", s) # remove words between brackets
95
- s = re.sub(r"\(([^)]+?)\)", "", s) # remove words between parenthesis
96
- s = self.clean(s).lower()
97
-
98
- if self.split_letters:
99
- s = " ".join(regex.findall(r"\X", s, regex.U))
100
-
101
- s = re.sub(r"\s+", " ", s) # replace any successive whitespace characters with a space
102
-
103
- return s
104
-
105
-
106
- class BasicMultilingualTextNormalizer:
107
- def __init__(self, remove_diacritics: bool = True):
108
- # When keeping diacritics, also keep combining marks (category 'M'):
109
- # scripts like Devanagari encode vowel signs and the virama as
110
- # combining marks, so stripping them mangles words.
111
- self.clean = remove_symbols_and_diacritics if remove_diacritics else remove_symbols_keep_marks
112
-
113
- def __call__(self, s: str):
114
- s = s.lower()
115
- s = re.sub(r"[<\[][^>\]]*[>\]]", "", s) # remove words between brackets
116
- s = re.sub(r"\(([^)]+?)\)", "", s) # remove words between parenthesis
117
- s = self.clean(s).lower()
118
-
119
- # Remove punctuation and extra spaces
120
- s = regex.sub(r"[^\w\s]", "", s)
121
- s = re.sub(r"\s+", " ", s).strip()
122
-
123
- return s
124
-
125
-
126
- class EnglishNumberNormalizer:
127
- """
128
- Convert any spelled-out numbers into arabic numbers, while handling:
129
-
130
- - remove any commas
131
- - keep the suffixes such as: `1960s`, `274th`, `32nd`, etc.
132
- - spell out currency symbols after the number. e.g. `$20 million` -> `20000000 dollars`
133
- - spell out `one` and `ones`
134
- - interpret successive single-digit numbers as nominal: `one oh one` -> `101`
135
- """
136
-
137
- def __init__(self):
138
- super().__init__()
139
-
140
- self.zeros = {"o", "oh", "zero"}
141
- # fmt: off
142
- self.ones = {
143
- name: i
144
- for i, name in enumerate(
145
- ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"],
146
- start=1,
147
- )
148
- }
149
- # fmt: on
150
- self.ones_plural = {
151
- "sixes" if name == "six" else name + "s": (value, "s") for name, value in self.ones.items()
152
- }
153
- self.ones_ordinal = {
154
- "zeroth": (0, "th"),
155
- "first": (1, "st"),
156
- "second": (2, "nd"),
157
- "third": (3, "rd"),
158
- "fifth": (5, "th"),
159
- "twelfth": (12, "th"),
160
- **{
161
- name + ("h" if name.endswith("t") else "th"): (value, "th")
162
- for name, value in self.ones.items()
163
- if value > 3 and value != 5 and value != 12
164
- },
165
- }
166
- self.ones_suffixed = {**self.ones_plural, **self.ones_ordinal}
167
-
168
- self.tens = {
169
- "twenty": 20,
170
- "thirty": 30,
171
- "forty": 40,
172
- "fifty": 50,
173
- "sixty": 60,
174
- "seventy": 70,
175
- "eighty": 80,
176
- "ninety": 90,
177
- }
178
- self.tens_plural = {name.replace("y", "ies"): (value, "s") for name, value in self.tens.items()}
179
- self.tens_ordinal = {name.replace("y", "ieth"): (value, "th") for name, value in self.tens.items()}
180
- self.tens_suffixed = {**self.tens_plural, **self.tens_ordinal}
181
-
182
- self.multipliers = {
183
- "hundred": 100,
184
- "thousand": 1_000,
185
- "million": 1_000_000,
186
- "billion": 1_000_000_000,
187
- "trillion": 1_000_000_000_000,
188
- "quadrillion": 1_000_000_000_000_000,
189
- "quintillion": 1_000_000_000_000_000_000,
190
- "sextillion": 1_000_000_000_000_000_000_000,
191
- "septillion": 1_000_000_000_000_000_000_000_000,
192
- "octillion": 1_000_000_000_000_000_000_000_000_000,
193
- "nonillion": 1_000_000_000_000_000_000_000_000_000_000,
194
- "decillion": 1_000_000_000_000_000_000_000_000_000_000_000,
195
- }
196
- self.multipliers_plural = {name + "s": (value, "s") for name, value in self.multipliers.items()}
197
- self.multipliers_ordinal = {name + "th": (value, "th") for name, value in self.multipliers.items()}
198
- self.multipliers_suffixed = {**self.multipliers_plural, **self.multipliers_ordinal}
199
- self.decimals = {*self.ones, *self.tens, *self.zeros}
200
-
201
- self.preceding_prefixers = {
202
- "minus": "-",
203
- "negative": "-",
204
- "plus": "+",
205
- "positive": "+",
206
- }
207
- self.following_prefixers = {
208
- "pound": "£",
209
- "pounds": "£",
210
- "euro": "€",
211
- "euros": "€",
212
- "dollar": "$",
213
- "dollars": "$",
214
- "cent": "¢",
215
- "cents": "¢",
216
- }
217
- self.prefixes = set(list(self.preceding_prefixers.values()) + list(self.following_prefixers.values()))
218
- self.suffixers = {
219
- "per": {"cent": "%"},
220
- "percent": "%",
221
- }
222
- self.specials = {"and", "double", "triple", "point"}
223
-
224
- self.words = {
225
- key
226
- for mapping in [
227
- self.zeros,
228
- self.ones,
229
- self.ones_suffixed,
230
- self.tens,
231
- self.tens_suffixed,
232
- self.multipliers,
233
- self.multipliers_suffixed,
234
- self.preceding_prefixers,
235
- self.following_prefixers,
236
- self.suffixers,
237
- self.specials,
238
- ]
239
- for key in mapping
240
- }
241
- self.literal_words = {"one", "ones"}
242
-
243
- def process_words(self, words: List[str]) -> Iterator[str]:
244
- prefix: Optional[str] = None
245
- value: Optional[Union[str, int]] = None
246
- skip = False
247
-
248
- def to_fraction(s: str):
249
- try:
250
- return Fraction(s)
251
- except ValueError:
252
- return None
253
-
254
- def is_digit_token(token: Optional[str]) -> bool:
255
- """True for tokens that continue a digit sequence ("four", "oh", "20")."""
256
- return token is not None and bool(
257
- re.match(r"^\d+$", token)
258
- or token in self.zeros
259
- or token in self.ones
260
- or token in self.tens
261
- )
262
-
263
- def output(result: Union[str, int]):
264
- nonlocal prefix, value
265
- result = str(result)
266
- if prefix is not None:
267
- result = prefix + result
268
- value = None
269
- prefix = None
270
- return result
271
-
272
- if len(words) == 0:
273
- return
274
-
275
- for i, current in enumerate(words):
276
- prev = words[i - 1] if i != 0 else None
277
- next = words[i + 1] if i != len(words) - 1 else None
278
- if skip:
279
- skip = False
280
- continue
281
-
282
- next_is_numeric = next is not None and re.match(r"^\d+(\.\d+)?$", next)
283
- has_prefix = current[0] in self.prefixes
284
- current_without_prefix = current[1:] if has_prefix else current
285
- if re.match(r"^\d+(\.\d+)?$", current_without_prefix):
286
- # arabic numbers (potentially with signs and fractions)
287
- f = to_fraction(current_without_prefix)
288
- if f is None:
289
- raise ValueError("Converting the fraction failed")
290
-
291
- if value is not None:
292
- if isinstance(value, str) and value.endswith("."):
293
- # concatenate decimals / ip address components
294
- value = str(value) + str(current)
295
- continue
296
- else:
297
- yield output(value)
298
-
299
- prefix = current[0] if has_prefix else prefix
300
- if f.denominator == 1:
301
- value = f.numerator # store integers as int
302
- else:
303
- value = current_without_prefix
304
- elif current not in self.words:
305
- # non-numeric words
306
- if value is not None:
307
- yield output(value)
308
- yield output(current)
309
- elif current in self.zeros:
310
- # "oh" is far more often the interjection than a spoken zero, so
311
- # read it as a digit only inside a digit sequence: the sequence
312
- # has to continue on the right ("four oh one", "nineteen oh
313
- # five"), and with nothing pending on the left it takes two more
314
- # digit tokens, i.e. a serial/phone-style reading ("oh seven nine
315
- # eight"). On its own — including the doubled "oh oh" — it stays
316
- # a word. "o" and "zero" are unchanged.
317
- next2 = words[i + 2] if i + 2 < len(words) else None
318
- in_number = is_digit_token(next) and (
319
- value is not None or is_digit_token(next2)
320
- )
321
- if current == "oh" and not in_number:
322
- if value is not None:
323
- yield output(value) # don't drop a pending number
324
- yield output(current)
325
- else:
326
- value = str(value or "") + "0"
327
- elif current in self.ones:
328
- ones = self.ones[current]
329
-
330
- if value is None:
331
- value = ones
332
- elif isinstance(value, str) or prev in self.ones:
333
- if prev in self.tens and ones < 10: # replace the last zero with the digit
334
- value = value[:-1] + str(ones)
335
- else:
336
- value = str(value) + str(ones)
337
- elif ones < 10:
338
- if value % 10 == 0:
339
- value += ones
340
- else:
341
- value = str(value) + str(ones)
342
- else: # eleven to nineteen
343
- if value % 100 == 0:
344
- value += ones
345
- else:
346
- value = str(value) + str(ones)
347
- elif current in self.ones_suffixed:
348
- # ordinal or cardinal; yield the number right away
349
- ones, suffix = self.ones_suffixed[current]
350
- if value is None:
351
- yield output(str(ones) + suffix)
352
- elif isinstance(value, str) or prev in self.ones:
353
- if prev in self.tens and ones < 10:
354
- yield output(value[:-1] + str(ones) + suffix)
355
- else:
356
- yield output(str(value) + str(ones) + suffix)
357
- elif ones < 10:
358
- if value % 10 == 0:
359
- yield output(str(value + ones) + suffix)
360
- else:
361
- yield output(str(value) + str(ones) + suffix)
362
- else: # eleven to nineteen
363
- if value % 100 == 0:
364
- yield output(str(value + ones) + suffix)
365
- else:
366
- yield output(str(value) + str(ones) + suffix)
367
- value = None
368
- elif current in self.tens:
369
- tens = self.tens[current]
370
- if value is None:
371
- value = tens
372
- elif isinstance(value, str):
373
- value = str(value) + str(tens)
374
- else:
375
- if value % 100 == 0:
376
- value += tens
377
- else:
378
- value = str(value) + str(tens)
379
- elif current in self.tens_suffixed:
380
- # ordinal or cardinal; yield the number right away
381
- tens, suffix = self.tens_suffixed[current]
382
- if value is None:
383
- yield output(str(tens) + suffix)
384
- elif isinstance(value, str):
385
- yield output(str(value) + str(tens) + suffix)
386
- else:
387
- if value % 100 == 0:
388
- yield output(str(value + tens) + suffix)
389
- else:
390
- yield output(str(value) + str(tens) + suffix)
391
- elif current in self.multipliers:
392
- multiplier = self.multipliers[current]
393
- if value is None:
394
- value = multiplier
395
- elif isinstance(value, str) or value == 0:
396
- f = to_fraction(value)
397
- p = f * multiplier if f is not None else None
398
- if f is not None and p.denominator == 1:
399
- value = p.numerator
400
- else:
401
- yield output(value)
402
- value = multiplier
403
- else:
404
- before = value // 1000 * 1000
405
- residual = value % 1000
406
- value = before + residual * multiplier
407
- elif current in self.multipliers_suffixed:
408
- multiplier, suffix = self.multipliers_suffixed[current]
409
- if value is None:
410
- yield output(str(multiplier) + suffix)
411
- elif isinstance(value, str):
412
- f = to_fraction(value)
413
- p = f * multiplier if f is not None else None
414
- if f is not None and p.denominator == 1:
415
- yield output(str(p.numerator) + suffix)
416
- else:
417
- yield output(value)
418
- yield output(str(multiplier) + suffix)
419
- else: # int
420
- before = value // 1000 * 1000
421
- residual = value % 1000
422
- value = before + residual * multiplier
423
- yield output(str(value) + suffix)
424
- value = None
425
- elif current in self.preceding_prefixers:
426
- # apply prefix (positive, minus, etc.) if it precedes a number
427
- if value is not None:
428
- yield output(value)
429
-
430
- if next in self.words or next_is_numeric:
431
- prefix = self.preceding_prefixers[current]
432
- else:
433
- yield output(current)
434
- elif current in self.following_prefixers:
435
- # apply prefix (dollars, cents, etc.) only after a number
436
- if value is not None:
437
- prefix = self.following_prefixers[current]
438
- yield output(value)
439
- else:
440
- yield output(current)
441
- elif current in self.suffixers:
442
- # apply suffix symbols (percent -> '%')
443
- if value is not None:
444
- suffix = self.suffixers[current]
445
- if isinstance(suffix, dict):
446
- if next in suffix:
447
- yield output(str(value) + suffix[next])
448
- skip = True
449
- else:
450
- yield output(value)
451
- yield output(current)
452
- else:
453
- yield output(str(value) + suffix)
454
- else:
455
- yield output(current)
456
- elif current in self.specials:
457
- if next not in self.words and not next_is_numeric:
458
- # apply special handling only if the next word can be numeric
459
- if value is not None:
460
- yield output(value)
461
- yield output(current)
462
- elif current == "and":
463
- # ignore "and" after hundreds, thousands, etc.
464
- if prev not in self.multipliers:
465
- if value is not None:
466
- yield output(value)
467
- yield output(current)
468
- elif current == "double" or current == "triple":
469
- if next in self.ones or next in self.zeros:
470
- repeats = 2 if current == "double" else 3
471
- ones = self.ones.get(next, 0)
472
- value = str(value or "") + str(ones) * repeats
473
- skip = True
474
- else:
475
- if value is not None:
476
- yield output(value)
477
- yield output(current)
478
- elif current == "point":
479
- if next in self.decimals or next_is_numeric:
480
- value = str(value or "") + "."
481
- else:
482
- # should all have been covered at this point
483
- raise ValueError(f"Unexpected token: {current}")
484
- else:
485
- # all should have been covered at this point
486
- raise ValueError(f"Unexpected token: {current}")
487
-
488
- if value is not None:
489
- yield output(value)
490
-
491
- def preprocess(self, s: str):
492
- # replace "<number> and a half" with "<number> point five"
493
- results = []
494
-
495
- segments = re.split(r"\band\s+a\s+half\b", s)
496
- for i, segment in enumerate(segments):
497
- if len(segment.strip()) == 0:
498
- continue
499
- if i == len(segments) - 1:
500
- results.append(segment)
501
- else:
502
- results.append(segment)
503
- last_word = segment.rsplit(maxsplit=2)[-1]
504
- if last_word in self.decimals or last_word in self.multipliers:
505
- results.append("point five")
506
- else:
507
- results.append("and a half")
508
-
509
- s = " ".join(results)
510
-
511
- # put a space at number/letter boundary
512
- s = re.sub(r"([a-z])([0-9])", r"\1 \2", s)
513
- s = re.sub(r"([0-9])([a-z])", r"\1 \2", s)
514
-
515
- # but remove spaces which could be a suffix
516
- s = re.sub(r"([0-9])\s+(st|nd|rd|th|s)\b", r"\1\2", s)
517
-
518
- return s
519
-
520
- def postprocess(self, s: str):
521
- def combine_cents(m: Match):
522
- try:
523
- currency = m.group(1)
524
- integer = m.group(2)
525
- cents = int(m.group(3))
526
- return f"{currency}{integer}.{cents:02d}"
527
- except ValueError:
528
- return m.string
529
-
530
- def extract_cents(m: Match):
531
- try:
532
- return f"¢{int(m.group(1))}"
533
- except ValueError:
534
- return m.string
535
-
536
- # apply currency postprocessing; "$2 and ¢7" -> "$2.07"
537
- s = re.sub(r"([€£$])([0-9]+) (?:and )?¢([0-9]{1,2})\b", combine_cents, s)
538
- s = re.sub(r"[€£$]0.([0-9]{1,2})\b", extract_cents, s)
539
-
540
- # write "one(s)" instead of "1(s)", just for the readability
541
- s = re.sub(r"\b1(s?)\b", r"one\1", s)
542
-
543
- return s
544
-
545
- def __call__(self, s: str):
546
- s = self.preprocess(s)
547
- s = " ".join(word for word in self.process_words(s.split()) if word is not None)
548
- s = self.postprocess(s)
549
-
550
- return s
551
-
552
-
553
- class EnglishSpellingNormalizer:
554
- """
555
- Applies British-American spelling mappings as listed in [1].
556
-
557
- [1] https://www.tysto.com/uk-us-spelling-list.html
558
- """
559
-
560
- def __init__(self, english_spelling_mapping):
561
- self.mapping = english_spelling_mapping
562
-
563
- def __call__(self, s: str):
564
- return " ".join(self.mapping.get(word, word) for word in s.split())
565
-
566
-
567
- class EnglishAcronymNormalizer:
568
- """
569
- Collapse sequences of single-character tokens (letters or digits) into single words.
570
-
571
- This normalizes acronym spacing so that both spaced-out and joined forms match:
572
- - "b b c" -> "bbc"
573
- - "5 g" -> "5g"
574
-
575
- Lone single-character words surrounded by multi-character words are left untouched
576
- (e.g. "a big cat" stays "a big cat").
577
- """
578
-
579
- def __call__(self, s: str) -> str:
580
- words = s.split()
581
- result = []
582
- i = 0
583
- while i < len(words):
584
- if len(words[i]) == 1 and words[i].isalnum():
585
- # Start of a potential acronym run
586
- run = [words[i]]
587
- j = i + 1
588
- while j < len(words) and len(words[j]) == 1 and words[j].isalnum():
589
- run.append(words[j])
590
- j += 1
591
- # Require 3+ tokens if the run contains common words "a" or "i",
592
- # otherwise 2+ is enough (e.g. "5 g" -> "5g")
593
- has_common_word = any(c in ("a", "i") for c in run)
594
- min_run = 3 if has_common_word else 2
595
- if len(run) >= min_run:
596
- result.append("".join(run))
597
- else:
598
- result.extend(run)
599
- i = j
600
- else:
601
- result.append(words[i])
602
- i += 1
603
- return " ".join(result)
604
-
605
-
606
- class EnglishNameNormalizer:
607
- """
608
- Collapse common name spelling variants to a single canonical form.
609
-
610
- This is intentionally conservative and token-based so it can be extended
611
- with project-specific aliases when needed.
612
- """
613
-
614
- def __init__(self, english_name_mapping=english_name_normalizer):
615
- self.mapping = english_name_mapping
616
-
617
- def __call__(self, s: str):
618
- return " ".join(self.mapping.get(word, word) for word in s.split())
619
-
620
-
621
- class EnglishTextNormalizer:
622
- def __init__(self, english_spelling_mapping=english_spelling_normalizer):
623
- # Filler words / hesitations to remove. Written as regexes so that
624
- # arbitrary elongation is covered without enumerating every spelling
625
- # ("uh", "uhh", "uuuh", "uhhhh", ...). Each alternative is wrapped in
626
- # \b...\b below, so a shorter alternative cannot match a prefix of a
627
- # longer token and the order of the single-token patterns is irrelevant.
628
- # Hyphens are word boundaries too, which is why most hyphenated forms
629
- # need no entry ("um-hmm" is matched as "um" + "hmm") — but any whose
630
- # halves are not both fillers must be listed *before* the patterns,
631
- # otherwise only the first half is matched ("ah-ha" -> "ha").
632
- filler_words = [
633
- "ah-ha", # "ha" alone is not a filler, so match the pair first
634
- r"a+h+m*", # ah, aah, ahh, ahhh, aaah, ahm, ahmm
635
- r"a+h+a+", # aha, ahaa, ahaaa
636
- r"e+h+m*", # eh, ehh, eeeh, ehhh, ehm, ehmm
637
- r"e+m+", # em, emm
638
- r"e+r+m*", # er, err, errr, erm
639
- r"h+a+h+", # hah, hahh
640
- r"h+e+h+", # heh, hehh
641
- r"h+m+", # hm, hmm, hmmm, hhm
642
- r"h+u+h+", # huh, huhh
643
- r"m{2,}", # mm, mmm, mmmm
644
- r"m+h+m*", # mh, mhm, mhmm, mmhm
645
- r"t+s+k+", # tsk
646
- r"u+g+h+", # ugh, uuugh
647
- r"u+h+m*", # uh, uuh, uhh, uhhh, uuuh, uhm, uuuhm
648
- r"u+h+u+[hm]*", # uhuh, uhum
649
- r"u+m+h*", # um, umm, ummm, uuum, umh
650
- # Irregular forms, not worth a pattern of their own.
651
- "ahem", "eheh", "ehehe", "ehr", "hmmph", "hum", "hunh", "mhum", "mmkay",
652
- ]
653
- self.ignore_patterns = r"\b(" + "|".join(filler_words) + r")\b"
654
- self.replacers = {
655
- # Bare o'clock times: the ":00" is not spoken as words, so drop it
656
- # ("2:00 AM" -> "2 am"). Applied here, while the colon is still
657
- # present, so that a time is distinguishable from an unrelated
658
- # digit sequence — by the time symbols are stripped "3:00" and
659
- # "3 00" look alike. Without this the minutes are absorbed into the
660
- # hour ("3:00" -> "30") or left as a stray token ("11:00" -> "11 0").
661
- r"\b(\d{1,2}):00\b": r"\1",
662
- # common contractions
663
- r"\bwon't\b": "will not",
664
- r"\bcan't\b": "can not",
665
- r"\blet's\b": "let us",
666
- r"\bain't\b": "aint",
667
- r"\by'all\b": "you all",
668
- r"\bwanna\b": "want to",
669
- r"\bgotta\b": "got to",
670
- r"\bgonna\b": "going to",
671
- r"\bi'ma\b": "i am going to",
672
- r"\bimma\b": "i am going to",
673
- r"\bwoulda\b": "would have",
674
- r"\bcoulda\b": "could have",
675
- r"\bshoulda\b": "should have",
676
- r"\bma'am\b": "madam",
677
- # contractions in titles/prefixes
678
- r"\bmr\b": "mister ",
679
- r"\bmrs\b": "missus ",
680
- r"\bst\b": "saint ",
681
- r"\bdr\b": "doctor ",
682
- r"\bprof\b": "professor ",
683
- r"\bcapt\b": "captain ",
684
- r"\bgov\b": "governor ",
685
- r"\bald\b": "alderman ",
686
- r"\bgen\b": "general ",
687
- r"\bsen\b": "senator ",
688
- r"\brep\b": "representative ",
689
- r"\bpres\b": "president ",
690
- r"\brev\b": "reverend ",
691
- r"\bhon\b": "honorable ",
692
- r"\basst\b": "assistant ",
693
- r"\bassoc\b": "associate ",
694
- r"\blt\b": "lieutenant ",
695
- r"\bcol\b": "colonel ",
696
- r"\bjr\b": "junior ",
697
- r"\bsr\b": "senior ",
698
- r"\besq\b": "esquire ",
699
- # prefect tenses, ideally it should be any past participles, but it's harder..
700
- r"'d been\b": " had been",
701
- r"'s been\b": " has been",
702
- r"'d gone\b": " had gone",
703
- r"'s gone\b": " has gone",
704
- r"'d done\b": " had done", # "'s done" is ambiguous
705
- r"'s got\b": " has got",
706
- # general contractions
707
- r"n't\b": " not",
708
- r"'re\b": " are",
709
- r"\b(it|he|she|what|that|who|here|there|how|when|where|why|this)'s\b": r"\1 is",
710
- r"'d\b": " would",
711
- r"'ll\b": " will",
712
- r"'t\b": " not",
713
- r"'ve\b": " have",
714
- r"'m\b": " am",
715
- }
716
- self.standardize_numbers = EnglishNumberNormalizer()
717
- self.standardize_spellings = EnglishSpellingNormalizer(english_spelling_mapping)
718
- self.standardize_names = EnglishNameNormalizer()
719
- self.standardize_acronyms = EnglishAcronymNormalizer()
720
- # Multi-word compound mappings — defined in english_abbreviations.py
721
- self.compound_words = english_compound_normalizer
722
-
723
- def __call__(self, s: str):
724
- s = s.lower()
725
-
726
- s = re.sub(r"[<\[][^>\]]*[>\]]", "", s) # remove words between brackets
727
- s = re.sub(r"\(([^)]+?)\)", "", s) # remove words between parenthesis
728
- s = re.sub(self.ignore_patterns, "", s)
729
- s = re.sub(r"\s+'", "'", s) # standardize when there's a space before an apostrophe
730
-
731
- for pattern, replacement in self.replacers.items():
732
- s = re.sub(pattern, replacement, s)
733
-
734
- s = re.sub(r"(\d),(\d)", r"\1\2", s) # remove commas between digits
735
- s = re.sub(r"\.([^0-9]|$)", r" \1", s) # remove periods not followed by numbers
736
- s = remove_symbols_and_diacritics(s, keep=".%$¢€£") # keep some symbols for numerics
737
-
738
- # Normalize hardcoded compound words (e.g. "wi fi" -> "wifi" after hyphen removal)
739
- for pattern, replacement in self.compound_words.items():
740
- s = re.sub(pattern, replacement, s)
741
-
742
- s = self.standardize_numbers(s)
743
- s = self.standardize_spellings(s)
744
- s = self.standardize_names(s)
745
- s = self.standardize_acronyms(s)
746
-
747
- # now remove prefix/suffix symbols that are not preceded/followed by numbers
748
- s = re.sub(r"[.$¢€£]([^0-9])", r" \1", s)
749
- s = re.sub(r"([^0-9])%", r"\1 ", s)
750
-
751
- s = re.sub(r"\s+", " ", s) # replace any successive whitespace characters with a space
752
-
753
- return s
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
evaluation/standard_asr/vendor/provenance.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "repository": "https://github.com/huggingface/open_asr_leaderboard",
3
- "revision": "48219c6028db0517d704600d92f31edfc96e8c23",
4
- "license": "Apache-2.0",
5
- "upstream_sha256": {
6
- "normalizer/normalizer.py": "490b56393484ef386b486f3679cc2261264af280b3512154431e0bdcf2778295",
7
- "normalizer/english_abbreviations.py": "52997cc963e0bd6568d15554ad8d5fb0759f20f361483632a22f90d2d0e07db1",
8
- "normalizer/data_utils.py": "738f362b477ee357f743a567b8bbd69fac49e56dce0a477cbdd52dec863842b8",
9
- "normalizer/eval_utils.py": "27138d5884e39f5e6422e1dc48ce60dc2f5c15a56e63117115d7e6088d29e449"
10
- },
11
- "vendored_sha256": {
12
- "LICENSE": "5ee13882fce0975f0ad3c3d5c2042af4896c2a669be2d6df5b3d256811267c85",
13
- "english_abbreviations.py": "52997cc963e0bd6568d15554ad8d5fb0759f20f361483632a22f90d2d0e07db1",
14
- "__init__.py": "8c39e42af3204c41c564c970e24525da160663836b54acc1b629e4342f862334",
15
- "multilingual.py": "4c8db6c4171c8c2f5567d2ed625a3a1f0d45156af45ca42d9555c0c9b61a29d5",
16
- "normalizer.py": "490b56393484ef386b486f3679cc2261264af280b3512154431e0bdcf2778295"
17
- },
18
- "modifications": {
19
- "normalizer.py": "None",
20
- "english_abbreviations.py": "None",
21
- "multilingual.py": "Exact MultilingualNormalizer and normalize_compound_pairs definitions extracted; imports minimized, empty FILLER_WORDS preserved."
22
- }
23
- }