예제 #1
0
    def get_list_match_synapse(cls, order, synapse_order_tuple):
        list_match_synapse = list()
        for synapse in cls.brain.synapses:
            if synapse.enabled:
                for signal in synapse.signals:
                    # we are only concerned by synapse with a order type of signal
                    if signal.name == "order":
                        # get the type of matching expected, by default "normal"
                        expected_matching_type = "normal"
                        signal_order = None

                        if isinstance(signal.parameters, str) or isinstance(signal.parameters, six.text_type):
                            signal_order = signal.parameters
                        if isinstance(signal.parameters, dict):
                            try:
                                signal_order = signal.parameters["text"]
                            except KeyError:
                                logger.debug("[OrderAnalyser] Warning, missing parameter 'text' in order. "
                                             "Order will be skipped")
                                continue

                            expected_matching_type = cls.get_matching_type(signal)

                            order = cls.order_correction(order, signal)

                        if cls.is_order_matching(user_order=order,
                                                 signal_order=signal_order,
                                                 expected_order_type=expected_matching_type):
                            # the order match the synapse, we add it to the returned list
                            logger.debug("Order found! Run synapse name: %s" % synapse.name)
                            Utils.print_info("Brain: order recognized")
                            Utils.print_success(" * Running synapse \"%s\"" % synapse.name)
                            list_match_synapse.append(synapse_order_tuple(synapse=synapse, order=signal_order))
        return list_match_synapse
예제 #2
0
    def test_remove_spaces_in_brackets(self):
        """
        Test the Utils remove_spaces_in_brackets
        """

        sentence = "This is the {{ bracket   }}"
        expected_result = "This is the {{bracket}}"
        self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence),
                         expected_result,
                         "Fail to remove spaces in one bracket")

        sentence = "This is the {{ bracket   }} {{  second     }}"
        expected_result = "This is the {{bracket}} {{second}}"
        self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence),
                         expected_result,
                         "Fail to remove spaces in two brackets")

        # test with json
        sentence = "{\"params\": {\"apikey\": \"ISNOTMYPASSWORD\", " \
                   "\"query\": \"met le chauffage a {{ valeur }} degres\"}}"
        expected_result = "{\"params\": {\"apikey\": \"ISNOTMYPASSWORD\", " \
                          "\"query\": \"met le chauffage a {{valeur}} degres\"}}"
        self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence),
                         expected_result,
                         "Fail to remove spaces in two brackets")
예제 #3
0
    def say(self, message):
        """
        USe TTS to speak out loud the Message.
        A message can be a string, a list or a dict
        If it's a string, simply use the TTS with the message
        If it's a list, we select randomly a string in the list and give it to the TTS
        If it's a dict, we use the template given in parameter to create a string that we give to the TTS
        :param message: Can be a String or a dict or a list

        .. raises:: TTSModuleNotFound
        """
        logger.debug("[NeuronModule] Say() called with message: %s" % message)

        tts_message = None

        # we can save parameters from the neuron in memory
        Cortex.save_neuron_parameter_in_memory(self.brain_memory, message)

        if isinstance(message, str) or isinstance(message, six.text_type):
            logger.debug("[NeuronModule] message is string")
            tts_message = message

        if isinstance(message, list):
            logger.debug("[NeuronModule] message is list")
            tts_message = random.choice(message)

        if isinstance(message, dict):
            logger.debug("[NeuronModule] message is dict")
            tts_message = self._get_message_from_dict(message)

        if tts_message is not None:
            logger.debug("[NeuronModule] tts_message to say: %s" % tts_message)
            self.tts_message = tts_message
            Utils.print_info("Player Engine: " + tts_message)
            # save in brain memory the last tts message
            Cortex.save("brain_last_tts_message", tts_message)

            # process the audio only if the mute flag is false
            if self.settings.options.mute:
                logger.debug("[NeuronModule] mute is True, Brain.ai is muted")
            else:
                logger.debug(
                    "[NeuronModule] mute is False, make Brain.ai speaking")
                HookManager.on_start_speaking()
                # get the instance of the TTS module
                tts_folder = None
                if self.settings.resources:
                    tts_folder = self.settings.resources.tts_folder
                tts_module_instance = Utils.get_dynamic_class_instantiation(
                    package_name="tts",
                    module_name=self.tts.name,
                    parameters=self.tts.parameters,
                    resources_dir=tts_folder)

                # generate the audio file and play it
                tts_module_instance.say(tts_message)
                HookManager.on_stop_speaking()
