Переглянути джерело

[Feature]#135 Improve neuron neuronTransmitter to manage params in
answers

[Feature] Improvement of the neurontransmitter to manage params

[Feature] #135 fix typos and algos

monf 8 роки тому
батько
коміт
b3ed7748e9

+ 64 - 0
Tests/test_neuron_module.py

@@ -3,6 +3,10 @@ import unittest
 import mock
 
 from kalliope.core.NeuronModule import NeuronModule, TemplateFileNotFoundException
+from kalliope.core.Models.Neuron import Neuron
+from kalliope.core.Models.Synapse import Synapse
+from kalliope.core.Models.Brain import Brain
+from kalliope.core.Models.Order import Order
 
 
 class TestNeuronModule(unittest.TestCase):
@@ -107,3 +111,63 @@ class TestNeuronModule(unittest.TestCase):
     def test_get_content_of_file(self):
         expected_result = "hello, this is a {{ test }}"
         self.assertEqual(NeuronModule._get_content_of_file(self.file_template), expected_result)
+
+    def test_run_synapse_by_name_with_order(self):
+        """
+        Test to start a synapse with a specific given order
+        Scenarii :
+            - Neuron has been found and launched
+            - Neuron has not been found
+        """
+
+        # Init
+        neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
+        neuron2 = Neuron(name='neurone2', parameters={'var2': 'val2'})
+        neuron3 = Neuron(name='neurone3', parameters={'var3': 'val3'})
+        neuron4 = Neuron(name='neurone4', parameters={'var4': 'val4'})
+
+        signal1 = Order(sentence="the sentence")
+        signal2 = Order(sentence="the second sentence")
+        signal3 = Order(sentence="part of the third sentence")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        synapse2 = Synapse(name="Synapse2", neurons=[neuron3, neuron4], signals=[signal2])
+        synapse3 = Synapse(name="Synapse3", neurons=[neuron2, neuron4], signals=[signal3])
+
+        all_synapse_list = [synapse1,
+                            synapse2,
+                            synapse3]
+
+        br = Brain(synapses=all_synapse_list)
+
+        order = "This is the order"
+        synapse_name = "Synapse2"
+        answer = "This is the {{ answer }}"
+
+        with mock.patch("kalliope.core.OrderAnalyser.start") as mock_orderAnalyser_start:
+            neuron_mod = NeuronModule()
+            neuron_mod.brain = br
+
+            # Success
+            self.assertTrue(neuron_mod.run_synapse_by_name_with_order(order=order,
+                                                                        synapse_name=synapse_name,
+                                                                        order_template=answer),
+                              "fail to find the proper synapse")
+
+            # mock_orderAnalyser_start.assert_called_once()
+            mock_orderAnalyser_start.assert_called_once_with(synapses_to_run=[synapse2],
+                                                             external_order=answer)
+            mock_orderAnalyser_start.reset_mock()
+
+            # Fail
+            synapse_name = "Synapse5"
+            self.assertFalse(neuron_mod.run_synapse_by_name_with_order(order=order,
+                                                                      synapse_name=synapse_name,
+                                                                       order_template=answer),
+                            "fail to NOT find the synapse")
+
+            mock_orderAnalyser_start.assert_not_called()
+            mock_orderAnalyser_start.reset_mock()
+
+
+

+ 104 - 41
Tests/test_order_analyser.py

@@ -5,6 +5,7 @@ from kalliope.core.OrderAnalyser import OrderAnalyser
 from kalliope.core.Models.Neuron import Neuron
 from kalliope.core.Models.Synapse import Synapse
 from kalliope.core.Models.Brain import Brain
+from kalliope.core.Models.Settings import Settings
 from kalliope.core.Models.Order import Order
 
 
@@ -21,7 +22,9 @@ class TestOrderAnalyser(unittest.TestCase):
         Scenarii :
             - Order matchs a synapse and the synapse has been launched.
             - Order does not match but have a default synapse.
