WeTextProcessing 0.1.12__tar.gz → 0.2.1__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.
Files changed (121) hide show
  1. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/PKG-INFO +1 -1
  2. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/PKG-INFO +1 -1
  3. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/SOURCES.txt +49 -1
  4. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/cardinal.py +2 -1
  5. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/license_plate.py +4 -1
  6. WeTextProcessing-0.2.1/itn/zh_itn_tagger.fst +0 -0
  7. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/cardinal.py +4 -2
  8. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/math.py +14 -5
  9. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/measure.py +1 -4
  10. WeTextProcessing-0.2.1/tn/en_tn_tagger.fst +0 -0
  11. WeTextProcessing-0.2.1/tn/en_tn_verbalizer.fst +0 -0
  12. WeTextProcessing-0.2.1/tn/english/__init__.py +0 -0
  13. WeTextProcessing-0.2.1/tn/english/data/__init__.py +0 -0
  14. WeTextProcessing-0.2.1/tn/english/data/address/__init__.py +13 -0
  15. WeTextProcessing-0.2.1/tn/english/data/date/__init__.py +0 -0
  16. WeTextProcessing-0.2.1/tn/english/data/electronic/__init__.py +0 -0
  17. WeTextProcessing-0.2.1/tn/english/data/measure/__init__.py +13 -0
  18. WeTextProcessing-0.2.1/tn/english/data/money/__init__.py +0 -0
  19. WeTextProcessing-0.2.1/tn/english/data/number/__init__.py +13 -0
  20. WeTextProcessing-0.2.1/tn/english/data/ordinal/__init__.py +0 -0
  21. WeTextProcessing-0.2.1/tn/english/data/roman/__init__.py +0 -0
  22. WeTextProcessing-0.2.1/tn/english/data/telephone/__init__.py +0 -0
  23. WeTextProcessing-0.2.1/tn/english/data/time/__init__.py +13 -0
  24. WeTextProcessing-0.2.1/tn/english/data/whitelist/__init__.py +0 -0
  25. WeTextProcessing-0.2.1/tn/english/normalizer.py +92 -0
  26. WeTextProcessing-0.2.1/tn/english/rules/__init__.py +0 -0
  27. WeTextProcessing-0.2.1/tn/english/rules/cardinal.py +186 -0
  28. WeTextProcessing-0.2.1/tn/english/rules/date.py +319 -0
  29. WeTextProcessing-0.2.1/tn/english/rules/decimal.py +194 -0
  30. WeTextProcessing-0.2.1/tn/english/rules/electronic.py +213 -0
  31. WeTextProcessing-0.2.1/tn/english/rules/fraction.py +139 -0
  32. WeTextProcessing-0.2.1/tn/english/rules/measure.py +327 -0
  33. WeTextProcessing-0.2.1/tn/english/rules/money.py +124 -0
  34. WeTextProcessing-0.2.1/tn/english/rules/ordinal.py +96 -0
  35. WeTextProcessing-0.2.1/tn/english/rules/punctuation.py +81 -0
  36. WeTextProcessing-0.2.1/tn/english/rules/roman.py +149 -0
  37. WeTextProcessing-0.2.1/tn/english/rules/telephone.py +180 -0
  38. WeTextProcessing-0.2.1/tn/english/rules/time.py +167 -0
  39. WeTextProcessing-0.2.1/tn/english/rules/whitelist.py +153 -0
  40. WeTextProcessing-0.2.1/tn/english/rules/word.py +59 -0
  41. WeTextProcessing-0.2.1/tn/english/test/__init__.py +0 -0
  42. WeTextProcessing-0.2.1/tn/english/test/cardinal_test.py +28 -0
  43. WeTextProcessing-0.2.1/tn/english/test/date_test.py +28 -0
  44. WeTextProcessing-0.2.1/tn/english/test/decimal_test.py +28 -0
  45. WeTextProcessing-0.2.1/tn/english/test/electronic_test.py +28 -0
  46. WeTextProcessing-0.2.1/tn/english/test/fraction_test.py +28 -0
  47. WeTextProcessing-0.2.1/tn/english/test/measure_test.py +28 -0
  48. WeTextProcessing-0.2.1/tn/english/test/money_test.py +28 -0
  49. WeTextProcessing-0.2.1/tn/english/test/normalizer_test.py +28 -0
  50. WeTextProcessing-0.2.1/tn/english/test/ordinal_test.py +28 -0
  51. WeTextProcessing-0.2.1/tn/english/test/roman_test.py +28 -0
  52. WeTextProcessing-0.2.1/tn/english/test/telephone_test.py +28 -0
  53. WeTextProcessing-0.2.1/tn/english/test/time_test.py +28 -0
  54. WeTextProcessing-0.2.1/tn/english/test/utils.py +32 -0
  55. WeTextProcessing-0.2.1/tn/english/test/whitelist_test.py +28 -0
  56. WeTextProcessing-0.2.1/tn/english/test/word_test.py +28 -0
  57. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/main.py +22 -11
  58. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/processor.py +17 -1
  59. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/token_parser.py +11 -2
  60. WeTextProcessing-0.2.1/tn/utils.py +92 -0
  61. WeTextProcessing-0.2.1/tn/zh_tn_tagger.fst +0 -0
  62. WeTextProcessing-0.1.12/itn/zh_itn_tagger.fst +0 -0
  63. WeTextProcessing-0.1.12/tn/zh_tn_tagger.fst +0 -0
  64. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/LICENSE +0 -0
  65. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/README.md +0 -0
  66. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/dependency_links.txt +0 -0
  67. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/entry_points.txt +0 -0
  68. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/requires.txt +0 -0
  69. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/WeTextProcessing.egg-info/top_level.txt +0 -0
  70. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/__init__.py +0 -0
  71. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/__main__.py +0 -0
  72. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/__init__.py +0 -0
  73. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/inverse_normalizer.py +0 -0
  74. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/__init__.py +0 -0
  75. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/char.py +0 -0
  76. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/date.py +0 -0
  77. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/fraction.py +0 -0
  78. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/math.py +0 -0
  79. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/measure.py +0 -0
  80. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/money.py +0 -0
  81. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/postprocessor.py +0 -0
  82. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/time.py +0 -0
  83. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/rules/whitelist.py +0 -0
  84. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/test/__init__.py +0 -0
  85. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/test/normalizer_test.py +0 -0
  86. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/chinese/test/utils.py +0 -0
  87. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/main.py +0 -0
  88. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/itn/zh_itn_verbalizer.fst +0 -0
  89. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/setup.cfg +0 -0
  90. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/setup.py +0 -0
  91. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/__init__.py +0 -0
  92. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/__main__.py +0 -0
  93. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/__init__.py +0 -0
  94. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/normalizer.py +0 -0
  95. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/__init__.py +0 -0
  96. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/char.py +0 -0
  97. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/date.py +0 -0
  98. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/fraction.py +0 -0
  99. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/money.py +0 -0
  100. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/postprocessor.py +0 -0
  101. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/preprocessor.py +0 -0
  102. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/sport.py +0 -0
  103. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/time.py +0 -0
  104. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/rules/whitelist.py +0 -0
  105. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/__init__.py +0 -0
  106. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/cardinal_test.py +0 -0
  107. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/char_test.py +0 -0
  108. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/date_test.py +0 -0
  109. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/fraction_test.py +0 -0
  110. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/math_test.py +0 -0
  111. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/measure_test.py +0 -0
  112. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/money_test.py +0 -0
  113. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/normalizer_test.py +0 -0
  114. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/postprocessor_test.py +0 -0
  115. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/preprocessor_test.py +0 -0
  116. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/sport_test.py +0 -0
  117. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/time_test.py +0 -0
  118. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/token_parser_test.py +0 -0
  119. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/utils.py +0 -0
  120. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/chinese/test/whitelist_test.py +0 -0
  121. {WeTextProcessing-0.1.12 → WeTextProcessing-0.2.1}/tn/zh_tn_verbalizer.fst +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: WeTextProcessing
