⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Chatbot in russian with speech recognition using PocketSphinx and speech synthesis using RHVoice. The AttentionSeq2Seq model is used. Imlemented using Python3+TensorFlow+Keras.

License

Notifications You must be signed in to change notification settings

dbklim/Voice_ChatBot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

106 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Voice ChatBot

Проект состоит из двух частей - голосовой бот и RESTful сервер для взаимодействия с ним.

Для запуска бота локально нужно выполнить python3 bot.py (или run_bot.sh) и в предложенном меню выбрать желаемый вариант работы (подробнее тут).

Для запуска RESTful сервера, предоставляющего интерфейс для взаимодействия с модулями голосового бота, нужно выполнить python3 rest_server.py (или run_rest_server.sh) (подробнее тут).

Для сборки docker-образа на основе RESTful сервера выполните sudo docker build -t voice_chatbot:0.1 . (подробнее тут).

ВНИМАНИЕ! Это был мой дипломный проект, по этому архитектура и код тут не очень хорошие, я это понимаю и как появится время - всё обновлю.

Зависимости

Полный список всех необходимых для работы зависимостей:

  1. Для Python3.5-3.6: decorator, Flask (>=1.0.2), Flask-HTTPAuth (>=3.2.4), gensim, gevent (>=1.3.7), h5py, Keras (>=2.2.4), matplotlib, numpy, pocketsphinx, pydub, simpleaudio, recurrentshop, requests, seq2seq, tensorflow[-gpu].
  2. Для Ubuntu: ffmpeg, x264, x265, make, git, scons, gcc, pkg-config, pulseaudio, libpulse-dev, portaudio19-dev, libglibmm-2.4-dev, libasound-dev, libao4, libao-dev, sonic, sox, swig, flite1-dev, net-tools, zip, unzip.
  3. Данные для обучения и готовые модели: необходимо вручную загрузить из Google Drive архив Voice_ChatBot_data.zip(3Gb) и распаковать в корень проекта (папки data и install_files).

Если вы используете Ubuntu 16.04 или выше, для установки всех пакетов можно воспользоваться install_packages.sh (проверено в Ubuntu 16.04 и 18.04). По умолчанию будет установлен TensorFlow для CPU. Если у вас есть видеокарта nvidia с утановленным официальным драйвером версии 410, вы можете установить TensorFlowGPU. Для этого необходимо при запуске install_packages.sh передать параметр gpu. Например:

./install_packages.sh gpu

В этом случае из моего Google Drive будет загружено 2 архива:

  1. Install_CUDA10.0_cuDNN_for410.zip(2.0Gb) с CUDA 10.0 и cuDNN 7.5.0 (если был передан параметр gpu). Установка будет выполнена автоматически, но если что-то пошло не так, есть инструкция Install.txt в загруженном архиве.
  2. Voice_ChatBot_data.zip(3Gb) с данными для обучения и готовыми моделями. Он будет автоматически распакован в папки data и install_files в корне проекта.

Если вы не можете или не хотите воспользоваться скриптом для установки всех необходимых пакетов, нужно вручную установить RHVoice и CMUclmtk_v0.7, используя инструкции в install_files/Install RHVoice.txt и install_files/Install CMUclmtk.txt. Так же необходимо скопировать файлы языковой, акустической модели и словаря для PocketSphinx из temp/ в /usr/local/lib/python3.6/dist-packages/pocketsphinx/model (у вас путь к python3.6 может отличаться). Файлы языковой модели prepared_questions_plays_ru.lm и словаря prepared_questions_plays_ru.dic необходимо переименовать в ru_bot_plays_ru.lm и ru_bot_plays_ru.dic (либо изменить их название в speech_to_text.py, если у вас есть своя языковая модель и словарь).

Бот

