Forráskód Böngészése

[feature] add stt correction

nico 7 éve
szülő
commit
9b3c269767

+ 21 - 0
Tests/test_order_analyser.py

@@ -285,6 +285,27 @@ class TestOrderAnalyser(unittest.TestCase):
         self.assertTrue(OrderAnalyser.is_order_matching(user_order=test_order,
                                                         signal_order=test_signal))
 
+    def test_override_order_with_correction(self):
+        # test with provided correction
+        order = "this is my test"
+        stt_correction = [{
+            "input": "test",
+            "output": "order"
+        }]
+        expected_output = "this is my order"
+        new_order = OrderAnalyser.override_order_with_correction(order=order, stt_correction=stt_correction)
+        self.assertEquals(new_order, expected_output)
+
+        # missing key input
+        order = "this is my test"
+        stt_correction = [{
+            "wrong_key": "test",
+            "output": "order"
+        }]
+        expected_output = "this is my test"
+        new_order = OrderAnalyser.override_order_with_correction(order=order, stt_correction=stt_correction)
+        self.assertEquals(new_order, expected_output)
+
 
 if __name__ == '__main__':
     unittest.main()

+ 48 - 0
kalliope/core/OrderAnalyser.py

@@ -2,6 +2,7 @@
 import collections
 from collections import Counter
 import six
+import yaml
 from jinja2 import Template
 
 from kalliope.core.NeuronParameterLoader import NeuronParameterLoader
@@ -59,6 +60,8 @@ class OrderAnalyser:
                     # get the type of matching expected, by default "normal"
                     expected_matching_type = "normal"
                     signal_order = None
+                    stt_correction = None
+                    stt_correction_file = None
 
                     if isinstance(signal.parameters, str) or isinstance(signal.parameters, six.text_type):
                         signal_order = signal.parameters
@@ -74,6 +77,23 @@ class OrderAnalyser:
                         except KeyError:
                             logger.debug("[OrderAnalyser] Warning, missing parameter 'matching-type' in order. "
                                          "Fallback to 'normal'")
+                        try:
+                            stt_correction = signal.parameters["stt-correction"]
+                            logger.debug("[OrderAnalyser] stt-correction provided by user")
+                        except KeyError:
+                            logger.debug("[OrderAnalyser] No stt-correction provided")
+
+                        try:
+                            stt_correction_file = signal.parameters["stt-correction-file"]
+                            logger.debug("[OrderAnalyser] stt-correction-file provided by user")
+                        except KeyError:
+                            logger.debug("[OrderAnalyser] No stt-correction-file provided")
+
+                    if stt_correction_file is not None:
+                        stt_correction = cls.load_stt_correction_file(stt_correction_file)
+
+                    if stt_correction is not None:
+                        order = cls.override_order_with_correction(order, stt_correction)
 
                     if cls.is_order_matching(user_order=order,
                                              signal_order=signal_order,
@@ -232,3 +252,31 @@ class OrderAnalyser:
         signal_order = t.render(**parameters_from_user_order)
 
         return signal_order
+
+    @classmethod
+    def override_order_with_correction(cls, order, stt_correction):
+        logger.debug("[OrderAnalyser] override_order_this_correction: stt_correction list: %s" % stt_correction)
+        logger.debug("[OrderAnalyser] override_order_this_correction: order before correction: %s" % order)
+        for correction in stt_correction:
+            try:
+                input_val = str(correction["input"])
+                output_val = str(correction["output"])
+            except KeyError as e:
+                logger.debug("[OrderAnalyser] override_order_this_correction: "
+                             "Missing key %s. Order will not be modified" % e)
+                return order
+
+            if str(input_val) in order.split():
+                logger.debug("[OrderAnalyser] STT override '%s' by '%s'" % (input_val, output_val))
+                order = order.replace(input_val, output_val)
+                break
+
+        return order
+
+    @classmethod
+    def load_stt_correction_file(cls, stt_correction_file):
+        stt_correction_file_path = Utils.get_real_file_path(stt_correction_file)
+        stt_correction_file = open(stt_correction_file_path, "r")
+        stt_correction = yaml.load(stt_correction_file)
+
+        return stt_correction

+ 84 - 4
kalliope/signals/order/README.md

@@ -12,10 +12,12 @@ An **order** signal is a word, or a sentence caught by the microphone and proces
 
 Other way to write an order, with parameters:
 
-| parameter     | required | default            | choices                        | comment                                  |
-|---------------|----------|--------------------|--------------------------------|------------------------------------------|
-| text          | YES      | The order to match |                                |                                          |
-| matching-type | NO       | normal             | normal, strict, ordered-strict | Type of matching. See explanation bellow |
+| parameter           | required | default | choices                        | comment                                                |
+|---------------------|----------|---------|--------------------------------|--------------------------------------------------------|
+| text                | YES      |         |                                | The order to match                                     |
+| matching-type       | NO       | normal  | normal, strict, ordered-strict | Type of matching. See explanation bellow               |
+| stt-correction      | NO       |         |                                | List of words from the order to replace by other words |
+| stt-correction-file | NO       |         |                                | Same as stt-correction but load words from a YAML file |
 
 **Matching-type:**
 - **normal**: Will match if all words are present in the spoken order.
@@ -101,6 +103,84 @@ signals:
 In this example, with a `strict` matching type, the synapse would be triggered if the user say:
 - please do this action
 
+### stt-correction
+
+This option allow you to replace some words from the captured order by other word. 
+
+Syntax:
+```yml
+signals:
+    - order:
+        text: "<sentence>"
+        stt-correction:
+          - input: "words to replace"
+            output: "replacing words" 
+```
+
+E.g
+```yml
+- name: "stt-correction-test"
+    signals:
+      - order:
+          text: "this is my order"
+          stt-correction:
+            - input: "test"
+              output: "order"
+    neurons:
+      - debug:
+          message: "hello"
+```
+In this example, if you pronounce "this is my test", the word test will be translated into "order" and so the signal "stt-correction-test" would b triggered.
+
+This feature can be useful when working with numbers.
+For example, you know that your STT engine return all number as string and you need them as integer for your neurons.
+
+E.g:
+```yml
+- name: "mm-say"
+    signals:
+      - order:
+          text: "this is my number {{ number }}"
+          stt-correction:
+            - input: "one"
+              output: 1
+    neurons:
+      - debug:
+          message: "{{ number }}"
+```
+
+In this example, if you say "this is my number one", Kalliope will translate the word "one" into "1".
+
+### stt_correction_file
+
+This option allow to set a list of corrections from a YAML file instead of writing them directly in the order.
+
+Syntax:
+```yml
+signals:
+    - order:
+        text: "<sentence>"
+        stt-correction-file: "<path to yaml file>"   
+```
+
+E.g
+```yml
+- name: "stt-correction-test"
+    signals:
+      - order:
+          text: "this is my order"
+          stt-correction-file: "my_stt_correction_file.yml"            
+    neurons:
+      - debug:
+          message: "hello"
+```
+
+Where `my_stt_correction_file.yml` would looks like the following: 
+```yml
+- input: "test"
+  output: "order"
+```
+
 ### Notes
 
 > **Important note:** SST engines can misunderstand what you say, or translate your sentence into text containing some spelling mistakes.