Диалог с пользователем через командную строку: программа Yes/No на Python
Диалоговые программы используются везде, примером может служить любое приложение на вашем компьютере (браузер, видеоплееры, текстовые редакторы и т. д.). Диалог Yes/No — это простой пример диалоговой программы, работающей с командной строкой.
Что такое диалоговая программа и зачем она нужна
Программа, в которой предусмотрено взаимодействие с пользователем, называется диалоговой (интерактивной).
Ввод текста, нажатия на кнопки, загрузка файлов — всё это способы взаимодействия пользователя с приложением.
Диалог между программой и пользователем — это важная часть любого проекта. Если программа работает с одними строго определенными данными, она не несёт какого-либо практического смысла.
Диалоговая программа Yes/No на Python
Диалог может вестись как через графический интерфейс, так и через командную строку. С помощью Python можно реализовать и то и другое, однако общение с пользователем через терминал имеет более простую реализацию и требует меньше кода.
Суть такой программы проста: пользователь отвечает на вопросы, вводя в консоль Yes – да, или No – нет. Не стоит думать, что сейчас актуально взаимодействовать с программой только через графический интерфейс, командная строка также используется.
Понятно, что диалог через командную строку чаще используется продвинутыми пользователями или техническими специалистами, которых не пугает работа в режиме текстовых команд.
Консольный диалог Yes/No особенно актуален, потому что не требует реализовывать графический интерфейс, который может быть бесполезен для выполнения определённых задач.
Реализация функции диалога Yes/No на Python
Написать консольную диалоговую программу на Python очень просто, однако нужно учесть и продумать некоторые нюансы, такие как неверный ввод от пользователя. Yes/no легко можно заменить на Да/нет, но давайте следовать общепринятым стандартам и использовать английский язык.
Объявление функции
Поместим всю логику диалоговой программы в отдельную функцию, которую объявим так:
Здесь аргументы означают следующее:
Начальные настройки
Предположим, что пользователь может вводить не только «yes», но и «y» или «ye». Обработка каждого вариант с помощью условных операторов if — else нецелесообразна и требует много лишнего кода. Поэтому поместим все варианты ответа в словарь:
default_answer позволяет указать предпочтительный вариант ответа, однако это не очевидно для обычного пользователя. В зависимости от содержимого default_answer будем выводить соответствующую подсказку:
При вводе аргумента default_answer тоже можно допустить ошибку, поэтому в блоке else мы возбуждаем исключение, которое указывает на неверный ввод.
Основной цикл
Необходимо продумать следующие ситуации, когда пользователь:
Для реализации лучше использовать бесконечный цикл. Сначала необходимо вывести вопрос и подсказку, а затем получить ввод пользователя:
Подробнее про ввод и вывод данных можно почитать здесь.
Теперь ввод необходимо обработать так, чтобы при правильном вводе происходил выход из цикла, а при неправильном цикл начинался заново:
Полный код функции
Соединив все вместе, получаем готовую к использованию функцию для диалога с пользователем:
Пример программы
Предположим, что функция получает несколько вопросов из файла, результаты ответов записываются в другой файл, тогда код программы будет выглядеть так:
С помощью метода строк strip удалим лишние символы.
Перед запуском программы на Python надо не забыть подготовить файл с вопросами qst.txt такого вида:
Результатом выполнения будет следующее:
Содержимое файла результата будет следующим:
Диалог с пользователем
Напишем программу, которая сумеет провести с пользователем короткий, более или менее осмысленный диалог.
Сначала программа спрашивает у пользователя, какое у него настроение. Затем ответ анализируется. Предполагается, что пользователь отвечает словом или фразой, записанной строчными буквами.
Если в ответе пользователя есть ключевые слова вроде «хорошее», «прекрасно» (в любой форме), программа отвечает что-нибудь подходящее — например «Отлично, у меня тоже всё хорошо ».
Если же встречаются слова вроде «плохо», то нужно ответить что-то подходящее и на этот случай (например, «Ничего, скоро всё наладится»).
Если ключевых слов того или другого типа не найдено, программа отвечает что-то нейтральное или извиняется и говорит, что не понимает пользователя. То же происходит, если в ответе есть «не» или вопросительный знак.
Случай, когда в ответе есть и «хорошие», и «плохие» слова, можно не рассматривать.
Многошаговый диалог с пользователем
Здравствуйте, уважаемые коллеги! С недавних пор самостоятельно изучаю Django и пытаюсь писать с.
Диалог с пользователем
Подскажите пож,как в Swing организовать стандартное окно с функционалом «назад» «далее» «прервать».
Диалог с пользователем
Итак, через set /p прошу пользователя ввести некое значение, которое задаю переменной %p%. Теперь.
Многократный диалог с пользователем
Помогите пожалуйста,нужно с помощью функции организовать многократный диалог с пользователем о.
Как и каким интерфейсом сделать опросник?
У меня есть проект питон и мне его надо перебросить в Qt Designer.
Как и каким интерфейсом это сделать?
Так-же какие блоки использовать в Qt Designer для создания именно такого опросника так сказать?
2 ответа 2
Этого материала по созданию простого приложения с использованием qt-designer’а более чем достаточно. Во всяком случае, ваш проект легко переносится на форму.
Если хотите автоматизировать такие процессы в дальнейшем нарабатывайте собственную библиотеку шаблонов.
Ваш проект перебросить никуда не получится. Все надо создавать с нуля. С целью дальнейшего вашего развития, создан пример демонстрирующий одну из возможностей создания опросников.
PyQt — набор привязок графического фреймворка Qt для языка программирования Python, выполненный в виде расширения Python.
Qt Designer — кроссплатформенная свободная среда для разработки графических интерфейсов программ использующих библиотеку Qt. Входит в состав Qt framework.
Запускаем с консоли:
Запустите Qt Designer и посмотрите как выглядит созданная форма:
Вам придется самостоятельно найти Книги и учебные ресурсы по PyQt5 и Qt Designer если вам это будет интересно.
Создание простого разговорного чатбота в python
Как вы думаете, сложно ли написать на Python собственного чатбота, способного поддержать беседу? Оказалось, очень легко, если найти хороший набор данных. Причём это можно сделать даже без нейросетей, хотя немного математической магии всё-таки понадобится.
Идти будем маленькими шагами: сначала вспомним, как загружать данные в Python, затем научимся считать слова, постепенно подключим линейную алгебру и теорвер, и под конец сделаем из получившегося болтательного алгоритма бота для Телеграм.
Этот туториал подойдёт тем, кто уже немножко трогал пальцем Python, но не особо знаком с машинным обучением. Я намеренно не пользовался никакими nlp-шными библиотеками, чтобы показать, что нечто работающее можно собрать и на голом sklearn.
Поиск ответа в диалоговом датасете
Год назад меня попросили показать ребятам, которые прежде не занимались анализом данных, какое-нибудь вдохновляющее приложение машинного обучения, которое можно собрать самостоятельно. Я попробовал собрать вместе с ними бота-болталку, и у нас это действительно получилось за один вечер. Процесс и результат нам понравились, и написал об этом в своем блоге. А теперь подумал, что и Хабру будет интересно.
Итак, начинаем. Наша задача — сделать алгоритм, который на любую фразу будет давать уместный ответ. Например, на «как дела?» отвечать «отлично, а у тебя?». Самый простой способ добиться этого — найти готовую базу вопросов и ответов. Например, взять субтитры из большого количества кинофильмов.
Я, впрочем, поступлю ещё более по-читерски, и возьму данные из соревнования Яндекс.Алгоритм 2018 — это те же диалоги из фильмов, для которых работники Толоки разметили хорошие и неплохие продолжения. Яндекс собирал эти данные, чтобы обучать Алису (статьи о её кишках 1, 2, 3). Собственно, Алисой я и был вдохновлен, когда придумывал этого бота. В таблице от Яндекса даны три последних фразы и ответ на них (reply), но мы будем пользоваться только самой последней из них (context_0).
Векторизация текстов
Теперь говорим о том, как превратить тексты в числовые векторы, чтобы осуществлять по ним приближённый поиск.
Мы уже познакомились с библиотекой pandas в Python — она позволяет загружать таблицы, осуществлять поиск в них, и т.п. Теперь затронем библиотеку scikit-learn (sklearn), которая позволяет более хитрые манипуляции с данными — то, что называется машинным обучением. Это значит, что любому алгоритму сперва нужно показать данные (fit), чтобы он узнал о них что-то важное. В результате алгоритм «научится» делать с этими данными что-то полезное — преобразовывать их (transform), или даже предсказывать неизвестные величины (predict).
В данном случае мы хотим преобразовать тексты («вопросы») в числовые векторы. Это нужно, чтобы можно было находить «близкие» друг к другу тексты, пользуясь математическим понятием расстояние. Расстояние между двумя точками можно рассчитать по теореме Пифагора — как корень из суммы квадратов разностей их координат. В математике это называется Евклидовой метрикой. Если мы сможем превращать тексты в объекты, у которых есть координаты, то мы сможем вычислять Евклидову метрику и, например, находить в базе вопрос, наиболее всего похожий на «о чём ты думаешь?».
Самый простой способ задать координаты текста — это пронумеровать все слова в языке, и сказать, что i-тая координата текста равна числу вхождений в него i-того слова. Например, для текста «я не могу не плакать» координата слова «не» равна 2, координаты слов «я», «могу» и «плакать» равны 1, а координаты всех остальных слов (коих десятки тысяч) равны 0. Такое представление теряет информацию о порядке слов, но всё равно работает неплохо.
Проблема в том, что у слов, которые встречаются часто (например, частиц «и» и «а») координаты будут несоразмерно большие, хотя информации они несут мало. Чтобы смягчить эту проблему, координату каждого слова можно поделить на логарифм числа текстов, где такое слово встречается — это называется tf-idf и тоже работает неплохо.
Проблема только одна: в нашей базе 60 тысяч текстовых «вопросов», в которых содержится 14 тысяч различных слов. Если превратить все вопросы в векторы, получится матрица 60к*14к. Работать с такой не очень классно, поэтому дальше мы поговорим о сокращении размерности.
Сокращение размерности
Мы уже поставили задачу создания болталочного чатбота, скачали и векторизовали данные для его обучения. Теперь у нас есть числовая матрица, представляющая реплики пользователей. Она состоит из 60 тысяч строк (столько было реплик в базе диалогов) и 14 тысяч столбцов (столько в них было различных слов). Сейчас наша задача — сделать её поменьше. Например, представить каждый текст не 14123-мерным, а всего лишь 300-мерным вектором.
Достичь этого можно, умножив нашу матрицу размера 60049х14123 на специально подобранную матрицу проекции размера 14123х300, в итоге получим результат 60049х300. Алгоритм PCA (метод главных компонент) подбирает матрицу проекции так, чтобы исходную матрицу можно было потом восстановить с наименьшей среднеквадратической ошибкой. В нашем случае получилось сохранить около 44% об исходной матрице, хотя размерность сократилась почти в 50 раз.
За счёт чего возможно такое эффективное сжатие? Напомним, что исходная матрица содержит счётчики упоминания отдельных слов в текстах. Но слова, как правило, употреблятся не независимо друг от друга, а в контексте. Например, чем больше раз в тексте новости встречается слово «блокировка», тем больше раз, скорее всего в этом тексте встретится также слово «телеграм». А вот корреляция слова «блокировка», например, со словом «кафтан» отрицательная — они встречаются в разных контекстах.
Так вот, получается, что метод главных компонент запоминает не все 14 тысяч слов, а 300 типовых контекстов, по которым эти слова потом можно пытаться восстановить. Столбцы матрицы проекции, соответствующие синонимичным словам, обычно похожи друг на друга, потому что эти слова часто встречаются в одном контексте. А значит, можно сократить избыточные измерения, не потеряв при этом в информативности.
Во многих современных приложениях матрицу проекции слов вычисляют нейросети (например, word2vec). Но на самом деле простой линейной алгебры для практически полезного результата уже достаточно. Метод главных компонент вычислительно сводится к SVD, а оно — к расчёту собственных векторов и собственных чисел матрицы. Впрочем, программировать это можно, даже не зная деталей.
Поиск ближайших соседей
В предыдущих разделах мы закачали в python корпус диалогов, векторизовали его, и сократили размерность, а теперь хотим наконец научиться искать в нашем 300-мерном пространстве ближайших соседей и наконец-то осмысленно отвечать на вопросы.
Поскольку научились отображать вопросы в Евклидово пространство не очень высокой размерности, поиск соседей в нём можно осуществлять довольно быстро. Мы воспользуемся уже готовым алгоритмом поиска соседей BallTree. Но мы напишем свою модель-обёртку, которая выбирала бы одного из k ближайших соседей, причём чем ближе сосед, тем выше вероятность его выбора. Ибо брать всегда одного самого близкого соседа — скучно, но не завязываться на сходство совсем — опасно.
Поэтому мы хотим превратить найденные расстояния от запроса до текстов-эталонов в вероятности выбора этих текстов. Для этого можно использовать функцию softmax, которая ещё часто стоит на выходе из нейросетей. Она превращает свои аргументы в набор неотрицательных чисел, сумма которых равна 1 — как раз то, что нам нужно. Дальше полученные «вероятности» мы можем использовать для случайного выбора ответа.
Фразы, которые будет вводить пользователь, надо пропускать через все три алгоритма — векторизатор, метод главных компонент, и алгоритм выбора ответа. Чтобы писать меньше кода, можно связать их в единую цепочку (pipeline), применяющую алгоритмы последовательно.
В результате мы получили алгоритм, который по вопросу пользователя способен найти похожий на него вопрос и выдать ответ на него. И иногда это ответы даже звучат почти осмысленно.
Публикация бота в Telegram
Мы уже разобрались, как сделать чатбота-болталку, который бы выдавал примерно уместные ответы на запросы пользователя. Теперь показываю, как выпустить такого чатбота в Телеграм.
Проще всего использовать для этого готовую обёртку Telegram API для питона — например, pytelegrambotapi. Итак, пошаговая инструкция:
Полный код к статье я намеренно не выкладываю — вы получите гораздо больше удовольствия и полезного опыта, когда напечатаете его сами, и получите работающего бота в результате собственных усилий. Ну или если вам очень лень это делать, можете поболтать с моей версией ботика.
Пишем генератор тестов на Python
Здравствуйте!В данной статье я хотел бы показать пример программы на Python,которая генерирует билеты на основе вопросов из текстового файла.
Текстовый файл с вопросами:
Внизу на рисунке представлена Excel-форма (файл TicketTemplate.xlsx):
Скрипт ticketgenerator.py:
import random
import openpyxl
# читает файл в список
def read2list(file):
# открываем файл в режиме чтения utf-8
file = open(file, ‘r’, encoding=’utf-8′)
# читаем все строки и удаляем переводы строк
lines = file.readlines()
lines = [line.rstrip(‘\n’) for line in lines]
# возвращает 5 случайных вопросов
def get_questions():
answers = read2list(‘answers_data.txt’)
items = random.choices(population=answers, k=5)
return items
# класс шаблон билета
class TicketTemplate:
def __init__(self, my_book=’./TicketTemplate.xlsx’):
self.book_name = my_book
self.book = None
self.sheet = None
def open(self):
self.book = openpyxl.load_workbook(self.book_name)
self.sheet = self.book.active
def get_cell_value(self, row, column):
return self.sheet.cell(row=row, column=column).value
def set_cell_value(self, row, column, value):
self.sheet.cell(row=row, column=column).value = value
def get_rows(self):
rows = [self.get_cell_value(1, 1), self.get_cell_value(3, 1),
self.get_cell_value(4, 1), self.get_cell_value(5, 1),
self.get_cell_value(6, 1), self.get_cell_value(7, 1)
]
def set_ticket_number(self, number):
self.sheet.cell(row=1, column=1).value = ‘Билет №’ str(number)
def set_questions(self, questions):
for row, question in enumerate(questions):
question_number = row 1
self.set_cell_value(row 3, 1, ‘<0>. <1>‘.format(question_number, question.strip()))
def flush(self):
self.book.save(self.book_name)
def save(self, file_name):
self.book.save(file_name)
Используется следующим образом:
from tiсketgenerator import *
tt = TicketTemplate()
tt.open()
for ticket in range(1, 31):
tt.set_ticket_number(ticket)
tt.set_questions(get_questions())
tt.save(‘./Билеты/Билет №<0>.xlsx’.format(ticket))
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.