Skip to content

Commit 80fc2f2

Browse files
committed
feat: telephone with double/IP/serial/country code, 446/470 (95%)
1 parent dbaab50 commit 80fc2f2

2 files changed

Lines changed: 60 additions & 32 deletions

File tree

itn/english/rules/telephone.py

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from pynini import closure, cross, string_file
16-
from pynini.lib.pynutil import delete, insert
15+
from pynini import closure, cross, string_file, union
16+
from pynini.lib.pynutil import add_weight, delete, insert
1717

1818
from itn.english.rules.cardinal import Cardinal
1919
from tn.processor import Processor
@@ -30,42 +30,70 @@ def __init__(self, cardinal=None):
3030

3131
def build_tagger(self):
3232
ds = delete(" ")
33-
34-
# Single digit: spoken word -> digit character
3533
digit = string_file(get_abs_path("../itn/english/data/numbers/digit.tsv"))
3634
zero = string_file(get_abs_path("../itn/english/data/numbers/zero.tsv"))
37-
single_digit = digit | zero | cross("o", "0") | cross("oh", "0")
38-
39-
# 10 digits formatted as XXX-XXX-XXXX
40-
ten_digits = (
41-
single_digit + ds + single_digit + ds + single_digit
42-
+ insert("-")
43-
+ ds + single_digit + ds + single_digit + ds + single_digit
44-
+ insert("-")
45-
+ ds + single_digit + ds + single_digit + ds + single_digit + ds + single_digit
46-
)
35+
single = digit | zero | cross("o", "0") | cross("oh", "0")
36+
37+
# "double X" => XX
38+
double = union(*[cross(f"double {w}", f"{d}{d}")
39+
for w, d in [("one","1"),("two","2"),("three","3"),("four","4"),
40+
("five","5"),("six","6"),("seven","7"),("eight","8"),
41+
("nine","9"),("zero","0"),("oh","0"),("o","0")]])
42+
43+
# two-digit cardinal: twenty three => 23
44+
two_digit = self.cardinal.graph_no_exception @ (self.DIGIT + self.DIGIT)
4745

48-
# Optional country code: "plus X" or just digits before the main number
49-
country_code_digits = (
50-
closure(single_digit + ds, 0, 2) + single_digit
46+
# a token is 1 or 2 digits
47+
token = single | double | add_weight(two_digit, 0.002)
48+
49+
# sequence of tokens separated by spaces
50+
seq = token + closure(ds + token)
51+
52+
# phone: XXX-XXX-XXXX
53+
phone = seq @ (
54+
self.DIGIT ** 3 + insert("-") + self.DIGIT ** 3 + insert("-") + self.DIGIT ** 4
5155
)
56+
57+
# country code
5258
country_code = (
53-
closure(cross("plus ", "+"), 0, 1) + country_code_digits
59+
insert('country_code: "')
60+
+ closure(cross("plus ", "+"), 0, 1)
61+
+ (closure(single + ds, 0, 2) + single | add_weight(two_digit, 0.002))
62+
+ insert('"')
5463
)
55-
optional_country_code = closure(
56-
country_code + insert(" ") + ds, 0, 1
64+
optional_cc = closure(country_code + ds + insert(" "), 0, 1)
65+
66+
graph = optional_cc + insert('number_part: "') + phone + insert('"')
67+
68+
# SSN: XXX-XX-XXXX
69+
ssn = seq @ (
70+
self.DIGIT ** 3 + insert("-") + self.DIGIT ** 2 + insert("-") + self.DIGIT ** 4
5771
)
72+
graph |= insert('number_part: "') + ssn + insert('"')
5873

59-
graph = optional_country_code + ten_digits
60-
final_graph = insert('value: "') + graph + insert('"')
61-
self.tagger = self.add_tokens(final_graph)
74+
# IP: X.X.X.X
75+
ip_token = single + closure(ds + single, 0, 2) | add_weight(two_digit, 0.002)
76+
ip = ip_token + (cross(" dot ", ".") + ip_token) ** 3
77+
graph |= insert('number_part: "') + add_weight(ip, -0.001) + insert('"')
6278

63-
def build_verbalizer(self):
64-
value = (
65-
delete("value:")
66-
+ self.DELETE_SPACE
67-
+ delete('"')
68-
+ self.NOT_QUOTE.plus
69-
+ delete('"')
79+
# credit card: XXXX XXXX XXXX XXXX or XXXX XXXXXX XXXXX
80+
cc = seq @ (
81+
self.DIGIT ** 4 + insert(" ") + self.DIGIT ** 4
82+
+ insert(" ") + self.DIGIT ** 4 + insert(" ") + self.DIGIT ** 4
7083
)
71-
self.verbalizer = self.delete_tokens(value)
84+
graph |= insert('number_part: "') + cc + insert('"')
85+
86+
# serial: mixed alpha+digits, at least one digit, length >= 3
87+
serial_char = single | add_weight(two_digit, 0.002) | self.ALPHA
88+
serial = serial_char + closure(ds + serial_char, 2)
89+
serial = serial @ (closure(self.ALPHA | self.DIGIT) + self.DIGIT + closure(self.ALPHA | self.DIGIT))
90+
graph |= insert('number_part: "') + add_weight(serial, 0.001) + insert('"')
91+
92+
self.tagger = self.add_tokens(graph)
93+
94+
def build_verbalizer(self):
95+
cc = delete('country_code: "') + self.NOT_QUOTE.plus + delete('"')
96+
num = delete(' number_part: "') + self.NOT_QUOTE.plus + delete('"')
97+
num_only = delete('number_part: "') + self.NOT_QUOTE.plus + delete('"')
98+
graph = cc + self.DELETE_SPACE + insert(" ") + num | num_only
99+
self.verbalizer = self.delete_tokens(graph)

tn/token_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"measure": ["numerator", "denominator", "value", "units"],
3333
"money": ["currency", "value", "decimal", "quantity"],
3434
"time": ["hour", "minute", "second", "noon", "zone"],
35-
"telephone": ["value"],
35+
"telephone": ["country_code", "number_part"],
3636
"electronic": ["username", "domain", "protocol"],
3737
}
3838

0 commit comments

Comments
 (0)