Browse Source

[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 years ago
parent
commit
b3ed7748e9

+ 64 - 0
Tests/test_neuron_module.py

@@ -3,6 +3,10 @@ import unittest
 import mock
 import mock
 
 
 from kalliope.core.NeuronModule import NeuronModule, TemplateFileNotFoundException
 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):
 class TestNeuronModule(unittest.TestCase):
@@ -107,3 +111,63 @@ class TestNeuronModule(unittest.TestCase):
     def test_get_content_of_file(self):
     def test_get_content_of_file(self):
         expected_result = "hello, this is a {{ test }}"
         expected_result = "hello, this is a {{ test }}"
         self.assertEqual(NeuronModule._get_content_of_file(self.file_template), expected_result)
         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.Neuron import Neuron
 from kalliope.core.Models.Synapse import Synapse
 from kalliope.core.Models.Synapse import Synapse
 from kalliope.core.Models.Brain import Brain
 from kalliope.core.Models.Brain import Brain
+from kalliope.core.Models.Settings import Settings
 from kalliope.core.Models.Order import Order
 from kalliope.core.Models.Order import Order
 
 
 
 
@@ -21,7 +22,9 @@ class TestOrderAnalyser(unittest.TestCase):
         Scenarii :
         Scenarii :
             - Order matchs a synapse and the synapse has been launched.
             - Order matchs a synapse and the synapse has been launched.
             - Order does not match but have a default synapse.
             - 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
         # Init
         neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
         neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
@@ -43,9 +46,6 @@ class TestOrderAnalyser(unittest.TestCase):
 
 
         br = Brain(synapses=all_synapse_list)
         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:
         with mock.patch("kalliope.core.OrderAnalyser._start_neuron") as mock_start_neuron_method:
             # assert synapses have been launched
             # assert synapses have been launched
             order_to_match = "this is the sentence"
             order_to_match = "this is the sentence"
@@ -81,6 +81,35 @@ class TestOrderAnalyser(unittest.TestCase):
                               expected_result,
                               expected_result,
                               "Fail to no synapse because no synapse matchs and no default defined")
                               "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):
     def test_start_neuron(self):
         """
         """
         Testing params association and starting a Neuron
         Testing params association and starting a Neuron
@@ -181,12 +210,12 @@ class TestOrderAnalyser(unittest.TestCase):
         sentence_to_test = "this is the order"
         sentence_to_test = "this is the order"
 
 
         # Success
         # 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")
                         "Fail matching order with the expected sentence")
 
 
         # Failure
         # Failure
         sentence_to_test = "unexpected sentence"
         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")
                          "Fail to ensure the expected sentence is not matching the order")
 
 
     def test_get_split_order_without_bracket(self):
     def test_get_split_order_without_bracket(self):
@@ -389,83 +418,67 @@ class TestOrderAnalyser(unittest.TestCase):
                           expected_result,
                           expected_result,
                           "Fail matching 'synapse with all key worlds' from the complete synapse list and the order")
                           "Fail matching 'synapse with all key worlds' from the complete synapse list and the order")
 
 
