コード例 #1
0
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser(self)

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._rdf_collection = RDFCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self._authentication = None
        self._authorisation = None

        self._default_oob = None
        self._oob = {}

        self._regex_templates = {}

        self._dynamics_collection = DynamicsCollection()

        self.load(self._configuration)
コード例 #2
0
    def test_load_learnf_files_none_directory(self):
        client = TestClient()
        brain = client.bot_factory.bot('bot').brain

        parser = AIMLParser(brain)

        configuration = TempAimlConfiguraton(extension='aiml')
        parser.load_learnf_files_from_directory(configuration)
コード例 #3
0
    def setUp(self):
        config = BrainConfiguration()
        config.files.aiml_files._errors = "/tmp/errors.txt"

        test_brain = Brain(configuration=config)
        self.parser = AIMLParser(brain=test_brain)
        self.parser.create_debug_storage(config)
        self.assertIsNotNone(self.parser)
コード例 #4
0
    def test_load_single_file(self):
        client = TestClient()
        brain = client.bot_factory.bot('bot').brain

        aimlfile = os.path.dirname(__file__) + os.sep + "basic.aiml"
        parser = AIMLParser(brain)

        configuration = TempAimlConfiguraton(file=aimlfile)
        parser.load_single_file(configuration)
コード例 #5
0
    def test_load_learnf_files_from_directory(self):
        client = TestClient()
        brain = client.bot_factory.bot('bot').brain

        learnf_path = os.path.dirname(__file__) + os.sep
        parser = AIMLParser(brain)

        configuration = TempAimlConfiguraton(learnfpath=learnf_path,
                                             extension='aiml')
        parser.load_learnf_files_from_directory(configuration)
コード例 #6
0
    def test_load_files_from_directory_empty(self):
        client = TestClient()
        brain = client.bot_factory.bot('bot').brain

        aimldir = os.path.dirname(__file__) + os.sep
        aimlfiles = []
        parser = AIMLParser(brain)

        configuration = TempAimlConfiguraton(file=aimlfiles,
                                             dirs=aimldir,
                                             extension='aiml')
        parser.load_files_from_directory(configuration)
コード例 #7
0
class PatternMatcherBaseClass(PatternTestBaseClass):
    @classmethod
    def setUpClass(cls):
        logging.getLogger().setLevel(logging.DEBUG)
        PatternMatcherBaseClass.bot = TestBot()
        PatternMatcherBaseClass.clientid = "matcher_test"

    def setUp(self):
        self._dump_graph = True
        self.graph = PatternGraph()
        self.matcher = AIMLParser()

    def dump_graph(self):
        if self._dump_graph is True:
            self.graph.dump()

    def add_pattern_to_graph(self,
                             pattern,
                             topic="*",
                             that="*",
                             template="test"):

        pattern_element = ET.fromstring("<pattern>%s</pattern>" % (pattern))
        topic_element = ET.fromstring("<topic>%s</topic>" % (topic))
        that_element = ET.fromstring("<that>%s</that>" % (that))
        template_node = TemplateWordNode(template)

        self.matcher.pattern_parser.add_pattern_to_graph(
            pattern_element, topic_element, that_element, template_node)

    def match_sentence(self, sentence, topic="*", that="*"):

        return self.matcher.match_sentence(PatternMatcherBaseClass.bot,
                                           PatternMatcherBaseClass.clientid,
                                           Sentence(sentence), topic, that)
コード例 #8
0
ファイル: base.py プロジェクト: Doshmaku/program-y
class PatternMatcherBaseClass(PatternTestBaseClass):

    @classmethod
    def setUpClass(cls):
        logging.getLogger().setLevel(logging.DEBUG)
        PatternMatcherBaseClass.bot = TestBot()
        PatternMatcherBaseClass.clientid = "matcher_test"

    def setUp(self):
        self._dump_graph = True
        self.graph = PatternGraph()
        self.matcher =  AIMLParser()

    def dump_graph(self):
        if self._dump_graph is True:
            self.graph.dump()

    def add_pattern_to_graph(self, pattern, topic="*", that="*", template="test"):

        pattern_element = ET.fromstring("<pattern>%s</pattern>"%(pattern))
        topic_element =  ET.fromstring("<topic>%s</topic>"%(topic))
        that_element = ET.fromstring("<that>%s</that>"%(that))
        template_node = TemplateWordNode(template)

        self.matcher.pattern_parser.add_pattern_to_graph(pattern_element, topic_element, that_element, template_node)

    def match_sentence(self, sentence, topic="*", that="*"):

        return self.matcher.match_sentence( PatternMatcherBaseClass.bot,
                                            PatternMatcherBaseClass.clientid,
                                            Sentence(sentence),
                                            topic,
                                            that)
コード例 #9
0
    def test_load_file_contents(self):
        client = TestClient()
        brain = client.bot_factory.bot('bot').brain

        aimlfile = os.path.dirname(__file__) + os.sep + "basic.aiml"
        loader = AIMLLoader(AIMLParser(brain))
        loader.load_file_contents("TestClient", aimlfile)