-            - Order does not match and does not ahve default synapse.
+            - Order does not match and does not have default synapse.
+            - Provide synapse without any external orders
+            - Provide synapse with any external orders
         """
         # Init
         neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
@@ -43,9 +46,6 @@ class TestOrderAnalyser(unittest.TestCase):
 
         br = Brain(synapses=all_synapse_list)
 
-        def _start_neuron_mock(cls, neuron, params):
-            pass
-
         with mock.patch("kalliope.core.OrderAnalyser._start_neuron") as mock_start_neuron_method:
             # assert synapses have been launched
             order_to_match = "this is the sentence"
@@ -81,6 +81,35 @@ class TestOrderAnalyser(unittest.TestCase):
                               expected_result,
                               "Fail to no synapse because no synapse matchs and no default defined")
 
+            # Provide synapse to run
+            order_to_match = "this is the sentence"
+            oa = OrderAnalyser(order=order_to_match,
+                               brain=br)
+            expected_result = [synapse1]
+            synapses_to_run = [synapse1]
+
+            self.assertEquals(oa.start(synapses_to_run=synapses_to_run),
+                              expected_result,
+                              "Fail to run the provided synapse to run")
+            calls = [mock.call(neuron1, {}), mock.call(neuron2, {})]
+            mock_start_neuron_method.assert_has_calls(calls=calls)
+            mock_start_neuron_method.reset_mock()
+
+            # Provide synapse and external orders
+            order_to_match = "this is an external sentence"
+            oa = OrderAnalyser(order=order_to_match,
+                               brain=br)
+            external_orders = "this is an external {{ order }}"
+            synapses_to_run = [synapse2]
+            expected_result = [synapse2]
+
+            self.assertEquals(oa.start(synapses_to_run=synapses_to_run, external_order=external_orders),
+                              expected_result,
+                              "Fail to run a provided synapse with external order")
+            calls = [mock.call(neuron3, {"order":u"sentence"}), mock.call(neuron4, {"order":u"sentence"})]
+            mock_start_neuron_method.assert_has_calls(calls=calls)
+            mock_start_neuron_method.reset_mock()
+
     def test_start_neuron(self):
         """
         Testing params association and starting a Neuron
@@ -181,12 +210,12 @@ class TestOrderAnalyser(unittest.TestCase):
         sentence_to_test = "this is the order"
 
         # Success
-        self.assertTrue(OrderAnalyser._spelt_order_match_brain_order_via_table(order_to_test, sentence_to_test),
+        self.assertTrue(OrderAnalyser.spelt_order_match_brain_order_via_table(order_to_test, sentence_to_test),
                         "Fail matching order with the expected sentence")
 
         # Failure
         sentence_to_test = "unexpected sentence"
-        self.assertFalse(OrderAnalyser._spelt_order_match_brain_order_via_table(order_to_test, sentence_to_test),
+        self.assertFalse(OrderAnalyser.spelt_order_match_brain_order_via_table(order_to_test, sentence_to_test),
                          "Fail to ensure the expected sentence is not matching the order")
 
     def test_get_split_order_without_bracket(self):
@@ -389,83 +418,67 @@ class TestOrderAnalyser(unittest.TestCase):
                           expected_result,
                           "Fail matching 'synapse with all key worlds' from the complete synapse list and the order")
 
-    def test_get_synapse_params(self):
-        # Init
-        neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
-        neuron2 = Neuron(name='neurone2', parameters={'var2': 'val2'})
-
-        signal1 = Order(sentence="this is the {{ sentence }}")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+    def test_get_params_from_order(self):
 
+        string_order = "this is the {{ sentence }}"
         order_to_check = "this is the value"
         expected_result = {'sentence': 'value'}
 
-        self.assertEquals(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEquals(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                           expected_result,
-                          "Fail to retrieve 'the params' of the synapse from the order")
+                          "Fail to retrieve 'the params' of the string_order from the order")
 
         # Multiple match
-        signal1 = Order(sentence="this is the {{ sentence }}")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        string_order = "this is the {{ sentence }}"
 
         order_to_check = "this is the value with multiple words"
         expected_result = {'sentence': 'value with multiple words'}
 
-        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEqual(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                          expected_result,
-                         "Fail to retrieve the 'multiple words params' of the synapse from the order")
+                         "Fail to retrieve the 'multiple words params' of the string_order from the order")
 
         # Multiple params