-    def test_get_synapse_params(self):
+    def test_get_params_from_order(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])
 
 
+        string_order = "this is the {{ sentence }}"
         order_to_check = "this is the value"
         order_to_check = "this is the value"
         expected_result = {'sentence': '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,
                           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
         # Multiple match
-        signal1 = Order(sentence="this is the {{ sentence }}")
+        string_order = "this is the {{ sentence }}"
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
 
         order_to_check = "this is the value with multiple words"
         order_to_check = "this is the value with multiple words"
         expected_result = {'sentence': '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,
                          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
         # Multiple params
-        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
+        string_order = "this is the {{ sentence }} with multiple {{ params }}"
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
 
         order_to_check = "this is the value with multiple words"
         order_to_check = "this is the value with multiple words"
         expected_result = {'sentence': 'value',
         expected_result = {'sentence': 'value',
                             'params':'words'}
                             '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,
                          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
         # Multiple params with multiple words
-        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
+        string_order = "this is the {{ sentence }} with multiple {{ params }}"
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
 
         order_to_check = "this is the multiple values with multiple values as words"
         order_to_check = "this is the multiple values with multiple values as words"
         expected_result = {'sentence': 'multiple values',
         expected_result = {'sentence': 'multiple values',
                            'params': 'values as words'}
                            '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,
                          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
         # params at the begining of the sentence
-        signal1 = Order(sentence="{{ sentence }} this is the sentence")
+        string_order = "{{ sentence }} this is the sentence"
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
 
         order_to_check = "hello world this is the multiple values with multiple values as words"
         order_to_check = "hello world this is the multiple values with multiple values as words"
         expected_result = {'sentence': 'hello world'}
         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,
                          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
         # all of the sentence is a variable
-        signal1 = Order(sentence="{{ sentence }}")
+        string_order = "{{ sentence }}"
-
-        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
 
         order_to_check = "this is the all sentence is a variable"
         order_to_check = "this is the all sentence is a variable"
         expected_result = {'sentence': '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,
                          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):
     def test_get_default_synapse_from_sysnapses_list(self):
         # Init
         # Init
@@ -494,6 +507,56 @@ class TestOrderAnalyser(unittest.TestCase):
                           expected_result,
                           expected_result,
                           "Fail to match the expected default Synapse")
                           "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__':
 if __name__ == '__main__':
     unittest.main()
     unittest.main()

+ 36 - 1
brain_examples/neurotransmitter.yml

@@ -18,7 +18,6 @@
   - name: "synapse1"
   - name: "synapse1"
     signals:
     signals:
       - order: "pose moi une question"
       - order: "pose moi une question"
-      - order: "pose-moi une question"
     neurons:
     neurons:
       - say:
       - say:
           message: "aimez vous les frites?"
           message: "aimez vous les frites?"
@@ -51,6 +50,42 @@
   - name: "synapse4"
   - name: "synapse4"
     signals:
     signals:
       - order: "synapse4"
       - 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:
     neurons:
       - say:
       - say:
           message: "Je n'ai pas compris votre réponse"
           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_file = brain_file
         self.brain_yaml = brain_yaml
         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):
     def __eq__(self, other):
         """
         """
         This is used to compare 2 objects
         This is used to compare 2 objects

+ 29 - 3
kalliope/core/NeuronModule.py

@@ -1,12 +1,12 @@
 # coding: utf8
 # coding: utf8
 import logging
 import logging
-import os
 import random
 import random
 
 
 import sys
 import sys
 from jinja2 import Template
 from jinja2 import Template
 
 
 from kalliope.core import OrderListener
 from kalliope.core import OrderListener
+from kalliope.core import OrderAnalyser
 from kalliope.core.SynapseLauncher import SynapseLauncher
 from kalliope.core.SynapseLauncher import SynapseLauncher
 from kalliope.core.Utils.Utils import Utils
 from kalliope.core.Utils.Utils import Utils
 from kalliope.core.ConfigurationManager import SettingLoader, BrainLoader
 from kalliope.core.ConfigurationManager import SettingLoader, BrainLoader
@@ -182,6 +182,32 @@ class NeuronModule(object):
     def run_synapse_by_name(self, name):
     def run_synapse_by_name(self, name):
         SynapseLauncher.start_synapse(name=name, brain=self.brain)
         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
     @staticmethod
     def _get_content_of_file(real_file_template_path):
     def _get_content_of_file(real_file_template_path):
         """
         """
@@ -212,8 +238,8 @@ class NeuronModule(object):
         :param callback: A callback function
         :param callback: A callback function
         """
         """
         # call the order listener
         # call the order listener
-        oa = OrderListener(callback=callback)
+        ol = OrderListener(callback=callback)
-        oa.start()
+        ol.start()
 
 
     def get_neuron_name(self):
     def get_neuron_name(self):
         """
         """

+ 62 - 26
kalliope/core/OrderAnalyser.py

@@ -31,33 +31,61 @@ class OrderAnalyser:
         self.brain = brain
         self.brain = brain
         logger.debug("OrderAnalyser, Received order: %s" % self.order)
         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
         This method matches the incoming messages to the signals/order sentences provided in the Brain
         """
         """
 
 
-        # create a dict of synapses that have been launched
+        # if list of synapse is not provided, let's find one
-        launched_synapses = self._get_matching_synapse_list(self.brain.synapses, self.order)
+        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:
+        # return the list of launched synapse
-            Utils.print_info("No synapse match the captured order: %s" % self.order)
+        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:
+            if settings.default_synapse is not None:
-                default_synapse = self._get_default_synapse_from_sysnapses_list(self.brain.synapses,
+                default_synapse = cls._get_default_synapse_from_sysnapses_list(brain.synapses,
-                                                                                self.settings.default_synapse)
+                                                                                settings.default_synapse)
 
 
                 if default_synapse is not None:
                 if default_synapse is not None:
                     logger.debug("Default synapse found %s" % default_synapse)
                     logger.debug("Default synapse found %s" % default_synapse)
                     Utils.print_info("Default synapse found: %s, running it" % default_synapse.name)
                     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:
+        return synapse_to_run
-            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
 
 
     @classmethod
     @classmethod
     def _get_matching_synapse_list(cls, all_synapses_list, order_to_match):
     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 synapse in all_synapses_list:
             for signal in synapse.signals:
             for signal in synapse.signals:
                 if type(signal) == Order:
                 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)
                         matching_synapses_list.append(synapse)
                         logger.debug("Order found! Run neurons: %s" % synapse.neurons)
                         logger.debug("Order found! Run neurons: %s" % synapse.neurons)
                         Utils.print_success("Order matched in the brain. Running synapse \"%s\"" % synapse.name)
                         Utils.print_success("Order matched in the brain. Running synapse \"%s\"" % synapse.name)
         return matching_synapses_list
         return matching_synapses_list
 
 
     @classmethod
     @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
         :param order_to_check: the order to match
         :type order_to_check: str
         :type order_to_check: str
         :return: the dict key/value
         :return: the dict key/value
         """
         """
         params = dict()
         params = dict()
-        for signal in synapse.signals:
+        if cls._is_containing_bracket(string_order):
-            if cls._is_containing_bracket(signal.sentence):
+            params = cls._associate_order_params_to_values(order_to_check, string_order)
-                params = cls._associate_order_params_to_values(order_to_check, signal.sentence)
+            logger.debug("Parameters for order: %s" % params)
-                logger.debug("Parameters for order: %s" % params)
         return params
         return params
 
 
     @classmethod
     @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.
         Associate params and Starts a neuron.
 
 
@@ -146,6 +179,9 @@ class OrderAnalyser:
         :type order: str
         :type order: str
         :return: the dict corresponding to the key / value of the params
         :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+(?=[^\{\{\}\}]*\}\})'
         pattern = '\s+(?=[^\{\{\}\}]*\}\})'
         # Remove white spaces (if any) between the variable and the double brace then split
         # 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()
         list_word_in_order = re.sub(pattern, '', order_to_check).split()