コード例 #10
0
    def setUp(self):
        self.parser = TemplateGraph(AIMLParser())
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")

        test_node = PatternOneOrMoreWildCardNode("*")

        self.test_sentence._matched_context = MatchContext(max_search_depth=100, max_search_timeout=-1)
        self.test_sentence._matched_context._matched_nodes = [Match(Match.WORD, test_node, 'one'),
                                                             Match(Match.WORD, test_node, 'two'),
                                                             Match(Match.WORD, test_node, 'three'),
                                                             Match(Match.WORD, test_node, 'four'),
                                                             Match(Match.WORD, test_node, 'five'),
                                                             Match(Match.WORD, test_node, 'six'),
                                                             Match(Match.TOPIC, test_node, '*'),
                                                             Match(Match.THAT, test_node, '*')]

        test_config = ProgramyConfiguration(self.get_client_config(),
                                            brain_config=self.get_brain_config(),
                                            bot_config=self.get_bot_config())

        self.test_bot = Bot(Brain(self.get_brain_config()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)
コード例 #11
0
ファイル: brain.py プロジェクト: rollingstone/program-y
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser()

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self.load(self._configuration)
コード例 #12
0
    def test_check_aiml_tag_no_namespace(self):
        aiml = ET.fromstring("""<?xml version="1.0" encoding="ISO-8859-1"?>
            <aiml version="1.01">
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
        """)

        tag_name, namespace = AIMLParser.check_aiml_tag(aiml)
        self.assertEquals("aiml", tag_name)
        self.assertEquals(None, namespace)
コード例 #13
0
    def upload_from_file(self,
                         filename,
                         format=Store.XML_FORMAT,
                         commit=True,
                         verbose=False):
        count = 0
        success = 0

        try:
            groupname = self.get_just_filename_from_filepath(filename)
            print(groupname)

            tree = ET.parse(filename, parser=LineNumberingParser())
            aiml = tree.getroot()

            for expression in aiml:
                tag_name, namespace = AIMLParser.tag_and_namespace_from_text(
                    expression.tag)
                if tag_name == 'topic':
                    topic = expression.attrib['name']
                    for topic_expression in expression:
                        that = self.find_element_str("that", topic_expression,
                                                     namespace)
                        pattern = self.find_element_str(
                            "pattern", topic_expression, namespace)
                        template = self.find_element_str(
                            "template", topic_expression, namespace)
                        if self.store_category(groupname, "*", topic, that,
                                               pattern, template) is True:
                            success += 1
                        count += 1

                elif tag_name == 'category':
                    topic = self.find_element_str("topic", expression,
                                                  namespace)
                    that = self.find_element_str("that", expression, namespace)
                    pattern = self.find_element_str("pattern", expression,
                                                    namespace)
                    template = self.find_element_str("template", expression,
                                                     namespace)
                    if self.store_category(groupname, "*", topic, that,
                                           pattern, template) is True:
                        success += 1
                    count += 1

        except Exception as excep:
            YLogger.exception(
                self, "Failed to load contents of AIML file from [%s]", excep,
                filename)

        return count, success
コード例 #14
0
    def test_check_aiml_tag_not_aiml(self):
        aiml = ET.fromstring("""<?xml version="1.0" encoding="ISO-8859-1"?>
            <aipl version="1.01"
                  xmlns="http://alicebot.org/2001/AIML"
                  xmlns:aiml="http://alicebot.org/2001/AIML"
                  xmlns:html="http://www.w3.org/TR/REC-html40">
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aipl>
        """)

        with self.assertRaises(ParserException):
            _, _ = AIMLParser.check_aiml_tag(aiml)
コード例 #15
0
    def test_check_aiml_tag(self):
        aiml = ET.fromstring("""<?xml version="1.0" encoding="ISO-8859-1"?>
            <aiml version="1.01"
                  xmlns="http://alicebot.org/2001/AIML"
                  xmlns:aiml="http://alicebot.org/2001/AIML"
                  xmlns:html="http://www.w3.org/TR/REC-html40">
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
        """)

        tag_name, namespace = AIMLParser.check_aiml_tag(aiml)
        self.assertEquals("aiml", tag_name)
        self.assertEquals("{http://alicebot.org/2001/AIML}", namespace)
コード例 #16
0
ファイル: brain.py プロジェクト: Doshmaku/program-y
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser()

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self.load(self._configuration)
コード例 #17
0
    def setUp(self):
        self.parser = TemplateGraph(AIMLParser())
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)
コード例 #18
0
class Brain(object):
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser(self)

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._rdf_collection = RDFCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self._authentication = None
        self._authorisation = None

        self._default_oob = None
        self._oob = {}

        self._regex_templates = {}

        self._dynamics_collection = DynamicsCollection()

        self.load(self._configuration)

    @property
    def configuration(self):
        return self._configuration

    @property
    def aiml_parser(self):
        return self._aiml_parser

    @property
    def denormals(self):
        return self._denormal_collection

    @property
    def normals(self):
        return self._normal_collection

    @property
    def genders(self):
        return self._gender_collection

    @property
    def persons(self):
        return self._person_collection

    @property
    def person2s(self):
        return self._person2_collection

    @property
    def rdf(self):
        return self._rdf_collection

    @property
    def sets(self):
        return self._sets_collection

    @property
    def maps(self):
        return self._maps_collection

    @property
    def properties(self):
        return self._properties_collection

    @property
    def preprocessors(self):
        return self._preprocessors

    @property
    def postprocessors(self):
        return self._postprocessors

    @property
    def authentication(self):
        return self._authentication

    @property
    def authorisation(self):
        return self._authorisation

    @property
    def default_oob(self):
        return self._default_oob

    @property
    def oobs(self):
        return self._oob

    @property
    def regex_templates(self):
        return self._regex_templates

    @property
    def dynamics(self):
        return self._dynamics_collection

    def load_binary(self, brain_configuration):
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading binary brain from [%s]" %
                         brain_configuration.binaries.binary_filename)
        try:
            start = datetime.datetime.now()
            gc.disable()
            f = open(brain_configuration.binaries.binary_filename, "rb")
            self._aiml_parser = pickle.load(f)
            gc.enable()
            f.close()
            stop = datetime.datetime.now()
            diff = stop - start
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Brain load took a total of %.2f sec" %
                             diff.total_seconds())
            load_aiml = False
        except Exception as e:
            logging.exception(e)
            if brain_configuration.binaries.load_aiml_on_binary_fail is True:
                load_aiml = True
            else:
                raise e

    def load_aiml(self, brain_configuration):
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading aiml source brain")
        self._aiml_parser.load_aiml(brain_configuration)

    def save_binary(self, brain_configuration):
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Saving binary brain to [%s]" %
                         brain_configuration.binaries.binary_filename)
        start = datetime.datetime.now()
        f = open(brain_configuration.binaries.binary_filename, "wb")
        pickle.dump(self._aiml_parser, f)
        f.close()
        stop = datetime.datetime.now()
        diff = stop - start
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Brain save took a total of %.2f sec" %
                         diff.total_seconds())

    def load(self, brain_configuration: BrainConfiguration):

        if brain_configuration.binaries.load_binary is True:
            self.load_binary(brain_configuration)

        self.load_aiml(brain_configuration)

        if brain_configuration.binaries.save_binary is True:
            self.save_binary(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading collections")
        self.load_collections(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading services")
        self.load_services(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading security services")
        self.load_security_services(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading oob processors")
        self.load_oob_processors(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading regex templates")
        self.load_regex_templates(brain_configuration)

        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading dynamics sets, maps and vars")
        self.load_dynamics(brain_configuration)

    def _load_denormals(self, brain_configuration):
        if brain_configuration.files.denormal is not None:
            total = self._denormal_collection.load_from_filename(
                brain_configuration.files.denormal)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d denormalisations", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for denormal")

    def _load_normals(self, brain_configuration):
        if brain_configuration.files.normal is not None:
            total = self._normal_collection.load_from_filename(
                brain_configuration.files.normal)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d normalisations", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for normal")

    def _load_genders(self, brain_configuration):
        if brain_configuration.files.gender is not None:
            total = self._gender_collection.load_from_filename(
                brain_configuration.files.gender)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d genderisations", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for gender")

    def _load_persons(self, brain_configuration):
        if brain_configuration.files.person is not None:
            total = self._person_collection.load_from_filename(
                brain_configuration.files.person)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d persons", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for person")

    def _load_person2s(self, brain_configuration):
        if brain_configuration.files.person2 is not None:
            total = self._person2_collection.load_from_filename(
                brain_configuration.files.person2)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d person2s", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for person2")

    def _load_properties(self, brain_configuration):
        if brain_configuration.files.properties is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.files.properties)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d properties", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for properties")

    def _load_rdf(self, brain_configuration):
        if brain_configuration.files.rdf_files is not None and brain_configuration.files.rdf_files.files is not None:
            total = self._rdf_collection.load(
                brain_configuration.files.rdf_files)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d rdf files", total)
        elif brain_configuration.files.triples is not None:
            total = self._rdf_collection.load_from_filename(
                brain_configuration.files.triples)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d triples", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for triples")

    def _load_sets(self, brain_configuration):
        total = self._sets_collection.load(brain_configuration.files.set_files)
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loaded a total of %d sets files", total)

    def _load_maps(self, brain_configuration):
        total = self._maps_collection.load(brain_configuration.files.map_files)
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loaded a total of %d maps files", total)

    def _load_preprocessors(self, brain_configuration):
        if brain_configuration.files.preprocessors is not None:
            total = self._preprocessors.load(
                brain_configuration.files.preprocessors)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d pre processors", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for pre processors")

    def _load_postprocessors(self, brain_configuration):
        if brain_configuration.files.postprocessors is not None:
            total = self._postprocessors.load(
                brain_configuration.files.postprocessors)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d post processors", total)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No configuration setting for post processors")

    def load_collections(self, brain_configuration):
        self._load_denormals(brain_configuration)
        self._load_normals(brain_configuration)
        self._load_genders(brain_configuration)
        self._load_persons(brain_configuration)
        self._load_person2s(brain_configuration)
        self._load_properties(brain_configuration)
        self._load_rdf(brain_configuration)
        self._load_sets(brain_configuration)
        self._load_maps(brain_configuration)
        self._load_preprocessors(brain_configuration)
        self._load_postprocessors(brain_configuration)

    def load_services(self, brain_configuration):
        ServiceFactory.preload_services(brain_configuration.services)

    def load_security_services(self, brain_configuration):
        if brain_configuration.security is not None:
            if brain_configuration.security.authentication is not None:
                if brain_configuration.security.authentication.classname is not None:
                    try:
                        classobject = ClassLoader.instantiate_class(
                            brain_configuration.security.authentication.
                            classname)
                        self._authentication = classobject(
                            brain_configuration.security.authentication)
                    except Exception as excep:
                        logging.exception(excep)
            else:
                if logging.getLogger().isEnabledFor(logging.DEBUG):
                    logging.debug("No authentication configuration defined")

            if brain_configuration.security.authorisation is not None:
                if brain_configuration.security.authorisation.classname is not None:
                    try:
                        classobject = ClassLoader.instantiate_class(
                            brain_configuration.security.authorisation.
                            classname)
                        self._authorisation = classobject(
                            brain_configuration.security.authorisation)
                    except Exception as excep:
                        logging.exception(excep)
            else:
                if logging.getLogger().isEnabledFor(logging.DEBUG):
                    logging.debug("No authorisation configuration defined")

        else:
            if logging.getLogger().isEnabledFor(logging.DEBUG):
                logging.debug(
                    "No security configuration defined, running open...")

    def load_dynamics(self, brain_configuration):
        if brain_configuration.dynamics is not None:
            self._dynamics_collection.load_from_configuration(
                brain_configuration.dynamics)
        else:
            if logging.getLogger().isEnabledFor(logging.DEBUG):
                logging.debug("No dynamics configuration defined...")

    def pre_process_question(self, bot, clientid, question):
        return self.preprocessors.process(bot, clientid, question)

    def parse_last_sentences_from_response(self, response):
        response = re.sub(r'<\s*br\s*/>\s*', ".", response)
        response = re.sub(r'<br></br>*', ".", response)
        sentences = response.split(".")
        sentences = [x for x in sentences if x]
        last_sentence = sentences[-1]
        that_pattern = TextUtils.strip_all_punctuation(last_sentence)
        that_pattern = that_pattern.strip()
        return that_pattern

    def load_oob_processors(self, brain_configuration):
        if brain_configuration.oob is not None:
            if brain_configuration.oob.default() is not None:
                try:
                    if logging.getLogger().isEnabledFor(logging.INFO):
                        logging.info("Loading default oob")
                    classobject = ClassLoader.instantiate_class(
                        brain_configuration.oob.default().classname)
                    self._default_oob = classobject()
                except Exception as excep:
                    logging.exception(excep)

            for oob_name in brain_configuration.oob.oobs():
                try:
                    if logging.getLogger().isEnabledFor(logging.INFO):
                        logging.info("Loading oob: %s" % oob_name)
                    classobject = ClassLoader.instantiate_class(
                        brain_configuration.oob.oob(oob_name).classname)
                    self._oob[oob_name] = classobject()
                except Exception as excep:
                    logging.exception(excep)

    def load_regex_templates(self, brain_configuration):
        if brain_configuration.files.regex_templates is not None:
            collection = PropertiesCollection()
            total = collection.load_from_filename(
                brain_configuration.files.regex_templates)
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Loaded a total of %d regex templates", total)

            for pair in collection.pairs:
                name = pair[0]
                pattern = pair[1]
                try:
                    self._regex_templates[name] = re.compile(pattern)
                except Exception:
                    if logging.getLogger().isEnabledFor(logging.INFO):
                        logging.error("Invalid regex template [%s]" % pattern)

    def regex_template(self, name):
        if name in self._regex_templates:
            return self._regex_templates[name]
        else:
            return None

    def strip_oob(self, response):
        m = re.compile("(.*)(<\s*oob\s*>.*<\/\s*oob\s*>)(.*)")
        g = m.match(response)
        if g is not None:
            front = g.group(1).strip()
            back = g.group(3).strip()
            response = ""
            if front != "":
                response = front + " "
            response += back
            oob = g.group(2)
            return response, oob
        return response, None

    def process_oob(self, bot, clientid, oob_command):

        oob_content = ET.fromstring(oob_command)

        if oob_content.tag == 'oob':
            for child in oob_content.findall('./'):
                if child.tag in self._oob:
                    oob_class = self._oob[child.tag]
                    return oob_class.process_out_of_bounds(
                        bot, clientid, child)
                else:
                    return self._default_oob.process_out_of_bounds(
                        bot, clientid, child)

        return ""

    def post_process_response(self, bot, clientid, response: str):
        return self.postprocessors.process(bot, clientid, response)

    def dump_tree(self):
        self._aiml_parser.pattern_parser.root.dump(tabs="")

    def ask_question(self,
                     bot,
                     clientid,
                     sentence,
                     srai=False,
                     brain_question_context=None):

        if brain_question_context is not None:
            brain_question_context.clientid = clientid
            brain_question_context.srai = srai
            brain_question_context.sentence = sentence

        if self.authentication is not None:
            if self.authentication.authenticate(clientid) is False:
                if logging.getLogger().isEnabledFor(logging.ERROR):
                    logging.error("[%s] failed authentication!")
                return self.authentication.configuration.denied_srai

        conversation = bot.get_conversation(clientid)

        topic_pattern = conversation.property("topic")
        if topic_pattern is None:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("No Topic pattern default to [*]")
            topic_pattern = "*"
        else:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Topic pattern = [%s]", topic_pattern)

        if brain_question_context is not None:
            brain_question_context.topic = topic_pattern

        try:
            that_question = conversation.previous_nth_question(1)
            that_sentence = that_question.current_sentence()

            # If the last response was valid, i.e not none and not empty string, then use
            # that as the that_pattern, otherwise we default to '*' as pattern
            if that_sentence.response is not None and that_sentence.response != '':
                that_pattern = self.parse_last_sentences_from_response(
                    that_sentence.response)
                if logging.getLogger().isEnabledFor(logging.INFO):
                    logging.info("That pattern = [%s]", that_pattern)
            else:
                if logging.getLogger().isEnabledFor(logging.INFO):
                    logging.info("That pattern, no response, default to [*]")
                that_pattern = "*"

        except Exception:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("No That pattern default to [*]")
            that_pattern = "*"

        if brain_question_context is not None:
            brain_question_context.that = that_pattern

        match_context = self._aiml_parser.match_sentence(
            bot,
            clientid,
            sentence,
            topic_pattern=topic_pattern,
            that_pattern=that_pattern)

        if match_context is not None:

            if brain_question_context is not None:
                brain_question_context.match_context = match_context

            template_node = match_context.template_node()
            if logging.getLogger().isEnabledFor(logging.DEBUG):
                logging.debug("AIML Parser evaluating template [%s]",
                              template_node.to_string())
            response = template_node.template.resolve(bot, clientid)

            if brain_question_context is not None:
                brain_question_context.raw_response = response

            if "<oob>" in response:
                response, oob = self.strip_oob(response)
                if oob is not None:
                    oob_response = self.process_oob(bot, clientid, oob)

                    if brain_question_context is not None:
                        brain_question_context.raw_response = response
                        brain_question_context.oob_response = oob_response

                    response = response + " " + oob_response

            return response

        return None
