Das Projekt besteht aus zwei Teilen – einem Voice-Bot und einem RESTful-Server für die Interaktion damit.
Um den Bot lokal auszuführen, müssen Sie python3 bot.py
(oder run_bot.sh
) ausführen und die gewünschte Betriebsoption im vorgeschlagenen Menü auswählen (weitere Details hier).
Um einen RESTful-Server zu starten, der eine Schnittstelle für die Interaktion mit Voice-Bot-Modulen bereitstellt, müssen Sie python3 rest_server.py
(oder run_rest_server.sh
) ausführen (weitere Details hier).
Um ein Docker-Image basierend auf einem RESTful-Server zu erstellen, führen Sie sudo docker build -t voice_chatbot:0.1 .
(weitere Details hier).
AUFMERKSAMKEIT! Dies war mein Abschlussprojekt, daher sind die Architektur und der Code hier nicht sehr gut. Ich verstehe das und werde zu gegebener Zeit alles aktualisieren.
Eine vollständige Liste aller für den Betrieb erforderlichen Abhängigkeiten:
Voice_ChatBot_data.zip
(3 GB) manuell von Google Drive herunterladen und in das Stammverzeichnis des Projekts entpacken (Ordner data
und install_files
). Wenn Sie Ubuntu 16.04 oder höher verwenden, können Sie install_packages.sh
(getestet auf Ubuntu 16.04 und 18.04) verwenden, um alle Pakete zu installieren. Standardmäßig wird TensorFlow für CPU installiert. Wenn Sie eine NVIDIA-Grafikkarte mit der offiziellen Treiberversion 410 haben, können Sie TensorFlowGPU installieren. Dazu müssen Sie beim Ausführen von install_packages.sh
den Parameter gpu
übergeben. Zum Beispiel:
./install_packages.sh gpu
In diesem Fall werden 2 Archive von meinem Google Drive heruntergeladen:
Install_CUDA10.0_cuDNN_for410.zip
(2,0 GB) mit CUDA 10.0 und cuDNN 7.5.0 (wenn der gpu
Parameter übergeben wurde). Die Installation wird automatisch abgeschlossen, aber wenn etwas schief geht, gibt es im heruntergeladenen Archiv eine Install.txt
Anweisung.Voice_ChatBot_data.zip
(3 GB) mit Trainingsdaten und vorgefertigten Modellen. Es wird automatisch in data
und install_files
im Projektstammverzeichnis entpackt. Wenn Sie das Skript nicht zur Installation aller erforderlichen Pakete verwenden können oder möchten, müssen Sie RHVoice und CMUclmtk_v0.7 mithilfe der Anweisungen in install_files/Install RHVoice.txt
und install_files/Install CMUclmtk.txt
manuell installieren. Sie müssen außerdem die Sprach-, Akustikmodell- und Wörterbuchdateien für PocketSphinx von temp/
nach /usr/local/lib/python3.6/dist-packages/pocketsphinx/model
kopieren (Ihr Pfad zu python3.6
kann anders sein). Die Dateien des Sprachmodells prepared_questions_plays_ru.lm
und des Wörterbuchs prepared_questions_plays_ru.dic
müssen in ru_bot_plays_ru.lm
und ru_bot_plays_ru.dic
umbenannt werden (oder ihren Namen in speech_to_text.py
ändern, wenn Sie über ein eigenes Sprachmodell und Wörterbuch verfügen).
Der Bot basiert auf einem wiederkehrenden neuronalen Netzwerk, dem AttentionSeq2Seq-Modell. In der aktuellen Implementierung besteht es aus 2 bidirektionalen LSTM-Zellen im Encoder, einer Aufmerksamkeitsschicht und 2 LSTM-Zellen im Decoder. Mithilfe eines Aufmerksamkeitsmodells können Sie eine „weiche“ Korrespondenz zwischen Eingabe- und Ausgabesequenzen herstellen, was die Qualität und Produktivität verbessert. Die Eingabedimension in der letzten Konfiguration beträgt 500 und die Sequenzlänge beträgt 26 (d. h. die maximale Länge von Sätzen im Trainingssatz). Wörter werden mit dem Word2vec-Encoder (mit einem Wörterbuch von 445.000 Wörtern) aus der Gensim-Bibliothek in Vektoren umgewandelt. Das seq2seq-Modell wird mit Keras und RecurrentShop implementiert. Das trainierte seq2seq-Modell (dessen Gewichte sich in data/plays_ru/model_weights_plays_ru.h5
befinden) mit den in den Quelldateien angegebenen Parametern hat eine Genauigkeit von 99,19 % (d. h. der Bot wird 1577 von 1601 Fragen richtig beantworten).
Derzeit gibt es 3 Datensätze zum Trainieren des Bots: 1601 Frage-Antwort-Paare aus verschiedenen Stücken ( data/plays_ru
), 136.000 Paare aus verschiedenen Werken ( data/conversations_ru
, dank NLP Datasets) und 2.500.000 Paare aus Untertiteln für 347 TV-Serien ( data/subtitles_ru
, weitere Details im russischen Untertitel-Datensatz). Die word2vec-Modelle werden auf allen Datensätzen trainiert, das neuronale Netzwerk wird jedoch nur auf dem Playsets-Datensatz trainiert.
Das Training des Word2Vec-Modells und eines neuronalen Netzwerks anhand eines Datensatzes von Spielen ohne Änderung der Parameter dauert auf NVIDIA GTX 1070 und Intel Core i7 etwa 7,5 Stunden. Die Schulung zu Datensätzen aus Werken und Untertiteln auf dieser Hardware wird mindestens mehrere Tage dauern.
Der Bot kann in mehreren Modi arbeiten:
Das Trainingsset besteht aus 1600 Frage-%%-Antwortpaaren aus verschiedenen russischen Theaterstücken. Es wird in der Datei data/plays_ru/plays_ru.txt
gespeichert. Jedes Fragenpaar %% Antwort wird in eine neue Zeile geschrieben, d. h. Es gibt nur ein Paar in einer Zeile.
Alle für das Training notwendigen Phasen werden von den Methoden prepare()
oder load_prepared()
und train()
der Klasse TextToText
aus text_to_text.py
und der Methode build_language_model()
LanguageModel
aus dem Modul preparing_speech_to_text.py
ausgeführt. Oder Sie können die train()
Funktion des bot.py
Moduls verwenden.
Um den Bot im Trainingsmodus auszuführen, müssen Sie bot.py
mit dem train
-Parameter ausführen. Zum Beispiel so:
python3 bot.py train
Oder Sie können einfach bot.py
(oder run_bot.sh
) ausführen und Modus 1 und 1 aus dem vorgeschlagenen Menü auswählen.
Der Lernprozess besteht aus mehreren Phasen:
1. Vorbereitung des Trainingsbeispiels.
Zur Vorbereitung des Trainingsbeispiels wird das Modul source_to_prepared.py
, bestehend aus der Klasse SourceToPrepared
, verwendet. Diese Klasse liest einen Trainingssatz aus einer Datei, trennt Fragen und Antworten, entfernt nicht unterstützte Zeichen und Satzzeichen und wandelt die resultierenden Fragen und Antworten in Sequenzen fester Größe um (unter Verwendung von <PAD>
-Füllwörtern). Dieser Kurs bereitet auch Fragen an das Netzwerk vor und verarbeitet dessen Antworten. Zum Beispiel:
Eingabe: "Зачем нужен этот класс? %% Для подготовки данных"
Ausgabe: [['<PAD>', ..., '<PAD>', '?', 'класс', 'этот', 'нужен', 'Зачем', '<GO>'], ['Для', 'подготовки', 'данных', '<EOS>', '<PAD>', ..., '<PAD>']]
Das Trainingsbeispiel wird aus der Datei data/plays_ru/plays_ru.txt
gelesen, die konvertierten [Frage, Antwort]-Paare werden in der Datei data/plays_ru/prepared_plays_ru.pkl
gespeichert. Außerdem wird ein Histogramm der Größen von Fragen und Antworten erstellt, das in data/plays_ru/histogram_of_sizes_sentences_plays_ru.png
gespeichert wird.
Um ein Trainingsbeispiel aus einem auf Spielen basierenden Datensatz vorzubereiten, übergeben Sie einfach den Namen der entsprechenden Datei an die Methode prepare_all()
. Um ein Trainingsbeispiel aus einem auf Werken oder Untertiteln basierenden Datensatz vorzubereiten, müssen Sie zuerst combine_conversations()
oder combine_subtitles()
und dann preapre_all()
aufrufen.
2. Übersetzung von Wörtern in reale Vektoren.
Für diese Phase ist das Modul word_to_vec.py
verantwortlich, das aus der Klasse WordToVec
besteht. Diese Klasse kodiert Sequenzen fester Größe (d. h. unsere Fragen und Antworten) in reale Vektoren. Es wird der Word2vec-Encoder aus der Gensim-Bibliothek verwendet. Die Klasse implementiert Methoden zum gleichzeitigen Kodieren aller [Frage-Antwort]-Paare aus dem Trainingssatz in Vektoren sowie zum Kodieren einer Frage an das Netzwerk und zum Dekodieren ihrer Antwort. Zum Beispiel:
Eingabe: [['<PAD>', ..., '<PAD>', '?', 'класс', 'этот', 'нужен', 'Зачем', '<GO>'], ['Для', 'кодирования', 'предложений', '<EOS>', '<PAD>', ..., '<PAD>']]
Ausgabe: [[[0.43271607, 0.52814275, 0.6504923, ...], [0.43271607, 0.52814275, 0.6504923, ...], ...], [[0.5464854, 1.01612, 0.15063584, ...], [0.88263285, 0.62758327, 0.6659863, ...], ...]]
(d. h. jedes Wort wird als Vektor mit einer Länge von 500 codiert (dieser Wert kann geändert werden, das size
in der Methode build_word2vec()
))
Paare [Frage, Antwort] werden aus der Datei data/plays_ru/prepared_plays_ru.pkl
gelesen (die in der vorherigen Phase erhalten wurde; um die Qualität des Modells zu erweitern und zu verbessern, wird empfohlen, zusätzlich einen vorverarbeiteten Datensatz aus data/subtitles_ru/prepared_subtitles_ru.pkl
zu übergeben data/subtitles_ru/prepared_subtitles_ru.pkl
an die Methode build_word2vec()
) werden codierte Paare in der Datei data/plays_ru/encoded_plays_ru.npz
gespeichert . Außerdem wird während des Arbeitsprozesses eine Liste aller verwendeten Wörter erstellt, d. h. ein Wörterbuch, das in der Datei data/plays_ru/w2v_vocabulary_plays_ru.txt
gespeichert ist. Das trainierte word2vec-Modell wird auch in data/plays_ru/w2v_model_plays_ru.bin
gespeichert.
Um Wörter aus dem Trainingssatz in Vektoren zu übersetzen, übergeben Sie einfach den Namen der entsprechenden Datei an die Methode build_word2vec()
und legen Sie die gewünschten Parameter fest.
3. Netzwerkschulung.
In dieser Phase wird das seq2seq-Modell anhand zuvor vorbereiteter Daten trainiert. Verantwortlich dafür ist das Modul text_to_text.py
, bestehend aus der Klasse TextToText
. Diese Klasse trainiert das Netzwerk, speichert das Netzwerkmodell und die Gewichtungskoeffizienten und ermöglicht Ihnen eine bequeme Interaktion mit dem trainierten Modell.
Für das Training benötigen Sie eine Datei data/plays_ru/encoded_plays_ru.npz
die [Frage, Antwort]-Paare enthält, die in Vektoren codiert sind, die in der vorherigen Phase erhalten wurden. Während des Trainingsprozesses wird nach jeder 5. Epoche (dieser Wert kann geändert werden) das extreme Zwischenergebnis des Netzwerktrainings in der Datei data/plays_ru/model_weights_plays_ru_[номер_итерации].h5
und bei der letzten Iteration in der Datei data/plays_ru/model_weights_plays_ru.h5
gespeichert. data/plays_ru/model_weights_plays_ru.h5
(Iteration – ein Netzwerk-Trainingszyklus, eine bestimmte Anzahl von Epochen, danach werden die Gewichte in einer Datei gespeichert und Sie können beispielsweise die Genauigkeit des Netzwerks bewerten oder andere anzeigen Standardmäßig beträgt die Anzahl der Epochen 5 und die Gesamtzahl der Iterationen beträgt 200. Das Netzwerkmodell wird in der Datei data/plays_ru/model_plays_ru.json
gespeichert.
Nach dem Training des Netzwerks wird die Qualität des Trainings bewertet, indem alle Fragen an die Eingabe des trainierten Netzwerks gesendet und die Antworten des Netzwerks mit den Standardantworten aus dem Trainingssatz verglichen werden. Wenn die Genauigkeit des geschätzten Modells über 75 % liegt, werden die falschen Antworten aus dem Netzwerk in der Datei data/plays_ru/wrong_answers_plays_ru.txt
gespeichert (damit sie später analysiert werden können).
Um das Netzwerk zu trainieren, übergeben Sie einfach den Namen der entsprechenden Datei an die train()
Methode und legen Sie die gewünschten Parameter fest.
4. Erstellen eines Sprachmodells und Wörterbuchs für PocketSphinx.
Diese Phase ist erforderlich, wenn Spracherkennung verwendet werden soll. In dieser Phase werden ein statisches Sprachmodell und ein phonetisches Wörterbuch für PocketSphinx basierend auf Fragen aus dem Trainingssatz erstellt (Achtung: Je mehr Fragen im Trainingssatz enthalten sind, desto länger dauert es, bis PocketSphinx Sprache erkennt). Verwenden Sie dazu build_language_model()
(die text2wfreq, wfreq2vocab, text2idngram
und idngram2lm
von CMUclmtk_v0.7 zugreift) der Klasse LanguageModel
aus dem Modul „ preparing_speech_to_text.py
. Diese Methode verwendet Fragen aus der Datei mit dem ursprünglichen Trainingsbeispiel (bevor sie vom Modul source_to_prepared.py
vorbereitet werden), speichert das Sprachmodell in der Datei temp/prepared_questions_plays_ru.lm
und das Wörterbuch in temp/prepared_questions_plays_ru.dic
( plays_ru
kann ändern sich je nachdem, welches Trainingsset verwendet wurde). Am Ende der Arbeit werden das Sprachmodell und das Wörterbuch nach /usr/local/lib/python3.х/dist-packages/pocketsphinx/model
mit den Namen ru_bot_plays_ru.lm
und ru_bot_plays_ru.dic
kopiert ( plays_ru
kann sich ändern). Auf die gleiche Weise wie im vorherigen Schritt müssen Sie das Root-Benutzerkennwort eingeben.
Für die Interaktion mit dem trainierten seq2seq-Modell ist die Funktion predict()
(ein Wrapper über die Methode predict()
der Klasse TextToText
“ aus dem Modul text_to_text.py
“) des Moduls bot.py
vorgesehen. Diese Funktion unterstützt mehrere Betriebsarten. Im Textmodus, d.h. Wenn der Benutzer eine Frage über die Tastatur eingibt und das Netzwerk mit Text antwortet, wird nur die predict()
Methode der TextToText
-Klasse aus dem text_to_text.py
-Modul verwendet. Diese Methode akzeptiert eine Zeichenfolge mit einer Frage an das Netzwerk und gibt eine Zeichenfolge mit der Antwort des Netzwerks zurück. Zum Arbeiten benötigen Sie: die Datei data/plays_ru/w2v_model_plays_ru.bin
mit dem trainierten word2vec-Modell, die Datei data/plays_ru/model_plays_ru.json
mit den Parametern des Netzwerkmodells und die Datei data/plays_ru/model_weights_plays_ru.h5
mit dem Gewichte des trainierten Netzwerks.
Um den Bot in diesem Modus auszuführen, müssen Sie bot.py
mit dem predict
-Parameter ausführen. Zum Beispiel so:
python3 bot.py predict
Sie können auch einfach bot.py
(oder run_bot.sh
) ausführen und im vorgeschlagenen Menü Modus 2 und 1 auswählen.
Dieser Modus unterscheidet sich vom vorherigen darin, dass der Parameter speech_synthesis = True
an die Funktion predict()
bot.py
übergeben wird. Dies bedeutet, dass die Interaktion mit dem Netzwerk auf die gleiche Weise wie im Modus 2 abläuft, die Antwort des Netzwerks jedoch zusätzlich angesprochen wird.
Antworten äußern, d.h. Sprachsynthese, implementiert in der get()
-Methode der TextToSpeech
-Klasse aus dem text_to_speech.py
Modul. Diese Klasse erfordert die Installation von RHVoice-client und übergibt ihm mithilfe von Befehlszeilenargumenten die erforderlichen Parameter für die Sprachsynthese (Informationen zur Installation von RHVoice und Beispiele für den Zugriff auf RHVoice-client finden Sie in install_files/Install RHVoice.txt
). Die get()
Methode verwendet als Eingabe die Zeichenfolge, die in Sprache umgewandelt werden muss, und bei Bedarf den Namen der WAV-Datei, in der die synthetisierte Sprache gespeichert wird (mit einer Abtastrate von 32 kHz und einer Tiefe von 16 Bit, Mono; wenn nicht angegeben, wird die Sprache sofort nach der Synthese abgespielt. Beim Erstellen eines Objekts der TextToSpeech
-Klasse können Sie den Namen der zu verwendenden Stimme angeben. Es werden 4 Stimmen unterstützt: männlich Aleksandr und drei weiblich – Anna, Elena und Irina (weitere Details im RHVoice Wiki).
Um den Bot in diesem Modus auszuführen, müssen Sie bot.py
mit den Parametern predict -ss
ausführen. Zum Beispiel so:
python3 bot.py predict -ss
Sie können auch einfach bot.py
(oder run_bot.sh
) ausführen und im vorgeschlagenen Menü Modus 3 und 1 auswählen.
Um in diesem Modus zu arbeiten, müssen Sie den Parameter speech_recognition = True
an die Funktion predict()
des Moduls bot.py
übergeben. Das bedeutet, dass die Interaktion mit dem Netzwerk bzw. die Eingabe von Fragen per Sprache erfolgen wird.
Die Spracherkennung wird in der Methode get()
der Klasse SpeechToText
speech_to_text.py
implementiert. Diese Klasse verwendet PocketSphinx und ein Sprachmodell mit einem Wörterbuch ( ru_bot_plays_ru.lm
und ru_bot_plays_ru.dic
), die im Netzwerktrainingsmodus erstellt wurden. Die get()
Methode kann in zwei Modi arbeiten: from_file
– Spracherkennung aus einer .wav- oder .opus-Datei mit einer Abtastfrequenz >=16 kHz, 16 Bit, Mono (der Dateiname wird als Argument an die Funktion übergeben) und from_microphone
- Spracherkennung über ein Mikrofon. Der Betriebsmodus wird beim Erstellen einer Instanz der SpeechRecognition
-Klasse festgelegt, weil Das Laden des Sprachmodells dauert einige Zeit (je größer das Modell, desto länger dauert das Laden).
Um den Bot in diesem Modus auszuführen, müssen Sie bot.py
mit den Parametern predict -sr
ausführen. Zum Beispiel so:
python3 bot.py predict -sr
Sie können auch einfach bot.py
ausführen (oder run_bot.sh
ausführen) und im vorgeschlagenen Menü Modus 4 und 1 auswählen.
Dies ist eine Kombination aus Modus 3 und 4.
Um in diesem Modus zu arbeiten, müssen Sie die Parameter speech_recognition = True
und speech_synthesis = True
an die Funktion predict()
des Moduls bot.py
übergeben. Das bedeutet, dass Fragen per Sprache eingegeben und Netzwerkantworten gesprochen werden. Eine Beschreibung der verwendeten Module finden Sie in der Beschreibung der Modi 3 und 4.
Um den Bot in diesem Modus auszuführen, müssen Sie bot.py
mit den Parametern predict -ss -sr
ausführen. Zum Beispiel so:
python3 bot.py predict -sr -ss
oder
python3 bot.py predict -ss -sr
Sie können auch einfach bot.py
ausführen (oder run_bot.sh
ausführen) und im vorgeschlagenen Menü Modus 5 und 1 auswählen.
Dieser Server stellt eine REST-API für die Interaktion mit dem Bot bereit. Wenn der Server startet, wird ein neuronales Netzwerk geladen, das auf einem Datensatz von Plays trainiert wurde. Datensätze aus Werken und Untertiteln werden noch nicht unterstützt.
Der Server wird mit Flask und im Multithread-Modus (Produktionsversion) mit gevent.pywsgi.WSGIServer implementiert. Der Server hat außerdem eine Begrenzung der Größe der empfangenen Daten im Anforderungshauptteil von 16 MB. Die Implementierung befindet sich im Modul rest_server.py
.
Sie können den WSGI-Server starten, indem Sie run_rest_server.sh
ausführen (wobei der WSGI-Server bei 0.0.0.0:5000
gestartet wird).
Der Server unterstützt Befehlszeilenargumente, die den Start etwas erleichtern. Die Argumente haben die folgende Struktur: [ключ(-и)] [адрес:порт]
.
Mögliche Schlüssel:
-d
– einen Test-Flask-Server starten (wenn der Schlüssel nicht angegeben ist, wird der WSGI-Server gestartet)-s
– Starten Sie den Server mit https-Unterstützung (verwendet ein selbstsigniertes Zertifikat, das mit OpenSSL abgerufen wurde) Gültige Optionen адрес:порт
:
host:port
– Start auf dem angegebenen host
und port
localaddr:port
– Start mit automatischer Erkennung der Maschinenadresse im lokalen Netzwerk und des angegebenen port
host:0
oder localaddr:0
– wenn port = 0
, wird jeder verfügbare Port automatisch ausgewähltListe möglicher Kombinationen von Befehlszeilenargumenten und deren Beschreibung:
5000
. Beispiel: python3 rest_server.py
host:port
– Starten Sie den WSGI-Server auf dem angegebenen host
und port
. Beispiel: python3 rest_server.py 192.168.2.102:5000
-d
– Starten Sie einen Test-Flask-Server unter 127.0.0.1:5000
. Beispiel: python3 rest_server.py -d
-d host:port
– Starten Sie einen Test-Flask-Server auf dem angegebenen host
und port
. Beispiel: python3 rest_server.py -d 192.168.2.102:5000
-d localaddr:port
– Starten Sie einen Test-Flask-Server mit automatischer Erkennung der Maschinenadresse im lokalen Netzwerk und des Ports port
. Beispiel: python3 rest_server.py -d localaddr:5000
-s
– Starten Sie einen WSGI-Server mit https-Unterstützung, automatischer Erkennung der Maschinenadresse im lokalen Netzwerk und Port 5000
. Beispiel: python3 rest_server.py -s
-s host:port
– Starten Sie einen WSGI-Server mit https-Unterstützung auf dem angegebenen host
und port
. Beispiel: python3 rest_server.py -s 192.168.2.102:5000
-s -d
– Starten Sie einen Test-Flask-Server mit https-Unterstützung unter 127.0.0.1:5000
. Beispiel: python3 rest_server.py -s -d
-s -d host:port
– startet einen Test-Flask-Server mit https-Unterstützung auf dem angegebenen host
und port
. Beispiel: python3 rest_server.py -s -d 192.168.2.102:5000
-s -d localaddr:port
– startet einen Test-Flask-Server mit https-Unterstützung, automatischer Erkennung der Maschinenadresse im lokalen Netzwerk und Port port
. Beispiel: python3 rest_server.py -s -d localaddr:5000
Der Server kann den verfügbaren Port selbst auswählen; dazu müssen Sie Port 0
in host:port
oder localaddr:port
angeben (zum Beispiel: python3 rest_server.py -d localaddr:0
).
Insgesamt werden 5 Abfragen unterstützt:
/chatbot/about
gibt Informationen über das Projekt zurück/chatbot/questions
gibt eine Liste aller unterstützten Fragen zurück/chatbot/speech-to-text
, akzeptiert eine .wav/.opus-Datei und gibt die erkannte Zeichenfolge zurück/chatbot/text-to-speech
, nimmt einen String und gibt eine .wav-Datei mit synthetisierter Sprache zurück/chatbot/text-to-text
, akzeptiert eine Zeichenfolge und gibt die Antwort des Bots als Zeichenfolge zurück 1. Der Server verfügt über eine grundlegende HTTP-Autorisierung. Diese. Um Zugriff auf den Server zu erhalten, müssen Sie jeder Anfrage einen Header hinzufügen, der login:password enthält und mit base64
codiert ist (login: bot
, Passwort: test_bot
). Beispiel in Python:
import requests
import base64
auth = base64.b64encode('testbot:test'.encode())
headers = {'Authorization' : "Basic " + auth.decode()}
Es wird so aussehen:
Authorization: Basic dGVzdGJvdDp0ZXN0
2. In der Spracherkennungsanforderung (Nummer 3) erwartet der Server eine .wav- oder .opus-Datei (>=16 kHz 16 Bit Mono) mit aufgezeichneter Sprache, die ebenfalls mithilfe der base64
-Kodierung an JSON übertragen wird (d. h. öffnet .wav / .opus-Datei, in ein Byte-Array eingelesen, dann base64
kodiert, das resultierende Array wird aus der Byte-Form in einen String dekodiert utf-8
und in json platziert), in Python sieht es so aus:
# Формирование запроса
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. Bei der Anfrage zur Sprachsynthese (Nummer 4) sendet der Server eine JSON-Antwort mit einer WAV-Datei (16 Bit, 32 kHz Mono) mit synthetisierter Sprache, die wie oben beschrieben codiert wurde (um sie wieder zu decodieren, müssen Sie dies tun). Holen Sie sich von JSON die gewünschte Zeichenfolge in ein Byte-Array, dekodieren Sie sie dann mit base64
und schreiben Sie sie zur späteren Wiedergabe in eine Datei oder einen Stream. Beispiel in 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)
Alle übertragenen Daten werden in JSON verpackt (einschließlich fehlerhafter Antworten).
{
"text" : "Информация о проекте."
}
{
"text" : ["Вопрос 1",
"Вопрос 2",
"Вопрос 3"]
}
{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}
oder
{
"opus" : "ZFZm10IBUklQVZFZm10IBARLASBAAEOpH..."
}
Der Server sendet ihm:
{
"text" : "который час"
}
{
"text" : "который час"
}
Der Server sendet ihm:
{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}
{
"text" : "прощай"
}
Der Server sendet ihm:
{
"text" : "это снова я"
}
1. GET-Anfrage an /chatbot/about
Ein Beispiel für eine Anfrage, die python-requests
generiert:
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
Ein Beispiel für eine Anfrage, die Curl generiert ( 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
In beiden Fällen antwortete der Server:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 305
Date: Fri, 02 Nov 2018 15:13:21 GMT
{
"text" : "Информация о проекте."
}
2. GET-Anfrage an /chatbot/questions
Ein Beispiel für eine Anfrage, die python-requests
generiert:
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
Ein Beispiel für eine Anfrage, die Curl generiert ( 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
In beiden Fällen antwortete der Server:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1086
Date: Fri, 02 Nov 2018 15:43:06 GMT
{
"text" : ["Что случилось?",
"Срочно нужна твоя помощь.",
"Ты уезжаешь?",
...]
}
3. POST-Anfrage /chatbot/speech-to-text
Ein Beispiel für eine Anfrage, die python-requests
generiert:
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..."
}
Ein Beispiel für eine Anfrage, die Curl generiert ( 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..."
}
Der Server antwortete:
HTTP/1.1 200 OK
Content-Length: 81
Date: Fri, 02 Nov 2018 15:57:13 GMT
Content-Type: application/json
{
"text" : "Распознные слова из аудиозаписи"
}
4. POST-Anfrage /chatbot/text-to-speech
Ein Beispiel für eine Anfrage, die python-requests
generiert:
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" : "который час"
}
Ein Beispiel für eine Anfrage, die Curl generiert ( 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" : "который час"
}
Der Server antwortete:
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-Anfrage /chatbot/text-to-text
Ein Beispiel für eine Anfrage, die python-requests
generiert:
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" : "прощай"
}
Ein Beispiel für eine Anfrage, die Curl generiert ( 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" : "прощай"
}
Der Server antwortete:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 68
Date: Fri, 02 Nov 2018 16:41:22 GMT
{
"text" : "это снова я"
}
Das Projekt enthält eine Docker-Datei, mit der Sie ein Docker-Image basierend auf diesem Projekt erstellen können. Wenn Sie install_packages.sh
zum Installieren aller Abhängigkeiten verwendet haben und Docker noch nicht installiert haben, müssen Sie es manuell installieren. Zum Beispiel so (getestet auf 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
Führen Sie nach der Installation sudo systemctl status docker
aus, um sicherzustellen, dass alles installiert ist und funktioniert (in der Ausgabe dieses Befehls finden Sie eine Zeile mit grünem Text active (running)
).
Um das Image zu erstellen, müssen Sie im Terminal in den Ordner mit dem Projekt gehen und ausführen ( -t
– Terminal starten, .
– das Verzeichnis, aus dem Docker Build aufgerufen wird (Punkt – das bedeutet, dass sich alle Dateien für das Image in befinden das aktuelle Verzeichnis), voice_chatbot:0.1
- Bildbezeichnung und seine Version):
sudo docker build -t voice_chatbot:0.1 .
Nachdem Sie diesen Vorgang erfolgreich abgeschlossen haben, können Sie die verfügbaren Bilder auflisten, indem Sie Folgendes ausführen:
sudo docker images
In der resultierenden Liste sehen Sie unser Bild - voice_chatbot:0.1
.
Jetzt können Sie dieses Image ausführen ( -t
– Terminal starten, -i
– interaktiver Modus, --rm
– Container löschen, nachdem er fertig ist, -p 5000:5000
– alle Verbindungen auf Port 5000 an den Host-Rechner weiterleiten Container auf dem Port 5000 (Sie können auch explizit eine andere Adresse angeben, zu der Sie sich extern verbinden müssen, zum Beispiel: -p 127.0.0.1:5000:5000
)):
sudo docker run -ti --rm -p 5000:5000 voice_chatbot:0.1
Dadurch startet der RESTful-Server bei 0.0.0.0:5000
und Sie können unter der im Terminal angegebenen Adresse darauf zugreifen (sofern Sie beim Starten des Images keine andere angegeben haben).
Hinweis : Das zusammengesetzte Docker-Image wiegt 5,2 GB. Zu den Quelldateien des Projekts gehört auch eine .dockerignore
Datei, die die Namen von Dateien enthält, die nicht zum Image hinzugefügt werden müssen. Um die Größe des endgültigen Bildes zu minimieren, wurden alle Dateien, die sich auf den Datensatz aus Geschichten und Untertiteln beziehen, Dateien mit Zwischenergebnissen der Datenverarbeitung und des Trainings neuronaler Netze davon ausgeschlossen. Das bedeutet, dass das Bild nur die trainierten Netzwerkdateien und Rohquelldatensätze enthält.
Für alle Fälle gibt es in den Quelldateien des Projekts eine Datei command_for_docker.txt
, die den minimal erforderlichen Befehlssatz für die Arbeit mit Docker enthält.
Wenn Sie Fragen haben oder zusammenarbeiten möchten, können Sie mir unter [email protected] oder auf LinkedIn schreiben.