예제 #4
0
 def __init__(self, file_path=None):
     self.file_path = file_path
     if self.file_path is None:
         self.file_path = Utils.get_real_file_path(FILE_NAME)
     else:
         self.file_path = Utils.get_real_file_path(file_path)
     # if the returned file path is none, the file doesn't exist
     if self.file_path is None:
         raise SettingNotFound("Settings.yml file not found")
     self.yaml_config = self._get_yaml_config()
     self.settings = self._get_settings()
예제 #5
0
    def test_find_all_matching_brackets(self):
        """
        Test the Utils find all matching brackets
        """
        sentence = "This is the {{bracket}}"
        expected_result = ["{{bracket}}"]
        self.assertEqual(Utils.find_all_matching_brackets(sentence=sentence),
                         expected_result, "Fail to match one bracket")

        sentence = "This is the {{bracket}} {{second}}"
        expected_result = ["{{bracket}}", "{{second}}"]
        self.assertEqual(Utils.find_all_matching_brackets(sentence=sentence),
                         expected_result, "Fail to match two brackets")
예제 #6
0
    def _replace_brackets_by_loaded_parameter(cls, neuron_parameters, loaded_parameters=dict()):
        """
        Receive a value (which can be a str or dict or list) and instantiate value in double brace bracket
        by the value specified in the loaded_parameters dict.
        This method will call itself until all values has been instantiated
        :param neuron_parameters: value to instantiate. Str or dict or list
        :param loaded_parameters: dict of parameters
        """
        logger.debug("[NeuronLauncher] replacing brackets from %s, using %s" % (neuron_parameters, loaded_parameters))

        if isinstance(neuron_parameters, str) or isinstance(neuron_parameters, six.text_type):
            # replace bracket parameter only if the str contains brackets
            if Utils.is_containing_bracket(neuron_parameters):
                settings = cls.load_settings()
                # Priority to memory over the variables
                loaded_parameters.update(settings.variables)
                memory_dict = dict()
                # add variables from the short term memory to the list of loaded parameters that can be used in a template
                # the final dict is added into a key "brain_memory" to not override existing keys loaded form the order
                memory_dict["brain_memory"] = Cortex.get_memory()
                loaded_parameters.update(memory_dict)
                # check that the parameter to replace is available in the loaded_parameters dict
                if cls._neuron_parameters_are_available_in_loaded_parameters(neuron_parameters, loaded_parameters):
                    # add parameters from global variable into the final loaded parameter dict
                    neuron_parameters = jinja2.Template(neuron_parameters).render(loaded_parameters)
                    neuron_parameters = Utils.encode_text_utf8(neuron_parameters)
                    return str(neuron_parameters)
                else:
                    raise NeuronParameterNotAvailable
            return neuron_parameters

        if isinstance(neuron_parameters, dict):
            returned_dict = dict()
            for key, value in neuron_parameters.items():
                # following keys are reserved by brain core
                if key in "say_template" or key in "file_template" or key in "brain_memory" \
                        or key in "from_answer_link":
                    returned_dict[key] = value
                else:
                    returned_dict[key] = cls._replace_brackets_by_loaded_parameter(value, loaded_parameters)
            return returned_dict

        if isinstance(neuron_parameters, list):
            returned_list = list()
            for el in neuron_parameters:
                templated_value = cls._replace_brackets_by_loaded_parameter(el, loaded_parameters)
                returned_list.append(templated_value)
            return returned_list
        # in all other case (boolean or int for example) we return the value as it
        return neuron_parameters
예제 #7
0
    def save_neuron_parameter_in_memory(cls, brain_memory_dict, neuron_parameters):
        """
        receive a dict of value send by the child neuron
        save in brain memory all value

        E.g
        dict_parameter_to_save = {"my_key_to_save_in_memory": "{{ output_val_from_neuron }}"}
        neuron_parameter = {"output_val_from_neuron": "this_is_a_value" }

        then the cortex will save in memory the key "my_key_to_save_in_memory" and attach the value "this_is_a_value"

        :param neuron_parameters: dict of parameter the neuron has processed and send to the neurone module to
                be processed by the TTS engine
        :param brain_memory_dict: a dict of key value the user want to save from the dict_neuron_parameter
        """

        if brain_memory_dict is not None:
            logger.debug("[Cortex] save_memory - User want to save: %s" % brain_memory_dict)
            logger.debug("[Cortex] save_memory - Available parameters in the neuron: %s" % neuron_parameters)

            for key, value in brain_memory_dict.items():
                # ask the cortex to save in memory the target "key" if it was in parameters of the neuron
                if isinstance(neuron_parameters, dict):
                    if Utils.is_containing_bracket(value):
                        value = jinja2.Template(value).render(neuron_parameters)
                    Cortex.save(key, value)