Основа бота - рекуррентная нейронная сеть, модель AttentionSeq2Seq. В текущей реализации она состоит из 2 двунаправленных LSTM ячеек в кодировщике, слоя внимания и 2 LSTM ячеек в декодировщике. Использование модели внимания позволяет установить "мягкое" соответствие между входными и выходными последовательностями, что повышает качество и производительность. Размерность входа в последней конфигурации равна 500 и длина последовательности 26 (т.е. максимальная длина предложений в обучающей выборке). Слова переводятся в вектора с помощью кодировщика word2vec (со словарём на 445.000 слов) из бибилотеки gensim. Модель seq2seq реализована с помощью Keras и RecurrentShop. Обученная модель seq2seq (веса которой находятся в data/plays_ru/model_weights_plays_ru.h5) с параметрами, которые указаны в исходных файлах, имеет точность 99.19% (т.е. бот ответит на 1577 из 1601 вопросов правильно).

На данный момент предусмотрено 3 набора данных для обучения бота: 1601 пара вопрос-ответ из различных пьес (data/plays_ru), 136.000 пар из различных произведений (data/conversations_ru, спасибо NLP Datasets) и 2.500.000 пар из субтитров к 347 сериалам (data/subtitles_ru, подробнее в Russian subtitles dataset). Модели word2vec обучены для всех наборов данных, но нейронная сеть обучена только на наборе данных из пьес.

Обучение модели word2vec и нейронной сети на наборе данных из пьес без изменения параметров длится примерно 7.5 часов на nvidia gtx1070 и intel core i7. Обучение на наборах данных из произведений и субтитров на данном железе будет длиться минимум нескольких суток.

Бот умеет работать в нескольких режимах:

  1. Обучение модели seq2seq.
  2. Работа с обученной моделью seq2seq в текстовом режиме.
  3. Работа с обученной моделью seq2seq с озвучиванием ответов с помощью RHVoice.
  4. Работа с обученной моделью seq2seq с распознаванием речи с помощью PocketSphinx.
  5. Работа с обученной моделью seq2seq с озвучиванием ответов и распознаванием речи.

1. Обучение модели seq2seq

Обучающая выборка состоит из 1600 пар вопрос %% ответ, взятых из различных русских пьес. Она хранится в файле data/plays_ru/plays_ru.txt. Каждая пара вопрос %% ответ пишется с новой строки, т.е. на одной строке только одна пара.

Все необходимые для обучения этапы выполняются методами prepare() или load_prepared() и train() класса TextToText из модуля text_to_text.py и метод build_language_model() класса LanguageModel из модуля preparing_speech_to_text.py. Или можно использовать функцию train() модуля bot.py.

Для запуска бота в режиме обучения нужно запустить bot.py с параметром train. Например, так:

python3 bot.py train

Или можно просто запустить bot.py (или выполнить run_bot.sh) и в предложенном меню выбрать режим 1 и 1.

Процесс обучения состоит из нескольких этапов:

1. Подготовка обучающей выборки.

Для подготовки обучающей выборки предназначен модуль source_to_prepared.py, состоящий из класса SourceToPrepared. Данный класс считывает обучающую выборку из файла, разделяет вопросы и ответы, удаляет неподдерживаемые символы и знаки препинания, преобразует полученные вопросы и ответы в последовательности фиксированного размера (с помощью слов-наполнителей <PAD>). Так же этот класс осуществляет подготовку вопросов к сети и обработку её ответов. Например:

Вход: "Зачем нужен этот класс? %% Для подготовки данных"

Выход: [['<PAD>', ..., '<PAD>', '?', 'класс', 'этот', 'нужен', 'Зачем', '<GO>'], ['Для', 'подготовки', 'данных', '<EOS>', '<PAD>', ..., '<PAD>']]

Обучающая выборка считывается из файла data/plays_ru/plays_ru.txt, преобразованные пары [вопрос,ответ] сохраняются в файл data/plays_ru/prepared_plays_ru.pkl. Так же при этом строится гистограмма размеров вопросов и ответов, которая сохраняется в data/plays_ru/histogram_of_sizes_sentences_plays_ru.png.