-        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        string_order = "this is the {{ sentence }} with multiple {{ params }}"
 
         order_to_check = "this is the value with multiple words"
         expected_result = {'sentence': 'value',
                             'params':'words'}
 
-        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEqual(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                          expected_result,
-                         "Fail to retrieve the 'multiple params' of the synapse from the order")
+                         "Fail to retrieve the 'multiple params' of the string_order from the order")
 
         # Multiple params with multiple words
-        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        string_order = "this is the {{ sentence }} with multiple {{ params }}"
 
         order_to_check = "this is the multiple values with multiple values as words"
         expected_result = {'sentence': 'multiple values',
                            'params': 'values as words'}
 
-        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEqual(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                          expected_result,
-                         "Fail to retrieve the 'multiple params with multiple words' of the synapse from the order")
+                         "Fail to retrieve the 'multiple params with multiple words' of the string_order from the order")
 
         # params at the begining of the sentence
-        signal1 = Order(sentence="{{ sentence }} this is the sentence")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        string_order = "{{ sentence }} this is the sentence"
 
         order_to_check = "hello world this is the multiple values with multiple values as words"
         expected_result = {'sentence': 'hello world'}
 
-        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEqual(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                          expected_result,
-                         "Fail to retrieve the 'params at the begining of the sentence' of the synapse from the order")
+                         "Fail to retrieve the 'params at the begining of the sentence' of the string_order from the order")
 
         # all of the sentence is a variable
-        signal1 = Order(sentence="{{ sentence }}")
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        string_order = "{{ sentence }}"
 
         order_to_check = "this is the all sentence is a variable"
         expected_result = {'sentence': 'this is the all sentence is a variable'}
 
-        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+        self.assertEqual(OrderAnalyser._get_params_from_order(string_order=string_order, order_to_check=order_to_check),
                          expected_result,
-                         "Fail to retrieve the 'all of the sentence is a variable' of the synapse from the order")
+                         "Fail to retrieve the 'all of the sentence is a variable' of the string_order from the order")
 
     def test_get_default_synapse_from_sysnapses_list(self):
         # Init
@@ -494,6 +507,56 @@ class TestOrderAnalyser(unittest.TestCase):
                           expected_result,
                           "Fail to match the expected default Synapse")
 
+    def test_find_synapse_to_run(self):
+        """
+        Test to find the good synapse to run
+        Scenarii:
+            - Find the synapse
+            - No synpase found, no default synapse
+            - No synapse found, run the default synapse
+        """
+        # Init
+        neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
+        neuron2 = Neuron(name='neurone2', parameters={'var2': 'val2'})
+        neuron3 = Neuron(name='neurone3', parameters={'var3': 'val3'})
+        neuron4 = Neuron(name='neurone4', parameters={'var4': 'val4'})
+
+        signal1 = Order(sentence="this is the sentence")
+        signal2 = Order(sentence="this is the second sentence")
+        signal3 = Order(sentence="that is part of the third sentence")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+        synapse2 = Synapse(name="Synapse2", neurons=[neuron3, neuron4], signals=[signal2])
+        synapse3 = Synapse(name="Synapse3", neurons=[neuron2, neuron4], signals=[signal3])
+
+        all_synapse_list = [synapse1,
+                            synapse2,
+                            synapse3]
+
+        br = Brain(synapses=all_synapse_list)
+        st = Settings()
+        # Find synapse
+        order = "this is the sentence"
+        expected_result = [synapse1]
+        self.assertEquals(OrderAnalyser._find_synapse_to_run(brain=br,settings=st, order=order),
+                          expected_result,
+                          "Fail to run the proper synapse matching the order")
+
+        # No Default synapse
+        order = "No default synapse"
+        expected_result = []
+        self.assertEquals(OrderAnalyser._find_synapse_to_run(brain=br,settings=st, order=order),
+                          expected_result,
+                          "Fail to run no synapse, when no default is defined")
+
+        # Default synapse
+        st = Settings(default_synapse="Synapse2")
+        order = "default synapse"
+        expected_result = [synapse2]
+        self.assertEquals(OrderAnalyser._find_synapse_to_run(brain=br, settings=st, order=order),
+                          expected_result,
+                          "Fail to run the default synapse")
+
 
 if __name__ == '__main__':
     unittest.main()