コード例 #19
0
ファイル: brain.py プロジェクト: Doshmaku/program-y
class Brain(object):

    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser()

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self.load(self._configuration)

    @property
    def configuration(self):
        return self._configuration

    @property
    def aiml_parser(self):
        return self._aiml_parser

    @property
    def denormals(self):
        return self._denormal_collection

    @property
    def normals(self):
        return self._normal_collection

    @property
    def genders(self):
        return self._gender_collection

    @property
    def persons(self):
        return self._person_collection

    @property
    def person2s(self):
        return self._person2_collection

    @property
    def predicates(self):
        return self._predicates_collection

    @property
    def pronounds(self):
        return self._pronouns_collection

    @property
    def triples(self):
        return self._triples_collection

    @property
    def sets(self):
        return self._sets_collection

    @property
    def maps(self):
        return self._maps_collection

    @property
    def properties(self):
        return self._properties_collection

    @property
    def preprocessors(self):
        return self._preprocessors

    @property
    def postprocessors(self):
        return self._postprocessors

    def load(self, brain_configuration: BrainConfiguration):
        self._aiml_parser.load_aiml(brain_configuration)
        self.load_collections(brain_configuration)
        self.load_services(brain_configuration)

    def _load_denormals(self, brain_configuration):
        if brain_configuration.denormal is not None:
            total = self._denormal_collection.load_from_filename(brain_configuration.denormal)
            logging.info("Loaded a total of %d denormalisations", total)
        else:
            logging.warning("No configuration setting for denormal")

    def _load_normals(self, brain_configuration):
        if brain_configuration.normal is not None:
            total = self._normal_collection.load_from_filename(brain_configuration.normal)
            logging.info("Loaded a total of %d normalisations", total)
        else:
            logging.warning("No configuration setting for normal")

    def _load_genders(self, brain_configuration):
        if brain_configuration.gender is not None:
            total = self._gender_collection.load_from_filename(brain_configuration.gender)
            logging.info("Loaded a total of %d genderisations", total)
        else:
            logging.warning("No configuration setting for gender")

    def _load_persons(self, brain_configuration):
        if brain_configuration.person is not None:
            total = self._person_collection.load_from_filename(brain_configuration.person)
            logging.info("Loaded a total of %d persons", total)
        else:
            logging.warning("No configuration setting for person")

    def _load_person2s(self, brain_configuration):
        if brain_configuration.person2 is not None:
            total = self._person2_collection.load_from_filename(brain_configuration.person2)
            logging.info("Loaded a total of %d person2s", total)
        else:
            logging.warning("No configuration setting for person2")

    def _load_predicates(self, brain_configuration):
        if brain_configuration.predicates is not None:
            total = self._predicates_collection.load_from_filename(brain_configuration.predicates)
            logging.info("Loaded a total of %d predicates", total)
        else:
            logging.warning("No configuration setting for predicates")

    def _load_pronouns(self, brain_configuration):
        if brain_configuration.pronouns is not None:
            total = self._pronouns_collection.load_from_filename(brain_configuration.pronouns)
            logging.info("Loaded a total of %d pronouns", total)
        else:
            logging.warning("No configuration setting for pronouns")

    def _load_properties(self, brain_configuration):
        if brain_configuration.properties is not None:
            total = self._properties_collection.load_from_filename(brain_configuration.properties)
            logging.info("Loaded a total of %d properties", total)
        else:
            logging.warning("No configuration setting for properties")

    def _load_triples(self, brain_configuration):
        if brain_configuration.triples is not None:
            total = self._properties_collection.load_from_filename(brain_configuration.triples)
            logging.info("Loaded a total of %d triples", total)
        else:
            logging.warning("No configuration setting for triples")

    def _load_sets(self, brain_configuration):
        if brain_configuration.set_files is not None:
            total = self._sets_collection.load(brain_configuration.set_files)
            logging.info("Loaded a total of %d sets files", total)
        else:
            logging.warning("No configuration setting for set files")

    def _load_maps(self, brain_configuration):
        if brain_configuration.map_files is not None:
            total = self._maps_collection.load(brain_configuration.map_files)
            logging.info("Loaded a total of %d maps files", total)
        else:
            logging.warning("No configuration setting for map files")

    def _load_preprocessors(self, brain_configuration):
        if brain_configuration.preprocessors is not None:
            total = self._preprocessors.load(brain_configuration.preprocessors)
            logging.info("Loaded a total of %d pre processors", total)
        else:
            logging.warning("No configuration setting for pre processors")

    def _load_postprocessors(self, brain_configuration):
        if brain_configuration.postprocessors is not None:
            total = self._postprocessors.load(brain_configuration.postprocessors)
            logging.info("Loaded a total of %d post processors", total)
        else:
            logging.warning("No configuration setting for post processors")

    def load_collections(self, brain_configuration):
        self._load_denormals(brain_configuration)
        self._load_normals(brain_configuration)
        self._load_genders(brain_configuration)
        self._load_persons(brain_configuration)
        self._load_person2s(brain_configuration)
        self._load_predicates(brain_configuration)
        self._load_pronouns(brain_configuration)
        self._load_properties(brain_configuration)
        self._load_triples(brain_configuration)
        self._load_sets(brain_configuration)
        self._load_maps(brain_configuration)
        self._load_preprocessors(brain_configuration)
        self._load_postprocessors(brain_configuration)

    def load_services(self, brain_configuration):
        ServiceFactory.preload_services(brain_configuration.services)

    def pre_process_question(self, bot, clientid, question):
        return self.preprocessors.process(bot, clientid, question)

    def ask_question(self, bot, clientid, sentence) -> str:

        conversation = bot.get_conversation(clientid)

        topic_pattern = conversation.predicate("topic")
        if topic_pattern is None:
            logging.info("No Topic pattern default to [*]")
            topic_pattern = "*"
        else:
            logging.info("Topic pattern = [%s]", topic_pattern)

        try:
            that_question = conversation.nth_question(2)
            that_sentence = that_question.current_sentence()

            # If the last response was valid, i.e not none and not empty string, then use
            # that as the that_pattern, otherwise we default to '*' as pattern
            if that_sentence.response is not None and that_sentence.response != '':
                that_pattern = TextUtils.strip_all_punctuation(that_sentence.response)
                logging.info("That pattern = [%s]", that_pattern)
            else:
                logging.info("That pattern, no response, default to [*]")
                that_pattern = "*"

        except Exception:
            logging.info("No That pattern default to [*]")
            that_pattern = "*"

        match_context =  self._aiml_parser.match_sentence(bot, clientid,
                                                        sentence,
                                                        topic_pattern=topic_pattern,
                                                        that_pattern=that_pattern)

        if match_context is not None:
            template_node = match_context.template_node()
            logging.debug("AIML Parser evaluating template [%s]", template_node.to_string())
            return template_node.template.resolve(bot, clientid)

        return None

    def post_process_response(self, bot, clientid, response: str):
        return self.postprocessors.process(bot, clientid, response)

    def dump_tree(self):
        self._aiml_parser.pattern_parser.root.dump(tabs="")

    def write_learnf_to_file(self, bot, clientid, pattern, topic, that, template):
        learnf_path = "%s/learnf%s" % (self._configuration.aiml_files.files, self._configuration.aiml_files.extension)
        logging.debug("Writing learnf to %s", learnf_path)

        if os.path.isfile(learnf_path) is False:
            file = open(learnf_path, "w+")
            file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            file.write('<aiml>\n')
            file.write('</aiml>\n')
            file.close()

        tree = ET.parse(learnf_path)
        root = tree.getroot()

        # Add our new element
        child = ET.Element("category")
        child.append(pattern)
        child.append(topic)
        child.append(that)
        child.append(template.xml_tree(bot, clientid))

        root.append(child)

        tree.write(learnf_path, method="xml")
