owensong commited on
Commit
dcc5418
·
verified ·
1 Parent(s): e64e6aa

Stage verified Inflect v2 release candidate and evaluation evidence

Browse files
Files changed (3) hide show
  1. README.md +8 -8
  2. inflect_nano_v2_frontend.py +46 -0
  3. release_manifest.json +120 -15
README.md CHANGED
@@ -15,11 +15,11 @@ tags:
15
 
16
  <h1 align="center">Inflect-Micro-v2</h1>
17
 
18
- <p align="center"><strong>A complete 24 kHz text-to-waveform TTS system in 9,356,513 parameters.</strong><br>One English voice. CPU-ready. No external vocoder.</p>
19
-
20
- <p align="center"><a href="https://huggingface.co/spaces/owensong/Inflect-v2-Private-Playground"><strong>Try Micro and Nano in the browser</strong></a></p>
21
-
22
- Inflect-Micro-v2 is designed for local applications where the entire speech stack must fit below **10M parameters**. The count includes text encoding, duration modeling, latent generation, and waveform decoding. It does not hide a separately downloaded vocoder.
23
 
24
  ## Listen First
25
 
@@ -67,9 +67,9 @@ The selected Inflect-Micro-v2 checkpoint scored **4.406 UTMOS22** and **1.23% se
67
  - All four systems synthesize the same 200 unseen English prompts.
68
  - Semantic WER uses Whisper-large-v3 and the disclosed English text normalizer.
69
  - UTMOS22 uses `tarepan/SpeechMOS` v1.2.0 with 5,000 paired bootstrap samples.
70
- - NISQA dimensions, signal diagnostics, categorized ASR failures, speaker consistency, and multi-seed robustness are under `evaluation/`.
71
- - `evaluation/asr_robustness.json` separates sentence failures, semantic character errors, tail WER, and category-level errors.
72
- - Competitor results apply only to the named checkpoints and voices, not every configuration of those projects.
73
 
74
  </details>
75
 
 
15
 
16
  <h1 align="center">Inflect-Micro-v2</h1>
17
 
18
+ <p align="center"><strong>A complete 24 kHz text-to-waveform TTS system in 9,356,513 parameters.</strong><br>One English voice. CPU-ready. No external vocoder.</p>
19
+
20
+ <p align="center"><a href="https://huggingface.co/spaces/owensong/Inflect-v2-Private-Playground"><strong>Try Micro and Nano in the browser</strong></a></p>
21
+
22
+ Inflect-Micro-v2 is designed for local applications where the entire speech stack must fit below **10M parameters**. The count includes text encoding, duration modeling, latent generation, and waveform decoding. It does not hide a separately downloaded vocoder.
23
 
24
  ## Listen First
25
 
 
67
  - All four systems synthesize the same 200 unseen English prompts.
68
  - Semantic WER uses Whisper-large-v3 and the disclosed English text normalizer.
69
  - UTMOS22 uses `tarepan/SpeechMOS` v1.2.0 with 5,000 paired bootstrap samples.
70
+ - NISQA dimensions, signal diagnostics, categorized ASR failures, speaker consistency, and multi-seed robustness are under `evaluation/`.
71
+ - `evaluation/asr_robustness.json` separates sentence failures, semantic character errors, tail WER, and category-level errors.
72
+ - Competitor results apply only to the named checkpoints and voices, not every configuration of those projects.
73
 
74
  </details>
75
 
inflect_nano_v2_frontend.py CHANGED
@@ -119,6 +119,40 @@ def _digit_words(text: str) -> str:
119
  return " ".join(_words(int(ch)) for ch in text if ch.isdigit())
120
 
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  def _expand_money(match: re.Match[str]) -> str:
123
  raw = match.group(1).replace(",", "")
124
  dollars, _, cents = raw.partition(".")
@@ -208,6 +242,18 @@ def normalize_text(text: str) -> str:
208
  text = re.sub(rf"\b{re.escape(src)}", dst, text, flags=re.IGNORECASE)