+ 36 - 1
brain_examples/neurotransmitter.yml

@@ -18,7 +18,6 @@
   - name: "synapse1"
     signals:
       - order: "pose moi une question"
-      - order: "pose-moi une question"
     neurons:
       - say:
           message: "aimez vous les frites?"
@@ -51,6 +50,42 @@
   - name: "synapse4"
     signals:
       - order: "synapse4"
+    neurons:
+      - say:
+          message: "Je n'ai pas compris votre réponse"
+
+
+  - name: "synapse5"
+    signals:
+      - order: "demande-moi la météo"
+    neurons:
+      - say:
+          message: "De quelle ville voulez-vous connaitre la météo?"
+      - neurotransmitter:
+          from_answer_link:
+            - synapse: "synapse6"
+              answers:
+                - "la météo à {{ location }}"
+          default: "synapse7"
+
+  - name: "synapse6"
+    signals:
+      - order: "quel temps fait-il {{ location }}"
+    neurons:
+      - openweathermap:
+          api_key: "your-api"
+          lang: "fr"
+          temp_unit: "celsius"
+          country: "FR"
+          args:
+            - location
+          say_template:
+          - "Aujourd'hui a {{ location }} le temps est {{ weather_today }} avec une température de {{ temp_today_temp }} degrés et demain le temps sera {{ weather_tomorrow }} avec une température de {{ temp_tomorrow_temp }} degrés"
+
+
+  - name: "synapse7"
+    signals:
+      - order: "synapse7"
     neurons:
       - say:
           message: "Je n'ai pas compris votre réponse"

+ 16 - 0
kalliope/core/Models/Brain.py

@@ -10,6 +10,22 @@ class Brain:
         self.brain_file = brain_file
         self.brain_yaml = brain_yaml
 
