Zurück zum Blog
·Engineering

Von gesprochenen Worten zu sauberem Text: So funktioniert Inverse Text Normalization


Spracherkennungsmodelle geben Worte aus. Wenn Sie aber diktieren "das Meeting ist am fünfzehnten Januar um halb drei nachmittags und das Budget liegt bei dreitausend Dollar", wollen Sie diese Worte nicht genau so sehen. Sie wollen: "Das Meeting ist am 15. Januar um 14:30 Uhr und das Budget liegt bei $3,000."

Die Umwandlung von gesprochener Form in geschriebene Form nennt man Inverse Text Normalization, kurz ITN. Sie ist das Gegenteil dessen, was ein Text-to-Speech-System tut, das geschriebenen Text in gesprochene Form überführt. Und sie ist eine dieser Funktionen, die unsichtbar sind, wenn sie funktionieren, und extrem frustrierend, wenn sie es nicht tun.

Was ITN abdeckt

ITN umfasst mehr Arten von Transformationen, als die meisten Menschen vermuten:

  • Zahlen. "zweiundvierzig" -> "42", "drei Komma eins vier" -> "3.14", "minus sieben" -> "-7"
  • Währungen. "dreitausend Dollar" -> "$3,000", "fünfzig Euro" -> "€50"
  • Datum und Uhrzeit. "fünfzehnter Januar zweitausendsechsundzwanzig" -> "15. Januar 2026", "halb drei nachmittags" -> "2:30 PM"
  • Ordnungszahlen. "der dritte Eintrag" -> "der 3. Eintrag"
  • Einheiten. "fünf Kilometer" -> "5 km", "zwanzig Grad Celsius" -> "20°C"
  • Satzzeichen. "Komma" -> ",", "Punkt" -> ".", "Fragezeichen" -> "?"
  • Sprachbefehle. "neue Zeile" -> echter Zeilenumbruch, "Doppelpunkt" -> ":"

Jede dieser Transformationen wirkt für sich genommen simpel. Die Komplexität entsteht durch Mehrdeutigkeit. Bedeutet "eins" die Zahl 1 oder ein Pronomen? Bedeutet "Mai" den Monat oder das Modalverb im Englischen? Bedeutet "Bindestrich" ein Zeichen oder das wörtliche Wort?

Warum wir unsere eigene Engine gebaut haben

Die meisten ASR-Anbieter bringen grundlegende ITN in ihrer Cloud-Pipeline mit. Wenn Sie Sprache aber lokal verarbeiten, brauchen Sie auch lokale ITN - und die Optionen sind begrenzt. Bestehende Open-Source-Bibliotheken sind meist Python-basiert, für Batch-Verarbeitung gebaut und stark auf Englisch fokussiert.

Wir brauchten etwas anderes:

  • Echtzeit-Performance. ITN läuft auf jedem Abschnitt einer Streaming-Transkription. Sie muss Text in Mikrosekunden verarbeiten, nicht in Millisekunden.
  • CJK-Unterstützung. Chinesisch und Japanisch haben vollkommen andere Zahlensysteme, Satzzeichenkonventionen und Formatierungsregeln. "三千美元" muss genauso zu "$3,000" werden wie "three thousand dollars".
  • Native Integration. Wir brauchen eine Bibliothek, die in einer Swift-macOS-App läuft, ohne eine Python-Runtime zu bündeln oder über einen Subprozess zu bridgen.

Finite-State-Transducer

Unsere ITN-Engine basiert auf Finite-State-Transducern, kurz FSTs. Ein FST ist eine Zustandsmaschine, die eine Eingabesequenz liest und eine Ausgabesequenz erzeugt. Für ITN ist die Eingabe eine Folge gesprochener Worte, die Ausgabe die normalisierte Schreibform.

Der entscheidende Vorteil von FSTs gegenüber Regex oder regelbasiertem String-Replacement ist Komponierbarkeit. Sie können kleine FSTs für einzelne Transformationen bauen - eines für Kardinalzahlen, eines für Daten, eines für Währungen - und sie zu einem einzigen Transducer komponieren, der alle Fälle gleichzeitig abdeckt, inklusive deterministischer Prioritäten, wenn Regeln sich überlappen.