コード例 #20
0
class AIMLParserTests(unittest.TestCase):

    def setUp(self):
        self.parser = AIMLParser(supress_warnings=True, stop_on_invalid=True)
        self.assertIsNotNone(self.parser)

    def test_parse_from_file_valid(self):
        filename = os.path.dirname(__file__)+ '/valid.aiml'
        self.parser.parse_from_file(filename)

    def test_parse_from_file_invalid(self):
        filename = os.path.dirname(__file__)+ '/invalid.aiml'
        self.parser.parse_from_file(filename)

    def test_crud(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text(
                """Blah Blah Blah
                """)

    def test_no_aiml(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                """)
        self.assertTrue(str(raised.exception).startswith("no element found:"))

    def test_no_content(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text(
                """
                """)
        self.assertTrue(str(raised.exception).startswith("no element found:"))

    def test_base_aiml_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no categories in aiml file")

    def test_base_aiml_topic_no_name(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, missing name attribute for topic")

    def test_base_aiml_topic_no_category(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no categories in topic")

    def test_base_aiml_topic_category_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no template node found in category")

    def test_base_aiml_topic_at_multiple_levels(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                            <topic name="test2" />
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, topic exists in category AND as parent node")

    def test_base_aiml_topic_category_no_template(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                            <pattern>*</pattern>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no template node found in category")

    def test_base_aiml_category_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no template node found in category")

    def test_base_aiml_category_no_template(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <pattern>*</pattern>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error, no template node found in category")

    def test_base_aiml_topic_empty_parent_node(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="">
                        <category>
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic name empty or null")

    def test_base_aiml_topic_with_something_else(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <xxxx>
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </xxxx>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Error unknown child node of topic, xxxx")

    def test_base_aiml_topic_empty_child_node1(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <topic name="" />
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic node text is empty")

    def test_base_aiml_topic_empty_child_node2(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <topic></topic>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic node text is empty")

    def test_base_aiml_that_empty_child_node(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <that></that>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "That node text is empty")

    def test_base_aiml_topic_category_template(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_topic_category_template_multi_line(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>
                            RESPONSE1,
                            RESPONSE2.
                            RESPONSE3
                        </template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE1, RESPONSE2. RESPONSE3")

    def test_base_aiml_category_template(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_that(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <topic>something</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "something")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_topic_that(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <topic>other</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "other")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_multiple_categories(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Hello</pattern>
                    <template>Hiya</template>
                </category>
                <category>
                    <pattern>Goodbye</pattern>
                    <template>See ya</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_a_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_and_out_of_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Welcome</pattern>
                    <template>Hello there</template>
                </category>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
                <category>
                    <pattern>Interesting</pattern>
                    <template>Yes</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(4, len(self.parser.pattern_parser.root.children))

        node1 = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node1)
        self.assertIsInstance(node1, PatternWordNode)
        self.assertEquals(node1.word, "Interesting")

        topic = node1.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node2 = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node2)
        self.assertIsInstance(node2, PatternWordNode)
        self.assertEquals(node2.word, "Goodbye")

        topic = node2.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node3 = self.parser.pattern_parser.root.children[2]
        self.assertIsNotNone(node3)
        self.assertIsInstance(node3, PatternWordNode)
        self.assertEquals(node3.word, "Hello")

        topic = node3.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node4 = self.parser.pattern_parser.root.children[3]
        self.assertIsNotNone(node4)
        self.assertIsInstance(node4, PatternWordNode)
        self.assertEquals(node4.word, "Welcome")

        topic = node4.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_match_sentence(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hiya</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump()

        context = self.parser.match_sentence(None, "test", Sentence("HELLO"), "*", "*")
        self.assertIsNotNone(context)
        self.assertEqual("Hiya", context.template_node().template.resolve(None, None))
コード例 #21
0
 def setUp(self):
     self.parser = AIMLParser(supress_warnings=True, stop_on_invalid=True)
     self.assertIsNotNone(self.parser)
コード例 #22
0
ファイル: brain.py プロジェクト: vladimirmyshkovski/program-y
class Brain(object):
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser(self)

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self._authentication = None
        self._authorisation = None

        self._default_oob = None
        self._oob = {}

        self.load(self._configuration)

    @property
    def configuration(self):
        return self._configuration

    @property
    def aiml_parser(self):
        return self._aiml_parser

    @property
    def denormals(self):
        return self._denormal_collection

    @property
    def normals(self):
        return self._normal_collection

    @property
    def genders(self):
        return self._gender_collection

    @property
    def persons(self):
        return self._person_collection

    @property
    def person2s(self):
        return self._person2_collection

    @property
    def predicates(self):
        return self._predicates_collection

    @property
    def pronouns(self):
        return self._pronouns_collection

    @property
    def triples(self):
        return self._triples_collection

    @property
    def sets(self):
        return self._sets_collection

    @property
    def maps(self):
        return self._maps_collection

    @property
    def properties(self):
        return self._properties_collection

    @property
    def preprocessors(self):
        return self._preprocessors

    @property
    def postprocessors(self):
        return self._postprocessors

    @property
    def authentication(self):
        return self._authentication

    @property
    def authorisation(self):
        return self._authorisation

    @property
    def default_oob(self):
        return self._default_oob

    @property
    def oobs(self):
        return self._oob

    def load_binary(self, brain_configuration):
        logging.info("Loading binary brain from [%s]" %
                     brain_configuration.binaries.binary_filename)
        try:
            start = datetime.datetime.now()
            gc.disable()
            f = open(brain_configuration.binaries.binary_filename, "rb")
            self._aiml_parser = pickle.load(f)
            gc.enable()
            f.close()
            stop = datetime.datetime.now()
            diff = stop - start
            logging.info("Brain load took a total of %.2f sec" %
                         diff.total_seconds())
            load_aiml = False
        except Exception as e:
            logging.exception(e)
            if brain_configuration.binaries.load_aiml_on_binary_fail is True:
                load_aiml = True
            else:
                raise e

    def load_aiml(self, brain_configuration):
        logging.info("Loading aiml source brain")
        self._aiml_parser.load_aiml(brain_configuration)

    def save_binary(self, brain_configuration):
        logging.info("Saving binary brain to [%s]" %
                     brain_configuration.binaries.binary_filename)
        start = datetime.datetime.now()
        f = open(brain_configuration.binaries.binary_filename, "wb")
        pickle.dump(self._aiml_parser, f)
        f.close()
        stop = datetime.datetime.now()
        diff = stop - start
        logging.info("Brain save took a total of %.2f sec" %
                     diff.total_seconds())

    def load(self, brain_configuration: BrainConfiguration):

        if brain_configuration.binaries.load_binary is True:
            self.load_binary(brain_configuration)

        self.load_aiml(brain_configuration)

        if brain_configuration.binaries.save_binary is True:
            self.save_binary(brain_configuration)

        logging.info("Loading collections")
        self.load_collections(brain_configuration)

        logging.info("Loading services")
        self.load_services(brain_configuration)

        logging.info("Loading security services")
        self.load_security_services(brain_configuration)

        logging.info("Loading oob processors")
        self.load_oob_processors(brain_configuration)

    def _load_denormals(self, brain_configuration):
        if brain_configuration.files.denormal is not None:
            total = self._denormal_collection.load_from_filename(
                brain_configuration.files.denormal)
            logging.info("Loaded a total of %d denormalisations", total)
        else:
            logging.warning("No configuration setting for denormal")

    def _load_normals(self, brain_configuration):
        if brain_configuration.files.normal is not None:
            total = self._normal_collection.load_from_filename(
                brain_configuration.files.normal)
            logging.info("Loaded a total of %d normalisations", total)
        else:
            logging.warning("No configuration setting for normal")

    def _load_genders(self, brain_configuration):
        if brain_configuration.files.gender is not None:
            total = self._gender_collection.load_from_filename(
                brain_configuration.files.gender)
            logging.info("Loaded a total of %d genderisations", total)
        else:
            logging.warning("No configuration setting for gender")

    def _load_persons(self, brain_configuration):
        if brain_configuration.files.person is not None:
            total = self._person_collection.load_from_filename(
                brain_configuration.files.person)
            logging.info("Loaded a total of %d persons", total)
        else:
            logging.warning("No configuration setting for person")

    def _load_person2s(self, brain_configuration):
        if brain_configuration.files.person2 is not None:
            total = self._person2_collection.load_from_filename(
                brain_configuration.files.person2)
            logging.info("Loaded a total of %d person2s", total)
        else:
            logging.warning("No configuration setting for person2")

    def _load_predicates(self, brain_configuration):
        if brain_configuration.files.predicates is not None:
            total = self._predicates_collection.load_from_filename(
                brain_configuration.files.predicates)
            logging.info("Loaded a total of %d predicates", total)
        else:
            logging.warning("No configuration setting for predicates")

    def _load_pronouns(self, brain_configuration):
        if brain_configuration.files.pronouns is not None:
            total = self._pronouns_collection.load_from_filename(
                brain_configuration.files.pronouns)
            logging.info("Loaded a total of %d pronouns", total)
        else:
            logging.warning("No configuration setting for pronouns")

    def _load_properties(self, brain_configuration):
        if brain_configuration.files.properties is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.files.properties)
            logging.info("Loaded a total of %d properties", total)
        else:
            logging.warning("No configuration setting for properties")

    def _load_triples(self, brain_configuration):
        if brain_configuration.files.triples is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.files.triples)
            logging.info("Loaded a total of %d triples", total)
        else:
            logging.warning("No configuration setting for triples")

    def _load_sets(self, brain_configuration):
        total = self._sets_collection.load(brain_configuration.files.set_files)
        logging.info("Loaded a total of %d sets files", total)

    def _load_maps(self, brain_configuration):
        total = self._maps_collection.load(brain_configuration.files.map_files)
        logging.info("Loaded a total of %d maps files", total)

    def _load_preprocessors(self, brain_configuration):
        if brain_configuration.files.preprocessors is not None:
            total = self._preprocessors.load(
                brain_configuration.files.preprocessors)
            logging.info("Loaded a total of %d pre processors", total)
        else:
            logging.warning("No configuration setting for pre processors")

    def _load_postprocessors(self, brain_configuration):
        if brain_configuration.files.postprocessors is not None:
            total = self._postprocessors.load(
                brain_configuration.files.postprocessors)
            logging.info("Loaded a total of %d post processors", total)
        else:
            logging.warning("No configuration setting for post processors")

    def load_collections(self, brain_configuration):
        self._load_denormals(brain_configuration)
        self._load_normals(brain_configuration)
        self._load_genders(brain_configuration)
        self._load_persons(brain_configuration)
        self._load_person2s(brain_configuration)
        self._load_predicates(brain_configuration)
        self._load_pronouns(brain_configuration)
        self._load_properties(brain_configuration)
        self._load_triples(brain_configuration)
        self._load_sets(brain_configuration)
        self._load_maps(brain_configuration)
        self._load_preprocessors(brain_configuration)
        self._load_postprocessors(brain_configuration)

    def load_services(self, brain_configuration):
        ServiceFactory.preload_services(brain_configuration.services)

    def load_security_services(self, brain_configuration):
        if brain_configuration.security is not None:
            if brain_configuration.security.authentication is not None:
                if brain_configuration.security.authentication.classname is not None:
                    try:
                        classobject = ClassLoader.instantiate_class(
                            brain_configuration.security.authentication.
                            classname)
                        self._authentication = classobject(
                            brain_configuration.security.authentication)
                    except Exception as excep:
                        logging.exception(excep)
            else:
                logging.debug("No authentication configuration defined")

            if brain_configuration.security.authorisation is not None:
                if brain_configuration.security.authorisation.classname is not None:
                    try:
                        classobject = ClassLoader.instantiate_class(
                            brain_configuration.security.authorisation.
                            classname)
                        self._authorisation = classobject(
                            brain_configuration.security.authorisation)
                    except Exception as excep:
                        logging.exception(excep)
            else:
                logging.debug("No authorisation configuration defined")

        else:
            logging.debug("No security configuration defined, running open...")

    def pre_process_question(self, bot, clientid, question):
        return self.preprocessors.process(bot, clientid, question)

    def ask_question(self, bot, clientid, sentence) -> str:

        if self.authentication is not None:
            if self.authentication.authenticate(clientid) is False:
                logging.error("[%s] failed authentication!")
                return self.authentication.configuration.denied_srai

        conversation = bot.get_conversation(clientid)

        topic_pattern = conversation.predicate("topic")
        if topic_pattern is None:
            logging.info("No Topic pattern default to [*]")
            topic_pattern = "*"
        else:
            logging.info("Topic pattern = [%s]", topic_pattern)

        try:
            that_question = conversation.nth_question(2)
            that_sentence = that_question.current_sentence()

            # If the last response was valid, i.e not none and not empty string, then use
            # that as the that_pattern, otherwise we default to '*' as pattern
            if that_sentence.response is not None and that_sentence.response != '':
                that_pattern = TextUtils.strip_all_punctuation(
                    that_sentence.response)
                logging.info("That pattern = [%s]", that_pattern)
            else:
                logging.info("That pattern, no response, default to [*]")
                that_pattern = "*"

        except Exception:
            logging.info("No That pattern default to [*]")
            that_pattern = "*"

        match_context = self._aiml_parser.match_sentence(
            bot,
            clientid,
            sentence,
            topic_pattern=topic_pattern,
            that_pattern=that_pattern)

        if match_context is not None:
            template_node = match_context.template_node()
            logging.debug("AIML Parser evaluating template [%s]",
                          template_node.to_string())
            response = template_node.template.resolve(bot, clientid)
            if "<oob>" in response:
                response, oob = self.strip_oob(response)
                if oob is not None:
                    oob_response = self.process_oob(bot, clientid, oob)
                    response = response + " " + oob_response
            return response

        return None

    def load_oob_processors(self, brain_configuration):
        if brain_configuration.oob is not None:
            if brain_configuration.oob.default() is not None:
                try:
                    logging.info("Loading default oob")
                    classobject = ClassLoader.instantiate_class(
                        brain_configuration.oob.default().classname)
                    self._default_oob = classobject()
                except Exception as excep:
                    logging.exception(excep)

            for oob_name in brain_configuration.oob.oobs():
                try:
                    logging.info("Loading oob: %s" % oob_name)
                    classobject = ClassLoader.instantiate_class(
                        brain_configuration.oob.oob(oob_name).classname)
                    self._oob[oob_name] = classobject()
                except Exception as excep:
                    logging.exception(excep)

    def strip_oob(self, response):
        m = re.compile("(.*)(<\s*oob\s*>.*<\/\s*oob\s*>)(.*)")
        g = m.match(response)
        if g is not None:
            front = g.group(1).strip()
            back = g.group(3).strip()
            response = ""
            if front != "":
                response = front + " "
            response += back
            oob = g.group(2)
            return response, oob
        return response, None

    def process_oob(self, bot, clientid, oob_command):

        oob_content = ET.fromstring(oob_command)

        if oob_content.tag == 'oob':
            for tag in oob_content:
                if tag in self._oob:
                    oob_class = self._oob[tag]
                    return oob_class.process_out_of_bounds(bot, clientid, tag)
                else:
                    return self._default_oob.process_out_of_bounds(
                        bot, clientid, tag)

        return ""

    def post_process_response(self, bot, clientid, response: str):
        return self.postprocessors.process(bot, clientid, response)

    def dump_tree(self):
        self._aiml_parser.pattern_parser.root.dump(tabs="")
コード例 #23
0
class AIMLParserTests(unittest.TestCase):
    def setUp(self):
        self.parser = AIMLParser(supress_warnings=True, stop_on_invalid=True)
        self.assertIsNotNone(self.parser)

    def test_parse_from_file_valid(self):
        filename = os.path.dirname(__file__) + '/valid.aiml'
        self.parser.parse_from_file(filename)

    def test_parse_from_file_invalid(self):
        filename = os.path.dirname(__file__) + '/invalid.aiml'
        self.parser.parse_from_file(filename)

    def test_crud(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text("""Blah Blah Blah
                """)

    def test_no_aiml(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                """)
        self.assertTrue(str(raised.exception).startswith("no element found:"))

    def test_no_content(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text("""
                """)
        self.assertTrue(str(raised.exception).startswith("no element found:"))

    def test_base_aiml_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no categories in aiml file")

    def test_base_aiml_topic_no_name(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, missing name attribute for topic")

    def test_base_aiml_topic_no_category(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no categories in topic")

    def test_base_aiml_topic_category_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no template node found in category")

    def test_base_aiml_topic_at_multiple_levels(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                            <topic name="test2" />
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, topic exists in category AND as parent node")

    def test_base_aiml_topic_category_no_template(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <category>
                            <pattern>*</pattern>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no template node found in category")

    def test_base_aiml_category_no_content(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no template node found in category")

    def test_base_aiml_category_no_template(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <pattern>*</pattern>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error, no template node found in category")

    def test_base_aiml_topic_empty_parent_node(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="">
                        <category>
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </category>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic name empty or null")

    def test_base_aiml_topic_with_something_else(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <topic name="test">
                        <xxxx>
                            <pattern>*</pattern>
                            <template>RESPONSE</template>
                        </xxxx>
                    </topic>
                </aiml>
                """)
        self.assertEqual(raised.exception.message,
                         "Error unknown child node of topic, xxxx")

    def test_base_aiml_topic_empty_child_node1(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <topic name="" />
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic node text is empty")

    def test_base_aiml_topic_empty_child_node2(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <topic></topic>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "Topic node text is empty")

    def test_base_aiml_that_empty_child_node(self):
        with self.assertRaises(ParserException) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                <aiml>
                    <category>
                        <that></that>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </aiml>
                """)
        self.assertEqual(raised.exception.message, "That node text is empty")

    def test_base_aiml_topic_category_template(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE")

    def test_base_aiml_topic_category_template_multi_line(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>
                            RESPONSE1,
                            RESPONSE2.
                            RESPONSE3
                        </template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE1, RESPONSE2. RESPONSE3")

    def test_base_aiml_category_template(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE")

    def test_base_aiml_category_template_that(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE")

    def test_base_aiml_category_template_topic(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <topic>something</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "something")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE")

    def test_base_aiml_category_template_topic_that(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <topic>other</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "other")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"),
                         "RESPONSE")

    def test_base_aiml_multiple_categories(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Hello</pattern>
                    <template>Hiya</template>
                </category>
                <category>
                    <pattern>Goodbye</pattern>
                    <template>See ya</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_a_topic(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_and_out_of_topic(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Welcome</pattern>
                    <template>Hello there</template>
                </category>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
                <category>
                    <pattern>Interesting</pattern>
                    <template>Yes</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(4, len(self.parser.pattern_parser.root.children))

        node1 = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node1)
        self.assertIsInstance(node1, PatternWordNode)
        self.assertEquals(node1.word, "Interesting")

        topic = node1.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node2 = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node2)
        self.assertIsInstance(node2, PatternWordNode)
        self.assertEquals(node2.word, "Goodbye")

        topic = node2.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node3 = self.parser.pattern_parser.root.children[2]
        self.assertIsNotNone(node3)
        self.assertIsInstance(node3, PatternWordNode)
        self.assertEquals(node3.word, "Hello")

        topic = node3.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node4 = self.parser.pattern_parser.root.children[3]
        self.assertIsNotNone(node4)
        self.assertIsInstance(node4, PatternWordNode)
        self.assertEquals(node4.word, "Welcome")

        topic = node4.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_match_sentence(self):

        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hiya</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump()

        context = self.parser.match_sentence(None, "test", Sentence("HELLO"),
                                             "*", "*")
        self.assertIsNotNone(context)
        self.assertEqual("Hiya",
                         context.template_node().template.resolve(None, None))

    def test_inline_br_html(self):

        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hello  <br/> World</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump(output_func=print)

    def test_inline_bold_html(self):

        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hello <bold>You</bold> World</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump(output_func=print)

    def test_iset(self):

        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Hello</pattern>
                    <template>Hi There</template>
                </category>
                <category>
                    <pattern># <iset>who, what</iset> are you</pattern>
                    <template>OK thanks</template>
                </category>
                <category>
                    <pattern># <iset>who, what</iset> is he</pattern>
                    <template>OK thanks</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump(output_func=print)
コード例 #24
0
class Brain(object):
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser()

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self.load(self._configuration)

    @property
    def aiml_parser(self):
        return self._aiml_parser

    @property
    def denormals(self):
        return self._denormal_collection

    @property
    def normals(self):
        return self._normal_collection

    @property
    def genders(self):
        return self._gender_collection

    @property
    def persons(self):
        return self._person_collection

    @property
    def person2s(self):
        return self._person2_collection

    @property
    def predicates(self):
        return self._predicates_collection

    @property
    def pronounds(self):
        return self._pronouns_collection

    @property
    def triples(self):
        return self._triples_collection

    @property
    def sets(self):
        return self._sets_collection

    @property
    def maps(self):
        return self._maps_collection

    @property
    def properties(self):
        return self._properties_collection

    @property
    def preprocessors(self):
        return self._preprocessors

    @property
    def postprocessors(self):
        return self._postprocessors

    def load(self, brain_configuration: BrainConfiguration):
        self._aiml_parser.load_aiml(brain_configuration)
        self.load_collections(brain_configuration)

    def load_collections(self, brain_configuration):
        if brain_configuration.denormal is not None:
            total = self._denormal_collection.load_from_filename(
                brain_configuration.denormal)
            logging.info("Loaded a total of %d denormalisations" % (total))
        else:
            logging.warning("No configuration setting for denormal")

        if brain_configuration.normal is not None:
            total = self._normal_collection.load_from_filename(
                brain_configuration.normal)
            logging.info("Loaded a total of %d normalisations" % (total))
        else:
            logging.warning("No configuration setting for normal")

        if brain_configuration.gender is not None:
            total = self._gender_collection.load_from_filename(
                brain_configuration.gender)
            logging.info("Loaded a total of %d genderisations" % (total))
        else:
            logging.warning("No configuration setting for gender")

        if brain_configuration.person is not None:
            total = self._person_collection.load_from_filename(
                brain_configuration.person)
            logging.info("Loaded a total of %d persons" % (total))
        else:
            logging.warning("No configuration setting for person")

        if brain_configuration.person2 is not None:
            total = self._person2_collection.load_from_filename(
                brain_configuration.person2)
            logging.info("Loaded a total of %d person2s" % (total))
        else:
            logging.warning("No configuration setting for person2")

        if brain_configuration.predicates is not None:
            total = self._predicates_collection.load_from_filename(
                brain_configuration.predicates)
            logging.info("Loaded a total of %d predicates" % (total))
        else:
            logging.warning("No configuration setting for predicates")

        if brain_configuration.pronouns is not None:
            total = self._pronouns_collection.load_from_filename(
                brain_configuration.pronouns)
            logging.info("Loaded a total of %d pronouns" % (total))
        else:
            logging.warning("No configuration setting for pronouns")

        if brain_configuration.properties is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.properties)
            logging.info("Loaded a total of %d properties" % (total))
        else:
            logging.warning("No configuration setting for properties")

        if brain_configuration.triples is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.triples)
            logging.info("Loaded a total of %d triples" % (total))
        else:
            logging.warning("No configuration setting for triples")

        if brain_configuration.set_files is not None:
            total = self._sets_collection.load(brain_configuration.set_files)
            logging.info("Loaded a total of %d sets files" % (total))
        else:
            logging.warning("No configuration setting for set files")

        if brain_configuration.map_files is not None:
            total = self._maps_collection.load(brain_configuration.map_files)
            logging.info("Loaded a total of %d maps files" % (total))
        else:
            logging.warning("No configuration setting for map files")

        if brain_configuration.preprocessors is not None:
            total = self._preprocessors.load(brain_configuration.preprocessors)
            logging.info("Loaded a total of %d pre processors" % (total))
        else:
            logging.warning("No configuration setting for pre processors")

        if brain_configuration.postprocessors is not None:
            total = self._postprocessors.load(
                brain_configuration.postprocessors)
            logging.info("Loaded a total of %d post processors" % (total))
        else:
            logging.warning("No configuration setting for post processors")

    def pre_process_question(self, question):
        return self.preprocessors.process(question)

    def ask_question(self, bot, clientid, sentence) -> str:

        conversation = bot.get_conversation(clientid)

        try:
            topic_pattern = conversation.predicate("topic")
        except:
            topic_pattern = "*"

        try:
            that_question = conversation.nth_question(2)
            that_sentence = that_question.current_sentence()
            that_pattern = that_sentence.text()
        except:
            that_pattern = "*"

        return self._aiml_parser.match_sentence(bot,
                                                clientid,
                                                sentence,
                                                topic_pattern=topic_pattern,
                                                that_pattern=that_pattern)

    def post_process_response(self, response: str):
        return self.postprocessors.process(response)

    def dump_tree(self):
        self._aiml_parser.pattern_parser.root.dump(tabs="")

    def write_learnf_to_file(self, bot, clientid, pattern, topic, that,
                             template):
        learnf_path = "%s/learnf%s" % (
            self._configuration.aiml_files.files,
            self._configuration.aiml_files.extension)
        logging.debug("Writing learnf to %s" % learnf_path)

        import os.path
        if os.path.isfile(learnf_path) is False:
            file = open(learnf_path, "w+")
            file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            file.write('<aiml>\n')
            file.write('</aiml>\n')
            file.close()

        tree = ET.parse(learnf_path)
        root = tree.getroot()

        # Add our new element
        child = ET.Element("category")
        child.append(pattern)
        child.append(topic)
        child.append(that)
        child.append(template.xml_tree(bot, clientid))

        root.append(child)

        tree.write(learnf_path, method="xml")
コード例 #25
0
 def test_check_aiml_tag_no_aiml(self):
     aiml = None
     with self.assertRaises(ParserException):
         tag_name, namespace = AIMLParser.check_aiml_tag(aiml)
コード例 #26
0
 def load_aiml_parser(self):
     self._load_pattern_nodes()
     self._load_template_nodes()
     return AIMLParser(self)
コード例 #27
0
 def setUp(self):
     self.parser = AIMLParser()
     self.assertIsNotNone(self.parser)
コード例 #28
0
 def setUp(self):
     self._dump_graph = True
     self.graph = PatternGraph()
     self.matcher = AIMLParser()
コード例 #29
0
 def setUp(self):
     self._clientid = "testid"
     self._brain = Brain(BrainConfiguration())
     self._bot = Bot(self._brain, BotConfiguration())
     self._aiml_parser = AIMLParser(self._brain)
コード例 #30
0
 def setUp(self):
     self.parser = AIMLParser(supress_warnings=True, stop_on_invalid=True)
     self.assertIsNotNone(self.parser)
コード例 #31
0
class AIMLParserErrorTests(unittest.TestCase):
    def setUp(self):
        config = BrainConfiguration()
        config.files.aiml_files._errors = "/tmp/errors.txt"

        test_brain = Brain(configuration=config)
        self.parser = AIMLParser(brain=test_brain)
        self.parser.create_debug_storage(config)
        self.assertIsNotNone(self.parser)

    def test_parse_from_file_invalid(self):
        filename = os.path.dirname(__file__) + '/invalid.aiml'
        self.parser.parse_from_file(filename)

    def test_no_content(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text("""
                """)

    def test_crud(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text("""Blah Blah Blah
                """)

    def test_no_aiml(self):
        with self.assertRaises(ParseError) as raised:
            self.parser.parse_from_text(
                """<?xml version="1.0" encoding="UTF-8"?>
                """)
        self.assertTrue(str(raised.exception).startswith("no element found:"))

    def test_base_aiml_category_no_content(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, no template node found in category\n",
                          self.parser._errors[0])

    def test_base_aiml_category_no_template(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, no template node found in category\n",
                          self.parser._errors[0])

    def test_base_aiml_topic_empty_parent_node(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="">
                    <category>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Topic name empty or null\n", self.parser._errors[0])

    def test_base_aiml_topic_with_something_else(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <xxxx>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </xxxx>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error unknown child node of topic, xxxx\n",
                          self.parser._errors[0])

    def test_base_aiml_topic_empty_child_node1(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <topic name="" />
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Topic node text is empty\n", self.parser._errors[0])

    def test_base_aiml_topic_empty_child_node2(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <topic></topic>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Topic node text is empty\n", self.parser._errors[0])

    def test_base_aiml_that_empty_child_node(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <that></that>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("That node text is empty\n", self.parser._errors[0])

    def test_base_aiml_topic_no_name(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, missing name attribute for topic\n",
                          self.parser._errors[0])

    def test_base_aiml_topic_no_category(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, no categories in topic\n",
                          self.parser._errors[0])

    def test_base_aiml_topic_category_no_content(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, no template node found in category\n",
                          self.parser._errors[0])

    def test_base_aiml_topic_at_multiple_levels(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <topic name="test2" />
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals(
            "Error, topic exists in category AND as parent node\n",
            self.parser._errors[0])

    def test_base_aiml_topic_category_no_template(self):
        self.parser.parse_from_text("""<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser._errors)
        self.assertEquals(1, len(self.parser._errors))
        self.assertEquals("Error, no template node found in category\n",
                          self.parser._errors[0])
コード例 #32
0
ファイル: base.py プロジェクト: Doshmaku/program-y
 def setUp(self):
     self._dump_graph = True
     self.graph = PatternGraph()
     self.matcher =  AIMLParser()
コード例 #33
0
class AIMLParserTests(unittest.TestCase):

    def setUp(self):
        self.parser = AIMLParser()
        self.assertIsNotNone(self.parser)

    def test_tag_name_from_namespace(self):
        tag, namespace = self.parser.tag_and_namespace_from_text("aiml")
        self.assertEquals("aiml", tag)
        self.assertIsNone(namespace)

        tag, namespace = self.parser.tag_and_namespace_from_text("{http://alicebot.org/2001/AIML}aiml")
        self.assertEquals("aiml", tag)
        self.assertEquals("{http://alicebot.org/2001/AIML}", namespace)

    def test_parse_from_file_valid(self):
        filename = os.path.dirname(__file__)+ '/valid.aiml'
        self.parser.parse_from_file(filename)

    def test_aiml_with_namespace(self):
        self.parser.parse_from_text(
        """<?xml version="1.0" encoding="ISO-8859-1"?>
            <aiml version="1.01"
                  xmlns="http://alicebot.org/2001/AIML"
                  xmlns:aiml="http://alicebot.org/2001/AIML"
                  xmlns:html="http://www.w3.org/TR/REC-html40">
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
        """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_topic_category_template(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>RESPONSE</template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_topic_category_template_multi_line(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>*</pattern>
                        <template>
                            RESPONSE1,
                            RESPONSE2.
                            RESPONSE3
                        </template>
                    </category>
                </topic>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE1, RESPONSE2. RESPONSE3")

    def test_base_aiml_category_template(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_that(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <topic>something</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "something")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        template = that.star.template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_category_template_topic_that(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>*</pattern>
                    <that>something</that>
                    <topic>other</topic>
                    <template>RESPONSE</template>
                </category>
            </aiml>
            """)

        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertTrue(self.parser.pattern_parser.root.has_one_or_more())

        node = self.parser.pattern_parser.root.star
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternOneOrMoreWildCardNode)
        self.assertEquals(node.wildcard, "*")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "other")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertEqual(len(that.children), 1)
        self.assertIsNotNone(that.children[0])
        self.assertIsInstance(that.children[0], PatternWordNode)
        self.assertEqual(that.children[0].word, "something")

        template = that.children[0].template
        self.assertIsNotNone(template)
        self.assertIsInstance(template, PatternTemplateNode)
        self.assertEqual(template.template.resolve(bot=None, clientid="test"), "RESPONSE")

    def test_base_aiml_multiple_categories(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Hello</pattern>
                    <template>Hiya</template>
                </category>
                <category>
                    <pattern>Goodbye</pattern>
                    <template>See ya</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertIsInstance(self.parser.pattern_parser.root, PatternRootNode)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_a_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(2, len(self.parser.pattern_parser.root.children))

        node = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Hello")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node)
        self.assertIsInstance(node, PatternWordNode)
        self.assertEquals(node.word, "Goodbye")

        topic = node.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_base_aiml_multiple_categories_in_and_out_of_topic(self):
        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Welcome</pattern>
                    <template>Hello there</template>
                </category>
                <topic name="test">
                    <category>
                        <pattern>Hello</pattern>
                        <template>Hiya</template>
                    </category>
                    <category>
                        <pattern>Goodbye</pattern>
                        <template>See ya</template>
                    </category>
                </topic>
                <category>
                    <pattern>Interesting</pattern>
                    <template>Yes</template>
                </category>
            </aiml>
            """)
        self.assertIsNotNone(self.parser.pattern_parser.root)
        self.assertEqual(4, len(self.parser.pattern_parser.root.children))

        node1 = self.parser.pattern_parser.root.children[0]
        self.assertIsNotNone(node1)
        self.assertIsInstance(node1, PatternWordNode)
        self.assertEquals(node1.word, "Interesting")

        topic = node1.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node2 = self.parser.pattern_parser.root.children[1]
        self.assertIsNotNone(node2)
        self.assertIsInstance(node2, PatternWordNode)
        self.assertEquals(node2.word, "Goodbye")

        topic = node2.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node3 = self.parser.pattern_parser.root.children[2]
        self.assertIsNotNone(node3)
        self.assertIsInstance(node3, PatternWordNode)
        self.assertEquals(node3.word, "Hello")

        topic = node3.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertEqual(len(topic.children), 1)
        self.assertIsNotNone(topic.children[0])
        self.assertIsInstance(topic.children[0], PatternWordNode)
        self.assertEqual(topic.children[0].word, "test")

        that = topic.children[0].that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

        node4 = self.parser.pattern_parser.root.children[3]
        self.assertIsNotNone(node4)
        self.assertIsInstance(node4, PatternWordNode)
        self.assertEquals(node4.word, "Welcome")

        topic = node4.topic
        self.assertIsNotNone(topic)
        self.assertIsInstance(topic, PatternTopicNode)
        self.assertTrue(topic.has_one_or_more())
        self.assertIsInstance(topic.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(topic.star.wildcard, "*")

        that = topic.star.that
        self.assertIsNotNone(that)
        self.assertIsInstance(that, PatternThatNode)
        self.assertTrue(that.has_one_or_more())
        self.assertIsInstance(that.star, PatternOneOrMoreWildCardNode)
        self.assertEquals(that.star.wildcard, "*")

    def test_match_sentence(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hiya</template>
                </category>
            </aiml>
            """)

        self.parser.pattern_parser.dump()

        bot = Bot(Brain(BrainConfiguration()), config=BotConfiguration())

        context = self.parser.match_sentence(bot, "test", Sentence("HELLO"), "*", "*")
        self.assertIsNotNone(context)
        self.assertEqual("Hiya", context.template_node().template.resolve(None, None))

    def test_inline_br_html(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hello  <br/> World</template>
                </category>
            </aiml>
            """)

    def test_inline_bold_html(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>HELLO</pattern>
                    <template>Hello <bold>You</bold> World</template>
                </category>
            </aiml>
            """)

    def test_iset(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <category>
                    <pattern>Hello</pattern>
                    <template>Hi There</template>
                </category>
                <category>
                    <pattern># <iset>who, what</iset> are you</pattern>
                    <template>OK thanks</template>
                </category>
                <category>
                    <pattern># <iset>who, what</iset> is he</pattern>
                    <template>OK thanks</template>
                </category>
            </aiml>
            """)

    def test_duplicate_topics(self):

        self.parser.parse_from_text(
            """<?xml version="1.0" encoding="UTF-8"?>
            <aiml>
                <topic name="TOPIC1">
                    <category>
                        <pattern>*</pattern>
                        <template>
                            Test Text
                        </template>
                    </category>
                </topic>
                <topic name="TOPIC2">
                    <category>
                        <pattern>*</pattern>
                        <template>
                            Test Text
                        </template>
                    </category>
                </topic>
            </aiml>
            """)
コード例 #34
0
ファイル: brain.py プロジェクト: rollingstone/program-y
class Brain(object):
    def __init__(self, configuration: BrainConfiguration):
        self._configuration = configuration
        self._aiml_parser = AIMLParser()

        self._denormal_collection = DenormalCollection()
        self._normal_collection = NormalCollection()
        self._gender_collection = GenderCollection()
        self._person_collection = PersonCollection()
        self._person2_collection = PersonCollection()
        self._predicates_collection = PredicatesCollection()
        self._pronouns_collection = PronounsCollection()
        self._triples_collection = TriplesCollection()
        self._sets_collection = SetCollection()
        self._maps_collection = MapCollection()
        self._properties_collection = PropertiesCollection()

        self._preprocessors = ProcessorLoader()
        self._postprocessors = ProcessorLoader()

        self.load(self._configuration)

    @property
    def configuration(self):
        return self._configuration

    @property
    def aiml_parser(self):
        return self._aiml_parser

    @property
    def denormals(self):
        return self._denormal_collection

    @property
    def normals(self):
        return self._normal_collection

    @property
    def genders(self):
        return self._gender_collection

    @property
    def persons(self):
        return self._person_collection

    @property
    def person2s(self):
        return self._person2_collection

    @property
    def predicates(self):
        return self._predicates_collection

    @property
    def pronounds(self):
        return self._pronouns_collection

    @property
    def triples(self):
        return self._triples_collection

    @property
    def sets(self):
        return self._sets_collection

    @property
    def maps(self):
        return self._maps_collection

    @property
    def properties(self):
        return self._properties_collection

    @property
    def preprocessors(self):
        return self._preprocessors

    @property
    def postprocessors(self):
        return self._postprocessors

    def load(self, brain_configuration: BrainConfiguration):
        self._aiml_parser.load_aiml(brain_configuration)
        self.load_collections(brain_configuration)
        self.load_services(brain_configuration)

    def _load_denormals(self, brain_configuration):
        if brain_configuration.denormal is not None:
            total = self._denormal_collection.load_from_filename(
                brain_configuration.denormal)
            logging.info("Loaded a total of %d denormalisations", total)
        else:
            logging.warning("No configuration setting for denormal")

    def _load_normals(self, brain_configuration):
        if brain_configuration.normal is not None:
            total = self._normal_collection.load_from_filename(
                brain_configuration.normal)
            logging.info("Loaded a total of %d normalisations", total)
        else:
            logging.warning("No configuration setting for normal")

    def _load_genders(self, brain_configuration):
        if brain_configuration.gender is not None:
            total = self._gender_collection.load_from_filename(
                brain_configuration.gender)
            logging.info("Loaded a total of %d genderisations", total)
        else:
            logging.warning("No configuration setting for gender")

    def _load_persons(self, brain_configuration):
        if brain_configuration.person is not None:
            total = self._person_collection.load_from_filename(
                brain_configuration.person)
            logging.info("Loaded a total of %d persons", total)
        else:
            logging.warning("No configuration setting for person")

    def _load_person2s(self, brain_configuration):
        if brain_configuration.person2 is not None:
            total = self._person2_collection.load_from_filename(
                brain_configuration.person2)
            logging.info("Loaded a total of %d person2s", total)
        else:
            logging.warning("No configuration setting for person2")

    def _load_predicates(self, brain_configuration):
        if brain_configuration.predicates is not None:
            total = self._predicates_collection.load_from_filename(
                brain_configuration.predicates)
            logging.info("Loaded a total of %d predicates", total)
        else:
            logging.warning("No configuration setting for predicates")

    def _load_pronouns(self, brain_configuration):
        if brain_configuration.pronouns is not None:
            total = self._pronouns_collection.load_from_filename(
                brain_configuration.pronouns)
            logging.info("Loaded a total of %d pronouns", total)
        else:
            logging.warning("No configuration setting for pronouns")

    def _load_properties(self, brain_configuration):
        if brain_configuration.properties is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.properties)
            logging.info("Loaded a total of %d properties", total)
        else:
            logging.warning("No configuration setting for properties")

    def _load_triples(self, brain_configuration):
        if brain_configuration.triples is not None:
            total = self._properties_collection.load_from_filename(
                brain_configuration.triples)
            logging.info("Loaded a total of %d triples", total)
        else:
            logging.warning("No configuration setting for triples")

    def _load_sets(self, brain_configuration):
        if brain_configuration.set_files is not None:
            total = self._sets_collection.load(brain_configuration.set_files)
            logging.info("Loaded a total of %d sets files", total)
        else:
            logging.warning("No configuration setting for set files")

    def _load_maps(self, brain_configuration):
        if brain_configuration.map_files is not None:
            total = self._maps_collection.load(brain_configuration.map_files)
            logging.info("Loaded a total of %d maps files", total)
        else:
            logging.warning("No configuration setting for map files")

    def _load_preprocessors(self, brain_configuration):
        if brain_configuration.preprocessors is not None:
            total = self._preprocessors.load(brain_configuration.preprocessors)
            logging.info("Loaded a total of %d pre processors", total)
        else:
            logging.warning("No configuration setting for pre processors")

    def _load_postprocessors(self, brain_configuration):
        if brain_configuration.postprocessors is not None:
            total = self._postprocessors.load(
                brain_configuration.postprocessors)
            logging.info("Loaded a total of %d post processors", total)
        else:
            logging.warning("No configuration setting for post processors")

    def load_collections(self, brain_configuration):
        self._load_denormals(brain_configuration)
        self._load_normals(brain_configuration)
        self._load_genders(brain_configuration)
        self._load_persons(brain_configuration)
        self._load_person2s(brain_configuration)
        self._load_predicates(brain_configuration)
        self._load_pronouns(brain_configuration)
        self._load_properties(brain_configuration)
        self._load_triples(brain_configuration)
        self._load_sets(brain_configuration)
        self._load_maps(brain_configuration)
        self._load_preprocessors(brain_configuration)
        self._load_postprocessors(brain_configuration)

    def load_services(self, brain_configuration):
        ServiceFactory.preload_services(brain_configuration.services)

    def pre_process_question(self, bot, clientid, question):
        return self.preprocessors.process(bot, clientid, question)

    def ask_question(self, bot, clientid, sentence) -> str:

        conversation = bot.get_conversation(clientid)

        topic_pattern = conversation.predicate("topic")
        if topic_pattern is None:
            logging.info("No Topic pattern default to [*]")
            topic_pattern = "*"
        else:
            logging.info("Topic pattern = [%s]", topic_pattern)

        try:
            that_question = conversation.nth_question(2)
            that_sentence = that_question.current_sentence()

            # If the last response was valid, i.e not none and not empty string, then use
            # that as the that_pattern, otherwise we default to '*' as pattern
            if that_sentence.response is not None and that_sentence.response != '':
                that_pattern = that_sentence.response
                logging.info("That pattern = [%s]", that_pattern)
            else:
                logging.info("That pattern, no response, default to [*]")
                that_pattern = "*"

        except Exception:
            logging.info("No That pattern default to [*]")
            that_pattern = "*"

        match_context = self._aiml_parser.match_sentence(
            bot,
            clientid,
            sentence,
            topic_pattern=topic_pattern,
            that_pattern=that_pattern)

        if match_context is not None:
            template_node = match_context.template_node()
            logging.debug("AIML Parser evaluating template [%s]",
                          template_node.to_string())
            return template_node.template.resolve(bot, clientid)

        return None

    def post_process_response(self, bot, clientid, response: str):
        return self.postprocessors.process(bot, clientid, response)

    def dump_tree(self):
        self._aiml_parser.pattern_parser.root.dump(tabs="")

    def write_learnf_to_file(self, bot, clientid, pattern, topic, that,
                             template):
        learnf_path = "%s/learnf%s" % (
            self._configuration.aiml_files.files,
            self._configuration.aiml_files.extension)
        logging.debug("Writing learnf to %s", learnf_path)

        if os.path.isfile(learnf_path) is False:
            file = open(learnf_path, "w+")
            file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            file.write('<aiml>\n')
            file.write('</aiml>\n')
            file.close()

        tree = ET.parse(learnf_path)
        root = tree.getroot()

        # Add our new element
        child = ET.Element("category")
        child.append(pattern)
        child.append(topic)
        child.append(that)
        child.append(template.xml_tree(bot, clientid))

        root.append(child)

        tree.write(learnf_path, method="xml")
コード例 #35
0
ファイル: brain.py プロジェクト: rkc007/program-y
 def load_aiml_parser(self):
     return AIMLParser(self)
コード例 #36
0
 def setUp(self):
     self._brain = Brain(BrainConfiguration())
     self._bot = Bot(self._brain, BotConfiguration())
     self.parser = AIMLParser(self._brain)
     self.assertIsNotNone(self.parser)