WeTextProcessing 0.1.12__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.12 → WeTextProcessing-0.2.0}/PKG-INFO +1 -1
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/PKG-INFO +1 -1
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/SOURCES.txt +47 -1
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/cardinal.py +2 -1
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/license_plate.py +4 -1
- WeTextProcessing-0.2.0/itn/zh_itn_tagger.fst +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/cardinal.py +4 -2
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/math.py +14 -5
- {WeTextProcessing-0.1.12 → 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.12 → WeTextProcessing-0.2.0}/tn/main.py +22 -11
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/processor.py +17 -1
- {WeTextProcessing-0.1.12 → 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.12/itn/zh_itn_tagger.fst +0 -0
- WeTextProcessing-0.1.12/tn/zh_tn_tagger.fst +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/LICENSE +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/README.md +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/dependency_links.txt +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/entry_points.txt +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/requires.txt +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/WeTextProcessing.egg-info/top_level.txt +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/__main__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/inverse_normalizer.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/char.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/date.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/fraction.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/math.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/measure.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/money.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/postprocessor.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/time.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/rules/whitelist.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/test/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/test/normalizer_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/chinese/test/utils.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/main.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/itn/zh_itn_verbalizer.fst +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/setup.cfg +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/setup.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/__main__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/normalizer.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/char.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/date.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/fraction.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/money.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/postprocessor.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/preprocessor.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/sport.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/time.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/rules/whitelist.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/__init__.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/cardinal_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/char_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/date_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/fraction_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/math_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/measure_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/money_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/normalizer_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/postprocessor_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/preprocessor_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/sport_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/time_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/token_parser_test.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/utils.py +0 -0
- {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.0}/tn/chinese/test/whitelist_test.py +0 -0
- {WeTextProcessing-0.1.12 → 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
|
|
@@ -134,8 +134,9 @@ class Cardinal(Processor):
|
|
|
134
134
|
cardinal |= (number + dot + digits.plus)
|
|
135
135
|
# cardinal string like 110 or 12306 or 13125617878, used in phone,
|
|
136
136
|
# 340621199806051223, used in ID card
|
|
137
|
+
idcard_last_char = digits | 'X' | 'x'
|
|
137
138
|
cardinal |= (digits**3 | digits**4 | digits**5 | digits**11
|
|
138
|
-
| digits**18)
|
|
139
|
+
| (digits**17 + idcard_last_char) | digits**18)
|
|
139
140
|
|
|
140
141
|
# 4. 特殊格式的数字 + 标准数字
|
|
141
142
|
# cardinal string like 23
|
|
@@ -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)
|
|
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
|
|
@@ -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()
|