WeTextProcessing 0.1.12__py3-none-any.whl → 0.2.0__py3-none-any.whl

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 (63) hide show
  1. {WeTextProcessing-0.1.12.dist-info → WeTextProcessing-0.2.0.dist-info}/METADATA +1 -1
  2. WeTextProcessing-0.2.0.dist-info/RECORD +112 -0
  3. {WeTextProcessing-0.1.12.dist-info → WeTextProcessing-0.2.0.dist-info}/WHEEL +1 -1
  4. itn/chinese/rules/cardinal.py +2 -1
  5. itn/chinese/rules/license_plate.py +4 -1
  6. itn/zh_itn_tagger.fst +0 -0
  7. tn/chinese/rules/cardinal.py +4 -2
  8. tn/chinese/rules/math.py +14 -5
  9. tn/chinese/rules/measure.py +1 -4
  10. tn/english/__init__.py +0 -0
  11. tn/english/data/__init__.py +0 -0
  12. tn/english/data/address/__init__.py +13 -0
  13. tn/english/data/date/__init__.py +0 -0
  14. tn/english/data/electronic/__init__.py +0 -0
  15. tn/english/data/measure/__init__.py +13 -0
  16. tn/english/data/money/__init__.py +0 -0
  17. tn/english/data/number/__init__.py +13 -0
  18. tn/english/data/ordinal/__init__.py +0 -0
  19. tn/english/data/roman/__init__.py +0 -0
  20. tn/english/data/telephone/__init__.py +0 -0
  21. tn/english/data/time/__init__.py +13 -0
  22. tn/english/data/whitelist/__init__.py +0 -0
  23. tn/english/normalizer.py +92 -0
  24. tn/english/rules/__init__.py +0 -0
  25. tn/english/rules/cardinal.py +186 -0
  26. tn/english/rules/date.py +319 -0
  27. tn/english/rules/decimal.py +194 -0
  28. tn/english/rules/electronic.py +213 -0
  29. tn/english/rules/fraction.py +139 -0
  30. tn/english/rules/measure.py +327 -0
  31. tn/english/rules/money.py +124 -0
  32. tn/english/rules/ordinal.py +96 -0
  33. tn/english/rules/punctuation.py +81 -0
  34. tn/english/rules/roman.py +149 -0
  35. tn/english/rules/telephone.py +180 -0
  36. tn/english/rules/time.py +167 -0
  37. tn/english/rules/whitelist.py +153 -0
  38. tn/english/rules/word.py +59 -0
  39. tn/english/test/__init__.py +0 -0
  40. tn/english/test/cardinal_test.py +28 -0
  41. tn/english/test/date_test.py +28 -0
  42. tn/english/test/decimal_test.py +28 -0
  43. tn/english/test/electronic_test.py +28 -0
  44. tn/english/test/fraction_test.py +28 -0
  45. tn/english/test/measure_test.py +28 -0
  46. tn/english/test/money_test.py +28 -0
  47. tn/english/test/normalizer_test.py +28 -0
  48. tn/english/test/ordinal_test.py +28 -0
  49. tn/english/test/roman_test.py +28 -0
  50. tn/english/test/telephone_test.py +28 -0
  51. tn/english/test/time_test.py +28 -0
  52. tn/english/test/utils.py +32 -0
  53. tn/english/test/whitelist_test.py +28 -0
  54. tn/english/test/word_test.py +28 -0
  55. tn/main.py +22 -11
  56. tn/processor.py +17 -1
  57. tn/token_parser.py +11 -2
  58. tn/utils.py +92 -0
  59. tn/zh_tn_tagger.fst +0 -0
  60. WeTextProcessing-0.1.12.dist-info/RECORD +0 -66
  61. {WeTextProcessing-0.1.12.dist-info → WeTextProcessing-0.2.0.dist-info}/LICENSE +0 -0
  62. {WeTextProcessing-0.1.12.dist-info → WeTextProcessing-0.2.0.dist-info}/entry_points.txt +0 -0
  63. {WeTextProcessing-0.1.12.dist-info → WeTextProcessing-0.2.0.dist-info}/top_level.txt +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.0
