يتكون المشروع من جزأين - روبوت صوتي وخادم RESTful للتفاعل معه.
لتشغيل الروبوت محليًا، تحتاج إلى تشغيل python3 bot.py
(أو run_bot.sh
) وتحديد خيار التشغيل المطلوب في القائمة المقترحة (مزيد من التفاصيل هنا).
لبدء تشغيل خادم RESTful الذي يوفر واجهة للتفاعل مع وحدات الروبوت الصوتي، تحتاج إلى تشغيل python3 rest_server.py
(أو run_rest_server.sh
) (مزيد من التفاصيل هنا).
لإنشاء صورة عامل إرساء استنادًا إلى خادم RESTful، قم بتشغيل sudo docker build -t voice_chatbot:0.1 .
(مزيد من التفاصيل هنا).
انتباه! كان هذا مشروع تخرجي، لذا فإن البنية والرمز هنا ليسا جيدين جدًا، وأنا أفهم ذلك، وبمجرد أن يتوفر لدي الوقت، سأقوم بتحديث كل شيء.
قائمة كاملة بجميع التبعيات المطلوبة للتشغيل:
Voice_ChatBot_data.zip
(3 جيجا بايت) يدويًا من Google Drive وفك ضغطه في جذر المشروع (مجلدات data
و install_files
). إذا كنت تستخدم Ubuntu 16.04 أو أعلى، فيمكنك استخدام install_packages.sh
(تم اختباره على Ubuntu 16.04 و18.04) لتثبيت جميع الحزم. افتراضيًا، سيتم تثبيت TensorFlow لوحدة المعالجة المركزية. إذا كان لديك بطاقة رسومات nvidia مثبت عليها إصدار برنامج التشغيل الرسمي 410، فيمكنك تثبيت TensorFlowGPU. للقيام بذلك، تحتاج إلى تمرير معلمة gpu
عند تشغيل install_packages.sh
. على سبيل المثال:
./install_packages.sh gpu
في هذه الحالة، سيتم تنزيل أرشيفين من Google Drive:
Install_CUDA10.0_cuDNN_for410.zip
(2.0 جيجا بايت) مع CUDA 10.0 وcuDNN 7.5.0 (إذا تم تمرير معلمة gpu
). سيتم إكمال التثبيت تلقائيًا، ولكن إذا حدث خطأ ما، فهناك تعليمات Install.txt
في الأرشيف الذي تم تنزيله.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. في التنفيذ الحالي، يتكون من خليتين LSTM ثنائي الاتجاه في جهاز التشفير، وطبقة انتباه، وخليتين LSTM في جهاز فك التشفير. يتيح لك استخدام نموذج الانتباه إنشاء مراسلات "ناعمة" بين تسلسلات الإدخال والإخراج، مما يؤدي إلى تحسين الجودة والإنتاجية. البعد المدخل في التكوين الأخير هو 500 وطول التسلسل هو 26 (أي الحد الأقصى لطول الجمل في مجموعة التدريب). يتم تحويل الكلمات إلى متجهات باستخدام برنامج تشفير word2vec (مع قاموس يضم 445000 كلمة) من مكتبة gensim. يتم تنفيذ نموذج seq2seq باستخدام Keras وRecurrentShop. يتمتع نموذج seq2seq المُدرب (الذي توجد أوزانه في data/plays_ru/model_weights_plays_ru.h5
) مع المعلمات المحددة في الملفات المصدر بدقة تبلغ 99.19% (أي أن الروبوت سوف يجيب على 1577 سؤالًا من أصل 1601 سؤالًا بشكل صحيح).
في الوقت الحالي، هناك 3 مجموعات من البيانات لتدريب الروبوت: 1601 زوجًا من الأسئلة والأجوبة من مسرحيات مختلفة ( data/plays_ru
)، و136000 زوجًا من أعمال مختلفة ( data/conversations_ru
، بفضل مجموعات بيانات البرمجة اللغوية العصبية) و2500000 زوجًا من الترجمات المصاحبة لـ 347 مسلسل تلفزيوني ( data/subtitles_ru
، مزيد من التفاصيل في مجموعة بيانات الترجمة الروسية). يتم تدريب نماذج word2vec على جميع مجموعات البيانات، ولكن يتم تدريب الشبكة العصبية فقط على مجموعة بيانات مجموعات التشغيل.
يستغرق تدريب نموذج word2vec والشبكة العصبية على مجموعة بيانات من عمليات التشغيل دون تغيير المعلمات حوالي 7.5 ساعة على nvidia gtx1070 وintel core i7. سيستمر التدريب على مجموعات البيانات من الأعمال والترجمات على هذا الجهاز عدة أيام على الأقل.
يمكن للبوت أن يعمل في عدة أوضاع:
تتكون مجموعة التدريب من 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
(الذي تم الحصول عليه في المرحلة السابقة؛ لتوسيع وتحسين جودة النموذج، يوصى بالإضافة إلى ذلك بتمرير مجموعة بيانات تمت معالجتها مسبقًا من data/subtitles_ru/prepared_subtitles_ru.pkl
الترجمة data/subtitles_ru/prepared_subtitles_ru.pkl
إلى طريقة build_word2vec()
) ، يتم حفظ الأزواج المشفرة في ملف 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
يحتوي على أزواج [سؤال، إجابة] مشفرة في المتجهات التي تم الحصول عليها في المرحلة السابقة. أثناء عملية التدريب، بعد كل فترة خامسة (يمكن تغيير هذه القيمة)، يتم حفظ النتيجة المتوسطة القصوى لتدريب الشبكة في الملف 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
في بنفس الطريقة كما في المرحلة السابقة، سوف تحتاج إلى إدخال كلمة مرور المستخدم الجذر).
للتفاعل مع نموذج 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 في القائمة المقترحة.
يختلف هذا الوضع عن الوضع السابق حيث يتم تمرير المعلمة speech_synthesis = True
إلى وظيفة predict()
الخاصة بوحدة bot.py
وهذا يعني أن التفاعل مع الشبكة سيستمر بنفس الطريقة كما في الوضع 2، ولكن سيتم أيضًا التعبير عن استجابة الشبكة.
الإجابات الصوتية ، أي. تركيب الكلام، الذي يتم تنفيذه في طريقة get()
لفئة TextToSpeech
من الوحدة text_to_speech.py
. تتطلب هذه الفئة تثبيت عميل RHVoice، وباستخدام وسيطات سطر الأوامر، تمرر له المعلمات الضرورية لتركيب الكلام (يمكنك الاطلاع على كيفية تثبيت RHVoice وأمثلة للوصول إلى عميل RHVoice في install_files/Install RHVoice.txt
). تأخذ طريقة get()
كمدخلات السلسلة التي تحتاج إلى تحويلها إلى كلام، وإذا لزم الأمر، اسم ملف wav الذي سيتم حفظ الكلام المركب فيه (بمعدل أخذ عينات يبلغ 32 كيلو هرتز وعمق 16 بت، أحادية إذا لم يتم تحديدها، سيتم تشغيل الكلام مباشرة بعد التوليف). عند إنشاء كائن من فئة TextToSpeech
، يمكنك تحديد اسم الصوت الذي سيتم استخدامه. يتم دعم 4 أصوات: ذكر ألكسندر وثلاثة أصوات إناث - آنا وإيلينا وإيرينا (مزيد من التفاصيل في RHVoice Wiki).
لتشغيل الروبوت في هذا الوضع، تحتاج إلى تشغيل bot.py
باستخدام معلمات predict -ss
. على سبيل المثال، مثل هذا:
python3 bot.py predict -ss
يمكنك أيضًا تشغيل bot.py
(أو تشغيل run_bot.sh
) واختيار الوضع 3 و1 في القائمة المقترحة.
للعمل في هذا الوضع، تحتاج إلى تمرير المعلمة speech_recognition = True
إلى وظيفة predict()
الخاصة بوحدة bot.py
وهذا يعني أن التفاعل مع الشبكة، أو بالأحرى إدخال الأسئلة، سيتم باستخدام الصوت.
يتم تنفيذ التعرف على الكلام في طريقة get()
لفئة SpeechToText
من وحدة speech_to_text.py
. يستخدم هذا الفصل PocketSphinx ونموذج اللغة مع القاموس ( ru_bot_plays_ru.lm
و ru_bot_plays_ru.dic
)، والتي تم إنشاؤها في وضع التدريب على الشبكة. يمكن أن تعمل طريقة get()
في وضعين: from_file
- التعرف على الكلام من ملف .wav أو .opus بتردد أخذ العينات > = 16 كيلو هرتز، 16 بت، أحادي (يتم تمرير اسم الملف كوسيطة دالة) و from_microphone
- الكلام التعرف من الميكروفون. يتم ضبط وضع التشغيل عند إنشاء مثيل لفئة SpeechRecognition
، لأنه يستغرق تحميل نموذج اللغة بعض الوقت (كلما كان النموذج أكبر، كلما استغرق تحميله وقتًا أطول).
لتشغيل الروبوت في هذا الوضع، تحتاج إلى تشغيل bot.py
باستخدام المعلمات predict -sr
. على سبيل المثال، مثل هذا:
python3 bot.py predict -sr
يمكنك أيضًا تشغيل bot.py
(أو تشغيل run_bot.sh
) واختيار الوضع 4 و1 في القائمة المقترحة.
هذا مزيج من الوضعين 3 و 4.
للعمل في هذا الوضع، تحتاج إلى تمرير المعلمات speech_recognition = True
و speech_synthesis = True
لوظيفة predict()
لوحدة bot.py
وهذا يعني أنه سيتم إدخال الأسئلة باستخدام الصوت، وسيتم نطق إجابات الشبكة. يمكن العثور على وصف للوحدات المستخدمة في وصف الوضعين 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 في القائمة المقترحة.
يوفر هذا الخادم واجهة REST API للتفاعل مع الروبوت. عندما يبدأ الخادم، يتم تحميل شبكة عصبية تم تدريبها على مجموعة بيانات من عمليات التشغيل. مجموعات البيانات من الأعمال والترجمات غير مدعومة بعد.
يتم تنفيذ الخادم باستخدام Flask، ووضع متعدد الخيوط (إصدار الإنتاج) باستخدام gevent.pywsgi.WSGIServer. لدى الخادم أيضًا حدًا لحجم البيانات المستلمة في نص الطلب يساوي 16 ميجابايت. يتم التنفيذ في وحدة rest_server.py
.
يمكنك بدء تشغيل خادم WSGI عن طريق تشغيل run_rest_server.sh
(بدء تشغيل خادم WSGI على 0.0.0.0:5000
).
يدعم الخادم وسيطات سطر الأوامر، مما يجعل بدء تشغيله أسهل قليلاً. تحتوي الوسائط على البنية التالية: [ключ(-и)] [адрес:порт]
.
المفاتيح المحتملة:
-d
- تشغيل خادم Flask اختباري (إذا لم يتم تحديد المفتاح، فسيتم تشغيل خادم WSGI)-s
- بدء تشغيل الخادم بدعم https (يستخدم شهادة موقعة ذاتيًا، يتم الحصول عليها باستخدام opensl) адрес:порт
:
host:port
- التشغيل على host
port
المحددينlocaladdr:port
- التشغيل مع الاكتشاف التلقائي لعنوان الجهاز على الشبكة المحلية port
المحددhost:0
أو localaddr:0
- إذا كان port = 0
، فسيتم تحديد أي منفذ متاح تلقائيًاقائمة المجموعات المحتملة لوسائط سطر الأوامر ووصفها:
5000
. على سبيل المثال: python3 rest_server.py
host:port
- قم بتشغيل خادم WSGI على host
port
المحددين. على سبيل المثال: python3 rest_server.py 192.168.2.102:5000
-d
- إطلاق خادم Flask الاختباري على 127.0.0.1:5000
. على سبيل المثال: python3 rest_server.py -d
-d host:port
- قم بتشغيل خادم Flask الاختباري على host
port
المحددين. على سبيل المثال: python3 rest_server.py -d 192.168.2.102:5000
-d localaddr:port
- إطلاق خادم Flask اختباري مع الكشف التلقائي عن عنوان الجهاز على الشبكة المحلية port
المنفذ. على سبيل المثال: python3 rest_server.py -d localaddr:5000
-s
- تشغيل خادم WSGI بدعم https، والاكتشاف التلقائي لعنوان الجهاز على الشبكة المحلية والمنفذ 5000
. على سبيل المثال: python3 rest_server.py -s
-s host:port
- قم بتشغيل خادم WSGI بدعم https على host
port
المحددين. على سبيل المثال: python3 rest_server.py -s 192.168.2.102:5000
-s -d
- إطلاق خادم Flask اختباري بدعم https على 127.0.0.1:5000
. على سبيل المثال: python3 rest_server.py -s -d
-s -d host:port
- يطلق خادم Flask اختباري بدعم https على host
port
المحددين. على سبيل المثال: python3 rest_server.py -s -d 192.168.2.102:5000
-s -d localaddr:port
- يطلق خادم Flask اختباري بدعم https، والاكتشاف التلقائي لعنوان الجهاز على الشبكة المحلية port
المنفذ. على سبيل المثال: python3 rest_server.py -s -d localaddr:5000
يمكن للخادم اختيار المنفذ المتاح نفسه؛ للقيام بذلك، تحتاج إلى تحديد المنفذ 0
في host:port
أو localaddr:port
(على سبيل المثال: python3 rest_server.py -d localaddr:0
).
يتم دعم إجمالي 5 استعلامات:
/chatbot/about
سيعيد معلومات حول المشروع/chatbot/questions
إلى عرض قائمة بجميع الأسئلة المدعومة/chatbot/speech-to-text
، ويقبل ملف wav/.opus ويعيد السلسلة التي تم التعرف عليها/chatbot/text-to-speech
، يأخذ سلسلة ويعيد ملف wav. مع الكلام المركب/chatbot/text-to-text
، ويقبل سلسلة ويعيد استجابة الروبوت كسلسلة 1. يتمتع الخادم بتخويل http الأساسي. أولئك. للوصول إلى الخادم، تحتاج إلى إضافة رأس لكل طلب يحتوي على تسجيل الدخول: كلمة المرور، المشفرة باستخدام base64
(تسجيل الدخول: bot
، كلمة المرور: test_bot
). مثال في بيثون:
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)، في بيثون يبدو كما يلي:
# Формирование запроса
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
واكتبها في ملف أو دفق لتشغيلها لاحقًا)، مثال في بيثون:
# Формирование запроса
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 (بما في ذلك الاستجابات التي تحتوي على أخطاء).
{
"text" : "Информация о проекте."
}
{
"text" : ["Вопрос 1",
"Вопрос 2",
"Вопрос 3"]
}
{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}
أو
{
"opus" : "ZFZm10IBUklQVZFZm10IBARLASBAAEOpH..."
}
سوف يرسل له الخادم:
{
"text" : "который час"
}
{
"text" : "который час"
}
سوف يرسل له الخادم:
{
"wav" : "UklGRuTkAABXQVZFZm10IBAAAAABAAEAAH..."
}
{
"text" : "прощай"
}
سوف يرسل له الخادم:
{
"text" : "это снова я"
}
1. احصل على طلب إلى /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 -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. احصل على طلب إلى /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 -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. نشر الطلب إلى /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 -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. نشر الطلب إلى /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 -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. إرسال الطلب إلى /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" : "это снова я"
}
يحتوي المشروع على ملف Dockerfile، والذي يسمح لك ببناء صورة عامل إرساء بناءً على هذا المشروع. إذا استخدمت 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
- تشغيل المحطة، .
- الدليل الذي يتم استدعاء بناء عامل الإرساء منه (نقطة - وهذا يعني أن جميع ملفات الصورة موجودة الدليل الحالي)، 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
ويمكنك الوصول إليه على العنوان المحدد في الوحدة الطرفية (إذا لم تحدد عنوانًا مختلفًا عند بدء الصورة).
ملاحظة : تزن صورة عامل الإرساء المجمعة 5.2 جيجابايت. تتضمن الملفات المصدر للمشروع أيضًا ملف .dockerignore
، الذي يحتوي على أسماء الملفات التي لا تحتاج إلى إضافتها إلى الصورة. ولتقليل حجم الصورة النهائية تم استبعاد جميع الملفات المتعلقة بمجموعة البيانات من القصص والعناوين الفرعية والملفات ذات النتائج المتوسطة لمعالجة البيانات وتدريب الشبكات العصبية. وهذا يعني أن الصورة تحتوي فقط على ملفات الشبكة المدربة ومجموعات بيانات المصدر الأولية.
فقط في حالة وجود ملف command_for_docker.txt
في الملفات المصدر للمشروع، والذي يحتوي على الحد الأدنى من مجموعة الأوامر المطلوبة للعمل مع عامل الإرساء.
إذا كان لديك أي أسئلة أو كنت ترغب في التعاون، يمكنك الكتابة لي على [email protected] أو على LinkedIn.