예제 #8
0
    def test_get_next_value_list(self):
        # Success
        list_to_test = {1, 2, 3}
        self.assertEqual(
            Utils.get_next_value_list(list_to_test), 2,
            "Fail to match the expected next value from the list")

        # Failure
        list_to_test = {1}
        self.assertEqual(
            Utils.get_next_value_list(list_to_test), None,
            "Fail to ensure there is no next value from the list")

        # Behaviour
        list_to_test = {}
        self.assertEqual(Utils.get_next_value_list(list_to_test), None,
                         "Fail to ensure the empty list return None value")
예제 #9
0
    def test_get_current_file_parent_path(self):
        """
        Expect to get back the parent path file
        """
        path_to_test = "../brain/core/Utils"
        expected_result = os.path.normpath("../brain/core")

        self.assertEqual(
            Utils.get_current_file_parent_path(path_to_test), expected_result,
            "fail getting the parent parent path from the given path")
예제 #10
0
    def test_encode_text_utf8(self):
        """
        Test encoding the text in utf8
        """
        sentence = "kâllìöpé"
        if sys.version_info[0] < 3:
            sentence = sentence.decode('utf8')
        expected_sentence = "kâllìöpé"

        self.assertEqual(Utils.encode_text_utf8(text=sentence),
                         expected_sentence)
예제 #11
0
    def serialize(self):
        """
        This method allows to serialize in a proper way this object

        :return: A dict of name and parameters
        :rtype: Dict
        """
        self.tts_message = Utils.encode_text_utf8(self.tts_message)
        return {
            'neuron_name': self.neuron_name,
            'generated_message': self.tts_message
        }
예제 #12
0
 def start_neuron(cls, neuron, parameters_dict=dict()):
     """
     Execute each neuron from the received neuron_list.
     Replace parameter if exist in the received dict of parameters_dict
     :param neuron: Neuron object to run
     :param parameters_dict: dict of parameter to load in each neuron if expecting a parameter
     :return: List of the instantiated neurons (no errors detected)
     """
     if neuron.parameters is not None:
         try:
             neuron.parameters = cls._replace_brackets_by_loaded_parameter(neuron.parameters, parameters_dict)
         except NeuronParameterNotAvailable:
             Utils.print_danger("Missing parameter in neuron %s. Execution skipped" % neuron.name)
             return None
     try:
         instantiated_neuron = NeuronLauncher.launch_neuron(neuron)
     except NeuronExceptions as e:
         Utils.print_danger("ERROR: Fail to execute neuron '%s'. "
                            '%s' ". -> Execution skipped" % (neuron.name, e.message))
         return None
     return instantiated_neuron
예제 #13
0
    def _get_file_template(cls, file_template, message_dict):
        real_file_template_path = Utils.get_real_file_path(file_template)
        if real_file_template_path is None:
            raise TemplateFileNotFoundException(
                "Template file %s not found in templates folder" %
                real_file_template_path)

        # load the content of the file as template
        t = Template(cls._get_content_of_file(real_file_template_path))
        returned_message = t.render(**message_dict)

        return returned_message
예제 #14
0
    def _get_split_order_without_bracket(order):
        """
        Get an order with bracket inside like: "hello my name is {{ name }}.
        return a list of string without bracket like ["hello", "my", "name", "is"]
        :param order: sentence to split
        :return: list of string without bracket
        """

        matches = Utils.find_all_matching_brackets(order)
        for match in matches:
            order = order.replace(match, "")
        # then split
        split_order = order.split()
        return split_order
예제 #15
0
 def _neuron_parameters_are_available_in_loaded_parameters(string_parameters, loaded_parameters):
     """
     Check that all parameters in brackets are available in the loaded_parameters dict
     
     E.g:
     string_parameters = "this is a {{ parameter1 }}"
     
     Will return true if the loaded_parameters looks like the following
     loaded_parameters { "parameter1": "a value"}        
     
     :param string_parameters: The string that contains one or more parameters in brace brackets
     :param loaded_parameters: Dict of parameter
     :return: True if all parameters in brackets have an existing key in loaded_parameters dict
     """
     list_parameters_with_brackets = Utils.find_all_matching_brackets(string_parameters)
     # remove brackets to keep only the parameter name
     for parameter_with_brackets in list_parameters_with_brackets:
         parameter = Utils.remove_spaces_in_brackets(parameter_with_brackets)
         parameter = parameter.replace("{{", "").replace("}}", "")
         if loaded_parameters is None or parameter not in loaded_parameters:
             Utils.print_danger("The parameter %s is not available in the order" % str(parameter))
             return False
     return True