Для подготовки обучающей выборки из набора данных на основе пьес достаточно передать методу prepare_all() имя соответствующего файла. Что бы подготовить обучающую выборку из набора данных на основе произведений или субтитров, нужно вначале вызвать combine_conversations() или combine_subtitles(), а после вызывать preapre_all().

2. Перевод слов в вещественные вектора.

За этот этап отвечает модуль word_to_vec.py, состоящий из класса WordToVec. Данный класс кодирует последовательности фиксированного размера (т.е. наши вопросы и ответы) в вещественные вектора. Использутся кодировщик word2vec из библиотеки gensim. В классе реализованы методы для кодирования сразу всех пар [вопрос,ответ] из обучающей выборки в вектора, а так же для кодирования вопроса к сети и декодирования её ответа. Например:

Вход: [['<PAD>', ..., '<PAD>', '?', 'класс', 'этот', 'нужен', 'Зачем', '<GO>'], ['Для', 'кодирования', 'предложений', '<EOS>', '<PAD>', ..., '<PAD>']]

Выход: [[[0.43271607, 0.52814275, 0.6504923, ...], [0.43271607, 0.52814275, 0.6504923, ...], ...], [[0.5464854, 1.01612, 0.15063584, ...], [0.88263285, 0.62758327, 0.6659863, ...], ...]] (т.е. каждое слово кодируется вектором с длинной 500 (это значение можно изменить, аргумент size в методе build_word2vec()))

Пары [вопрос,ответ] считываются из файла data/plays_ru/prepared_plays_ru.pkl (который был получен на предыдущем этапе, для расширения и повышения качества модели рекомендуется дополнительно передать методу build_word2vec() предобработанный набор данных из субтитров data/subtitles_ru/prepared_subtitles_ru.pkl), закодированные пары сохраняются в файл data/plays_ru/encoded_plays_ru.npz. Так же в процессе работы строится список всех используемых слов, т.е. словарь, который сохраняется в файле data/plays_ru/w2v_vocabulary_plays_ru.txt. Также сохраняется обученная модель word2vec в data/plays_ru/w2v_model_plays_ru.bin.

Для перевода слов из обучающей выборки в вектора достаточно передать методу build_word2vec() имя соответствующего файла и задать желаемые параметры.

3. Обучение сети.

На этом этапе выполняется обучение модели seq2seq на уже подготовленных ранее данных. За это отвечает модуль text_to_text.py, состоящий из класса TextToText. Данный класс осуществляет обучение сети, сохранение модели сети и весовых коэффициентов, и позволяет удобно взаимодействовать с обученной моделью.

Для обучение необходим файл data/plays_ru/encoded_plays_ru.npz, содержащий пары [вопрос,ответ], закодированные в вектора, которые были получены на предыдущем этапе. В процессе обучения после каждой 5-ой эпохи (это значение можно изменить) сохраняется крайний промежуточный результат обучения сети в файл data/plays_ru/model_weights_plays_ru_[номер_итерации].h5, а на последней итерации в файл data/plays_ru/model_weights_plays_ru.h5 (итерация - один цикл обучения сети, некоторое число эпох, после которых происходит сохранение весов в файл и можно например оценить точность работы сети или вывести другие её параметры. По умолчанию число эпох равно 5, а общее число итераций 200). Модель сети сохраняется в файле data/plays_ru/model_plays_ru.json.

После обучения сети выполняется оценка качества обучения путём подачи на вход обученной сети всех вопросов и сравнения ответов сети с эталонными ответами из обучающей выборки. Если точность оцениваемой модели получается выше 75%, то неправильные ответы сети сохраняются в файл data/plays_ru/wrong_answers_plays_ru.txt (что бы их можно было потом проанализировать).

Для обучения сети достаточно передать методу train() имя соответствующего файла и задать желаемые параметры.

4. Построение языковой модели и словаря для PocketSphinx.

