Рубрики
Без рубрики

Как справиться с разговором в чате в Python

Когда вы разрабатываете Chatbot, иногда для пользовательского опыта, вы не можете задать ваши сообщения, отправлять сообщения … Теги с Python, Django, Chatbot.

Когда вы разрабатываете Thatbot, иногда для пользовательского опыта вы не можете попросить вашего пользователя отправлять сообщения, такие как команды. Например, мы хотим построить угадать номер бота. Мы хотим, чтобы бот работает так:

Пользователь: Угадай Бот: От какого числа? Пользователь: : 25 бот: К каком количеству? Пользователь: 100 Бот: Угадай число от 25 до 100 Пользователь: 64 Бот: Слишком маленький Пользователь: 91 Бот: слишком большой …… Пользователь: 83 Бот: Верный! Вы провели 6 раз, чтобы угадать этот номер.

Тем не менее, распространенный способ, которым мы имеем дело с запросами на бэкэнде, является одним-запросом – один ответ. Это было бы катастрофой для отделения многих обработчиков из разговора. Почему? Подумайте, как хранить штаты? В глобальных переменных? Или база данных? Или redis? Как только вы попросите пользователям еще один вопрос, вам нужно изменить схему вашего состояния, и код становится более сложным.

В следующем я покажу вам, как иметь дело с разговорами и писать обработчик простым и простым способом, как это:

    def guess(self):
        '''Game function'''
        min_value = self.ask_number('From what number?')
        max_value = self.ask_number('To what number?')
        secret = randint(min_value, max_value)
        msg = f'Guess a number between {min_value} to {max_value}'
        counter = 0
        while True:
            counter += 1
            answer = self.ask_number(msg)
            if answer > secret:
                msg = 'Too large'
            elif answer < secret:
                msg = 'Too small'
            else:
                break
        self.reply(f'You spent {counter} times to guess the secret number.')

Например, я напишу линию бота, но не имеет значения, какую платформу вы развиваете. Я буду использовать Django, и все в порядке, если вы используете другие рамки.

Настройка среды

Это для настройки бота, вы можете пропустить это, если вы это знаете.

Клонировать мое репо:

git clone https://github.com/lancatlin/python-chatbot-context.git
cd python-chatbot-context
pipenv install
pipenv shell

Перейти к Разработчики линии создать бот. Выдайте токен и ваш секрет, положите их в .env файл.

LINE_TOKEN=YOUR_TOKEN
LINE_SECRET=YOUR_SECRET

Затем начните Django.

python manage.py migrate    # for first execution
python manage.py runserver

Используйте Ngrok или что-то подобное туннелю Localhost: 8000 на общедоступную конечную точку и зарегистрируйте URL-адрес API обмена сообщениями.

Идея описать

Основная идея состоит в том, чтобы заблокировать командный поток, пока не будет получено другое сообщение. Когда программа получает команду «Угадай», она будет выполнена в командной ните. Как только программа нуждается в входе от пользователя, он поместил сообщение в «Очередь запросов» в номере. Затем, когда сообщение входит в другой поток, он проверяет очередь запросов в комнату и помещает сообщение в очередь ответов, если не пусто.

Осуществлять

Мы реализуем это как MessageQueue класс:

# guess/message_queue.py
import queue
from threading import RLock
from .line import get_room


class RequestTimout(Exception):
    pass


class MessageQueue:
    __lock = RLock()
    __requests = {}
    __responses = {}

    @classmethod
    def create_if_not_exists(cls, room):
        '''Create the requests and responses queues for the room if not exists'''
        with cls.__lock:
            if room not in cls.__requests:
                cls.__requests[room] = queue.Queue(maxsize=1)

            if room not in cls.__responses:
                cls.__responses[room] = queue.Queue(maxsize=1)

    @classmethod
    def handle(cls, event):
        '''Handle the message, check whether there is room request for'''
        room = get_room(event)
        cls.create_if_not_exists(room)

        try:
            if not cls.__requests[room].empty():
                cls.__responses[room].put(event, timeout=1)
                cls.__requests[room].get()
                return True
            return False
        except queue.Empty:
            '''No request, ignore the message'''
            return False

    @classmethod
    def request(cls, room, timeout=30):
        '''Request a message, block until message comes in or timeout'''
        try:
            cls.create_if_not_exists(room)

            cls.__requests[room].put_nowait(True)
            return cls.__responses[room].get(timeout=timeout)

        except queue.Empty:
            MessageQueue.clear(room)
            raise RequestTimout

    @classmethod
    def clear(cls, room):
        '''Clear the requests'''
        cls.create_if_not_exists(room)
        try:
            cls.__requests[room].get_nowait()
        except queue.Empty:
            pass

С этим мы можем очень легко реализовать наше приложение догадаться.

# guess/guess.py
from .message_queue import MessageQueue, RequestTimout
from .line import reply_text, get_room, get_msg
from random import randint


class Guess:
    '''Guess handle a guess number game'''

    def __init__(self, event):
        self.event = event
        try:
            self.guess()
        except RequestTimout:
            self.reply('Timeout')

    def guess(self):
        '''Game function'''
        min_value = self.ask_number('From what number?')
        max_value = self.ask_number('To what number?')
        secret = randint(min_value, max_value)
        msg = f'Guess a number between {min_value} to {max_value}'
        counter = 0
        while True:
            counter += 1
            answer = self.ask_number(msg)
            if answer > secret:
                msg = 'Too large'
            elif answer < secret:
                msg = 'Too small'
            else:
                break
        self.reply(f'You spent {counter} times to guess the secret number.')

    def ask(self, *msg):
        '''Ask a question to current user'''
        self.reply(*msg)
        self.event = MessageQueue.request(get_room(self.event))
        return get_msg(self.event)

    def ask_number(self, *msg):
        '''Ask a number, if not number, ask again'''
        try:
            content = self.ask(*msg)
            return int(content)
        except ValueError:
            return self.ask_number('Please input an integer.', *msg)

    def reply(self, *msg):
        '''Reply words to user'''
        reply_text(self.event, *msg)

Вы можете увидеть, что главная функция проста, с 17 линиями кода. Более того, он может обрабатывать несколько пользовательских входов одновременно.

Получить полный код на Github Отказ

Особая благодарность Юкинамочизуки Для того, чтобы дать мне первоначальную идею от Его понятный бот проект Отказ

Оригинал размещен на Wancat.cc.

Оригинал: “https://dev.to/wancat/how-to-handle-conversation-in-chatbot-in-python-41c5”