예제 #16
0
    def launch_neuron(cls, neuron):
        """
        Start a neuron plugin
        :param neuron: neuron object
        :type neuron: Neuron
        :return:
        """
        logger.debug("Run neuron: \"%s\"" % (neuron.__str__()))
        settings = cls.load_settings()
        neuron_folder = None
        if settings.resources:
            neuron_folder = settings.resources.neuron_folder

        return Utils.get_dynamic_class_instantiation(package_name="neurons",
                                                     module_name=neuron.name,
                                                     parameters=neuron.parameters,
                                                     resources_dir=neuron_folder)
예제 #17
0
    def test_get_dynamic_class_instantiation(self):
        """
        Test that an instance as been instantiate properly.
        """
        sl = SettingLoader()
        sl.settings.resource_dir = '/var/tmp/test/resources'

        neuron = Neuron(
            name='Say',
            parameters={'message': 'test dynamic class instantiate'})
        self.assertTrue(
            isinstance(
                Utils.get_dynamic_class_instantiation(
                    package_name="neurons",
                    module_name=neuron.name.capitalize(),
                    parameters=neuron.parameters,
                    resources_dir='/var/tmp/test/resources'), Say),
            "Fail instantiate a class")
예제 #18
0
    def test_is_containing_bracket(self):
        #  Success
        order_to_test = "This test contains {{ bracket }}"
        self.assertTrue(
            Utils.is_containing_bracket(order_to_test),
            "Fail returning True when order contains spaced brackets")

        order_to_test = "This test contains {{bracket }}"
        self.assertTrue(
            Utils.is_containing_bracket(order_to_test),
            "Fail returning True when order contains right spaced bracket")

        order_to_test = "This test contains {{ bracket}}"
        self.assertTrue(
            Utils.is_containing_bracket(order_to_test),
            "Fail returning True when order contains left spaced bracket")

        order_to_test = "This test contains {{bracket}}"
        self.assertTrue(
            Utils.is_containing_bracket(order_to_test),
            "Fail returning True when order contains no spaced bracket")

        # Failure
        order_to_test = "This test does not contain bracket"
        self.assertFalse(Utils.is_containing_bracket(order_to_test),
                         "Fail returning False when order has no brackets")

        # Behaviour
        order_to_test = ""
        self.assertFalse(Utils.is_containing_bracket(order_to_test),
                         "Fail returning False when no order")

        # Behaviour int
        order_to_test = 6
        self.assertFalse(Utils.is_containing_bracket(order_to_test),
                         "Fail returning False when an int")

        # Behaviour unicode
        order_to_test = "j'aime les goûters l'été"
        self.assertFalse(Utils.is_containing_bracket(order_to_test),
                         "Fail returning False when an int")
예제 #19
0
    def _get_variables(settings):
        """
        Return the dict of variables from the settings.
        :param settings: The YAML settings file
        :return: dict
        """

        variables = dict()
        try:
            variables_files_name = settings["var_files"]
            # In case files are declared in settings.yml, make sure brain can access them.
            for files in variables_files_name:
                var = Utils.get_real_file_path(files)
                if var is None:
                    raise SettingInvalidException(
                        "Variables file %s not found" % files)
                else:
                    variables.update(YAMLLoader.get_config(var))
            return variables
        except KeyError:
            # User does not provide this settings
            return dict()
예제 #20
0
    def load_stt_plugin(self):
        if self.stt is None:
            self.stt_module_name = self.settings.default_stt_name

        logger.debug("[OrderListener] stt module name : %s" %
                     self.stt_module_name)
        for stt_object in self.settings.stts:
            if stt_object.name == self.stt_module_name:
                stt_object.parameters["callback"] = self.callback
                # add the audio file path to the list of parameter if set
                if self.audio_file_path is not None:
                    stt_object.parameters[
                        "audio_file_path"] = self.audio_file_path

                stt_folder = None
                if self.settings.resources:
                    stt_folder = self.settings.resources.stt_folder
                return Utils.get_dynamic_class_instantiation(
                    package_name='stt',
                    module_name=stt_object.name.capitalize(),
                    parameters=stt_object.parameters,
                    resources_dir=stt_folder)