Этот этап нужен в случае, если будет использоваться распознавание речи. На этом этапе осуществляется создание статической языковой модели и фонетического словаря для PocketSphinx на основе вопросов из обучающей выборки (осторожно: чем больше вопросов в обучающей выборке, тем дольше PocketSphinx будет распознавать речь). Для этого используется метод build_language_model() (которая обращается к text2wfreq, wfreq2vocab, text2idngram и idngram2lm из CMUclmtk_v0.7) класса LanguageModel из модуля preparing_speech_to_text.py. Данный метод использует вопросы из файла с исходной обучающей выборкой (до их подготовки модулем source_to_prepared.py), сохраняет языковую модель в файл temp/prepared_questions_plays_ru.lm, а словарь в temp/prepared_questions_plays_ru.dic (plays_ru может меняться, в зависимости от того, какая обучающая выборка была использована). В конце работы языковая модель и словарь будут скопированы в /usr/local/lib/python3.х/dist-packages/pocketsphinx/model с именами ru_bot_plays_ru.lm и ru_bot_plays_ru.dic (plays_ru может меняться так же, как и на предыдущем этапе, потребуется ввод пароля root-пользователя).


2. Работа с обученной моделью seq2seq в текстовом режиме

Для взаимодействия с обученной моделью seq2seq предназначена функция predict() (которая является обёрткой над методом predict() класса TextToText из модуля text_to_text.py) модуля bot.py. Данная функция поддерживает несколько режимов работы. В текстовом режиме, т.е. когда пользователь вводит вопрос с клавиатуры и сеть отвечает текстом, используется только метод predict() класса TextToText из модуля text_to_text.py. Данный метод принимает строку с вопросом к сети и возвращает строку с ответом сети. Для работы необходимы: файл data/plays_ru/w2v_model_plays_ru.bin с обученной моделью word2vec, файл data/plays_ru/model_plays_ru.json с параметрами модели сети и файл data/plays_ru/model_weights_plays_ru.h5 с весами обученной сети.

Для запуска бота в данном режиме нужно запустить bot.py с параметром predict. Например, так:

python3 bot.py predict

Так же можно просто запустить bot.py (или выполнить run_bot.sh) и в предложенном меню выбрать режим 2 и 1.


3. Работа с обученной моделью seq2seq с озвучиванием ответов с помощью RHVoice

Данный режим отличается от предыдущего тем, что функции predict() модуля bot.py передаётся параметр speech_synthesis = True. Это означает, что взаимодействие с сетью будет проходить так же, как и в режиме 2, но ответ сети дополнительно будет озвучиваться.

Озвучивание ответов, т.е. синтез речи, реализован в методе get() класса TextToSpeech из модуля text_to_speech.py. Данный класс требует установленного RHVoice-client и с помощью аргументов командной строки передаёт ему необходимые параметры для синтеза речи (об установке RHVoice и примеры обращения к RHVoice-client можно посмотреть в install_files/Install RHVoice.txt). Метод get() принимает на вход строку, которую нужно преобразовать в речь, и, если требуется, имя .wav файла, в который будет сохранена синтезированная речь (с частотой дискретизации 32 кГц и глубиной 16 бит, моно; если его не указывать - речь будет воспроизводиться сразу после синтеза). При создании объекта класса TextToSpeech можно указать имя используемого голоса. Поддерживается 4 голоса: мужской Aleksandr и три женских - Anna, Elena и Irina (подробнее в RHVoice Wiki).

Для запуска бота в данном режиме нужно запустить bot.py с параметрами predict -ss. Например, так:

python3 bot.py predict -ss

Так же можно просто запустить bot.py (или выполнить run_bot.sh) и в предложенном меню выбрать режим 3 и 1.


4. Работа с обученной моделью seq2seq с распознаванием речи с помощью PocketSphinx

Для работы в этом режиме необходимо функции predict() модуля bot.py передать параметр speech_recognition = True. Это означает, что взаимодействие с сетью, а точнее ввод вопросов, будет осуществляться с помощью голоса.