+    def get_synapse_by_name(self, synapse_name):
+        """
+        Get the synapse, using its synapse name, from the synapse list
+        :param synapse_name: the name of the synapse to get
+        :type synapse_name: str
+        :return: The Synapse corresponding to the name
+        :rtype: Synapse
+        """
+        synapse_launched = None
+        for synapse in self.synapses:
+            if synapse.name == synapse_name:
+                synapse_launched = synapse
+                # we found the synapse, we don't need to check the rest of the list
+                break
+        return synapse_launched
+
     def __eq__(self, other):
         """
         This is used to compare 2 objects

+ 29 - 3
kalliope/core/NeuronModule.py

@@ -1,12 +1,12 @@
 # coding: utf8
 import logging
-import os
 import random
 
 import sys
 from jinja2 import Template
 
 from kalliope.core import OrderListener
+from kalliope.core import OrderAnalyser
 from kalliope.core.SynapseLauncher import SynapseLauncher
 from kalliope.core.Utils.Utils import Utils
 from kalliope.core.ConfigurationManager import SettingLoader, BrainLoader
@@ -182,6 +182,32 @@ class NeuronModule(object):
     def run_synapse_by_name(self, name):
         SynapseLauncher.start_synapse(name=name, brain=self.brain)
 
+    def is_order_matching(self, order_said, order_match):
+        oa = OrderAnalyser(order=order_said, brain=self.brain)
+        return oa.spelt_order_match_brain_order_via_table(order_to_analyse=order_match, user_said=order_said)
+
+    def run_synapse_by_name_with_order(self, order, synapse_name, order_template):
+        """
+        Run a synapse using its name, and giving an order so it can retrieve its params.
+        Useful for neurotransmitters.
+        :param order: the order to match
+        :param synapse_name: the name of the synapse
+        :param order_template: order_template coming from the neurotransmitter
+        :return: True if a synapse as been found and started using its params
+        """
+        synapse_to_run = self.brain.get_synapse_by_name(synapse_name=synapse_name)
+        if synapse_to_run:
+            # Make a list with the synapse
+            logger.debug("[run_synapse_by_name_with_order]-> a synapse has been found  %s" % synapse_to_run.name)
+            list_to_run = list()
+            list_to_run.append(synapse_to_run)
+
+            oa = OrderAnalyser(order=order, brain=self.brain)
+            oa.start(synapses_to_run=list_to_run, external_order=order_template)
+        else:
+            logger.debug("[NeuronModule]-> run_synapse_by_name_with_order, the synapse has not been found : %s" % synapse_name)
+        return synapse_to_run is not None
+
     @staticmethod
     def _get_content_of_file(real_file_template_path):
         """
@@ -212,8 +238,8 @@ class NeuronModule(object):
         :param callback: A callback function
         """
         # call the order listener
-        oa = OrderListener(callback=callback)
-        oa.start()
+        ol = OrderListener(callback=callback)
+        ol.start()
 
     def get_neuron_name(self):
         """

+ 62 - 26
kalliope/core/OrderAnalyser.py

@@ -31,33 +31,61 @@ class OrderAnalyser:
         self.brain = brain
         logger.debug("OrderAnalyser, Received order: %s" % self.order)
 
-    def start(self):
+    def start(self, synapses_to_run=None, external_order=None):
         """
         This method matches the incoming messages to the signals/order sentences provided in the Brain
         """
 
-        # create a dict of synapses that have been launched
-        launched_synapses = self._get_matching_synapse_list(self.brain.synapses, self.order)
+        # if list of synapse is not provided, let's find one
+        if synapses_to_run is None and external_order is None:
+            # create a dict of synapses that have been launched
+            logger.debug("[orderAnalyser.start]-> No Synapse provided, let's find one")
+            synapses_to_run = self._find_synapse_to_run(brain=self.brain,
+                                                       settings=self.settings,
+                                                       order=self.order)
+
+        # retrieve params
+        for synapse in synapses_to_run:
+            # If no external orders has been provided then run signals sentences
+            if external_order is None:
+                logger.debug("[orderAnalyser.start]-> No external order provided, run the signals from the synapse")
+                for signal in synapse.signals:
+                    params = self._get_params_from_order(signal.sentence, self.order)
+            else:
+                logger.debug("[orderAnalyser.start]-> provided external order")
+                params = self._get_params_from_order(external_order, self.order)
+
+            # Start a neuron list with params
+            self._start_list_neurons(list_neurons=synapse.neurons,
+                                     params=params)
 
-        if not launched_synapses:
-            Utils.print_info("No synapse match the captured order: %s" % self.order)
+        # return the list of launched synapse
+        return synapses_to_run
+
+    @classmethod
+    def _find_synapse_to_run(cls, brain, settings, order):
+        """
+        Find the list of the synapse matching the order
+        :param brain: the brain
+        :param settings: the settings
+        :param order: the provided order to match
+        :return: the list of synapses launched
+        """
+
+        synapse_to_run = cls._get_matching_synapse_list(brain.synapses, order)
+        if not synapse_to_run:
+            Utils.print_info("No synapse match the captured order: %s" % order)
 
