Beispiel #1
0
    def __init__(self, config: ClientConfigurationData, client):

        assert config is not None
        assert client is not None

        self._questions = 0

        self._configuration = config
        self._client = client

        self._brain_factory = BrainFactory(self)

        self._question_depth = 0
        self._question_start_time = None

        self._spell_checker = None
        self.initiate_spellchecker()

        self._sentence_splitter = None
        self.initiate_sentence_splitter()

        self._sentence_joiner = None
        self.initiate_sentence_joiner()

        self._from_translator = None
        self._to_translator = None
        self.initiate_translator()

        self._sentiment_analyser = None
        self._sentiment_scores = None
        self.initiate_sentiment_analyser()

        self._conversation_mgr = ConversationManager(config.conversations)
        self._conversation_mgr.initialise(self._client.storage_factory)
Beispiel #2
0
class Bot:

    def __init__(self, config: ClientConfigurationData, client):

        assert config is not None
        assert client is not None

        self._questions = 0

        self._configuration = config
        self._client = client

        self._brain_factory = BrainFactory(self)

        self._question_depth = 0
        self._question_start_time = None

        self._spell_checker = None
        self.initiate_spellchecker()

        self._sentence_splitter = None
        self.initiate_sentence_splitter()

        self._sentence_joiner = None
        self.initiate_sentence_joiner()

        self._from_translator = None
        self._to_translator = None
        self.initiate_translator()

        self._sentiment_analyser = None
        self._sentiment_scores = None
        self.initiate_sentiment_analyser()

        self._conversation_mgr = ConversationManager(config.conversations)
        self._conversation_mgr.initialise(self._client.storage_factory)

    def post_initialise(self):
        brains = self.brain_factory.brains()
        for brain in brains:
            brain.post_initialise()

    @staticmethod
    def ylogger_type() -> str:
        return "bot"

    @property
    def num_questions(self) -> int:
        return self._questions

    @property
    def id(self) -> str:
        return self._configuration.section_name

    @property
    def client(self):
        return self._client

    @property
    def configuration(self) -> ClientConfigurationData:
        return self._configuration

    @property
    def brain_factory(self) -> BrainFactory:
        return self._brain_factory

    @property
    def spell_checker(self) -> SpellingChecker:
        return self._spell_checker

    def get_question_counts(self) -> int:
        return self._brain_factory.get_question_counts()

    def initiate_spellchecker(self):
        if self.configuration.spelling is not None:
            self._spell_checker = SpellingChecker.initiate_spellchecker(self.configuration.spelling,
                                                                        self.client.storage_factory)

    @property
    def sentence_splitter(self):
        return self._sentence_splitter

    def initiate_sentence_splitter(self) -> SentenceSplitter:
        if self.configuration.splitter is not None:
            self._sentence_splitter = SentenceSplitter.initiate_sentence_splitter(self.configuration.splitter)

    @property
    def sentence_joiner(self) -> SentenceJoiner:
        return self._sentence_joiner

    def initiate_sentence_joiner(self):
        if self.configuration.joiner is not None:
            self._sentence_joiner = SentenceJoiner.initiate_sentence_joiner(self.configuration.joiner)

    @property
    def from_translator(self) -> BaseTranslator:
        return self._from_translator

    @property
    def to_translator(self) -> BaseTranslator:
        return self._to_translator

    def initiate_translator(self):
        if self.configuration.from_translator is not None:
            self._from_translator = BaseTranslator.initiate_translator(self.configuration.from_translator)

        if self.configuration.to_translator is not None:
            self._to_translator = BaseTranslator.initiate_translator(self.configuration.to_translator)

    @property
    def sentiment_analyser(self) -> BaseSentimentAnalyser:
        return self._sentiment_analyser

    @property
    def sentiment_scores(self) -> SentimentScores:
        return self._sentiment_scores

    def initiate_sentiment_analyser(self):
        if self.configuration.sentiment_analyser is not None:
            self._sentiment_analyser, self._sentiment_scores = BaseSentimentAnalyser.initiate_sentiment_analyser(
                self.configuration.sentiment_analyser)

    @property
    def brain(self):
        return self._brain_factory.select_brain()

    @property
    def conversations(self) -> ConversationManager:
        return self._conversation_mgr

    @property
    def default_response(self) -> str:
        return self.configuration.default_response

    @property
    def default_response_srai(self) -> str:
        return self.configuration.default_response_srai

    @property
    def exit_response(self) -> str:
        return self.configuration.exit_response

    @property
    def exit_response_srai(self) -> str:
        return self.configuration.exit_response_srai

    @property
    def initial_question(self) -> str:
        return self.configuration.initial_question

    @property
    def initial_question_srai(self) -> str:
        return self.configuration.initial_question_srai

    @property
    def override_properties(self) -> bool:
        return self.configuration.override_properties

    def get_version_string(self, client_context) -> str:

        assert client_context is not None

        if client_context.brain.properties.has_property("version"):
            # The old version of returning the version string, did not distinquish
            # between App and Grammar version
            return "%s, v%s, initiated %s" % (
                client_context.brain.properties.property("name"),
                client_context.brain.properties.property("version"),
                client_context.brain.properties.property("birthdate"))
        else:
            # This version now does
            return "%s, App: v%s Grammar v%s, initiated %s" % (
                client_context.brain.properties.property("name"),
                client_context.brain.properties.property("app_version"),
                client_context.brain.properties.property("grammar_version"),
                client_context.brain.properties.property("birthdate"))

    def has_conversation(self, client_context) -> bool:

        assert self._conversation_mgr is not None

        return self._conversation_mgr.has_conversation(client_context)

    def get_conversation(self, client_context: ClientContext) -> Conversation:

        assert self._conversation_mgr is not None

        return self._conversation_mgr.get_conversation(client_context)

    def check_spelling_before(self, client_context: ClientContext, each_sentence):
        if self.spell_checker is not None:
            self.spell_checker.check_spelling_before(client_context, each_sentence)

    def check_spelling_and_retry(self, client_context, each_sentence):
        if self.spell_checker is not None:
            return self.spell_checker.check_spelling_and_retry(client_context, each_sentence)
        return None

    def get_default_response(self, client_context):

        assert client_context is not None

        if self.default_response_srai is not None:
            sentence = Sentence(client_context, self.default_response_srai)
            default_response = client_context.brain.ask_question(client_context, sentence)
            if default_response is None or not default_response:
                default_response = self.default_response
            return default_response
        else:
            return self.default_response

    def get_initial_question(self, client_context):

        assert client_context is not None

        if self.initial_question_srai is not None:
            sentence = Sentence(client_context, self.initial_question_srai)
            initial_question = client_context.brain.ask_question(client_context, sentence)
            if initial_question is None or not initial_question:
                initial_question = self.initial_question
            return initial_question
        else:
            return self.initial_question

    def get_exit_response(self, client_context):

        assert client_context is not None

        if self.exit_response_srai is not None:
            sentence = Sentence(client_context, self.exit_response_srai)
            exit_response = client_context.brain.ask_question(client_context, sentence)
            if exit_response is None or not exit_response:
                exit_response = self.exit_response

            return exit_response

        else:
            return self.exit_response

    def _brain_pre_process_question(self, client_context, text):
        pre_processed = client_context.brain.pre_process_question(client_context, text)
        YLogger.debug(client_context, "Pre Processed (%s): %s", client_context.userid, pre_processed)
        return pre_processed

    def pre_process_text(self, client_context, text, srai):

        assert client_context is not None
        assert client_context.brain is not None

        if srai is False:
            pre_processed = self._brain_pre_process_question(client_context, text)
        else:
            pre_processed = text

        if pre_processed is None or pre_processed == "":
            assert self.configuration is not None
            pre_processed = self.configuration.empty_string

        return pre_processed

    def get_question(self, client_context, pre_processed, srai):
        if srai is False:
            return Question.create_from_text(client_context, pre_processed, srai=srai)
        else:
            return Question.create_from_text(client_context, pre_processed, split=False, srai=srai)

    def combine_answers(self, answers, srai):

        assert answers is not None
        assert self._sentence_joiner is not None

        return self._sentence_joiner.combine_answers(answers, srai)

    def post_process_response(self, client_context, response, srai):
        if srai is False:

            assert client_context is not None

            answer = client_context.brain.post_process_response(client_context, response).strip()
            if not answer:
                answer = self.get_default_response(client_context)

        else:
            answer = response

        return answer

    def _brain_post_process_question(self, client_context, question):
        return client_context.brain.post_process_question(client_context, question)

    def post_process_question(self, client_context, question, srai):
        if srai is False:
            assert client_context is not None
            answer = self._brain_post_process_question(client_context, question)
            if not answer:
                answer = self.get_default_response(client_context)
        else:
            answer = question

        return answer

    def log_answer(self, client_context, text, answer, responselogger):
        YLogger.debug(client_context, "Processed Response (%s): %s", client_context.userid, answer)

        if responselogger is not None:
            responselogger.log_response(text, answer)

    def ask_question(self, client_context, text, srai=False, responselogger=None):

        assert client_context is not None

        # KS Added this to fix empty string UDC
        text = text.strip()

        if srai is False:
            client_context.bot = self
            client_context.brain = client_context.bot.brain

        assert client_context.bot is not None
        assert client_context.brain is not None

        self._questions += 1

        client_context.mark_question_start(text)

        pre_processed = self.pre_process_text(client_context, text, srai=False)

        question = self.get_question(client_context, pre_processed, srai)

        conversation = self.get_conversation(client_context)
        if len(conversation.questions) == 0:
            if self.client.trigger_manager is not None:
                self.client.trigger_manager.trigger(SystemTriggers.CONVERSATION_START, client_context)

        assert conversation is not None

        conversation.record_dialog(question)

        answers = self.process_sentences(client_context, question, srai, responselogger)

        client_context.reset_question()

        if srai is True:
            conversation.pop_dialog()

        conversation.save_sentiment()

        self._conversation_mgr.save_conversation(client_context)

        if self.client.trigger_manager is not None and srai is False:
            self.client.trigger_manager.trigger(SystemTriggers.QUESTION_ASKED, client_context)

        return self.combine_answers(answers, srai)

    def process_sentences(self, client_context, question, srai, responselogger):
        answers = []
        sentence_no = 0
        for sentence in question.sentences:
            question.current_sentence_no = sentence_no
            answer = self.process_sentence(client_context, sentence, srai, responselogger)
            answers.append(answer)
            sentence_no += 1

        return answers

    def process_sentence(self, client_context, sentence, srai, responselogger):

        assert client_context is not None
        assert client_context.brain is not None

        client_context.check_max_recursion()
        client_context.check_max_timeout()

        if srai is False:
            self.check_spelling_before(client_context, sentence)

        response = client_context.brain.ask_question(client_context, sentence, srai)

        if response is None and srai is False:
            response = self.check_spelling_and_retry(client_context, sentence)

        if response is not None:
            return self.handle_response(client_context, sentence, response, srai, responselogger)
        else:
            return self.handle_none_response(client_context, sentence, responselogger)

    def handle_response(self, client_context, sentence, response, srai, responselogger):

        assert sentence is not None

        YLogger.debug(client_context, "Raw Response (%s): %s", client_context.userid, response)
        sentence.response = response

        sentence.calculate_sentinment_score(client_context)
        answer = self.post_process_response(client_context, response, srai)
        self.log_answer(client_context, sentence.text, answer, responselogger)

        return answer

    def handle_none_response(self, client_context, sentence, responselogger):

        assert sentence is not None

        sentence.response = self.post_process_question(client_context, sentence.text(client_context), False)

        sentence.calculate_sentinment_score(client_context)

        if responselogger is not None:
            responselogger.log_unknown_response(sentence)

        return sentence.response