Распознавание речи реализовано в методе get() класса SpeechToText модуля speech_to_text.py. Данный класс использует PocketSphinx и языковую модель со словарём (ru_bot_plays_ru.lm и ru_bot_plays_ru.dic), которые были построены в режиме обучения сети. Метод get() может работать в двух режимах: from_file - распознавание речи из .wav или .opus файла с частотой дискретизации >=16кГц, 16bit, моно (имя файла передаётся в качестве аргумента функции) и from_microphone - распознавание речи с микрофона. Режим работы задаётся при создании экземпляра класса SpeechRecognition, т.к. загрузка языковой модели занимает некоторое время (чем больше модель, тем дольше она загружается).

Для запуска бота в данном режиме нужно запустить bot.py с параметрами predict -sr. Например, так:

python3 bot.py predict -sr

Так же можно просто запустить bot.py (или выполнить run_bot.sh) и в предложенном меню выбрать режим 4 и 1.


5. Работа с обученной моделью seq2seq с озвучиванием ответов и распознаванием речи

Это комбинация режимов 3 и 4.

Для работы в этом режиме необходимо функции predict() модуля bot.py передать параметры speech_recognition = True и speech_synthesis = True. Это означает, что ввод вопросов будет осуществляться с помощью голоса, а ответы сети будут озвучиваться. Описание используемых модулей можно найти в описании режимов 3 и 4.

Для запуска бота в данном режиме нужно запустить bot.py с параметрами predict -ss -sr. Например, так:

python3 bot.py predict -sr -ss

или

python3 bot.py predict -ss -sr

Так же можно просто запустить bot.py (или выполнить run_bot.sh) и в предложенном меню выбрать режим 5 и 1.

RESTful сервер

Данный сервер предоставляет REST-api для взаимодействия с ботом. При старте сервера загружается нейронная сеть, обученная на наборе данных из пьес. Наборы данных из произведений и субтитров пока не поддерживаются.

Сервер реализован с помощью Flask, а многопоточный режим (production-версия) с помощью gevent.pywsgi.WSGIServer. Также сервер имеет ограничение на размер принимаемых данных в теле запроса равное 16 Мб. Реализация находится в модуле rest_server.py.

Запустить WSGI сервер можно выполнив run_rest_server.sh (запуск WSGI сервера на 0.0.0.0:5000).

Сервер поддерживает аргументы командной строки, которые немного упрощают его запуск. Аргументы имеют следующую структуру: [ключ(-и)] [адрес:порт].

Возможные ключи:

  1. -d - запуск тестового Flask сервера (если ключ не указывать - будет запущен WSGI сервер)
  2. -s - запуск сервера с поддержкой https (используется самоподписанный сертификат, получен с помощью openssl)

Допустимые варианты адрес:порт:

  1. host:port - запуск на указанном host и port
  2. localaddr:port - запуск с автоопределением адреса машины в локальной сети и указанным port
  3. host:0 или localaddr:0 - если port = 0, то будет выбран любой доступный порт автоматически

Список возможных комбинаций аргументов командной строки и их описание:

  1. без аргументов - запуск WSGI сервера с автоопределением адреса машины в локальной сети и портом 5000. Например: python3 rest_server.py
  2. host:port - запуск WSGI сервера на указанном host и port. Например: python3 rest_server.py 192.168.2.102:5000
  3. -d - запуск тестового Flask сервера на 127.0.0.1:5000. Например: python3 rest_server.py -d
  4. -d host:port - запуск тестового Flask сервера на указанном host и port. Например: python3 rest_server.py -d 192.168.2.102:5000
  5. -d localaddr:port - запуск тестового Flask сервера с автоопределением адреса машины в локальной сети и портом port. Например: python3 rest_server.py -d localaddr:5000
  6. -s - запуск WSGI сервера с поддержкой https, автоопределением адреса машины в локальной сети и портом 5000. Например: python3 rest_server.py -s
  7. -s host:port - запуск WSGI сервера с поддержкой https на указанном host и port. Например: python3 rest_server.py -s 192.168.2.102:5000
  8. -s -d - запуск тестового Flask сервера с поддержкой https на 127.0.0.1:5000. Например: python3 rest_server.py -s -d
  9. -s -d host:port - запуск тестового Flask сервера с поддержкой https на указанном host и port. Например: python3 rest_server.py -s -d 192.168.2.102:5000
  10. -s -d localaddr:port - запуск тестового Flask сервера с поддержкой https, автоопределением адреса машины в локальной сети и портом port. Например: python3 rest_server.py -s -d localaddr:5000