-            if self.settings.default_synapse is not None:
-                default_synapse = self._get_default_synapse_from_sysnapses_list(self.brain.synapses,
-                                                                                self.settings.default_synapse)
+            if settings.default_synapse is not None:
+                default_synapse = cls._get_default_synapse_from_sysnapses_list(brain.synapses,
+                                                                                settings.default_synapse)
 
                 if default_synapse is not None:
                     logger.debug("Default synapse found %s" % default_synapse)
                     Utils.print_info("Default synapse found: %s, running it" % default_synapse.name)
-                    launched_synapses.append(default_synapse)
+                    synapse_to_run.append(default_synapse)
 
-        for synapse in launched_synapses:
-            params = self._get_synapse_params(synapse, self.order)
-            for neuron in synapse.neurons:
-                self._start_neuron(neuron, params)
-
-        # return the list of launched synapse
-        return launched_synapses
+        return synapse_to_run
 
     @classmethod
     def _get_matching_synapse_list(cls, all_synapses_list, order_to_match):
@@ -73,31 +101,36 @@ class OrderAnalyser:
         for synapse in all_synapses_list:
             for signal in synapse.signals:
                 if type(signal) == Order:
-                    if cls._spelt_order_match_brain_order_via_table(signal.sentence, order_to_match):
+                    if cls.spelt_order_match_brain_order_via_table(signal.sentence, order_to_match):
                         matching_synapses_list.append(synapse)
                         logger.debug("Order found! Run neurons: %s" % synapse.neurons)
                         Utils.print_success("Order matched in the brain. Running synapse \"%s\"" % synapse.name)
         return matching_synapses_list
 
     @classmethod
-    def _get_synapse_params(cls, synapse, order_to_check):
+    def _get_params_from_order(cls, string_order, order_to_check):
         """
-        Class method to get all params coming from a synapse. Returns a dict of key/value.
+        Class method to get all params coming from a string order. Returns a dict of key/value.
 
-        :param synapse: the synapse to check
+        :param string_order: the  string_order to check
         :param order_to_check: the order to match
         :type order_to_check: str
         :return: the dict key/value
         """
         params = dict()
-        for signal in synapse.signals:
-            if cls._is_containing_bracket(signal.sentence):
-                params = cls._associate_order_params_to_values(order_to_check, signal.sentence)
-                logger.debug("Parameters for order: %s" % params)
+        if cls._is_containing_bracket(string_order):
+            params = cls._associate_order_params_to_values(order_to_check, string_order)
+            logger.debug("Parameters for order: %s" % params)
         return params
 
     @classmethod
-    def _start_neuron(cls, neuron, params):
+    def _start_list_neurons(cls, list_neurons, params):
+        # start neurons
+        for neuron in list_neurons:
+            cls._start_neuron(neuron, params)
+
+    @staticmethod
+    def _start_neuron(neuron, params):
         """
         Associate params and Starts a neuron.
 
@@ -146,6 +179,9 @@ class OrderAnalyser:
         :type order: str
         :return: the dict corresponding to the key / value of the params
         """
+        logger.debug("[OrderAnalyser._associate_order_params_to_values] user order: %s, "
+                     "order to check: %s" % (order, order_to_check))
+
         pattern = '\s+(?=[^\{\{\}\}]*\}\})'
         # Remove white spaces (if any) between the variable and the double brace then split
         list_word_in_order = re.sub(pattern, '', order_to_check).split()
@@ -201,7 +237,7 @@ class OrderAnalyser:
         return next(ite, None)
 
     @classmethod
-    def _spelt_order_match_brain_order_via_table(cls, order_to_analyse, user_said):
+    def spelt_order_match_brain_order_via_table(cls, order_to_analyse, user_said):
         """
         return true if all string that are in the sentence are present in the order to test
         :param order_to_analyse: String order to test

+ 1 - 1
kalliope/core/OrderListener.py

@@ -21,7 +21,7 @@ class OrderListener(Thread):
 
     def __init__(self, callback=None, stt=None):
         """