209
 
210
  text = re.sub(r"\b([A-Z])(?:\.([A-Z]))+\.", lambda m: " ".join(re.findall(r"[A-Z]", m.group(0))), text)
 
 
 
 
 
 
 
 
 
 
 
 
211
  text = re.sub(r"\$(\d[\d,]*(?:\.\d{1,2})?)", _expand_money, text)
212
  text = re.sub(r"\b(0?[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01])/(20\d{2}|19\d{2})\b", _expand_date_slash, text)
213
  text = re.sub(r"\b(\d{1,2}):(\d{2})\s*([AaPp]\.?\s*[Mm]\.?)?\b", _expand_time, text)
 
119
  return " ".join(_words(int(ch)) for ch in text if ch.isdigit())
120
 
121
 
122
+ def _identifier_digits(text: str) -> str:
123
+ words = []
124
+ for index, character in enumerate(text):
125
+ if not character.isdigit():
126
+ continue
127
+ words.append("oh" if character == "0" and index > 0 else _words(int(character)))
128
+ return " ".join(words)
129
+
130
+
131
+ def _expand_identifier_token(token: str) -> str:
132
+ match = re.fullmatch(r"([A-Za-z]?)(\d+)([A-Za-z]?)", token)
133
+ if match is None:
134
+ return token
135
+ prefix, digits, suffix = match.groups()
136
+ pieces = []
137
+ if prefix:
138
+ pieces.append(LETTER_NAMES[prefix.upper()])
139
+ if len(digits) == 3 or digits.startswith("0"):
140
+ pieces.append(_identifier_digits(digits))
141
+ else:
142
+ pieces.append(_words(int(digits)))
143
+ if suffix:
144
+ pieces.append(LETTER_NAMES[suffix.upper()])
145
+ return " ".join(pieces)
146
+
147
+
148
+ def _expand_labeled_identifier(match: re.Match[str]) -> str:
149
+ return f"{match.group(1)} {_expand_identifier_token(match.group(2))}"
150
+
151
+
152
+ def _expand_street_number(match: re.Match[str]) -> str:
153
+ return _identifier_digits(match.group(1))
154
+
155
+
156
  def _expand_money(match: re.Match[str]) -> str:
157
  raw = match.group(1).replace(",", "")
158
  dollars, _, cents = raw.partition(".")
 
242
  text = re.sub(rf"\b{re.escape(src)}", dst, text, flags=re.IGNORECASE)
243
 
244
  text = re.sub(r"\b([A-Z])(?:\.([A-Z]))+\.", lambda m: " ".join(re.findall(r"[A-Z]", m.group(0))), text)
245
+ text = re.sub(
246
+ r"\b(apartment|apt\.?|suite|unit|room|flight|extension|order|invoice|locker|aisle|gate)\s+([A-Za-z]?\d{1,4}[A-Za-z]?)\b",
247
+ _expand_labeled_identifier,
248
+ text,
249
+ flags=re.IGNORECASE,
250
+ )
251
+ text = re.sub(
252
+ r"\b(\d{3})(?=\s+(?:North|South|East|West)\b)",
253
+ _expand_street_number,
254
+ text,
255
+ flags=re.IGNORECASE,
256
+ )
257
  text = re.sub(r"\$(\d[\d,]*(?:\.\d{1,2})?)", _expand_money, text)
258
  text = re.sub(r"\b(0?[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01])/(20\d{2}|19\d{2})\b", _expand_date_slash, text)
259
  text = re.sub(r"\b(\d{1,2}):(\d{2})\s*([AaPp]\.?\s*[Mm]\.?)?\b", _expand_time, text)
release_manifest.json CHANGED
@@ -11,20 +11,85 @@
11
  "standalone_cpu_smoke_audio_seconds": 3.616,
