def _recover_old_dm(self, id_meeting):

        if id_meeting in self.dm_dict.keys():
            self.dm = self.dm_dict[id_meeting]
        else:
            # só recupera da memória encontro que já foi marcado
            infos = db_interface.search_all_meeting_info(id_meeting)
            print(infos)
            self.dm = DialogManager(infos[0][0],
                                    self,
                                    og=self.og,
                                    id_meeting=id_meeting)
            self.dm.state = dialog_manager.dialog_manager_states.InfoCompleted(
                self.dm)
            self.dm.with_list = []
            self.dm.where = infos[0][1]
            self.dm.date = infos[0][4]
            self.dm.commitment = infos[0][3]
            self.dm.hour = infos[0][2]

            participantes = db_interface.search_clients_from_meeting(
                id_meeting)
            for pessoa in participantes:
                self.dm.with_list.append(pessoa[0])

            db_interface.update_meeting(id_meeting, infos)

            # self.dm.dispatch_msg('load_queues')
            self.dm.start()
            # Coloquei essa mensagem para aviso de que reunião voltou a discussão
            self.dm_dict[id_meeting] = self.dm
Ejemplo n.º 2
0
def main():
    # print('Por favor, escreva abaixo um texto (Ex: Quero marcar uma conversa com o Mateus no domingo /'
    #     ' I want to schedule a meeting with Adam the next week) \n')
    print('Por favor, diga a língua para o sistema ("pt" ou "en")')
    print('> ')
    language = input()
    dict_output = {'mode': 'response'}
    json_output = json.loads(json.dumps(dict_output))
    mode_manager = ModeManager()
    mode = mode_manager.which_mode(
        json.dumps(json_output, indent=4, sort_keys=True))
    file = open("tests/tests_phrases/frases_teste.txt", mode="r")

    semanticizer = Semanticizer(mode, initial_vars, 1, language)
    dm = DialogManager()
    dm.start()
    og = OutputGenerator()
    og.start()

    for line in file:
        print("\n" + "=" * 50)
        print("O texto é: ", line)
        print("\nA língua do documento é: ", language)
        my_json = execute_semanticizer(semanticizer, line)
        message = DialogMessage.from_json(my_json)
        message.id_user = 1
        dm.dispatch_msg(message)
Ejemplo n.º 3
0
def main():

    print('Por favor, diga a língua para o sistema ("pt" ou "en")')
    print('> ')
    language = input()
    dict_output = {'mode': 'regular'}
    json_output = json.loads(
        json.dumps(dict_output)
    )  # Clausula semântica (json) do OutputGenerator para o Semantizador
    file = open("tests/tests_phrases/frases_teste.txt", mode="r")
    dm = DialogManager()
    print("REMOVER PARA DEPLOY !!!!!!!!!!")
    dm.og.set_language(language)
    dm.start()
    semanticizer = Semanticizer('response', initial_vars, 1, language)
    #for line in file:  # testes em frases pre-escritas
    i = 0
    while True:
        print("Digite a frase")
        line = input()
        id_name = int(input("Digite o ID"))
        semanticizer.intent_entities = {}
        my_json = semanticizer.validate_and_semantize(line)
        print("JSON: ")
        print(my_json)
        message = DialogMessage.from_json((my_json))
        # altera entre as duas pessoas para simular corretamente
        message.id_user = id_name
        # if i == 1:
        #     i = 0
        #     message.id_user = 3
        # else:
        #     i = 1
        #     message.id_user = 1

        print("with_list%s\nintent%s\ndate%s\nhour%s\nplace%s" %
              (message.with_list, message.intent, message.date, message.hour,
               message.place))
        dm.dispatch_msg(message)