-        This class is called after we catch the hotword that have woke up Kalliope.
+        This class is called after we catch the hotword that has woken up Kalliope.
         We now wait for an order spoken out loud by the user, translate the order into a text and run the action
          attached to this order from settings
         :param callback: callback function to call

+ 5 - 12
kalliope/core/SynapseLauncher.py

@@ -22,21 +22,14 @@ class SynapseLauncher(object):
         :param name: Name (Unique ID) of the synapse to launch
         :param brain: Brain instance
         """
-        synapse_name_launch = name
-        # get the brain
-        cls.brain = brain
 
         # check if we have found and launched the synapse
-        synapse_launched = False
-        for synapse in cls.brain.synapses:
-            if synapse.name == synapse_name_launch:
-                cls._run_synapse(synapse)
-                synapse_launched = True
-                # we found the synapse, we don't need to check the rest of the list
-                break
-
-        if not synapse_launched:
+        synapse = brain.get_synapse_by_name(synapse_name=name)
+
+        if not synapse:
             raise SynapseNameNotFound("The synapse name \"%s\" does not exist in the brain file" % name)
+        else:
+            cls._run_synapse(synapse=synapse)
 
     @classmethod
     def _run_synapse(cls, synapse):

+ 33 - 0
kalliope/neurons/neurotransmitter/README.md

@@ -84,6 +84,39 @@ If the user say something that is not present in `answers`, he will be redirecte
           message: "I haven't understood your answer"
 ```
 
+
+Neurotransmitter also uses parameters in answers. You can provide parameters to your answers so they can be used by the synapse you are about to launch.
+/!\ The params defined in answers must match with the expected "args" params in the target synapse, otherwise an error is raised.
+
+```
+
+  - name: "synapse5"
+    signals:
+      - order: "give me the weather"
+    neurons:
+      - say:
+          message: "which town ?"
+      - neurotransmitter:
+          from_answer_link:
+            - synapse: "synapse6"
+              answers:
+                - "the weather in {{ location }}"
+
+  - name: "synapse6"
+    signals:
+      - order: "What is the weather in {{ location }}"
+    neurons:
+      - openweathermap:
+          api_key: "your-api"
+          lang: "fr"
+          temp_unit: "celsius"
+          country: "FR"
+          args:
+            - location
+          say_template:
+          - "Today in {{ location }} the weather is {{ weather_today }} with {{ temp_today_temp }} celsius"
+```
+
 ## Notes
 > When using the neuron neurotransmitter, you must set a `direct_link` or a `from_answer_link`, no both at the same time.
 

+ 9 - 9
kalliope/neurons/neurotransmitter/neurotransmitter.py

@@ -33,16 +33,16 @@ class Neurotransmitter(NeuronModule):
         logger.debug("Neurotransmitter, receiver audio from STT: %s" % audio)
         # print self.links
         # set a bool to know if we have found a valid answer
-        found = False
-        for el in self.from_answer_link:
-            if audio in el["answers"]:
-                found = True
-                self.run_synapse_by_name(el["synapse"])
-                # we don't need to check to rest of answer
-                break
-        if not found:
-            # the answer do not correspond to any answer. We run the default synapse
+        if audio is None:
             self.run_synapse_by_name(self.default)
+        else:
+            found = False
+            for el in self.from_answer_link:
+                for answer in el["answers"]:
+                    if self.is_order_matching(audio, answer):
+                        found = self.run_synapse_by_name_with_order(audio, el["synapse"], order_template=answer)
+            if not found: # the answer do not correspond to any answer. We run the default synapse
+                self.run_synapse_by_name(self.default)
 
     def _is_parameters_ok(self):
         """

+ 1 - 1
kalliope/stt/google/google.py

@@ -49,7 +49,7 @@ class Google(OrderListener):
 
     def _analyse_audio(self, audio):
         """
-        Confirm the audio exists annd run it in a Callback
+        Confirm the audio exists and run it in a Callback
         :param audio: the captured audio
         """