12
  "files": [
13
  {
14
- "path": "LICENSE",
15
- "bytes": 10455,
16
- "sha256": "12c48c640d1d0baf158d45175a4238b9227c71c77f50b0d15791b8efc08cd793"
17
- },
18
- {
19
- "path": "THIRD_PARTY_NOTICES.md",
20
- "bytes": 892,
21
- "sha256": "ef5343cd39713d313aefcfd09bb55fd6606ae2dacabeee13e0abdaa2e5b62589"
22
  },
23
  {
24
  "path": "config.json",
25
  "bytes": 1992,
26
  "sha256": "627f66cf339155d4b8524ce78b65230d2e2f33850f6e3f87f2e46c1add7e27d7"
27
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  {
29
  "path": "inference.py",
30
  "bytes": 6252,
@@ -32,14 +97,19 @@
32
  },
33
  {
34
  "path": "inflect_nano_v2_frontend.py",
35
- "bytes": 10246,
36
- "sha256": "9f800c7d86939b6eadbdec723d2411caaab820035f87de72ca8bece1a0ab3312"
37
  },
38
  {
39
  "path": "inflect_vits_frontend.py",
40
  "bytes": 2031,
41
  "sha256": "70eb4cdb96b2752015f72be984f5e62e0f26d7dc80e708875601702057b95cc2"
42
  },
 
 
 
 
 
43
  {
44
  "path": "model.pth",
45
  "bytes": 37529995,
@@ -50,6 +120,11 @@
50
  "bytes": 443,
51
  "sha256": "4c3d2d7c361792e3fe398745989dbf166dde40193122afdfbe8d2b1538b307ae"
52
  },
 
 
 
 
 
53
  {
54
  "path": "requirements.txt",
55
  "bytes": 128,
@@ -85,11 +160,6 @@
85
  "bytes": 206,
86
  "sha256": "16ca4890f3e0107250b4a522c0127779994a5a2b99fc35d6a27f93496a72153a"
87
  },
88
- {
89
- "path": "runtime/text/LICENSE",
90
- "bytes": 1053,
91
- "sha256": "f89accd9d66f6a011f19997d7a21cf71a35ffe2e2d0911b5460cbd0cab52a581"
92
- },
93
  {
94
  "path": "runtime/text/__init__.py",
95
  "bytes": 1572,
@@ -100,6 +170,11 @@
100
  "bytes": 2880,
101
  "sha256": "11dc7325547290e529c597e620f3aaf8d0bd8a2a2987d48eb42d2289534e42d1"
102
  },
 
 
 
 
 
103
  {
104
  "path": "runtime/text/symbols.py",
105
  "bytes": 642,
@@ -115,6 +190,31 @@
115
  "bytes": 7526,
116
  "sha256": "db11ba9b5ffd342abffc59229de7575a7d9e23468f91c6398e70eb4e01636716"
117
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  {
119
  "path": "smoke/manifest.jsonl",
120
  "bytes": 275,
@@ -144,6 +244,11 @@
144
  "path": "third_party/VITS_LICENSE.txt",
145
  "bytes": 1090,
146
  "sha256": "1cdf858b4d555567398b378b4a0166e97f7908c56607101b8bf9bb6754cdff3f"
 
 
 
 
 
147
  }
148
  ]
149
  }
 
11
  "standalone_cpu_smoke_audio_seconds": 3.616,
12
  "files": [
13
  {
14
+ "path": "assets/matched-evaluation.svg",
15
+ "bytes": 2513,
16
+ "sha256": "027f3ad488d19a3d2c5cc86ae4599bd29e50494d4f55377914cd5d954d2f56ca"
 
 
 
 
 
17
  },
18
  {
19
  "path": "config.json",
20
  "bytes": 1992,
21
  "sha256": "627f66cf339155d4b8524ce78b65230d2e2f33850f6e3f87f2e46c1add7e27d7"
22
  },
23
+ {
24
+ "path": "evaluation/asr.json",
25
+ "bytes": 862560,
26
+ "sha256": "756cfa30037a84a36a854adcd44fba2f549b40115d4e68515fab568a79b09cbd"
27
+ },
28
+ {
29
+ "path": "evaluation/asr_failures.json",
30
+ "bytes": 71601,
31
+ "sha256": "70e9e6d56db4380eb9a09248faf8b7923b3b96453920864479873c9c1a6547ad"
32
+ },
33
+ {
34
+ "path": "evaluation/asr_robustness.json",
35
+ "bytes": 34249,
36
+ "sha256": "624d547740371d4d746a0cb7fbd22e6301c317d83659e7c26e3435ffc9beff46"
37
+ },
38
+ {
39
+ "path": "evaluation/long_form.json",
40
+ "bytes": 417,
41
+ "sha256": "eec42c609379720df5426cdbee2d23b96ce2b6308d04edb2d6f8de46ee507ba9"
42
+ },
43
+ {
44
+ "path": "evaluation/long_form_asr.json",
45
+ "bytes": 12586,
46
+ "sha256": "353dc41dd4a3f4925a479f1d026a5ac642042c141d6a3335627fc3e5bec48c28"
47
+ },
48
+ {
49
+ "path": "evaluation/long_form_signal.json",
50
+ "bytes": 14483,
51
+ "sha256": "ffc932196d48e862ff5b722dbe72068755a72db99bfef91f1e8479e54ae0b3c1"
52
+ },
53
+ {
54
+ "path": "evaluation/multiseed_robustness.json",
55
+ "bytes": 41769,
56
+ "sha256": "a577da1dd4632f12d2a728976b02fd18e3aac7a9878385f023242b96ebf96ba9"
57
+ },
58
+ {
59
+ "path": "evaluation/nisqa.json",
60
+ "bytes": 56921,
61
+ "sha256": "9c1cbe99dd0994f02da9b30c07e70ca0a0487c2894367ee4c27b8df3d17d8cb9"
62
+ },
63
+ {
64
+ "path": "evaluation/package_qa.json",
65
+ "bytes": 608,
66
+ "sha256": "1a7228567fa1fe0af2f4255e97deda8dce6da705b07b4af6d509f282cb2c968d"
67
+ },
68
+ {
69
+ "path": "evaluation/runtime/cpu.json",
70
+ "bytes": 10730,
71
+ "sha256": "9159d0d8c0be3e318625468b77965c2360f86a2236524edd2aedabc0f837276a"
72
+ },
73
+ {
74
+ "path": "evaluation/runtime/cuda.json",
75
+ "bytes": 10894,
76
+ "sha256": "655913e46e21520550f19e3e19b6b280b2757a1a37dc0f305e8c93575094e43f"
77
+ },
78
+ {
79
+ "path": "evaluation/signal.json",
80
+ "bytes": 213439,
81
+ "sha256": "f88eebb932da1e15dc646d6545f4739949144ea09bc961cd02c30f9a40007a50"
82
+ },
83
+ {
84
+ "path": "evaluation/speaker_consistency.json",
85
+ "bytes": 12239,
86
+ "sha256": "e8df4cf787396b756721ba7672b384046ec837014e9b9298e04e1a327ac0a620"
87
+ },
88
+ {
89
+ "path": "evaluation/utmos22.json",
90
+ "bytes": 171875,
91
+ "sha256": "bb1f78fd36bbcf928aa71ca7376ff6d948f9e7e613c424caf5ce84e9e0ecf20d"
92
+ },
93
  {
94
  "path": "inference.py",
95
  "bytes": 6252,
 
97
  },
98
  {
99
  "path": "inflect_nano_v2_frontend.py",
100
+ "bytes": 11687,
101
+ "sha256": "530825406a4064ff8c7a873b35eb77920823734a98e77180e2aced48a6868dca"
102
  },
103
  {
104
  "path": "inflect_vits_frontend.py",
105
  "bytes": 2031,
106
  "sha256": "70eb4cdb96b2752015f72be984f5e62e0f26d7dc80e708875601702057b95cc2"
107
  },
108
+ {
109
+ "path": "LICENSE",
110
+ "bytes": 10455,
111
+ "sha256": "12c48c640d1d0baf158d45175a4238b9227c71c77f50b0d15791b8efc08cd793"
112
+ },
113
  {
114
  "path": "model.pth",
115
  "bytes": 37529995,
 
120
  "bytes": 443,
121
  "sha256": "4c3d2d7c361792e3fe398745989dbf166dde40193122afdfbe8d2b1538b307ae"
122
  },
123
+ {
124
+ "path": "README.md",
125
+ "bytes": 7126,
126
+ "sha256": "bfa9b01e2a571a83d2d59510ced6cd38c4e045255a80ed5fcf6fdb9b9a977ca3"
127
+ },
128
  {
129
  "path": "requirements.txt",
130
  "bytes": 128,
 
160
  "bytes": 206,
161
  "sha256": "16ca4890f3e0107250b4a522c0127779994a5a2b99fc35d6a27f93496a72153a"
162
  },
 
 
 
 
 
163
  {
164
  "path": "runtime/text/__init__.py",
165
  "bytes": 1572,
 
170
  "bytes": 2880,
171
  "sha256": "11dc7325547290e529c597e620f3aaf8d0bd8a2a2987d48eb42d2289534e42d1"
172
  },
173
+ {
174
+ "path": "runtime/text/LICENSE",
175
+ "bytes": 1053,
176
+ "sha256": "f89accd9d66f6a011f19997d7a21cf71a35ffe2e2d0911b5460cbd0cab52a581"
177
+ },
178
  {
179
  "path": "runtime/text/symbols.py",
180
  "bytes": 642,
 
190
  "bytes": 7526,
191
  "sha256": "db11ba9b5ffd342abffc59229de7575a7d9e23468f91c6398e70eb4e01636716"
192
  },
193
+ {
194
+ "path": "samples/male/conversational.wav",
195
+ "bytes": 180780,
196
+ "sha256": "f9e0f1d0ff2c5ced4ac05d8bc44b8a14a8b0c79ea36ed5aaa936df1840e899ed"
197
+ },
198
+ {
199
+ "path": "samples/male/names_places.wav",
200
+ "bytes": 182828,
201
+ "sha256": "fdeea745130c5d873fcb6ea8a5674d529c325739b2ad307fa422e7e2c9fd4997"
202
+ },
203
+ {
204
+ "path": "samples/male/numbers.wav",
205
+ "bytes": 229932,
206
+ "sha256": "a73cc26c31c11b1a78d26f8ebd382de4efb37b3514d7f2c91b9528ca79e7daf1"
207
+ },
208
+ {
209
+ "path": "samples/male/punctuation.wav",
210
+ "bytes": 255020,
211
+ "sha256": "ca433246649b7588982afa6dd67db2f40edf238b8ef87f865d8bb3eb885f386a"
212
+ },
213
+ {
214
+ "path": "samples/male/technical.wav",
215
+ "bytes": 192556,
216
+ "sha256": "2b59ad3d449c22b851d4a5f882f7a5e9d3413d0bc1e1037aa3374a3470c91114"
217
+ },
218
  {
219
  "path": "smoke/manifest.jsonl",
220
  "bytes": 275,
 
244
  "path": "third_party/VITS_LICENSE.txt",
245
  "bytes": 1090,
246
  "sha256": "1cdf858b4d555567398b378b4a0166e97f7908c56607101b8bf9bb6754cdff3f"
247
+ },
248
+ {
249
+ "path": "THIRD_PARTY_NOTICES.md",
250
+ "bytes": 892,
251
+ "sha256": "ef5343cd39713d313aefcfd09bb55fd6606ae2dacabeee13e0abdaa2e5b62589"
252
  }
253
  ]
254
  }