Ejemplo n.º 4
0
    def __init__(
        self,
        logic_config='json_configs/simple_example.json',
        telegram_cfg_path='json_configs/telegram.json',
        db_path='db/aiml.db',
        sql_debug=False,
        logging_lvl=logging.WARNING,
    ):
        # Read telegram token
        if 'SMART_BOT_TOKEN' in environ:
            self.tg_token = environ['SMART_BOT_TOKEN']
        elif os.path.exists(telegram_cfg_path):
            with open(telegram_cfg_path, 'r', encoding='utf-8') as config:
                self.tg_token = json.load(config)['token']
        else:
            raise ValueError('Telegram config file doesn\'t exist :{}'.format(
                telegram_cfg_path))

        self.db_adapter = logger.log_db_adapter.LogDBAdapter(
            db_path=db_path, create_tables=True, sql_debug=sql_debug)
        self.logger = BotLogger(db_adapter=self.db_adapter,
                                storage_type='sqlite',
                                logs_on=True)

        # инициализация telegram
        self.update_id = None
        self.bot = telegram.Bot(token=self.tg_token)

        try:
            self.update_id = self.bot.get_updates()[0].update_id
        except IndexError:
            self.update_id = None

        # self.updater = Updater(token=self.tg_token)
        # self.dispatcher = self.updater.dispatcher

        self.current_class = None

        self.custom_keyboard = None

        tree_generator = NodesTreeGenerator(logic_config)
        self.nodes_tree = tree_generator.gen_full_tree()

        # logs on
        logging.basicConfig(
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            level=logging_lvl)

        # # user message handlers
        # self.start_handler = CommandHandler('start', self.start)
        # self.dispatcher.add_handler(self.start_handler)
        #
        # self.uptime_handler = CommandHandler('uptime', self.uptime)
        # self.dispatcher.add_handler(self.uptime_handler)
        #
        # self.build_time_handler = CommandHandler('buildtime', self.buildtime)
        # self.dispatcher.add_handler(self.build_time_handler)
        #
        # self.echo_handler = MessageHandler(Filters.text, self.echo)
        # self.dispatcher.add_handler(self.echo_handler)
        #
        # self.voice_handler = MessageHandler(Filters.voice, self.voice)
        # self.dispatcher.add_handler(self.voice_handler)

        # initial data
        self.run_time = datetime.datetime.now()

        self.source_file = __file__
        self.build_time = os.path.getmtime(self.source_file)

        self.dialog_manager = DialogManager(self.nodes_tree)
