Skip to content

Commit bf1ee15

Browse files
docs: improve Premove ITN discovery metadata (#95)
1 parent c42b444 commit bf1ee15

14 files changed

Lines changed: 54 additions & 38 deletions

README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
Open-source, context-aware inverse text normalization for conversational
1111
voice-agent transcripts, with open weights.
1212

13+
Premove ITN converts spoken ASR output into canonical written forms for phone
14+
numbers, email addresses, identifiers, dates, times, money, measurements, and
15+
alphanumeric codes.
16+
1317
## The ambiguity
1418

1519
| System | Output |
@@ -28,7 +32,7 @@ These are the retained outputs for row `va6_collision_0013` in the
2832

2933
## Results
3034

31-
On our frozen benchmark, Premove reaches **99.50% semantic accuracy on the
35+
On our frozen benchmark, Premove ITN reaches **99.50% semantic accuracy on the
3236
voice-agent subset**, compared with 68.25% for `text-processing-rs` and 67.00%
3337
for NVIDIA Thutmose.
3438

@@ -99,13 +103,14 @@ That sent me looking for context-aware ITN. I tried [NVIDIA Thutmose](https://ca
99103
but on the structured values I cared about for tool calls, I still found
100104
surprisingly simple failures.
101105

102-
Premove came from a different idea: do not ask the model to perform the entire
103-
normalization. Generate the valid written forms first, then train the model
104-
only to decide which one fits the context. An exact decoder handles the rest.
106+
Premove ITN came from a different idea: do not ask the model to perform the
107+
entire normalization. Generate the valid written forms first, then train the
108+
model only to decide which one fits the context. An exact decoder handles the
109+
rest.
105110

106111
## How Premove ITN works
107112

108-
Premove splits normalization into three steps: **generate, score, decode**.
113+
Premove ITN splits normalization into three steps: **generate, score, decode**.
109114

110115
Simplified example:
111116

@@ -135,7 +140,7 @@ contextual source span + candidate kind labels + proposed replacement
135140
136141
3. DECODE
137142
138-
Candidates can overlap, so Premove uses exact dynamic programming
143+
Candidates can overlap, so Premove ITN uses exact dynamic programming
139144
to find the highest-scoring compatible path through the transcript.
140145
141146
@@ -148,7 +153,7 @@ context**. The decoder decides **which edits can coexist**.
148153

149154
## Supported forms
150155

151-
Premove covers English structured values commonly needed by voice agents:
156+
Premove ITN covers English structured values commonly needed by voice agents:
152157

153158
| Form | Example |
154159
| --- | --- |
@@ -168,7 +173,7 @@ Premove covers English structured values commonly needed by voice agents:
168173

169174
### Not supported
170175

171-
Premove currently targets English structured text. It does not provide
176+
Premove ITN currently targets English structured text. It does not provide
172177
first-class normalization for non-English speech, street addresses, free-form
173178
rewriting, or arbitrary application-specific formats.
174179

@@ -236,7 +241,7 @@ frozen evaluation was excluded from training and checkpoint selection; see the
236241

237242
The contextual scorer uses
238243
[`microsoft/deberta-v3-large`](https://huggingface.co/microsoft/deberta-v3-large)
239-
at a pinned revision as its encoder backbone. Premove adds a custom candidate
244+
at a pinned revision as its encoder backbone. Premove ITN adds a custom candidate
240245
scorer and exact decoder around the
241246
[DeBERTaV3 architecture](https://arxiv.org/abs/2111.09543).
242247

@@ -245,7 +250,7 @@ scorer and exact decoder around the
245250
Premove ITN source code and model weights are MIT licensed. The contextual
246251
scorer uses [`microsoft/deberta-v3-large`](https://huggingface.co/microsoft/deberta-v3-large)
247252
at a pinned revision as its encoder backbone. Candidate scoring and exact
248-
decoding are Premove-specific.
253+
decoding are Premove ITN-specific.
249254

250255
The Rust realization layer uses
251256
[`text-processing-rs`](https://github.com/FluidInference/text-processing-rs),

benchmarks/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ RAYON_NUM_THREADS=8 TOKENIZERS_PARALLELISM=false \
3535
--thutmose-artifact /path/to/itn_en_thutmose_bert.nemo
3636
```
3737

38-
Replace placeholder paths before running. The selected Premove checkpoint must
38+
Replace placeholder paths before running. The selected Premove ITN checkpoint must
3939
be available at the path in `data/models/production.json`. Model weights and
4040
caches are not committed. The runner refuses a Rust extension whose profile is
4141
not `release`, or which has debug assertions enabled. It records native build

benchmarks/export_inference_artifact.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def write_readme(root: Path, provenance: dict[str, Any]) -> None:
149149
| Thutmose | 59.39% | 57.61% | 268/400 (67.00%) | 15.98 ms |
150150
| text-processing-rs | 55.79% | 55.05% | 273/400 (68.25%) | 0.14 ms |
151151
152-
Premove leads the measured semantic accuracy overall and on the 400
152+
Premove ITN leads the measured semantic accuracy overall and on the 400
153153
voice-agent-domain rows. It does not lead latency. This is a balanced synthetic
154154
stress benchmark, not an estimate of production traffic accuracy, and the run
155155
was not blind.

benchmarks/run_comparison.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def row_kind(row: dict[str, Any]) -> str:
184184

185185

186186
def semantic_kind(row: dict[str, Any], span: dict[str, Any]) -> str | None:
187-
# The dataset deliberately leaves PERCENT unmapped because Premove has no
187+
# The dataset deliberately leaves PERCENT unmapped because Premove ITN has no
188188
# public PERCENT SpanKind. Structured and electronic values are scored by
189189
# their canonical form (case-insensitive for identifiers).
190190
value = span.get("premove_span_kind")

benchmarks/summarize_comparison.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def summarize(output: Path) -> None:
5353
lines = [
5454
"# First Evaluation",
5555
"",
56-
"Premove leads semantic entity accuracy overall and in the voice-agent group. It remains slower than both comparison backends. This is the repository's retained release-artifact result.",
56+
"Premove ITN leads semantic entity accuracy overall and in the voice-agent group. It remains slower than both comparison backends. This is the repository's retained release-artifact result.",
5757
"",
5858
"## Overall results",
5959
"",
@@ -86,7 +86,7 @@ def summarize(output: Path) -> None:
8686
)
8787
lines += [
8888
"",
89-
"| Domain | Premove | Thutmose | text-processing-rs |",
89+
"| Domain | Premove ITN | Thutmose | text-processing-rs |",
9090
"|---|---:|---:|---:|",
9191
]
9292
for domain in sorted(
@@ -132,7 +132,7 @@ def summarize(output: Path) -> None:
132132
"",
133133
"Each count below scores only the named entity, including entities in multi-entity sentences.",
134134
"",
135-
"| Category | Premove | Thutmose | text-processing-rs |",
135+
"| Category | Premove ITN | Thutmose | text-processing-rs |",
136136
"|---|---:|---:|---:|",
137137
]
138138
for category in sorted(categories[names[0]]):
@@ -157,7 +157,7 @@ def summarize(output: Path) -> None:
157157
"Warm-up records are saved separately for each backend. Thutmose also retains its startup warm-up in runtime metadata. Initialization timing is process/model initialization, not machine cold boot or first download.",
158158
"",
159159
"",
160-
"## Premove timing components",
160+
"## Premove ITN timing components",
161161
"",
162162
"| Component | Mean ms | p95 ms | p99 ms |",
163163
"|---|---:|---:|---:|",

docs/architecture.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Architecture
22

3-
Premove separates three jobs that are often combined in inverse text
3+
Premove ITN separates three jobs that are often combined in inverse text
44
normalization:
55

66
1. Rust generates valid written forms.
@@ -37,7 +37,7 @@ span as a possible normalization region.
3737
Repeated span text is deduplicated, then all unique spans are sent to Rust in
3838
one batched call. Rust evaluates the 13 supported realizer kinds and returns
3939
every valid written form for each span. If multiple kinds produce the same
40-
replacement for the same source span, Premove stores one candidate with
40+
replacement for the same source span, Premove ITN stores one candidate with
4141
multiple kind labels.
4242

4343
Each candidate contains:
@@ -78,7 +78,7 @@ flattening candidate metadata in stable input order.
7878
## Score candidates with sentence context
7979

8080
The complete transcript is encoded by DeBERTa once. For each candidate,
81-
Premove builds three feature groups:
81+
Premove ITN builds three feature groups:
8282

8383
```text
8484
source context
@@ -113,7 +113,7 @@ example, `seven eighty eight` can produce the same-kind alternatives `95` and
113113

114114
Candidate scores are not applied independently. Two high-scoring replacements
115115
can overlap, and selecting one changes which other edits remain possible.
116-
Premove therefore solves the complete sentence as a character-interval graph.
116+
Premove ITN therefore solves the complete sentence as a character-interval graph.
117117

118118
Candidates are weighted edges over source character intervals. Leaving a
119119
character unchanged is a zero-score `KEEP` edge. The decoder uses dynamic

docs/evaluations/voice-agent-itn-spec.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ collision groups intentionally use controlled sentence shells.
2525
## Backend-neutral contract
2626

2727
The backend-neutral semantic category and `premove_span_kind` are different
28-
fields. Every non-null Premove kind must be a current public `SpanKind` member.
29-
Each semantic category maps to at most one Premove kind. URL maps to
28+
fields. Every non-null Premove ITN kind must be a current public `SpanKind` member.
29+
Each semantic category maps to at most one Premove ITN kind. URL maps to
3030
`ELECTRONIC`. PERCENT remains a required benchmark category and has a null
31-
Premove mapping because Premove has no public PERCENT kind. This dataset does
32-
not add or change a Premove realization rule.
31+
Premove ITN mapping because Premove ITN has no public PERCENT kind. This dataset
32+
does not add or change a Premove ITN realization rule.
3333

3434
The headline inference adapter receives only `text`. It must not receive gold
35-
spans, categories, Premove kinds, domains, difficulty, or semantic values. An
35+
spans, categories, Premove ITN kinds, domains, difficulty, or semantic values. An
3636
oracle span-kind realizer result can be reported only as a separate diagnostic.
37-
Premove versus text-processing-rs is an upstream ablation comparison, not a
37+
Premove ITN versus text-processing-rs is an upstream ablation comparison, not a
3838
comparison of fully independent systems.
3939

4040
## Semantic equivalence

docs/getting-started.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ the complete support boundary.
108108

109109
## More examples
110110

111-
| Transcript | Premove output |
111+
| Transcript | Premove ITN output |
112112
| --- | --- |
113113
| `can you look up order d l t two nine eight two` | `can you look up order DLT2982` |
114114
| `I need to change flight m d o three five one` | `I need to change flight MDO351` |
@@ -118,4 +118,3 @@ the complete support boundary.
118118

119119
The last two rows use the same spoken value. Sentence context selects a time or
120120
a dollar amount without exposing categories or gold metadata to the model.
121-

docs/model-card.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ license: mit
1919
# Premove ITN v0.1.0
2020

2121
Premove ITN is an open-weight contextual inverse text normalization system for
22-
English voice-agent transcripts. It turns spoken-form ASR text into structured
22+
English voice-agent transcripts. It is the contextual scoring model used by the
23+
`premove-itn` Python package. It turns spoken-form ASR text into structured
2324
written text:
2425

2526
```text
@@ -104,13 +105,13 @@ match separately measures the complete canonical output.
104105
| Thutmose | 59.39% | 22.13% | 15.98 ms |
105106
| text-processing-rs | 55.79% | 16.53% | 0.14 ms |
106107

107-
Premove led measured semantic accuracy overall and on the 400 dedicated
108+
Premove ITN led measured semantic accuracy overall and on the 400 dedicated
108109
voice-agent rows. It did not lead latency.
109110

110111
Latency used sequential batch-one requests on an Apple M4 MacBook Air with
111112
MPS, an optimized Rust extension, and eight Rayon workers. Models were loaded
112113
and warmed before request latency was measured. Download and initialization
113-
are excluded. The Premove timing used the release Rust extension. The backend
114+
are excluded. The Premove ITN timing used the release Rust extension. The backend
114115
evaluation was blind: each backend received only transcript text.
115116
Independent human gold adjudication is a separate task and remains pending.
116117

@@ -121,7 +122,7 @@ and
121122

122123
## Intended use
123124

124-
Use Premove for English voice-agent transcripts in which numbers, dates,
125+
Use Premove ITN for English voice-agent transcripts in which numbers, dates,
125126
times, money, phone values, identifiers, URLs, and related structured values
126127
need sentence-level disambiguation. The runtime receives only transcript text.
127128
Candidate metadata is generated internally.

docs/platform-evidence/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This directory records the v0.1.0 compatibility certification.
66
Python 3.11, 3.12, and 3.13. Linux release wheels use the
77
`manylinux_2_28` platform contract.
88
- MPS and CPU each produced **1,500/1,500 exact output matches** against the
9-
retained First Evaluation Premove predictions.
9+
retained First Evaluation Premove ITN predictions.
1010
- `device="auto"` selected MPS on Apple Silicon and CPU on Linux.
1111
- Explicit unavailable-device checks passed for CUDA on macOS and MPS on the
1212
CPU-only Linux runner.

0 commit comments

Comments
 (0)