WeTextProcessing 0.1.11__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/PKG-INFO +1 -1
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/PKG-INFO +1 -1
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/SOURCES.txt +47 -1
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/cardinal.py +24 -23
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/license_plate.py +4 -1
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/measure.py +0 -3
- WeTextProcessing-0.2.0/itn/zh_itn_tagger.fst +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/cardinal.py +5 -2
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/math.py +14 -5
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/measure.py +1 -4
- WeTextProcessing-0.2.0/tn/english/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/address/__init__.py +13 -0
- WeTextProcessing-0.2.0/tn/english/data/date/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/electronic/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/measure/__init__.py +13 -0
- WeTextProcessing-0.2.0/tn/english/data/money/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/number/__init__.py +13 -0
- WeTextProcessing-0.2.0/tn/english/data/ordinal/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/roman/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/telephone/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/data/time/__init__.py +13 -0
- WeTextProcessing-0.2.0/tn/english/data/whitelist/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/normalizer.py +92 -0
- WeTextProcessing-0.2.0/tn/english/rules/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/rules/cardinal.py +186 -0
- WeTextProcessing-0.2.0/tn/english/rules/date.py +319 -0
- WeTextProcessing-0.2.0/tn/english/rules/decimal.py +194 -0
- WeTextProcessing-0.2.0/tn/english/rules/electronic.py +213 -0
- WeTextProcessing-0.2.0/tn/english/rules/fraction.py +139 -0
- WeTextProcessing-0.2.0/tn/english/rules/measure.py +327 -0
- WeTextProcessing-0.2.0/tn/english/rules/money.py +124 -0
- WeTextProcessing-0.2.0/tn/english/rules/ordinal.py +96 -0
- WeTextProcessing-0.2.0/tn/english/rules/punctuation.py +81 -0
- WeTextProcessing-0.2.0/tn/english/rules/roman.py +149 -0
- WeTextProcessing-0.2.0/tn/english/rules/telephone.py +180 -0
- WeTextProcessing-0.2.0/tn/english/rules/time.py +167 -0
- WeTextProcessing-0.2.0/tn/english/rules/whitelist.py +153 -0
- WeTextProcessing-0.2.0/tn/english/rules/word.py +59 -0
- WeTextProcessing-0.2.0/tn/english/test/__init__.py +0 -0
- WeTextProcessing-0.2.0/tn/english/test/cardinal_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/date_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/decimal_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/electronic_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/fraction_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/measure_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/money_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/normalizer_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/ordinal_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/roman_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/telephone_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/time_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/utils.py +32 -0
- WeTextProcessing-0.2.0/tn/english/test/whitelist_test.py +28 -0
- WeTextProcessing-0.2.0/tn/english/test/word_test.py +28 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/main.py +22 -11
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/processor.py +17 -1
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/token_parser.py +11 -2
- WeTextProcessing-0.2.0/tn/utils.py +92 -0
- WeTextProcessing-0.2.0/tn/zh_tn_tagger.fst +0 -0
- WeTextProcessing-0.1.11/itn/zh_itn_tagger.fst +0 -0
- WeTextProcessing-0.1.11/tn/zh_tn_tagger.fst +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/LICENSE +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/README.md +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/dependency_links.txt +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/entry_points.txt +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/requires.txt +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/top_level.txt +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/__main__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/inverse_normalizer.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/char.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/date.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/fraction.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/math.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/money.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/postprocessor.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/time.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/rules/whitelist.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/test/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/test/normalizer_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/chinese/test/utils.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/main.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/itn/zh_itn_verbalizer.fst +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/setup.cfg +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/setup.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/__main__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/normalizer.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/char.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/date.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/fraction.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/money.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/postprocessor.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/preprocessor.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/sport.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/time.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/rules/whitelist.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/__init__.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/cardinal_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/char_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/date_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/fraction_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/math_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/measure_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/money_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/normalizer_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/postprocessor_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/preprocessor_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/sport_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/time_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/token_parser_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/utils.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/chinese/test/whitelist_test.py +0 -0
- {WeTextProcessing-0.1.11 → WeTextProcessing-0.2.0}/tn/zh_tn_verbalizer.fst +0 -0
|
@@ -34,6 +34,7 @@ tn/__main__.py
|
|
|
34
34
|
tn/main.py
|
|
35
35
|
tn/processor.py
|
|
36
36
|
tn/token_parser.py
|
|
37
|
+
tn/utils.py
|
|
37
38
|
tn/zh_tn_tagger.fst
|
|
38
39
|
tn/zh_tn_verbalizer.fst
|
|
39
40
|
tn/chinese/__init__.py
|
|
@@ -66,4 +67,49 @@ tn/chinese/test/sport_test.py
|
|
|
66
67
|
tn/chinese/test/time_test.py
|
|
67
68
|
tn/chinese/test/token_parser_test.py
|
|
68
69
|
tn/chinese/test/utils.py
|
|
69
|
-
tn/chinese/test/whitelist_test.py
|
|
70
|
+
tn/chinese/test/whitelist_test.py
|
|
71
|
+
tn/english/__init__.py
|
|
72
|
+
tn/english/normalizer.py
|
|
73
|
+
tn/english/data/__init__.py
|
|
74
|
+
tn/english/data/address/__init__.py
|
|
75
|
+
tn/english/data/date/__init__.py
|
|
76
|
+
tn/english/data/electronic/__init__.py
|
|
77
|
+
tn/english/data/measure/__init__.py
|
|
78
|
+
tn/english/data/money/__init__.py
|
|
79
|
+
tn/english/data/number/__init__.py
|
|
80
|
+
tn/english/data/ordinal/__init__.py
|
|
81
|
+
tn/english/data/roman/__init__.py
|
|
82
|
+
tn/english/data/telephone/__init__.py
|
|
83
|
+
tn/english/data/time/__init__.py
|
|
84
|
+
tn/english/data/whitelist/__init__.py
|
|
85
|
+
tn/english/rules/__init__.py
|
|
86
|
+
tn/english/rules/cardinal.py
|
|
87
|
+
tn/english/rules/date.py
|
|
88
|
+
tn/english/rules/decimal.py
|
|
89
|
+
tn/english/rules/electronic.py
|
|
90
|
+
tn/english/rules/fraction.py
|
|
91
|
+
tn/english/rules/measure.py
|
|
92
|
+
tn/english/rules/money.py
|
|
93
|
+
tn/english/rules/ordinal.py
|
|
94
|
+
tn/english/rules/punctuation.py
|
|
95
|
+
tn/english/rules/roman.py
|
|
96
|
+
tn/english/rules/telephone.py
|
|
97
|
+
tn/english/rules/time.py
|
|
98
|
+
tn/english/rules/whitelist.py
|
|
99
|
+
tn/english/rules/word.py
|
|
100
|
+
tn/english/test/__init__.py
|
|
101
|
+
tn/english/test/cardinal_test.py
|
|
102
|
+
tn/english/test/date_test.py
|
|
103
|
+
tn/english/test/decimal_test.py
|
|
104
|
+
tn/english/test/electronic_test.py
|
|
105
|
+
tn/english/test/fraction_test.py
|
|
106
|
+
tn/english/test/measure_test.py
|
|
107
|
+
tn/english/test/money_test.py
|
|
108
|
+
tn/english/test/normalizer_test.py
|
|
109
|
+
tn/english/test/ordinal_test.py
|
|
110
|
+
tn/english/test/roman_test.py
|
|
111
|
+
tn/english/test/telephone_test.py
|
|
112
|
+
tn/english/test/time_test.py
|
|
113
|
+
tn/english/test/utils.py
|
|
114
|
+
tn/english/test/whitelist_test.py
|
|
115
|
+
tn/english/test/word_test.py
|
|
@@ -36,6 +36,10 @@ class Cardinal(Processor):
|
|
|
36
36
|
def build_tagger(self):
|
|
37
37
|
zero = string_file('itn/chinese/data/number/zero.tsv') # 0
|
|
38
38
|
digit = string_file('itn/chinese/data/number/digit.tsv') # 1 ~ 9
|
|
39
|
+
special_tilde = string_file(
|
|
40
|
+
'itn/chinese//data/number/special_tilde.tsv') # 七八十->70~80
|
|
41
|
+
special_dash = string_file(
|
|
42
|
+
'itn/chinese//data/number/special_dash.tsv') # 七八十->70-80
|
|
39
43
|
sign = string_file('itn/chinese/data/number/sign.tsv') # + -
|
|
40
44
|
dot = string_file('itn/chinese/data/number/dot.tsv') # .
|
|
41
45
|
|
|
@@ -82,7 +86,7 @@ class Cardinal(Processor):
|
|
|
82
86
|
ten_thousand |= (thousand | hundred) + accep("万") + delete(
|
|
83
87
|
"零").ques + (thousand | hundred | tens | teen | digits).ques
|
|
84
88
|
|
|
85
|
-
# 1. 利用基础数字所构建的包含0~9
|
|
89
|
+
# 1. 利用基础数字所构建的包含0~9的标准数字
|
|
86
90
|
# 个/十/百/千/万
|
|
87
91
|
number = digits | teen | tens | hundred | thousand | ten_thousand
|
|
88
92
|
# 兆/亿
|
|
@@ -90,25 +94,19 @@ class Cardinal(Processor):
|
|
|
90
94
|
(number + accep('亿') + delete('零').ques).ques + number)
|
|
91
95
|
# 负的xxx 1.11, 1.01
|
|
92
96
|
number = sign.ques + number + (dot + digits.plus).ques
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# 三百七八公里 => 370-80km, 三百七八十千克 => 370-80kg
|
|
101
|
-
special_3number = cross('十', '1') + digit + insert("~1") + digit
|
|
102
|
-
special_3number |= digit + delete('十') + digit + insert("-") + digit
|
|
103
|
-
special_3number |= digit + delete('百') + digit + insert("0-") + digit \
|
|
104
|
-
+ (insert("0") | add_weight(cross("十", "0"), -0.1))
|
|
105
|
-
number |= add_weight(special_3number, -100.0)
|
|
97
|
+
# 五六万 => 5~6万,三五千 => 3000~5000,六七百 => 600~700,三四十 => 30~40
|
|
98
|
+
number |= special_tilde
|
|
99
|
+
# 十七八 => 17-8, 四十五六 => 45-6, 三百七八十 => 370-80
|
|
100
|
+
_special_dash = cross('十', '1') + special_dash
|
|
101
|
+
_special_dash |= digit + delete('十') + special_dash
|
|
102
|
+
_special_dash |= digit + delete('百') + special_dash
|
|
103
|
+
number |= _special_dash
|
|
106
104
|
|
|
107
105
|
self.number = number.optimize()
|
|
108
|
-
self.
|
|
109
|
-
self.
|
|
106
|
+
self.special_tilde = special_tilde.optimize()
|
|
107
|
+
self.special_dash = _special_dash.optimize()
|
|
110
108
|
|
|
111
|
-
# 2. 利用基础数字所构建的不包含0~9
|
|
109
|
+
# 2. 利用基础数字所构建的不包含0~9的标准数字
|
|
112
110
|
# 十/百/千/万
|
|
113
111
|
number_exclude_0_to_9 = teen | tens | hundred | thousand | ten_thousand
|
|
114
112
|
# 兆/亿
|
|
@@ -123,8 +121,8 @@ class Cardinal(Processor):
|
|
|
123
121
|
# 五六万,三五千,六七百,三四十
|
|
124
122
|
# 十七八美元 => $17~18, 四十五六岁 => 45-6岁,
|
|
125
123
|
# 三百七八公里 => 370-80km, 三百七八十千克 => 370-80kg
|
|
126
|
-
number_exclude_0_to_9 |=
|
|
127
|
-
number_exclude_0_to_9 |= add_weight(
|
|
124
|
+
number_exclude_0_to_9 |= special_tilde
|
|
125
|
+
number_exclude_0_to_9 |= add_weight(_special_dash, -100.0)
|
|
128
126
|
|
|
129
127
|
self.number_exclude_0_to_9 = (sign.ques +
|
|
130
128
|
number_exclude_0_to_9).optimize()
|
|
@@ -136,16 +134,19 @@ class Cardinal(Processor):
|
|
|
136
134
|
cardinal |= (number + dot + digits.plus)
|
|
137
135
|
# cardinal string like 110 or 12306 or 13125617878, used in phone,
|
|
138
136
|
# 340621199806051223, used in ID card
|
|
137
|
+
idcard_last_char = digits | 'X' | 'x'
|
|
139
138
|
cardinal |= (digits**3 | digits**4 | digits**5 | digits**11
|
|
140
|
-
| digits**18)
|
|
139
|
+
| (digits**17 + idcard_last_char) | digits**18)
|
|
141
140
|
|
|
142
|
-
# 4. 特殊格式的数字 +
|
|
141
|
+
# 4. 特殊格式的数字 + 标准数字
|
|
143
142
|
# cardinal string like 23
|
|
144
143
|
if self.enable_standalone_number:
|
|
145
144
|
if self.enable_0_to_9:
|
|
146
|
-
|
|
145
|
+
# 特殊格式数字为第一优先级, 标准数字为第二优先级, 如 "一二三四"
|
|
146
|
+
# 优先转译为 "1234" 而非 "1~2 3~4"
|
|
147
|
+
cardinal |= add_weight(number, 0.1)
|
|
147
148
|
else:
|
|
148
|
-
cardinal |= number_exclude_0_to_9
|
|
149
|
+
cardinal |= add_weight(number_exclude_0_to_9, 0.1)
|
|
149
150
|
tagger = insert('value: "') + cardinal + (insert(" ") + cardinal).star \
|
|
150
151
|
+ insert('"')
|
|
151
152
|
self.tagger = self.add_tokens(tagger)
|
|
@@ -27,8 +27,11 @@ class LicensePlate(Processor):
|
|
|
27
27
|
|
|
28
28
|
def build_tagger(self):
|
|
29
29
|
digit = string_file('itn/chinese/data/number/digit.tsv') # 1 ~ 9
|
|
30
|
+
zero = string_file('itn/chinese/data/number/zero.tsv') # 0
|
|
31
|
+
digits = zero | digit
|
|
30
32
|
province = string_file(
|
|
31
33
|
'itn/chinese/data/license_plate/province.tsv') # 皖
|
|
32
|
-
license_plate = province + self.ALPHA + (self.ALPHA |
|
|
34
|
+
license_plate = province + self.ALPHA + (self.ALPHA | digits)**5
|
|
35
|
+
license_plate |= province + self.ALPHA + (self.ALPHA | digits)**6
|
|
33
36
|
tagger = insert('value: "') + license_plate + insert('"')
|
|
34
37
|
self.tagger = self.add_tokens(tagger)
|
|
@@ -31,7 +31,6 @@ class Measure(Processor):
|
|
|
31
31
|
def build_tagger(self):
|
|
32
32
|
units_en = string_file('itn/chinese/data/measure/units_en.tsv')
|
|
33
33
|
units_zh = string_file('itn/chinese/data/measure/units_zh.tsv')
|
|
34
|
-
digit = string_file('itn/chinese/data/number/digit.tsv') # 1 ~ 9
|
|
35
34
|
sign = string_file('itn/chinese/data/number/sign.tsv') # + -
|
|
36
35
|
to = cross('到', '~') | cross('到百分之', '~')
|
|
37
36
|
|
|
@@ -52,8 +51,6 @@ class Measure(Processor):
|
|
|
52
51
|
|
|
53
52
|
# 十千米每小时 => 10km/h, 十一到一百千米每小时 => 11~100km/h
|
|
54
53
|
measure = number + (to + number).ques + units
|
|
55
|
-
# 七八块钱
|
|
56
|
-
measure |= digit + insert("~") + digit + units
|
|
57
54
|
tagger = insert('value: "') + (measure | percent) + insert('"')
|
|
58
55
|
|
|
59
56
|
# 每小时十千米 => 10km/h, 每小时三十到三百一十一千米 => 30~311km/h
|
|
Binary file
|
|
@@ -64,11 +64,13 @@ class Cardinal(Processor):
|
|
|
64
64
|
number @= self.build_rule(
|
|
65
65
|
cross('二百', '两百')
|
|
66
66
|
| cross('二千', '两千')
|
|
67
|
-
| cross('二万', '两万'))
|
|
68
|
-
|
|
67
|
+
| cross('二万', '两万')).optimize()
|
|
68
|
+
percent = insert('百分之') + number + delete('%')
|
|
69
|
+
self.number = accep('约').ques + accep('人均').ques + (number | percent)
|
|
69
70
|
|
|
70
71
|
# cardinal string like 127.0.0.1, used in ID, IP, etc.
|
|
71
72
|
cardinal = digits.plus + (dot + digits.plus)**3
|
|
73
|
+
cardinal |= percent
|
|
72
74
|
# xxxx-xxx-xxx
|
|
73
75
|
cardinal |= digits.plus + (delete('-') + digits.plus)**2
|
|
74
76
|
# xxx-xxxxxxxx
|
|
@@ -76,6 +78,7 @@ class Cardinal(Processor):
|
|
|
76
78
|
# three or five or eleven phone numbers
|
|
77
79
|
phone_digits = digits @ self.build_rule(cross('一', '幺'))
|
|
78
80
|
phone = phone_digits**3 | phone_digits**5 | phone_digits**11
|
|
81
|
+
phone |= accep("尾号") + (accep("是") | accep("为")).ques + phone_digits**4
|
|
79
82
|
cardinal |= add_weight(phone, -1.0)
|
|
80
83
|
|
|
81
84
|
tagger = insert('value: "') + cardinal + insert('"')
|
|
@@ -15,23 +15,32 @@
|
|
|
15
15
|
from tn.chinese.rules.cardinal import Cardinal
|
|
16
16
|
from tn.processor import Processor
|
|
17
17
|
|
|
18
|
-
from pynini import string_file
|
|
18
|
+
from pynini import cross, string_file
|
|
19
19
|
from pynini.lib.pynutil import delete, insert
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class Math(Processor):
|
|
23
23
|
|
|
24
24
|
def __init__(self):
|
|
25
|
-
super().__init__(name=
|
|
25
|
+
super().__init__(name="math")
|
|
26
26
|
self.build_tagger()
|
|
27
27
|
self.build_verbalizer()
|
|
28
28
|
|
|
29
29
|
def build_tagger(self):
|
|
30
|
-
operator = string_file(
|
|
30
|
+
operator = string_file("tn/chinese/data/math/operator.tsv")
|
|
31
|
+
# When it appears alone, it is treated as punctuation
|
|
32
|
+
symbols = (
|
|
33
|
+
cross("~", "到")
|
|
34
|
+
| cross(":", "比")
|
|
35
|
+
| cross("<", "小于")
|
|
36
|
+
| cross(">", "大于")
|
|
37
|
+
)
|
|
31
38
|
|
|
32
39
|
number = Cardinal().number
|
|
33
|
-
tagger = (
|
|
34
|
-
|
|
40
|
+
tagger = (
|
|
41
|
+
number
|
|
42
|
+
+ (delete(" ").ques + (operator | symbols) + delete(" ").ques + number).star
|
|
43
|
+
)
|
|
35
44
|
tagger |= operator
|
|
36
45
|
tagger = insert('value: "') + tagger + insert('"')
|
|
37
46
|
self.tagger = self.add_tokens(tagger)
|
|
@@ -35,8 +35,6 @@ class Measure(Processor):
|
|
|
35
35
|
to = cross('-', '到') | cross('~', '到') | accep('到')
|
|
36
36
|
|
|
37
37
|
number = Cardinal().number
|
|
38
|
-
percent = insert('百分之') + number + delete('%')
|
|
39
|
-
|
|
40
38
|
number @= self.build_rule(cross('二', '两'), '[BOS]', '[EOS]')
|
|
41
39
|
# 1-11个,1个-11个
|
|
42
40
|
prefix = number + (rmspace + units).ques + to
|
|
@@ -55,8 +53,7 @@ class Measure(Processor):
|
|
|
55
53
|
prefix = cardinal + (rmspace + unit).ques + to
|
|
56
54
|
annual = prefix.ques + cardinal + unit
|
|
57
55
|
|
|
58
|
-
tagger = insert('value: "') + (measure |
|
|
59
|
-
| annual) + insert('"')
|
|
56
|
+
tagger = insert('value: "') + (measure | annual) + insert('"')
|
|
60
57
|
|
|
61
58
|
# 10km/h
|
|
62
59
|
rmsign = rmspace + delete('/') + rmspace
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
File without changes
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Copyright (c) 2022 Zhendong Peng (pzd17@tsinghua.org.cn)
|
|
2
|
+
# Copyright (c) 2024 Xingchen Song (sxc19@tsinghua.org.cn)
|
|
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
|
+
from tn.processor import Processor
|
|
17
|
+
from tn.english.rules.cardinal import Cardinal
|
|
18
|
+
from tn.english.rules.ordinal import Ordinal
|
|
19
|
+
from tn.english.rules.decimal import Decimal
|
|
20
|
+
from tn.english.rules.fraction import Fraction
|
|
21
|
+
from tn.english.rules.word import Word
|
|
22
|
+
from tn.english.rules.date import Date
|
|
23
|
+
from tn.english.rules.time import Time
|
|
24
|
+
from tn.english.rules.measure import Measure
|
|
25
|
+
from tn.english.rules.money import Money
|
|
26
|
+
from tn.english.rules.telephone import Telephone
|
|
27
|
+
from tn.english.rules.electronic import Electronic
|
|
28
|
+
from tn.english.rules.whitelist import WhiteList
|
|
29
|
+
from tn.english.rules.punctuation import Punctuation
|
|
30
|
+
|
|
31
|
+
from pynini.lib.pynutil import add_weight, delete
|
|
32
|
+
from importlib_resources import files
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Normalizer(Processor):
|
|
36
|
+
|
|
37
|
+
def __init__(self, cache_dir=None, overwrite_cache=False):
|
|
38
|
+
super().__init__(name='en_normalizer', ordertype="en_tn")
|
|
39
|
+
if cache_dir is None:
|
|
40
|
+
cache_dir = files("tn")
|
|
41
|
+
self.build_fst('en_tn', cache_dir, overwrite_cache)
|
|
42
|
+
|
|
43
|
+
def build_tagger(self):
|
|
44
|
+
cardinal = add_weight(Cardinal().tagger, 1.0)
|
|
45
|
+
ordinal = add_weight(Ordinal().tagger, 1.0)
|
|
46
|
+
decimal = add_weight(Decimal().tagger, 1.0)
|
|
47
|
+
fraction = add_weight(Fraction().tagger, 1.0)
|
|
48
|
+
date = add_weight(Date().tagger, 0.99)
|
|
49
|
+
time = add_weight(Time().tagger, 1.00)
|
|
50
|
+
measure = add_weight(Measure().tagger, 1.00)
|
|
51
|
+
money = add_weight(Money().tagger, 1.00)
|
|
52
|
+
telephone = add_weight(Telephone().tagger, 1.00)
|
|
53
|
+
electronic = add_weight(Electronic().tagger, 1.00)
|
|
54
|
+
word = add_weight(Word().tagger, 100)
|
|
55
|
+
whitelist = add_weight(WhiteList().tagger, 1.00)
|
|
56
|
+
punct = add_weight(Punctuation().tagger, 2.00)
|
|
57
|
+
# TODO(xcsong): add roman
|
|
58
|
+
tagger = punct.star + \
|
|
59
|
+
(cardinal | ordinal | word
|
|
60
|
+
| date | decimal | fraction
|
|
61
|
+
| time | measure | money
|
|
62
|
+
| telephone | electronic
|
|
63
|
+
| whitelist
|
|
64
|
+
| punct).optimize() + (punct.plus | self.DELETE_SPACE)
|
|
65
|
+
# delete the last space
|
|
66
|
+
self.tagger = tagger.star @ self.build_rule(delete(' '), r='[EOS]')
|
|
67
|
+
|
|
68
|
+
def build_verbalizer(self):
|
|
69
|
+
cardinal = Cardinal().verbalizer
|
|
70
|
+
ordinal = Ordinal().verbalizer
|
|
71
|
+
decimal = Decimal().verbalizer
|
|
72
|
+
fraction = Fraction().verbalizer
|
|
73
|
+
word = Word().verbalizer
|
|
74
|
+
date = Date().verbalizer
|
|
75
|
+
time = Time().verbalizer
|
|
76
|
+
measure = Measure().verbalizer
|
|
77
|
+
money = Money().verbalizer
|
|
78
|
+
telephone = Telephone().verbalizer
|
|
79
|
+
electronic = Electronic().verbalizer
|
|
80
|
+
whitelist = WhiteList().verbalizer
|
|
81
|
+
punct = Punctuation().verbalizer
|
|
82
|
+
verbalizer = \
|
|
83
|
+
(cardinal | ordinal | word
|
|
84
|
+
| date | decimal
|
|
85
|
+
| fraction | time
|
|
86
|
+
| measure | money
|
|
87
|
+
| telephone
|
|
88
|
+
| electronic
|
|
89
|
+
| whitelist
|
|
90
|
+
| punct).optimize() + punct.ques + self.INSERT_SPACE
|
|
91
|
+
self.verbalizer = verbalizer.star @ self.build_rule(delete(' '),
|
|
92
|
+
r='[EOS]')
|
|
File without changes
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# Copyright (c) 2024, WENET COMMUNITY. Xingchen Song (sxc19@tsinghua.org.cn).
|
|
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 pynini
|
|
17
|
+
from pynini.examples import plurals
|
|
18
|
+
from pynini.lib import pynutil
|
|
19
|
+
|
|
20
|
+
from tn.processor import Processor
|
|
21
|
+
from tn.utils import get_abs_path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Cardinal(Processor):
|
|
25
|
+
|
|
26
|
+
def __init__(self, deterministic: bool = False):
|
|
27
|
+
"""
|
|
28
|
+
Args:
|
|
29
|
+
deterministic: if True will provide a single transduction option,
|
|
30
|
+
for False multiple transduction are generated (used for audio-based normalization)
|
|
31
|
+
"""
|
|
32
|
+
super().__init__('cardinal', ordertype="en_tn")
|
|
33
|
+
self.deterministic = deterministic
|
|
34
|
+
self.build_tagger()
|
|
35
|
+
self.build_verbalizer()
|
|
36
|
+
|
|
37
|
+
def build_tagger(self):
|
|
38
|
+
"""
|
|
39
|
+
Finite state transducer for classifying cardinals, e.g.
|
|
40
|
+
-23 -> cardinal { negative: "true" integer: "twenty three" }
|
|
41
|
+
"""
|
|
42
|
+
# TODO replace to have "oh" as a default for "0"
|
|
43
|
+
graph = pynini.Far(
|
|
44
|
+
get_abs_path(
|
|
45
|
+
"english/data/number/cardinal_number_name.far")).get_fst()
|
|
46
|
+
graph_au = pynini.Far(
|
|
47
|
+
get_abs_path(
|
|
48
|
+
"english/data/number/cardinal_number_name_au.far")).get_fst()
|
|
49
|
+
self.graph_hundred_component_at_least_one_none_zero_digit = (
|
|
50
|
+
pynini.closure(self.DIGIT, 2, 3)
|
|
51
|
+
| pynini.difference(self.DIGIT, pynini.accep("0"))) @ graph
|
|
52
|
+
|
|
53
|
+
graph_digit = pynini.string_file(
|
|
54
|
+
get_abs_path("english/data/number/digit.tsv"))
|
|
55
|
+
graph_zero = pynini.string_file(
|
|
56
|
+
get_abs_path("english/data/number/zero.tsv"))
|
|
57
|
+
|
|
58
|
+
single_digits_graph = pynini.invert(graph_digit | graph_zero)
|
|
59
|
+
self.single_digits_graph = single_digits_graph + pynini.closure(
|
|
60
|
+
self.INSERT_SPACE + single_digits_graph)
|
|
61
|
+
|
|
62
|
+
if not self.deterministic:
|
|
63
|
+
# for a single token allow only the same normalization
|
|
64
|
+
# "007" -> {"oh oh seven", "zero zero seven"} not {"oh zero seven"}
|
|
65
|
+
single_digits_graph_zero = pynini.invert(graph_digit | graph_zero)
|
|
66
|
+
single_digits_graph_oh = pynini.invert(graph_digit) | pynini.cross(
|
|
67
|
+
"0", "oh")
|
|
68
|
+
|
|
69
|
+
self.single_digits_graph = single_digits_graph_zero + pynini.closure(
|
|
70
|
+
self.INSERT_SPACE + single_digits_graph_zero)
|
|
71
|
+
self.single_digits_graph |= single_digits_graph_oh + pynini.closure(
|
|
72
|
+
self.INSERT_SPACE + single_digits_graph_oh)
|
|
73
|
+
|
|
74
|
+
single_digits_graph_with_commas = pynini.closure(
|
|
75
|
+
self.single_digits_graph + self.INSERT_SPACE, 1,
|
|
76
|
+
3) + pynini.closure(
|
|
77
|
+
pynutil.delete(",") + single_digits_graph +
|
|
78
|
+
self.INSERT_SPACE + single_digits_graph +
|
|
79
|
+
self.INSERT_SPACE + single_digits_graph, 1)
|
|
80
|
+
|
|
81
|
+
graph = (pynini.closure(self.DIGIT, 1, 3) +
|
|
82
|
+
(pynini.closure(pynutil.delete(",") + self.DIGIT**3)
|
|
83
|
+
| pynini.closure(self.DIGIT**3))) @ graph
|
|
84
|
+
|
|
85
|
+
self.graph = graph
|
|
86
|
+
self.graph_with_and = self.add_optional_and(graph)
|
|
87
|
+
|
|
88
|
+
if self.deterministic:
|
|
89
|
+
long_numbers = pynini.compose(self.DIGIT**(5, ...),
|
|
90
|
+
self.single_digits_graph).optimize()
|
|
91
|
+
self.long_numbers = plurals._priority_union(
|
|
92
|
+
long_numbers, self.graph_with_and,
|
|
93
|
+
pynini.closure(self.VCHAR)).optimize()
|
|
94
|
+
cardinal_with_leading_zeros = pynini.compose(
|
|
95
|
+
pynini.accep("0") + pynini.closure(self.DIGIT),
|
|
96
|
+
self.single_digits_graph)
|
|
97
|
+
final_graph = self.long_numbers | cardinal_with_leading_zeros
|
|
98
|
+
final_graph |= self.add_optional_and(graph_au)
|
|
99
|
+
else:
|
|
100
|
+
leading_zeros = pynini.compose(
|
|
101
|
+
pynini.closure(pynini.accep("0"), 1), self.single_digits_graph)
|
|
102
|
+
cardinal_with_leading_zeros = (
|
|
103
|
+
leading_zeros + self.INSERT_SPACE + pynini.compose(
|
|
104
|
+
pynini.closure(self.DIGIT), self.graph_with_and))
|
|
105
|
+
self.long_numbers = self.graph_with_and | pynutil.add_weight(
|
|
106
|
+
self.single_digits_graph, 0.0001)
|
|
107
|
+
# add small weight to non-default graphs to make sure the deterministic option is listed first
|
|
108
|
+
final_graph = (self.long_numbers
|
|
109
|
+
| pynutil.add_weight(
|
|
110
|
+
single_digits_graph_with_commas, 0.0001)
|
|
111
|
+
| cardinal_with_leading_zeros).optimize()
|
|
112
|
+
|
|
113
|
+
one_to_a_replacement_graph = (
|
|
114
|
+
pynini.cross("one hundred", "a hundred")
|
|
115
|
+
| pynini.cross("one thousand", "thousand")
|
|
116
|
+
| pynini.cross("one million", "a million"))
|
|
117
|
+
final_graph |= pynini.compose(
|
|
118
|
+
final_graph,
|
|
119
|
+
one_to_a_replacement_graph.optimize() +
|
|
120
|
+
pynini.closure(self.VCHAR)).optimize()
|
|
121
|
+
# remove commas for 4 digits numbers
|
|
122
|
+
four_digit_comma_graph = (
|
|
123
|
+
self.DIGIT - "0") + pynutil.delete(",") + self.DIGIT**3
|
|
124
|
+
final_graph |= pynini.compose(four_digit_comma_graph.optimize(),
|
|
125
|
+
final_graph).optimize()
|
|
126
|
+
|
|
127
|
+
self.final_graph = final_graph
|
|
128
|
+
optional_minus_graph = pynini.closure(
|
|
129
|
+
pynutil.insert("negative: ") + pynini.cross("-", "\"true\" "), 0,
|
|
130
|
+
1)
|
|
131
|
+
final_graph = optional_minus_graph + pynutil.insert(
|
|
132
|
+
"integer: \"") + final_graph + pynutil.insert("\"")
|
|
133
|
+
final_graph = self.add_tokens(final_graph)
|
|
134
|
+
self.tagger = final_graph.optimize()
|
|
135
|
+
|
|
136
|
+
def add_optional_and(self, graph):
|
|
137
|
+
graph_with_and = graph
|
|
138
|
+
|
|
139
|
+
graph_with_and = pynutil.add_weight(graph, 0.00001)
|
|
140
|
+
not_quote = pynini.closure(self.NOT_QUOTE)
|
|
141
|
+
no_thousand_million = pynini.difference(
|
|
142
|
+
not_quote, not_quote + pynini.union("thousand", "million") +
|
|
143
|
+
not_quote).optimize()
|
|
144
|
+
integer = (not_quote + pynutil.add_weight(
|
|
145
|
+
pynini.cross("hundred ", "hundred and ") + no_thousand_million,
|
|
146
|
+
-0.0001)).optimize()
|
|
147
|
+
|
|
148
|
+
no_hundred = pynini.difference(
|
|
149
|
+
pynini.closure(self.VCHAR),
|
|
150
|
+
not_quote + pynini.accep("hundred") + not_quote).optimize()
|
|
151
|
+
integer |= (not_quote + pynutil.add_weight(
|
|
152
|
+
pynini.cross("thousand ", "thousand and ") + no_hundred,
|
|
153
|
+
-0.0001)).optimize()
|
|
154
|
+
|
|
155
|
+
optional_hundred = pynini.compose((self.DIGIT - "0")**3,
|
|
156
|
+
graph).optimize()
|
|
157
|
+
optional_hundred = pynini.compose(
|
|
158
|
+
optional_hundred,
|
|
159
|
+
pynini.closure(self.VCHAR) + pynini.cross(" hundred", "") +
|
|
160
|
+
pynini.closure(self.VCHAR))
|
|
161
|
+
graph_with_and |= pynini.compose(graph, integer).optimize()
|
|
162
|
+
graph_with_and |= optional_hundred
|
|
163
|
+
return graph_with_and
|
|
164
|
+
|
|
165
|
+
def build_verbalizer(self):
|
|
166
|
+
"""
|
|
167
|
+
Finite state transducer for verbalizing cardinal, e.g.
|
|
168
|
+
cardinal { negative: "true" integer: "23" } -> minus twenty three
|
|
169
|
+
"""
|
|
170
|
+
optional_sign = pynini.cross("negative: \"true\"", "minus ")
|
|
171
|
+
if not self.deterministic:
|
|
172
|
+
optional_sign |= pynini.cross("negative: \"true\"", "negative ")
|
|
173
|
+
optional_sign |= pynini.cross("negative: \"true\"", "dash ")
|
|
174
|
+
|
|
175
|
+
self.optional_sign = pynini.closure(optional_sign + self.DELETE_SPACE,
|
|
176
|
+
0, 1)
|
|
177
|
+
|
|
178
|
+
integer = pynini.closure(self.NOT_QUOTE)
|
|
179
|
+
|
|
180
|
+
self.integer = self.DELETE_SPACE + pynutil.delete(
|
|
181
|
+
"\"") + integer + pynutil.delete("\"")
|
|
182
|
+
integer = pynutil.delete("integer:") + self.integer
|
|
183
|
+
|
|
184
|
+
self.numbers = self.optional_sign + integer
|
|
185
|
+
delete_tokens = self.delete_tokens(self.numbers)
|
|
186
|
+
self.verbalizer = delete_tokens.optimize()
|