Ejemplo n.º 5
0
class SmartBot:
    def __init__(
        self,
        logic_config='json_configs/simple_example.json',
        telegram_cfg_path='json_configs/telegram.json',
        db_path='db/aiml.db',
        sql_debug=False,
        logging_lvl=logging.WARNING,
    ):
        # Read telegram token
        if 'SMART_BOT_TOKEN' in environ:
            self.tg_token = environ['SMART_BOT_TOKEN']
        elif os.path.exists(telegram_cfg_path):
            with open(telegram_cfg_path, 'r', encoding='utf-8') as config:
                self.tg_token = json.load(config)['token']
        else:
            raise ValueError('Telegram config file doesn\'t exist :{}'.format(
                telegram_cfg_path))

        self.db_adapter = logger.log_db_adapter.LogDBAdapter(
            db_path=db_path, create_tables=True, sql_debug=sql_debug)
        self.logger = BotLogger(db_adapter=self.db_adapter,
                                storage_type='sqlite',
                                logs_on=True)

        # инициализация telegram
        self.update_id = None
        self.bot = telegram.Bot(token=self.tg_token)

        try:
            self.update_id = self.bot.get_updates()[0].update_id
        except IndexError:
            self.update_id = None

        # self.updater = Updater(token=self.tg_token)
        # self.dispatcher = self.updater.dispatcher

        self.current_class = None

        self.custom_keyboard = None

        tree_generator = NodesTreeGenerator(logic_config)
        self.nodes_tree = tree_generator.gen_full_tree()

        # logs on
        logging.basicConfig(
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            level=logging_lvl)

        # # user message handlers
        # self.start_handler = CommandHandler('start', self.start)
        # self.dispatcher.add_handler(self.start_handler)
        #
        # self.uptime_handler = CommandHandler('uptime', self.uptime)
        # self.dispatcher.add_handler(self.uptime_handler)
        #
        # self.build_time_handler = CommandHandler('buildtime', self.buildtime)
        # self.dispatcher.add_handler(self.build_time_handler)
        #
        # self.echo_handler = MessageHandler(Filters.text, self.echo)
        # self.dispatcher.add_handler(self.echo_handler)
        #
        # self.voice_handler = MessageHandler(Filters.voice, self.voice)
        # self.dispatcher.add_handler(self.voice_handler)

        # initial data
        self.run_time = datetime.datetime.now()

        self.source_file = __file__
        self.build_time = os.path.getmtime(self.source_file)

        self.dialog_manager = DialogManager(self.nodes_tree)

    # command /start
    def start(self, bot: telegram.Bot, update: telegram.Update):
        self.send_message(bot,
                          update.message.chat_id,
                          text=self.nodes_tree.root_node.answer.text)

    # command /uptime
    def uptime(self, bot: telegram.Bot, update: telegram.Update):
        bot.send_message(chat_id=update.message.chat_id,
                         text=u'Время работы: ' +
                         str(datetime.datetime.now() - self.run_time))

    # command /buildtime
    def buildtime(self, bot: telegram.Bot, update: telegram.Update):
        bot.send_message(
            chat_id=update.message.chat_id,
            text='Время последней модификации скрипта[\'{}\']: {}'.format(
                self.source_file, str(time.ctime(self.build_time))))

    # voice message parser
    @staticmethod
    def voice(bot: telegram.Bot, update: telegram.Update):
        # bot.send_message(
        #     chat_id=update.message.chat_id,
        #     text=u'Получено аудио от ' + str(update.message.from_user)
        # )
        # bot.send_message(
        #     chat_id=update.message.chat_id,
        #     text=u'длительностью ' + str(update.message.voice.duration)
        # )
        # bot.send_message(
        #     chat_id=update.message.chat_id,
        #     text=u'ID файла: ' + update.message.voice.file_id)
        voice_file = bot.get_file(update.message.voice.file_id)
        voice_path = 'voice_tmp.oga'
        voice_file.download(custom_path=voice_path)
        #TODO
        res = speech2text(voice_path)
        # res = voice_api_test.speech2text(voice_path)
        bot.send_message(chat_id=update.message.chat_id,
                         text='[Получено аудио: {}]'.format(res[0][0]))
        return res[0][0]

    def send_message(self,
                     bot: telegram.Bot,
                     chat_id: str,
                     text: str = None,
                     file: str = None,
                     options: list = None):
        if options:
            self.custom_keyboard = [val for val in options]
            self.custom_keyboard.append([u'отмена'])
            reply_markup = ReplyKeyboardMarkup(self.custom_keyboard,
                                               one_time_keyboard=True)
        else:
            reply_markup = ReplyKeyboardRemove(remove_keyboard=True)
            self.custom_keyboard = None

        if text:
            self.logger.add_bot_answer(text)
            if options:
                self.logger.add_options(options)
            bot.send_message(chat_id=chat_id,
                             text=text,
                             reply_markup=reply_markup,
                             resize_keyboard=True,
                             parse_mode=telegram.ParseMode.MARKDOWN)

        if file is not None:
            if file != '':
                self.logger.add_file(file)
                bot.send_document(chat_id=chat_id,
                                  document=file,
                                  reply_markup=reply_markup)

    # non-command text
    def echo(self, bot: telegram.Bot):
        for update in bot.get_updates(offset=self.update_id, timeout=1):
            self.update_id = update.update_id + 1

            if type(update.message) is not telegram.Message:
                continue

            if update.message.voice:
                update.message.text = self.voice(bot, update)
                # continue

            # TODO: change 'not in' > 'in'
            if (len(update.message.entities)
                    and update.message.entities[0].type == 'bot_command'
                    and update.message.text not in ['/auth']):
                eval('self.{}(bot, update)'.format(update.message.text[1:]))
                return

            answer, current_node_name = self.dialog_manager.parse_message(
                update.message)
            self.logger.add_classification(current_node_name)
            self.send_message(bot,
                              update.message.chat_id,
                              text=answer.text,
                              file=answer.file,
                              options=answer.options)

    # def echo(self, bot, update):
    #     msg = update.message.text
    #     self.logger.add_user_message(update.message)
    #     if msg == 'отмена':
    #         answer = self.nodes_tree.go_to_root(msg)
    #     else:
    #         answer = self.nodes_tree.parse_message(msg)
    #     self.logger.add_classification(self.nodes_tree.current_node_name)
    #     self.send_message(
    #         bot,
    #         update.message.chat_id,
    #         text=answer.text,
    #         file=answer.file,
    #         options=answer.options
    #     )

    def run(self):
        while True:
            try:
                self.echo(self.bot)
            except NetworkError as e:
                print('Network error', e)
                time.sleep(0.01)
            except Unauthorized:
                # The user has removed or blocked the bot.
                self.update_id += 1
            except Exception as e:
                print(e)
                sys.exit()