Сервер может сам выбрать доступный порт, для этого нужно указать в host:port или localaddr:port порт 0 (например: python3 rest_server.py -d localaddr:0).

Всего поддерживается 5 запросов:

  1. GET-запрос на /chatbot/about, вернёт информацию о проекте
  2. GET-запрос на /chatbot/questions, вернёт список всех поддерживаемых вопросов
  3. POST-запрос на /chatbot/speech-to-text, принимает .wav/.opus-файл и возвращает распознанную строку
  4. POST-запрос на /chatbot/text-to-speech, принимает строку и возвращает .wav-файл с синтезированной речью
  5. POST-запрос на /chatbot/text-to-text, принимает строку и возвращает ответ бота в виде строки

Описание сервера

1. Сервер имеет базовую http-авторизацию. Т.е. для получения доступа к серверу надо в каждом запросе добавить заголовок, содержащий логин:пароль, закодированный с помощью base64 (логин: bot, пароль: test_bot). Пример на python:

import requests
import base64

auth = base64.b64encode('testbot:test'.encode())
headers = {'Authorization' : "Basic " + auth.decode()}

Выглядеть это будет так:

Authorization: Basic dGVzdGJvdDp0ZXN0

2. В запросе на распознавание речи (который под номером 3) сервер ожидает .wav или .opus файл (>=16кГц 16бит моно) с записанной речью, который так же передаётся в json с помощью кодировки base64 (т.е. открывается .wav/.opus-файл, читается в массив байт, потом кодирутеся base64, полученный массив декодируется из байтовой формы в строку utf-8 и помещается в json), в python это выглядит так:

# Формирование запроса
auth = base64.b64encode('testbot:test'.encode())
headers = {'Authorization' : "Basic " + auth.decode()}

with open('test.wav', 'rb') as audio:
    data = audio.read()
data = base64.b64encode(data)
data = {'wav' : data.decode()}

# Отправка запроса серверу
r = requests.post('http://' + addr + '/chatbot/speech-to-text', headers=headers, json=data)

# Разбор ответа
data = r.json()
data = data.get('text')
print(data)

3. В запросе на синтез речи (который под номером 4) сервер пришлёт в ответе json с .wav-файлом (16бит 32кГц моно) с синтезированной речью, который был закодирован так, как описано выше (что бы обратно его декодировать нужно из json получить нужную строку в массив байт, потом декодировать его с помощью base64 и записать в файл или поток, что бы потом воспроизвести), пример на python:

# Формирование запроса
auth = base64.b64encode('testbot:test'.encode())
headers = {'Authorization' : "Basic " + auth.decode()}
data = {'text':'который час'}

# Отправка запроса серверу
r = requests.post('http://' + addr + '/chatbot/text-to-speech', headers=headers, json=data)

# Разбор ответа
data = r.json()
data = base64.b64decode(data.get('wav'))
with open('/home/vladislav/Проекты/Voice chat bot/temp/answer.wav', 'wb') as audio:
    audio.write(data)

Передаваемые данные в каждом запросе

Все передаваемые данные обёрнуты в json (в том числе и ответы с ошибками).

  1. Сервер передаёт клиенту:
{
"text" : "Информация о проекте."
}
  1. Сервер передаёт клиенту:
{
"text" : ["Вопрос 1",
          "Вопрос 2",
          "Вопрос 3"]
}
  1. Клиент в теле запроса должен отправить:
{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}

или

{
"opus" : "ZFZm10IBUklQVZFZm10IBARLASBAAEOpH..."
}