Wir haben die FST-Runtime-Bibliothek libfst in Zig geschrieben. Zig gibt uns für diesen Anwendungsfall genau die Dinge, die zählen: C-ABI-Kompatibilität, damit die Bibliothek direkt in die Swift-App gelinkt wird, Zero-Cost-Abstractions für die Zustandsübergänge und präzise Kontrolle über Speicherallokation - keine Pausen durch Garbage Collection mitten in der Echtzeit-Textverarbeitung.

Die Pipeline zur Regelkompilierung

ITN-Regeln werden in Python als deklarative Transformationsspezifikationen formuliert. Jede Regel beschreibt ein Muster - Eingabeworte - und einen Ersatz - Ausgabetext. Die Python-Toolchain kompiliert diese Regeln in binäre FST-Dateien - kompakte, optimierte Transducer-Repräsentationen, die die Zig-Runtime lädt und ausführt.

Diese Aufteilung lässt uns Regeln schnell weiterentwickeln - Python ist hervorragend für sprachliche Muster -, während die Runtime schnell bleibt. Ein neues Zahlenformat oder ein neues Währungssymbol hinzuzufügen bedeutet: Python-Regeldatei anpassen und neu kompilieren. Die Runtime-Binärdatei ändert sich nicht.

Aktuell liefern wir kompilierte FST-Regeldateien für Chinesisch, Japanisch und Englisch aus. Jede Sprache hat ihren eigenen Regelsatz, weil sich die Normalisierungskonventionen deutlich unterscheiden. Im Japanischen kommen vollbreite Satzzeichen und andere Zählwörter dazu. Im Chinesischen werden Zahlen in 10.000er-Gruppen statt in 1.000er-Gruppen gebildet. Englisch wiederum hat eigene Besonderheiten bei Ordnungszahlen und der Zwölf-Stunden-Zeit.

Sprachbefehle

ITN behandelt auch Sprachbefehle - gesprochene Phrasen, die auf Tastaturaktionen statt auf literalen Text abgebildet werden. Wenn Sie beim Diktieren "neue Zeile" sagen, wollen Sie einen echten Zeilenumbruch und nicht die Worte "neue Zeile". Wenn Sie "Komma" sagen, wollen Sie das Satzzeichen.

Das führt zu einer interessanten Disambiguierungsaufgabe. Die ITN-Engine muss entscheiden, ob "neue Zeile" ein Sprachbefehl ist oder Teil eines Satzes wie "das ist eine neue Zeile an Produkten". Wir lösen das über Kontext: Sprachbefehle werden in bestimmten syntaktischen Positionen erkannt, typischerweise nach einer Pause oder an Klauselgrenzen, und die Prioritätsordnung der FSTs sorgt dafür, dass Befehlsinterpretationen in mehrdeutigen Positionen bevorzugt werden.

Für CJK-Sprachen sind Sprachbefehle lokalisiert. Chinesische Nutzer sagen "换行" für einen Zeilenumbruch und "逗号" für ein Komma. Die FST-Regeln sind sprachspezifisch, daher hat jede Locale ihren eigenen natürlichen Befehlsschatz.

Das unsichtbare Feature

Gute ITN ist unsichtbar. Sie diktieren natürlich und der Text sieht richtig aus. Zahlen sind Zahlen, Daten sind Daten, Satzzeichen stehen dort, wo sie hingehören. In dem Moment, in dem Sie ein "$three thousand" manuell korrigieren oder die wörtlichen Worte "new line" löschen müssen, bricht die Illusion zusammen.

Wir investieren viel Engineering-Aufwand in ein Feature, das niemand bemerkt, wenn es perfekt funktioniert. Genau das ist der Punkt. Die beste Spracheingabe ist die, bei der Sie vergessen, dass Sie gar nicht tippen.

OnType ausprobieren - lokale Spracheingabe mit smarter Textnormalisierung für Englisch, Chinesisch und Japanisch.