Ejemplo n.º 6
0
import base64

from helpers.speech_kit import speech2text

from logger.bot_logger import BotLogger
import logger.log_db_adapter



# logic_config = 'json_configs/smart_home_example.json'
# logic_config = 'json_configs/iptv_example_search.json'
logic_config = 'json_configs/caller.json'
tree_generator = NodesTreeGenerator(
    logic_config)
nodes_tree = tree_generator.gen_full_tree()
dialog_manager = DialogManager(nodes_tree)
db_path = 'db/ai_api.db'
sql_debug = False
db_adapter = logger.log_db_adapter.LogDBAdapter(
    db_path=db_path,
    create_tables=True,
    sql_debug=sql_debug
)
logger = BotLogger(
    db_adapter=db_adapter,
    storage_type='sqlite',
    logs_on=True
)


class UserMessage:
    def _select_new_meeting(self, id_user):

        # self._save_old_dm()
        self.dm = DialogManager(id_user, self, og=self.og)
        self.dm_dict[self.dm.id_meeting] = self.dm
        self.dm.start()
class DialogManagerSelector(threading.Thread):
    def __init__(self, og):

        self.input_queue = queue.Queue()
        threading.Thread.__init__(self)
        self.pending_requests = {}
        self.language = None
        self.og = og
        self.dm = None
        self.users_active_meeting = {}
        self.pending_requests = {}
        self.dm_dict = {}
        self.dm_to_kill = Queue()

    def dispatch_msg(self, message, language):
        input_info = {"message": message, "language": language}
        self.input_queue.put(input_info)

    def kill_dm(self, id_meeting):
        self.dm_to_kill.put(id_meeting)

    def run(self):
        while True:
            if not self.input_queue.empty():
                input_info = self.input_queue.get()
                message = input_info["message"]
                self.language = input_info["language"]

                dialog_is_finished = self._dm_select(message)
                if self.dm is not None and dialog_is_finished:
                    if message.id_user in self.pending_requests:
                        del self.pending_requests[message.id_user]
                    self.dm.og.set_language(self.language)
                    self.dm.dispatch_msg(message)
                    self.users_active_meeting[
                        message.id_user] = self.dm.id_meeting
            if not self.dm_to_kill.empty():
                id_meeting = self.dm_to_kill.get()
                if id_meeting in self.dm_dict.keys():
                    del self.dm_dict[id_meeting]
                    keysEncontradas = []
                    for key in self.users_active_meeting.keys():
                        if self.users_active_meeting[key] == id_meeting:
                            keysEncontradas.append(key)
                    for key in keysEncontradas:
                        del self.users_active_meeting[key]

    '''
        Given the input message, select the aproprieated dm for the work
    '''

    def _dm_select(self, message):
        # caso esteja no get initial info, retorna independente de qualquer coisa
        if message.id_user in self.users_active_meeting.keys():
            dm = self.dm_dict[self.users_active_meeting[message.id_user]]
            if dm.state.__name__ == 'InitialInfo':
                self.dm = self.dm_dict[self.users_active_meeting[
                    message.id_user]]
                return True
        if 'marcar_compromisso' in message.intent:
            self._select_new_meeting(message.id_user)
            return True
        elif message.id_user in self.users_active_meeting.keys():
            self._select_active_meeting(message.id_user)
            return True
        elif message.id_user in self.pending_requests.keys() and \
                len(self.pending_requests[message.id_user]["hit_meetings"]) == 1:
            if self.pending_requests[message.id_user]["intent"]:
                message.intent = self.pending_requests[
                    message.id_user]["intent"]
                self._recover_old_dm(
                    self.pending_requests[message.id_user]["hit_meetings"][0])
                self._notify_revival_with_additional_info(message)
                return True
            elif message.intent:
                self._recover_old_dm(
                    self.pending_requests[message.id_user]["hit_meetings"][0])
                self._notify_revival_with_additional_info(message)
                return True
            else:
                self._send_output(intent='request_intent',
                                  user_id=message.id_user)
                return False
        else:
            meeting_found = self._find_meeting(message)
            if meeting_found and ("confirmacao" in message.intent
                                  or "resposta_negativa" in message.intent):
                self._recover_old_dm(
                    self.pending_requests[message.id_user]["hit_meetings"][0])
                self._notify_revival_with_additional_info(message)
                return True
            elif meeting_found:
                self._ask_for_specific_change(message)
            return False

    def _notify_revival_with_additional_info(self, message):

        intent = message.intent[0]
        if intent == "remarcar_compromisso":
            self.dm.notify_all_members_selector(
                ['notify_revival', 'change_date_hour'])
        elif intent == "mudar_lugar":
            self.dm.notify_all_members_selector(
                ['notify_revival', 'change_place_selector'])
        elif intent == "add_pessoa":
            self.dm.notify_all_members_selector(
                ['notify_revival', 'add_person_selector'])
        elif intent == "excl_pessoa":
            self.dm.notify_all_members_selector(
                ['notify_revival', 'excl_person_selector'])
        else:
            self.dm.notify_all_members_selector('notify_revival')

    def _ask_for_specific_change(self, message):

        intent = self.pending_requests[message.id_user]["intent"]
        if not intent:
            self._send_output(
                intent=['notify_found_meeting', 'request_intent'],
                user_id=message.id_user)
        elif intent[0] == "remarcar_compromisso":
            self._send_output(
                intent=['notify_found_meeting', 'request_new_date_hour'],
                user_id=message.id_user)
        elif intent[0] == "mudar_lugar":
            self._send_output(
                intent=['notify_found_meeting', 'request_new_place'],
                user_id=message.id_user)
        elif intent[0] == "add_pessoa":
            self._send_output(
                intent=['notify_found_meeting', 'request_add_person'],
                user_id=message.id_user)
        elif intent[0] == "excl_pessoa":
            self._send_output(
                intent=['notify_found_meeting', 'request_excl_person'],
                user_id=message.id_user)
        elif intent[0] == "desmarcar_compromisso":
            self._send_output(
                intent=['notify_found_meeting', 'request_cancel_meeting'],
                user_id=message.id_user)
        else:
            self._send_output(intent=['notify_found_meeting'],
                              user_id=message.id_user)

    def _recover_old_dm(self, id_meeting):

        if id_meeting in self.dm_dict.keys():
            self.dm = self.dm_dict[id_meeting]
        else:
            # só recupera da memória encontro que já foi marcado
            infos = db_interface.search_all_meeting_info(id_meeting)
            print(infos)
            self.dm = DialogManager(infos[0][0],
                                    self,
                                    og=self.og,
                                    id_meeting=id_meeting)
            self.dm.state = dialog_manager.dialog_manager_states.InfoCompleted(
                self.dm)
            self.dm.with_list = []
            self.dm.where = infos[0][1]
            self.dm.date = infos[0][4]
            self.dm.commitment = infos[0][3]
            self.dm.hour = infos[0][2]

            participantes = db_interface.search_clients_from_meeting(
                id_meeting)
            for pessoa in participantes:
                self.dm.with_list.append(pessoa[0])

            db_interface.update_meeting(id_meeting, infos)

            # self.dm.dispatch_msg('load_queues')
            self.dm.start()
            # Coloquei essa mensagem para aviso de que reunião voltou a discussão
            self.dm_dict[id_meeting] = self.dm

    def _select_new_meeting(self, id_user):

        # self._save_old_dm()
        self.dm = DialogManager(id_user, self, og=self.og)
        self.dm_dict[self.dm.id_meeting] = self.dm
        self.dm.start()

    def _select_active_meeting(self, id_user):

        # self._save_old_dm()
        self._recover_old_dm(self.users_active_meeting[id_user])
        # self.dm = self.dm_dict[self.users_active_meeting[id_user]]

    def _find_meeting(self, message):

        print("\n========= find_meeting.start ==========")
        if message.id_user in self.pending_requests:
            hit_meetings = self.pending_requests[
                message.id_user]["hit_meetings"]
        else:
            hit_meetings = []
            self.pending_requests[message.id_user] = {
                "hit_meetings": hit_meetings,
                "intent": message.intent
            }

        print("enquanto a lista de pessoas não funcionará")

        if message.person_know:
            print("\n==> Procurando todas os compromissos:")
            found = self._search_through_all_meetings(message, hit_meetings)
            if found:
                self.pending_requests[
                    message.id_user]["hit_meetings"] = hit_meetings
                return True

        if message.place_unknown:
            print("\n==> Procurando por 'onde (unknown)':")
            found = self._search_by_specific_info(message.place_unknown,
                                                  hit_meetings, 'onde',
                                                  message.place_unknown[0],
                                                  message.id_user)
            if found:
                self.pending_requests[
                    message.id_user]["hit_meetings"] = hit_meetings
                return True

        if message.place_known:
            print("\n==> Procurando por 'onde (known)':")
            found = self._search_by_specific_info(message.place_known,
                                                  hit_meetings, 'onde',
                                                  message.place_known[0],
                                                  message.id_user)
            if found:
                self.pending_requests[
                    message.id_user]["hit_meetings"] = hit_meetings
                return True

        if message.date:
            print("\n==> Procurando por 'dia':")
            found = self._search_by_specific_info(message.date, hit_meetings,
                                                  'dia', message.date[0],
                                                  message.id_user)
            if found:
                self.pending_requests[
                    message.id_user]["hit_meetings"] = hit_meetings
                return True

        if message.hour:
            print("\n==> Procurando por 'hora':")
            found = self._search_by_specific_info(message.hour, hit_meetings,
                                                  'quando', message.hour[0],
                                                  message.id_user)
            if found:
                self.pending_requests[
                    message.id_user]["hit_meetings"] = hit_meetings
                return True

        if len(hit_meetings) == 0:
            self.pending_requests[
                message.id_user]["hit_meetings"] = hit_meetings
            self._send_output(intent='notify_request_fail',
                              user_id=message.id_user)
        else:
            self.pending_requests[
                message.id_user]["hit_meetings"] = hit_meetings
            self._filter_data(hit_meetings, message)

        print("\n========= find_meeting.end ==========")
        self.dm = None

    def _search_through_all_meetings(self, message, hit_meetings):

        if message.person_know is not None and message.person_know != []:
            candidate_meetings = db_interface.search_meetings_from_client(
                message.id_user)
            for meeting in candidate_meetings:
                candidate_users = db_interface.search_clients_from_meeting(
                    meeting[0])
                candidatos = []
                hit = True
                for user in candidate_users:
                    candidatos.append(user[0])
                for person in message.person_know:
                    if person not in candidatos:
                        hit = False
                if hit:
                    hit_meetings.append(meeting[0])
            # here hit_meetings = [] contains all meetings id that have the data input from user
            if len(hit_meetings) == 1:
                # encontramos o encontro desejado
                # self._save_old_dm()
                # self._recover_old_dm(hit_meetings[0])
                return True
            return False

    def _search_by_specific_info(self, message, hit_meetings, column, info,
                                 user_id):

        if message is not None and message != []:
            if hit_meetings != []:
                for id_meeting in hit_meetings:
                    result = db_interface.search_info_from_meeting(
                        column, id_meeting)
                    if result[0][0][0] not in message:
                        hit_meetings.remove(id_meeting)
            else:
                results = db_interface.search_meeting_joining_tables(
                    column, info, user_id)
                for result in results:
                    hit_meetings.append(result[0])
            if len(hit_meetings) == 1:
                # self._recover_old_dm(hit_meetings[0])
                return True
            return False

    def _filter_data(self, hit_meetings, message):
        meeting_infos = []
        for meeting_id in hit_meetings:
            meeting_infos.append(
                db_interface.search_all_meeting_info(meeting_id))
        self._send_output(intent='disambiguate_meeting',
                          user_id=message.id_user,
                          extra_info=meeting_infos)

    # refatorar o send_output com as necessidades do selector
    def _send_output(self, intent, user_id, extra_info=None):
        response_dict = data["SelectorSemanticClauseTemplate"]
        response_dict["intent"] = intent
        response_dict["id_user"] = user_id
        response_dict["message_data"] = extra_info

        response_json = json.dumps(response_dict, indent=4, ensure_ascii=False)
        # message = DM_Message.from_json(response_json) trocar por isso em algum momento
        self.og.set_language(self.language)
        self.og.dispatch_msg(response_json)