Сервер ему передаст:

{
"text" : "который час"
}
  1. Клиент в теле запроса должен отправить:
{
"text" : "который час"
}

Сервер ему передаст:

{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}
  1. Клиент в теле запроса должен отправить:
{
"text" : "прощай"
}

Сервер ему передаст:

{
"text" : "это снова я"
}

Примеры запросов

1. GET-запрос на /chatbot/about

Пример запроса, который формирует python-requests:

GET /chatbot/about HTTP/1.1
Host: 192.168.2.83:5000
Connection: keep-alive
Accept-Encoding: gzip, deflate
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: python-requests/2.9.1

Пример запроса, который формирует curl (curl -v -u testbot:test -i http://192.168.2.83:5000/chatbot/about):

GET /chatbot/about HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: curl/7.47.0

В обоих случаях сервер ответил:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 305
Date: Fri, 02 Nov 2018 15:13:21 GMT

{
"text" : "Информация о проекте."
}

2. GET-запрос на /chatbot/questions

Пример запроса, который формирует python-requests:

GET /chatbot/questions HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: python-requests/2.9.1
Connection: keep-alive
Accept-Encoding: gzip, deflate

Пример запроса, который формирует curl (curl -v -u testbot:test -i http://192.168.2.83:5000/chatbot/questions):

GET /chatbot/questions HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: curl/7.47.0

В обоих случаях сервер ответил:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1086
Date: Fri, 02 Nov 2018 15:43:06 GMT

{
"text" : ["Что случилось?",
          "Срочно нужна твоя помощь.",
          "Ты уезжаешь?",
          ...]
}

3. POST-запрос на /chatbot/speech-to-text

Пример запроса, который формирует python-requests:

POST /chatbot/speech-to-text HTTP/1.1
Host: 192.168.2.83:5000
User-Agent: python-requests/2.9.1
Accept: */*
Content-Length: 10739
Connection: keep-alive
Content-Type: application/json
Authorization: Basic dGVzdGJvdDp0ZXN0
Accept-Encoding: gzip, deflate

{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}

Пример запроса, который формирует curl (curl -v -u testbot:test -i -H "Content-Type: application/json" -X POST -d '{"wav":"UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."}' http://192.168.2.83:5000/chatbot/speech-to-text):

POST /chatbot/speech-to-text HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: curl/7.47.0
Accept: */*
Content-Type: application/json
Content-Length: 10739

{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}

Сервер ответил:

HTTP/1.1 200 OK
Content-Length: 81
Date: Fri, 02 Nov 2018 15:57:13 GMT
Content-Type: application/json

{
"text" : "Распознные слова из аудиозаписи"
}

4. POST-запрос на /chatbot/text-to-speech

Пример запроса, который формирует python-requests:

POST /chatbot/text-to-speech HTTP/1.1
Host: 192.168.2.83:5000
Connection: keep-alive
Accept: */*
User-Agent: python-requests/2.9.1
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 73
Authorization: Basic dGVzdGJvdDp0ZXN0

{
"text" : "который час"
}

Пример запроса, который формирует curl (curl -v -u testbot:test -i -H "Content-Type: application/json" -X POST -d '{"text":"который час"}' http://192.168.2.83:5000/chatbot/text-to-speech):

POST /chatbot/text-to-speech HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: curl/7.47.0
Accept: */*
Content-Type: application/json
Content-Length: 32

{
"text" : "который час"
}

Сервер ответил:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 78151
Date: Fri, 02 Nov 2018 16:36:02 GMT

{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}

5. POST-запрос на /chatbot/text-to-text

Пример запроса, который формирует python-requests:

POST /chatbot/text-to-text HTTP/1.1
Host: 192.168.2.83:5000
Accept-Encoding: gzip, deflate
Content-Type: application/json
User-Agent: python-requests/2.9.1
Connection: keep-alive
Content-Length: 48
Accept: */*
Authorization: Basic dGVzdGJvdDp0ZXN0

{
"text" : "прощай"
}

Пример запроса, который формирует curl (curl -v -u testbot:test -i -H "Content-Type: application/json" -X POST -d '{"text":"прощай"}' http://192.168.2.83:5000/chatbot/text-to-text):

POST /chatbot/text-to-text HTTP/1.1
Host: 192.168.2.83:5000
Authorization: Basic dGVzdGJvdDp0ZXN0
User-Agent: curl/7.47.0
Accept: */*
Content-Type: application/json
Content-Length: 23

{
"text" : "прощай"
}

Сервер ответил:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 68
Date: Fri, 02 Nov 2018 16:41:22 GMT

{
"text" : "это снова я"
}

Предполагаемый алгоритм работы с сервером

  1. Запросить список вопросов у сервера (запрос 2) и отобразить его
  2. В зависимости от выбранного режима:
  • Записать речь с микрофона клиента
  • Отправить на сервер (запрос 3) и получить ответ с распознанным текстом
  • Отобразить текст в поле ввода
  • Отправить текст на сервер (запрос 5) и получить ответ бота
  • Отправить ответ бота на сервер (запрос 4) и получить аудиофайл с синтезированной речью
  • Воспроизвести аудиофайл
  1. Если клиент хочет узнать информацию о данном проекте, послать запрос 1 на сервер и отобразить полученные данные

Docker-образ с RESTful сервером

В проекте содержится Dockerfile, который позволяет собрать docker образ на основе данного проекта. Если для установки всех зависимостей вы использовали install_packages.sh и ранее Docker вы не устанавливали, вам необходимо установить его вручную. Например, так (проверено в Ubuntu 16.04-18.04):

sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
sudo apt-add-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main' -y
sudo apt-get -y update
sudo apt-get install -y docker-engine

После установки выполните sudo systemctl status docker что бы убедиться, что всё установилось и работает (в выводе данной команды вы найдёте строку с зелёным текстом active (running)).

Для сборки образа необходимо перейти в терминале в папку с проектом и выполнить (-t — запуск терминала, . — директория, из которой вызывается docker build (точка — значит в текущей директории находятся все файлы для образа), voice_chatbot:0.1 — метка образа и его версия):

sudo docker build -t voice_chatbot:0.1 .

После успешного выполнения данной операции вы можете вывести список имеющихся образов, выполнив:

sudo docker images

В полученном списке вы увидите наш образ — voice_chatbot:0.1.

Теперь вы можете запустить этот образ (-t — запуск терминала, -i — интерактивный режим, --rm — удалить контейнер после завершения его работы, -p 5000:5000 — пробросить все подключения на порт 5000 к машине-хосту в контейнер на порт 5000 (вы так же можете явно указать другой адрес, к которому нужно будет подключиться извне, например: -p 127.0.0.1:5000:5000)):

sudo docker run -ti --rm -p 5000:5000 voice_chatbot:0.1

В результате запустится RESTful сервер на 0.0.0.0:5000 и можно к нему обращаться по указанному в терминале адресу (если вы не указали другой при запуске образа).

Примечание: собранный docker-образ весит 5.2Гб. Исходные файлы проекта так же включают файл .dockerignore, в котором находятся имена файлов, которые не нужно добавлять в образ. Для минимизации размера итогового образа, из него были исключены все файлы, относящиеся к наборку данных из рассказов и из субтитров, файлы с промежуточными результатами обработки данных и обучения нейронной сети. Это значит, что образ содержит только файлы обученной сети и сырые исходные наборы данных.

На всякий случай, в исходных файлах проекта есть файл command_for_docker.txt, содержащий минимально необходимый набор команд для работы с docker.


Если у вас возникнут вопросы или вы хотите сотрудничать, можете написать мне на почту: [email protected] или в LinkedIn.

About

Chatbot in russian with speech recognition using PocketSphinx and speech synthesis using RHVoice. The AttentionSeq2Seq model is used. Imlemented using Python3+TensorFlow+Keras.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published