3
- Version: 0.1.12
3
+ Version: 0.2.1
4
4
  Summary: WeTextProcessing, including TN & ITN
5
5
  Home-page: https://github.com/wenet-e2e/WeTextProcessing
6
6
  Author: Zhendong Peng, Xingchen Song
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: WeTextProcessing
3
- Version: 0.1.12
3
+ Version: 0.2.1
4
4
  Summary: WeTextProcessing, including TN & ITN
5
5
  Home-page: https://github.com/wenet-e2e/WeTextProcessing
6
6
  Author: Zhendong Peng, Xingchen Song
@@ -31,9 +31,12 @@ itn/chinese/test/normalizer_test.py
31
31
  itn/chinese/test/utils.py
32
32
  tn/__init__.py
33
33
  tn/__main__.py
34
+ tn/en_tn_tagger.fst
35
+ tn/en_tn_verbalizer.fst
34
36
  tn/main.py
35
37
  tn/processor.py
36
38
  tn/token_parser.py
39
+ tn/utils.py
37
40
  tn/zh_tn_tagger.fst
38
41
  tn/zh_tn_verbalizer.fst
39
42
  tn/chinese/__init__.py
@@ -66,4 +69,49 @@ tn/chinese/test/sport_test.py
66
69
  tn/chinese/test/time_test.py