4
4
  Summary: WeTextProcessing, including TN & ITN
5
5
  Home-page: https://github.com/wenet-e2e/WeTextProcessing
6
6
  Author: Zhendong Peng, Xingchen Song
@@ -0,0 +1,112 @@
1
+ itn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ itn/__main__.py,sha256=jFh8bEB_lC5y7ab9VMqAxWRaI8D-SpBSTiHfMJC1b10,65
3
+ itn/main.py,sha256=NnT9Sh3VTEI0sX_DO9IGVsXCWtZyfRbzj9Sj_6cBxqM,2610
4
+ itn/zh_itn_tagger.fst,sha256=vRgLHTqqchvubK6kKt8_fHhbxRfBykCbLQfhFMk_I64,1080610
5
+ itn/zh_itn_verbalizer.fst,sha256=pHXRUfzls2UmWwTmHHhYmBWMusIfWpU3I7IwxeRjn28,119018
6
+ itn/chinese/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ itn/chinese/inverse_normalizer.py,sha256=HCNW5WCHEYeu60f8lxRmvpXh_48GcXa036EFFR9PQo0,3560
8
+ itn/chinese/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ itn/chinese/rules/cardinal.py,sha256=x3pBfnqzWr85BMkYSOJ87IPL_vAqrCGrUDJvugbq5ZY,7385
10
+ itn/chinese/rules/char.py,sha256=wWnTfzJqE5j7kvEao9rKSN29OVFGNnL25MxS7PcfWEM,965
11
+ itn/chinese/rules/date.py,sha256=dA_AQTXaKfO9U8Mtp-ZT9bYdsaOhp5GHC1UpArNm5DY,2319
12
+ itn/chinese/rules/fraction.py,sha256=cYfBcV3XrXo7SIKFOfvOKjFITnhqxJkyiEaU8byiI8A,1966
13
+ itn/chinese/rules/license_plate.py,sha256=DX9JJjQhh8L6G_8fkVWuabABtw5wjFwQdfS3zxili6M,1439
14
+ itn/chinese/rules/math.py,sha256=WmcZQdns7pY4v5gQajEacnHbedP3w_KJVn3WUvoeZkE,1199
15
+ itn/chinese/rules/measure.py,sha256=JJSdhporTtcXg5wQ4VSqcYlUCx58UOSuWvmOPMHiges,2985
16
+ itn/chinese/rules/money.py,sha256=lNixki_73PNefQUECRUYebmD461klNXTtKQm61o4Nu8,2160
17
+ itn/chinese/rules/postprocessor.py,sha256=Eq9aZc7T5OkZGQB15r2qeT8SblS5cvnEosqHjLTN8To,1144
18
+ itn/chinese/rules/time.py,sha256=4sX_3_lhnjQh0fkEBnP7rGnoTPbquHDXaV5lbeGW75M,1931
19
+ itn/chinese/rules/whitelist.py,sha256=UuvIORHZiezfAKWK7qL3QByTGxHMXVnOZp-lYrwmewk,1081
20
+ itn/chinese/test/__init__.py,sha256=eOXRztjSZS0xmUruH2eKjdHx6RtmMxBtae5aFxKrgaE,605
21
+ itn/chinese/test/normalizer_test.py,sha256=a9nqt-is07zYOl3XDAhjUyNzBlwBe3qdaHtvTT6dWn4,4832
22
+ itn/chinese/test/utils.py,sha256=aCZH5BL0dghGjemhVwfISBUxLFMG_ceMzwzuOb5ht28,1094
23
+ tn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ tn/__main__.py,sha256=OUMsgyp8SWb7raJY_py61uM29j023yE5po95O9yinzk,64
25
+ tn/main.py,sha256=Q45id3b2g71MPRLnaHpo8iWPc38MeyZKigNd5FinNvI,3578
26
+ tn/processor.py,sha256=aAcHF3mwyhbPDAwxZKD6tPho-xL6ZNJMrHuw5e7TaQo,4258
27
+ tn/token_parser.py,sha256=nsTYzug-gq2HYnTJHja_HXntoRVX3gITQAlI9z8WvWU,4487
28
+ tn/utils.py,sha256=lJLuW2jkobgXCyNYl29zhtyb3B80CS7Pqz7zqHRVr4c,2792
29
+ tn/zh_tn_tagger.fst,sha256=zZ7zLr-Y774X3lb9bnmUv9Fs3Gv-LXa44X0rMFL6a9g,3477714
30
+ tn/zh_tn_verbalizer.fst,sha256=VoZnjew7YiDRoDC6TgDHKXhrkcSGOz030Pnqad8JhcE,558366
31
+ tn/chinese/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ tn/chinese/normalizer.py,sha256=kCeK1Ab-58RVfpcNsvj_TL9mClsPFjTgjLnOxWFKbAI,3848
33
+ tn/chinese/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ tn/chinese/rules/cardinal.py,sha256=qPX9phKDlOctzKjwrru9kBprzb6rE6wyvj3WmHhID4E,3611
35
+ tn/chinese/rules/char.py,sha256=wWnTfzJqE5j7kvEao9rKSN29OVFGNnL25MxS7PcfWEM,965
36
+ tn/chinese/rules/date.py,sha256=Q1uqPOGSB6UJcrBY3ERs-gj_Caq9yA6Uxmk1NTfzmZo,2382
37
+ tn/chinese/rules/fraction.py,sha256=8K7YQp-QWXJI6iOswMS1PSf6-ocBnLOKiqzv8FIWHfc,1520
38
+ tn/chinese/rules/math.py,sha256=PB62l3LT9Y6LqURfE3driJHrDTmdxtPHSBSxwzpl3t0,1547
39
+ tn/chinese/rules/measure.py,sha256=pjkIzWRi2YxzDlkJoGtqde7vl5foCJ7xjvW70pHZTYs,2802
40
+ tn/chinese/rules/money.py,sha256=Bu9rNGIBP3QvbceyS4_NrHPfcFISf70vtoffiV_Ahuc,1567
41
+ tn/chinese/rules/postprocessor.py,sha256=a3wA2Aqg-MtyT-it_bqdj9_oJ2bG47gfzKwaL7dgXpk,2100
42
+ tn/chinese/rules/preprocessor.py,sha256=5pQ98OlMFxf8V3C74dTQc0uWeKUhZLA3jNVi61Z4fOA,1092
43
+ tn/chinese/rules/sport.py,sha256=6NSWEiJhSX3aymY5263JDgZkdUZP8BYdJFAc8l51R1c,1726
44
+ tn/chinese/rules/time.py,sha256=mfdAb7whCc0li6cDQKIwi10xcaM7EIjfI8mK7lIFyYQ,2047
45
+ tn/chinese/rules/whitelist.py,sha256=JzrL-UfedP7FSps5s4xhSjfEcCkVKzEEGdkZfE96i2E,1652
46
+ tn/chinese/test/__init__.py,sha256=eOXRztjSZS0xmUruH2eKjdHx6RtmMxBtae5aFxKrgaE,605
47
+ tn/chinese/test/cardinal_test.py,sha256=o0LVTOMNMIgwADl7wYHRBBH6s2fLli9kU5BaYxdIHBc,1246
48
+ tn/chinese/test/char_test.py,sha256=p4vG0iwc2FYn0uTbQQzWBq-TLgfIWMfgKqfu1vpP50o,954
49
+ tn/chinese/test/date_test.py,sha256=TEF8wYGl1Ubr_5daSnp92cJY2yCPv81aZ9j3BfA8osU,954
50
+ tn/chinese/test/fraction_test.py,sha256=w2Pa7yiHG85TbU8XWf-ZDbB49g52bI1pDOEZUdMxVnE,994
51
+ tn/chinese/test/math_test.py,sha256=w__bpbDFK4VsGK-fWenHfV9Y_SImBb6q9g-twplbqGc,954
52
+ tn/chinese/test/measure_test.py,sha256=k76Dz32DXvl6bBjbceISH4Xiz6xAhBwJRv3OYCvp0OE,982
53
+ tn/chinese/test/money_test.py,sha256=MrQQTJQHPql1mNIOljomlLyqIm-MS5xlvyIGT7KaboU,964
54
+ tn/chinese/test/normalizer_test.py,sha256=rRf9xpGpnhAICwnAhcMqOg5RSvJUxvSc5qy2U5kM1ak,1597
55
+ tn/chinese/test/postprocessor_test.py,sha256=KNXdVJQ3AyCsPqjiiFxk9QQoALUDRcSDvzsLa2OGxd4,1099
56
+ tn/chinese/test/preprocessor_test.py,sha256=ipNvTn0MYcR0MDyOQuT_hR8DKiDHWoYZb4coANX31Kk,1082
57
+ tn/chinese/test/sport_test.py,sha256=ZF4QpgbfIZ38bwnCE5a9gkR1jv1N6RvN4VECHQImOl8,964
58
+ tn/chinese/test/time_test.py,sha256=hLi3gCwVrV4oOdStWCwOeT6c9XTOatjOB8pFfbe6r0I,953
59
+ tn/chinese/test/token_parser_test.py,sha256=8JcSqlvaYTZ46rZgMsfAVNmcYez6t0gonhnx4nc-1ew,2614
60
+ tn/chinese/test/utils.py,sha256=aCZH5BL0dghGjemhVwfISBUxLFMG_ceMzwzuOb5ht28,1094
61
+ tn/chinese/test/whitelist_test.py,sha256=oPB-7_g8l6zhAeH5fp7NlaRJYcDNz7VAOKwhCnebGdc,1003
62
+ tn/english/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ tn/english/normalizer.py,sha256=vC5GwQkHpiSSwF-ASzBBWfk3t4Xccslkez4yP93Mp90,3777
64
+ tn/english/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ tn/english/data/address/__init__.py,sha256=EqFAHHjK7kJqR_FV8vBLddBJWhbVD8pREEfm8C5nSEE,623
66
+ tn/english/data/date/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ tn/english/data/electronic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
+ tn/english/data/measure/__init__.py,sha256=TS5NMVLZXlTIgbt7grYmlxBfRKrWELPnT9DedX9kYBk,610
69
+ tn/english/data/money/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ tn/english/data/number/__init__.py,sha256=TS5NMVLZXlTIgbt7grYmlxBfRKrWELPnT9DedX9kYBk,610
71
+ tn/english/data/ordinal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
+ tn/english/data/roman/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
+ tn/english/data/telephone/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
+ tn/english/data/time/__init__.py,sha256=TS5NMVLZXlTIgbt7grYmlxBfRKrWELPnT9DedX9kYBk,610
75
+ tn/english/data/whitelist/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
+ tn/english/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ tn/english/rules/cardinal.py,sha256=w3HvKbq86mZjb3MhXc96D_Ajaem1raCHs0pCGvhQaRs,8424
78
+ tn/english/rules/date.py,sha256=QoUczkPwAeYanT41_8Qpi_FqvuSfvXX5LHdEgcsLkVA,13683
79
+ tn/english/rules/decimal.py,sha256=s49eTpngiE4BZyLvfgsg45kpcemElWTLGx7VuxVR1Rw,8795
80
+ tn/english/rules/electronic.py,sha256=2XBnz3usFyFame2WcInVrtZEW5TPXXowANpLeBEjD7I,9190
81
+ tn/english/rules/fraction.py,sha256=ltGhbd1Qeb-BsuVCPYq8cc__k0Xkkn4WBUiz6dFs8J8,5685
82
+ tn/english/rules/measure.py,sha256=DjQnq_9UXL-pHdqaHkp3oUv4qEhiGB_764YmUEq9v6w,14025
83
+ tn/english/rules/money.py,sha256=0hjQWUdI4wWsOVKkkBs5lvFsQaMIWOQcs6oOLBhQzDM,5457
84
+ tn/english/rules/ordinal.py,sha256=xFUaNvPx2rKDJz3TMiE2RKje6gcvcVImr3sXixWfOKU,3989
85
+ tn/english/rules/punctuation.py,sha256=KyypaQs7SsQC1RCv-h4NGu4Jm-PvuSGUyM3mtPbCMws,2979
86
+ tn/english/rules/roman.py,sha256=pQFuSIjzWnMN-jiSuVqv3AxJEA9kA8s0NUgGpCCVbiU,6051
87
+ tn/english/rules/telephone.py,sha256=JkhHZU1O2h4a_W3QHVBY1lOQvq4Tys5JwAlL1Kkt8Pg,8275
88
+ tn/english/rules/time.py,sha256=7quSQrLifeJ4WLwAyDkuvGe1-lNomN_MjvFAP3zHBas,7764
89
+ tn/english/rules/whitelist.py,sha256=5pIEZyCadKmS7AAJ7G7JQhWFvo2oPszy0WxxIAMZr_E,6097
90
+ tn/english/rules/word.py,sha256=ySAa3qn6Wf1Qze9limjPfYJd37Kk2Juz9AZseGEFNu8,2366
91
+ tn/english/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
+ tn/english/test/cardinal_test.py,sha256=F7vP5ZIOxoQhRJ0Se597bHinRnFU_bOd2PzTo9M0xmg,1013
93
+ tn/english/test/date_test.py,sha256=dFOJXAdU19i3i7KZdt89PQ-c0EeGmjUhQCXT8bFE71o,973
94
+ tn/english/test/decimal_test.py,sha256=28Q4YCEPGRoQ-6s3zroyxUbVZ2GiALxZXjXmQcs9WwQ,1003
95
+ tn/english/test/electronic_test.py,sha256=iWgt4lFHDfrZZLyBAMSL5AOjATeFK1CrUDLLWUMll8I,1033
96
+ tn/english/test/fraction_test.py,sha256=aQrDwqjjfDN0CWM34VOOTINfos0MHzuY6Cjhv7cF9jE,1013
97
+ tn/english/test/measure_test.py,sha256=14dGDfjdbYiH0MYBmPD9JvfVAXW_-Fe4rPCrWJ72T-A,1003
98
+ tn/english/test/money_test.py,sha256=oVhT7JpTaTekOPuMLmaubSv5912ow35OsPquikULi2A,983
99
+ tn/english/test/normalizer_test.py,sha256=wNq2SE2DyGmDQQ4D1yFrYszE8czFvGOlvKwsCX2ymKQ,1006
100
+ tn/english/test/ordinal_test.py,sha256=sqrPIy9ZABNSKQaadU-GfYydnh3dUxk2SfkjlZfHfp4,1003
101
+ tn/english/test/roman_test.py,sha256=Lemo7K4I-EoJ34yeT9VVLTHOSOYVzpK3xnCQ38Fer5w,983
102
+ tn/english/test/telephone_test.py,sha256=I9xnKNXfWagRTHS8hvBvJKAqeFvH8_sjD5G3n8pEwys,1023
103
+ tn/english/test/time_test.py,sha256=4E_PS-D5caTUZgrI-UL7q0aoqmtD8np7yeXUkGyc1Qo,973
104
+ tn/english/test/utils.py,sha256=aCZH5BL0dghGjemhVwfISBUxLFMG_ceMzwzuOb5ht28,1094
105
+ tn/english/test/whitelist_test.py,sha256=fnlpnwiDgQWsl5ONZklWXEyLQoUSuwhdowcV7a8fXvw,1023
106
+ tn/english/test/word_test.py,sha256=ACguloXPl4Ttw8fj9F_wvr1coaQAoj_MLOJ74wyy-WY,954
107
+ WeTextProcessing-0.2.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
108
+ WeTextProcessing-0.2.0.dist-info/METADATA,sha256=xQnfep16ju1AcZJMNvB7AAbq_nKXqUonmz1kOqw29K4,5178
109
+ WeTextProcessing-0.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
110
+ WeTextProcessing-0.2.0.dist-info/entry_points.txt,sha256=iAd8tFSNA8AY5fUECPlk9KaDFC3ISvDjoKAZVsCWPjE,61
111
+ WeTextProcessing-0.2.0.dist-info/top_level.txt,sha256=6NasE_UheQezX9_0V3MbiOSnTQpvM_funMjv4wpMGgA,7
112
+ WeTextProcessing-0.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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)
itn/zh_itn_tagger.fst CHANGED
Binary file
@@ -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
tn/chinese/rules/math.py CHANGED
@@ -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
tn/english/__init__.py ADDED
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()