예제 #21
0
    def save_parameter_from_order_in_memory(cls, order_parameters):
        """
        Save key from the temp dict (where parameters loaded from the voice order where placed temporary)
        into the memory dict
        :param order_parameters: dict of key to save.  {'key_name_in_memory': 'key_name_in_temp_dict'}
        :return True if a value has been saved in the brain memory
        """
        order_saved = False
        if order_parameters is not None:
            logger.debug("[Cortex] save_parameter_from_order_in_memory - User want to save: %s" % order_parameters)
            logger.debug("[Cortex] save_parameter_from_order_in_memory - Available parameters in orders: %s"
                         % cls.temp)

            for key, value in order_parameters.items():
                # ask the cortex to save in memory the target "key" if it was in the order
                if Utils.is_containing_bracket(value):
                    # if the key exist in the temp dict we can load it with jinja
                    value = jinja2.Template(value).render(Cortex.temp)
                    if value:
                        Cortex.save(key, value)
                        order_saved = True

        return order_saved
예제 #22
0
    def is_ordered_strict_matching(cls, user_order, signal_order):
        """
       True if :
            - all word in the user_order are present in the signal_order
            - no additional word
            - same order as word present in signal_order
        :param user_order: order from the user
        :param signal_order: order in the signal
        :return: Boolean
        """
        logger.debug(
            "[OrderAnalyser] ordered_strict_matching called with user_order: %s, signal_order: %s" % (user_order,
                                                                                                      signal_order))
        if cls.is_normal_matching(user_order=user_order, signal_order=signal_order) and \
                cls.is_strict_matching(user_order=user_order, signal_order=signal_order):
            # if the signal order contains bracket, we need to instantiate it with loaded parameters from the user order
            if Utils.is_containing_bracket(signal_order):
                signal_order = cls._get_instantiated_order_signal_from_user_order(signal_order, user_order)

            split_user_order = user_order.split()
            split_signal_order = signal_order.split()
            return split_user_order == split_signal_order

        return False
예제 #23
0
    def test_get_real_file_path(self):
        """
        Expect to load the proper file following the order :
            - Provided absolute path
            - Current user path + file_name
            - /etc/brain + file_name
            - /path/to/brain/ +file_name
        """
        ###
        # Test the absolute path
        dir_path = "/tmp/brain/tests/"
        file_name = "test_real_file_path"
        absolute_path_to_test = os.path.join(dir_path, file_name)
        expected_result = absolute_path_to_test
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

        # touch the file
        open(absolute_path_to_test, 'a').close()

        self.assertEqual(Utils.get_real_file_path(absolute_path_to_test),
                         expected_result,
                         "Fail to match the given absolute path ")
        # Clean up
        if os.path.exists(absolute_path_to_test):
            os.remove(absolute_path_to_test)

        ###
        # test the Current path
        file_name = "test_real_file_path"
        expected_result = os.getcwd() + os.sep + file_name

        # touch the file
        open(file_name, 'a').close()

        self.assertEqual(Utils.get_real_file_path(file_name), expected_result,
                         "Fail to match the Current path ")
        # Clean up
        if os.path.exists(file_name):
            os.remove(file_name)

        ###
        # test /etc/brain
        # /!\ need permissions
        # dir_path = "/etc/brain/"
        # file_name = "test_real_file_path"
        # path_to_test = os.path.join(dir_path,file_name)
        # expected_result = "/etc/brain" + os.sep + file_name
        # if not os.path.exists(dir_path):
        #     os.makedirs(dir_path)
        #
        # # touch the file
        # open(path_to_test, 'a').close()
        #
        # self.assertEquals(Utils.get_real_file_path(file_name),
        #                   expected_result,
        #                   "Fail to match the /etc/brain path")
        # # Clean up
        # if os.path.exists(file_name):
        #     os.remove(file_name)

        ###
        # /an/unknown/path/brain/
        dir_path = "../brain/"
        file_name = "test_real_file_path"
        path_to_test = os.path.join(dir_path, file_name)
        expected_result = os.path.normpath(os.getcwd() + os.sep + os.pardir +
                                           os.sep + "brain" + os.sep +
                                           file_name)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

        # touch the file
        open(path_to_test, 'a').close()

        self.assertEqual(Utils.get_real_file_path(file_name), expected_result,
                         "Fail to match the /an/unknown/path/brain path")
        # Clean up
        if os.path.exists(expected_result):
            os.remove(expected_result)
예제 #24
0
    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