67
70
  tn/chinese/test/token_parser_test.py
68
71
  tn/chinese/test/utils.py
69
- tn/chinese/test/whitelist_test.py
72
+ tn/chinese/test/whitelist_test.py
73
+ tn/english/__init__.py
74
+ tn/english/normalizer.py
75
+ tn/english/data/__init__.py
76
+ tn/english/data/address/__init__.py
77
+ tn/english/data/date/__init__.py
78
+ tn/english/data/electronic/__init__.py
79
+ tn/english/data/measure/__init__.py
80
+ tn/english/data/money/__init__.py
81
+ tn/english/data/number/__init__.py
82
+ tn/english/data/ordinal/__init__.py
83
+ tn/english/data/roman/__init__.py
84
+ tn/english/data/telephone/__init__.py
85
+ tn/english/data/time/__init__.py
86
+ tn/english/data/whitelist/__init__.py
87
+ tn/english/rules/__init__.py
88
+ tn/english/rules/cardinal.py
89
+ tn/english/rules/date.py
90
+ tn/english/rules/decimal.py
91
+ tn/english/rules/electronic.py
92
+ tn/english/rules/fraction.py
93
+ tn/english/rules/measure.py
94
+ tn/english/rules/money.py
95
+ tn/english/rules/ordinal.py
96
+ tn/english/rules/punctuation.py
97
+ tn/english/rules/roman.py
98
+ tn/english/rules/telephone.py
99
+ tn/english/rules/time.py
100
+ tn/english/rules/whitelist.py
101
+ tn/english/rules/word.py
102
+ tn/english/test/__init__.py
103
+ tn/english/test/cardinal_test.py
104
+ tn/english/test/date_test.py
105
+ tn/english/test/decimal_test.py
106
+ tn/english/test/electronic_test.py
107
+ tn/english/test/fraction_test.py
108
+ tn/english/test/measure_test.py
109
+ tn/english/test/money_test.py
110
+ tn/english/test/normalizer_test.py
111
+ tn/english/test/ordinal_test.py
112
+ tn/english/test/roman_test.py
113
+ tn/english/test/telephone_test.py
114
+ tn/english/test/time_test.py
115
+ tn/english/test/utils.py
116
+ tn/english/test/whitelist_test.py
117
+ 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 | digit)**5
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)
@@ -64,11 +64,13 @@ class Cardinal(Processor):
64
64
  number @= self.build_rule(
65
65
  cross('二百', '两百')
66
66
  | cross('二千', '两千')
67
- | cross('二万', '两万'))
68
- self.number = accep('约').ques + accep('人均').ques + number.optimize()
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='math')
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('tn/chinese/data/math/operator.tsv')
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 = (number + ((delete(' ').ques + operator + delete(' ').ques +
34
- number).plus).ques)
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 | percent
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.
@@ -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.
@@ -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.
@@ -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.
@@ -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()