fraction.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. # Copyright NeMo (https://github.com/NVIDIA/NeMo). 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.
  14. import pynini
  15. from fun_text_processing.text_normalization.en.graph_utils import (
  16. DAMO_NOT_QUOTE,
  17. DAMO_SIGMA,
  18. GraphFst,
  19. delete_preserve_order,
  20. insert_space,
  21. )
  22. from pynini.lib import pynutil
  23. class FractionFst(GraphFst):
  24. """
  25. Finite state transducer for verbalizing fraction
  26. e.g. fraction { integer: "drei" numerator: "eins" denominator: "zwei" }-> drei ein halb
  27. e.g. fraction { numerator: "vier" denominator: "zwei" } -> vier halbe
  28. e.g. fraction { numerator: "drei" denominator: "vier" } -> drei viertel
  29. Args:
  30. ordinal: ordinal GraphFst
  31. deterministic: if True will provide a single transduction option,
  32. for False multiple transduction are generated (used for audio-based normalization)
  33. """
  34. def __init__(self, ordinal: GraphFst, deterministic: bool = True):
  35. super().__init__(name="fraction", kind="verbalize", deterministic=deterministic)
  36. optional_sign = pynini.closure(pynini.cross("negative: \"true\"", "minus ") + pynutil.delete(" "), 0, 1)
  37. change_one = pynini.cdrewrite(
  38. pynutil.add_weight(pynini.cross("eins", "ein"), weight=-0.0001), "[BOS]", "[EOS]", DAMO_SIGMA
  39. )
  40. change_numerator_two = pynini.cdrewrite(pynini.cross("zweitel", "halbe"), "[BOS]", "[EOS]", DAMO_SIGMA)
  41. integer = pynutil.delete("integer_part: \"") + change_one + pynutil.delete("\" ")
  42. numerator = pynutil.delete("numerator: \"") + change_one + pynutil.delete("\" ")
  43. denominator = (
  44. pynutil.delete("denominator: \"")
  45. + pynini.closure(DAMO_NOT_QUOTE)
  46. @ (
  47. pynini.cdrewrite(pynini.closure(ordinal.ordinal_stem, 0, 1), "", "[EOS]", DAMO_SIGMA)
  48. + pynutil.insert("tel")
  49. )
  50. @ change_numerator_two
  51. + pynutil.delete("\"")
  52. )
  53. integer += insert_space + pynini.closure(pynutil.insert("und ", weight=0.001), 0, 1)
  54. denominator_one_half = pynini.cdrewrite(pynini.cross("ein halbe", "ein halb"), "[BOS]", "[EOS]", DAMO_SIGMA)
  55. fraction_default = (numerator + insert_space + denominator) @ denominator_one_half
  56. self.graph = optional_sign + pynini.closure(integer, 0, 1) + fraction_default
  57. graph = self.graph + delete_preserve_order
  58. delete_tokens = self.delete_tokens(graph)
  59. self.fst = delete_tokens.optimize()