@@ -201,7 +237,7 @@ class OrderAnalyser:
         return next(ite, None)
         return next(ite, None)
 
 
     @classmethod
     @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
         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
         :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):
     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
         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
          attached to this order from settings
         :param callback: callback function to call
         :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 name: Name (Unique ID) of the synapse to launch
         :param brain: Brain instance
         :param brain: Brain instance
         """
         """
-        synapse_name_launch = name
-        # get the brain
-        cls.brain = brain
 
 
         # check if we have found and launched the synapse
         # check if we have found and launched the synapse
-        synapse_launched = False
+        synapse = brain.get_synapse_by_name(synapse_name=name)
-        for synapse in cls.brain.synapses:
+
-            if synapse.name == synapse_name_launch:
+        if not synapse:
-                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:
             raise SynapseNameNotFound("The synapse name \"%s\" does not exist in the brain file" % name)
             raise SynapseNameNotFound("The synapse name \"%s\" does not exist in the brain file" % name)
+        else:
+            cls._run_synapse(synapse=synapse)
 
 
     @classmethod
     @classmethod
     def _run_synapse(cls, synapse):
     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"
           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
 ## Notes
 > When using the neuron neurotransmitter, you must set a `direct_link` or a `from_answer_link`, no both at the same time.
 > 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)
         logger.debug("Neurotransmitter, receiver audio from STT: %s" % audio)
         # print self.links
         # print self.links
         # set a bool to know if we have found a valid answer
         # set a bool to know if we have found a valid answer
-        found = False
+        if audio is None:
-        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
             self.run_synapse_by_name(self.default)
             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):
     def _is_parameters_ok(self):
         """
         """

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

@@ -49,7 +49,7 @@ class Google(OrderListener):
 
 
     def _analyse_audio(self, audio):
     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
         :param audio: the captured audio
         """
         """