diff --git a/tn/english/data/measure/unit.tsv b/tn/english/data/measure/unit.tsv index c033ab8..adfe562 100644 --- a/tn/english/data/measure/unit.tsv +++ b/tn/english/data/measure/unit.tsv @@ -26,7 +26,6 @@ ghz gigahertz gw gigawatt gwh gigawatt hour hz hertz -" inch kbps kilobit per second kcal kilo calory kgf kilogram force @@ -124,4 +123,4 @@ ps PS s S tb TB tb YB -zb ZB \ No newline at end of file +zb ZB diff --git a/tn/english/normalizer.py b/tn/english/normalizer.py index d50e567..4fbf6e2 100644 --- a/tn/english/normalizer.py +++ b/tn/english/normalizer.py @@ -26,6 +26,7 @@ from tn.english.rules.telephone import Telephone from tn.english.rules.electronic import Electronic from tn.english.rules.whitelist import WhiteList +from tn.english.rules.punctuation import Punctuation from pynini.lib.pynutil import add_weight, delete from importlib_resources import files @@ -52,12 +53,15 @@ def build_tagger(self): electronic = add_weight(Electronic().tagger, 1.00) word = add_weight(Word().tagger, 100) whitelist = add_weight(WhiteList().tagger, 1.00) + punct = add_weight(Punctuation().tagger, 2.00) # TODO(xcsong): add roman - tagger = (cardinal | ordinal | word - | date | decimal | fraction - | time | measure | money - | telephone | electronic - | whitelist).optimize() + self.DELETE_SPACE + tagger = punct.star + \ + (cardinal | ordinal | word + | date | decimal | fraction + | time | measure | money + | telephone | electronic + | whitelist + | punct).optimize() + (punct.plus | self.DELETE_SPACE) # delete the last space self.tagger = tagger.star @ self.build_rule(delete(' '), r='[EOS]') @@ -74,12 +78,15 @@ def build_verbalizer(self): telephone = Telephone().verbalizer electronic = Electronic().verbalizer whitelist = WhiteList().verbalizer - verbalizer = (cardinal | ordinal | word - | date | decimal - | fraction | time - | measure | money - | telephone - | electronic - | whitelist).optimize() + self.INSERT_SPACE + punct = Punctuation().verbalizer + verbalizer = \ + (cardinal | ordinal | word + | date | decimal + | fraction | time + | measure | money + | telephone + | electronic + | whitelist + | punct).optimize() + punct.ques + self.INSERT_SPACE self.verbalizer = verbalizer.star @ self.build_rule(delete(' '), r='[EOS]') diff --git a/tn/english/rules/date.py b/tn/english/rules/date.py index dbd7972..bc0fde3 100644 --- a/tn/english/rules/date.py +++ b/tn/english/rules/date.py @@ -282,12 +282,6 @@ def build_tagger(self): final_graph |= graph_fy - prefix = pynutil.delete(pynini.union("{", "(", "<", "\"", - "'")).ques + self.DELETE_SPACE - suffix = self.DELETE_SPACE + pynutil.delete( - pynini.union("}", ")", ">", "\"", "'")).ques - final_graph = pynutil.add_weight( - prefix, -0.1) + final_graph + pynutil.add_weight(suffix, -0.1) self.tagger = self.add_tokens(final_graph) def build_verbalizer(self): diff --git a/tn/english/rules/punctuation.py b/tn/english/rules/punctuation.py new file mode 100644 index 0000000..821415c --- /dev/null +++ b/tn/english/rules/punctuation.py @@ -0,0 +1,81 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +from unicodedata import category + +from pynini.examples import plurals +from pynini import cross, union, closure, accep +from pynini.lib.pynutil import delete, insert + +from tn.processor import Processor +from tn.utils import get_abs_path, load_labels + + +class Punctuation(Processor): + + def __init__(self, deterministic: bool = False): + """ + Args: + deterministic: if True will provide a single transduction option, + for False multiple transduction are generated (used for audio-based normalization) + """ + super().__init__('p', ordertype="en_tn") + self.deterministic = deterministic + self.build_tagger() + self.build_verbalizer() + + def build_tagger(self): + """ + Finite state transducer for classifying punctuation + e.g. a, -> w { v: "a" } p { v: "," } + """ + s = "!#%&\'()*+,-./:;<=>?@^_`{|}~" + + punct_symbols_to_exclude = ["[", "]", "\"", "\\"] + punct_unicode = [ + chr(i) for i in range(sys.maxunicode) + if category(chr(i)).startswith("P") + and chr(i) not in punct_symbols_to_exclude + ] + + whitelist_symbols = load_labels( + get_abs_path("english/data/whitelist/symbol.tsv")) + whitelist_symbols = [x[0] for x in whitelist_symbols] + self.punct_marks = [ + p for p in punct_unicode + list(s) if p not in whitelist_symbols + ] + + self.punct = union(*self.punct_marks) + punct = closure(self.punct | cross('\\', '\\\\\\') | cross('"', '\\"'), + 1) + + emphasis = ( + accep("<") + + (( + closure(self.NOT_SPACE - union("<", ">"), 1) + # noqa + closure(accep("/"), 0, 1)) # noqa + | (accep("/") + closure(self.NOT_SPACE - union("<", ">"), 1))) + + accep(">")) # noqa + punct = plurals._priority_union(emphasis, punct, closure(self.VCHAR)) + + self.graph = punct + final_graph = insert("v: \"") + punct + insert("\"") + self.tagger = self.add_tokens(final_graph) + + def build_verbalizer(self): + punct = closure(self.punct | cross('\\\\\\', '\\') | cross('\\"', '"'), + 1) + verbalizer = delete('v: "') + punct + delete('"') + self.verbalizer = self.delete_tokens(verbalizer) diff --git a/tn/english/rules/word.py b/tn/english/rules/word.py index 02247ad..f47d7b5 100644 --- a/tn/english/rules/word.py +++ b/tn/english/rules/word.py @@ -14,9 +14,10 @@ # limitations under the License. from pynini.lib import pynutil -from pynini import cross, difference, union +from pynini import difference, union from tn.processor import Processor +from tn.english.rules.punctuation import Punctuation class Word(Processor): @@ -27,7 +28,7 @@ def __init__(self, deterministic: bool = False): deterministic: if True will provide a single transduction option, for False multiple transduction are generated (used for audio-based normalization) """ - super().__init__("word", ordertype="en_tn") + super().__init__("w", ordertype="en_tn") self.deterministic = deterministic self.build_tagger() self.build_verbalizer() @@ -35,11 +36,14 @@ def __init__(self, deterministic: bool = False): def build_tagger(self): """ Finite state transducer for classifying word. Considers sentence boundary exceptions. - e.g. sleep -> word { value: "sleep" } + e.g. sleep -> w { v: "sleep" } """ - self.char = difference(self.VCHAR, union('\\', '"', self.SPACE)) - chars = (self.char | cross('\\', '\\\\\\') | cross('"', '\\"')).plus - graph = (pynutil.insert("value: \"") + chars + + punct = Punctuation(self.deterministic).graph + default_graph = difference(self.NOT_SPACE, punct.project("input")) + symbols_to_exclude = union("$", "€", "₩", "£", "¥", "#", + "%") | self.DIGIT + self.char = difference(default_graph, symbols_to_exclude) + graph = (pynutil.insert("v: \"") + self.char.plus + pynutil.insert("\"")).optimize() final_graph = self.add_tokens(graph) self.tagger = final_graph.optimize() @@ -47,10 +51,9 @@ def build_tagger(self): def build_verbalizer(self): """ Finite state transducer for verbalizing word - e.g. word { value: "sleep" } -> sleep + e.g. w { v: "sleep" } -> sleep """ - chars = (self.char | cross('\\\\\\', '\\') | cross('\\"', '"')).plus - graph = pynutil.delete("value: ") + pynutil.delete( - "\"") + chars + pynutil.delete("\"") + graph = pynutil.delete("v: ") + pynutil.delete( + "\"") + self.char.plus + pynutil.delete("\"") final_graph = self.delete_tokens(graph) self.verbalizer = final_graph.optimize() diff --git a/tn/english/test/data/normalizer.txt b/tn/english/test/data/normalizer.txt index 2293abe..f4a5448 100644 --- a/tn/english/test/data/normalizer.txt +++ b/tn/english/test/data/normalizer.txt @@ -1,2 +1,2 @@ -this is 12th game, number 256, 2024-05-06, 2021-03-07 31.990 billion. ¾ people like chattts, let's eat at 03:43 p.m. run 10 km, give me $12.345 please, call 123-123-5678-1 Mt Hill "HAHAHA" billion 4 March => this is twelfth game, number 256, the sixth of may twenty twenty four , the seventh of march twenty twenty one thirty one point nine nine oh billion. three quarters people like chattts, let's eat at three forty three PM run ten kilometers, give me twelve point three four five dollars please, call one two three, one two three, five six seven eight, one Mt Hill "HAHAHA" billion the fourth of march -The National Map, accessed April 1, 2011" Site Description of Koppers Co. From the quartet's recording" Jefferson Friedman: Quartets,"" String Quartet no, Riots again broke out, Atassi resigned, and Syrian independence was deferred until after World War II. 1988 (1988) ( 1988) ( 1988). Starling, Arthur E.( 1988 ). this is 12th game, number 256, 2024-05-06, 2021-03-07 31.990 billion. 3/4 people like chattts Retrieved December 2011. Information on Album" Thepodule.com"" Biography by Amy Hanson". => The National Map, accessed the first of april , twenty eleven Site Description of Koppers company From the quartet's recording" Jefferson Friedman: Quartets,"" String Quartet no, Riots again broke out, Atassi resigned, and Syrian independence was deferred until after World War two nineteen eighty eight nineteen eighty eight nineteen eighty eight nineteen eighty eight ). Starling, Arthur E.( nineteen eighty eight ). this is twelfth game, number 256, the sixth of may twenty twenty four , the seventh of march twenty twenty one thirty one point nine nine oh billion. three quarters people like chattts Retrieved december twenty eleven. Information on Album" Thepodule.com"" Biography by Amy Hanson". +this is 12th game, number 256, 2024-05-06, 2021-03-07 31.990 billion. ¾ people like chattts, let's eat at 03:43 p.m. run 10 km, give me $12.345 please, call 123-123-5678-1 Mt Hill "HAHAHA" billion 4 March => this is twelfth game, number two hundred and fifty six, the sixth of may twenty twenty four, the seventh of march twenty twenty one thirty one point nine nine oh billion. three quarters people like chattts, let' s eat at three forty three PM run ten kilometers, give me twelve point three four five dollars please, call one two three, one two three, five six seven eight, one Mt Hill" HAHAHA" billion the fourth of march +The National Map, accessed April 1, 2011" Site Description of Koppers Co. From the quartet's recording" Jefferson Friedman: Quartets,"" String Quartet no, Riots again broke out, Atassi resigned, and Syrian independence was deferred until after World War II. 1988 (1988) ( 1988) ( 1988). Starling, Arthur E.( 1988 ). this is 12th game, number 256, 2024-05-06, 2021-03-07 31.990 billion. 3/4 people like chattts Retrieved December 2011. Information on Album" Thepodule.com"" Biography by Amy Hanson". => The National Map, accessed the first of april , twenty eleven" Site Description of Koppers company From the quartet' s recording" Jefferson Friedman: Quartets,"" String Quartet no, Riots again broke out, Atassi resigned, and Syrian independence was deferred until after World War two nineteen eighty eight( nineteen eighty eight )( nineteen eighty eight )( nineteen eighty eight). Starling, Arthur E.( nineteen eighty eight). this is twelfth game, number two fifty six, the sixth of may twenty twenty four, the seventh of march twenty twenty one thirty one point nine nine oh billion. three quarters people like chattts Retrieved december twenty eleven. Information on Album" Thepodule dot com"" Biography by Amy Hanson". diff --git a/tn/english/test/data/word.txt b/tn/english/test/data/word.txt index db7fea0..40b9c5a 100644 --- a/tn/english/test/data/word.txt +++ b/tn/english/test/data/word.txt @@ -4,5 +4,3 @@ smile => smile 国 => 国 A => A a => a -"HAHAH" => "HAHAH" -"HAHAH," => "HAHAH,"