Създаване на умение за състояние за Alice с помощта на безсървърни функции на Yandex.Cloud и Python

Да започнем с новините. Вчера Yandex.Cloud обяви стартирането на компютърна услуга без сървър Облачни функции на Yandex. Това означава: вие само пишете кода за вашата услуга (например уеб приложение или чатбот), а самият облак създава и поддържа виртуалните машини, където работи, и дори ги репликира, ако натоварването се увеличи. Изобщо не е нужно да мислите, много е удобно. И плащането е само за времето за изчисление.

Някои обаче може изобщо да не плащат. Това са разработчиците Външните умения на Алис, тоест вградени в него чатботове. Всеки програмист може да напише, хоства и регистрира такова умение, а от днес уменията дори не е необходимо да бъдат хоствани - просто качете своя код в облака във формата същата функция без сървър.

Но има няколко нюанса. Първо, вашият pit код може да изисква някои зависимости и плъзгането им в облака не е тривиално. Второ, всеки нормален чатбот трябва да съхранява някъде състоянието на диалога (следователно със състояние); Какъв е най-лесният начин да направите това във функция без сървър? Трето, как можете да напишете бързо и мръсно умение за Алис или дори някакъв вид бот с ненулев сюжет? Статията всъщност е за тези нюанси.

Създаване на умение за състояние за Alice с помощта на безсървърни функции на Yandex.Cloud и Python

Морална подготовка

За нетърпеливите: събирам необходимите зависимости с makefile, преди да кача функцията в облака, съхранявам състоянието на диалоговия прозорец в Yandex Object Storage (той поддържа S3 API) и използвам собствената си библиотека, за да управлявам диалоговия прозорец tgalice. В крайна сметка се оказва такъв демонстрационно умение. Сега нека разгледаме всичко това малко по-подробно.

За тези малко по-малко нетърпеливи, преди да се потопите в моята история за сложността, силно препоръчвам да започнете с нещо просто. А именно, създайте еднофайлова функция echobot, регистрирайте се и я тествайте в конзолата за разработчици Dialogs; подробности - в Блог за диалози и Облачна документация. И едва тогава започнете.

Ако искате веднага да почувствате за какво се борим тук, попитайте Алисактивирайте умението „ИТ хороскоп“.'. Трябва да се получи диалог, подобен на следния:

Алис: Здравей! Вие сте в умението „ИТ хороскоп“. Кажете „Старт“, за да разберете какво ви обещават звездите.
Потребител: Старт
О: Моля, посочете името си
Ю: Васисуалий
О: Сега ми кажете годината на вашето раждане. Само четири цифри, нищо допълнително.
Ю: Второ
О: Моля, опитайте отново. Въведете годината на вашето раждане - четири цифри.
Ю: 2002 г
Чудесна! Сега назовете месеца на раждане.
Ю: Февруари
Чудесна! Накрая ми кажи датата си на раждане - само цифра, само една или две цифри.
Ю: 18 г
A: Благодаря ти, Vasisualiy! Сега знаем: вие сте на 17 години и сте Водолей. Е, разбира се, имате късмет! Звездите ви казват: а что говорят звёзды, вы узнаете, запустив навык.

Проблемът е, че за да поддържате дори такъв прост диалог, трябва да запомните името и датата на раждане на потребителя, а в среда на функциониране без сървър това е нетривиално. Няма да е възможно да съхранявате контекста в RAM или като файл на диск, т.к Yandex.Cloud може да изпълнява функция на няколко виртуални машини едновременно и да превключва между тях по желание. Ще трябва да използвате някакво външно хранилище. Object Storage беше избрано като сравнително евтино и неусложнено хранилище директно в Yandex.Cloud (т.е. вероятно бързо). Като безплатна алтернатива можете да опитате например безплатно парче Облачно Монга някъде далеч. Има удобни обвивки на Python както за Object Storage (което поддържа интерфейса S3), така и за Mongo.

Друг проблем е, че за да получите достъп до Object Storage, MongoDB и всяка друга база данни или хранилище на данни, имате нужда от някои външни зависимости, които трябва да бъдат качени в Yandex Functions заедно с кода на вашата функция. И бих искал да направя това удобно. За съжаление, няма да е напълно удобно (като при Heroku), но може да се създаде някакъв основен комфорт чрез написване на скрипт за изграждане на средата (make file).

Как да стартирате умение за хороскоп

  1. Подгответе се: отидете на някоя машина с Linux. По принцип вероятно можете да работите и с Windows, но тогава ще трябва да направите малко магия със стартирането на makefile. И във всеки случай ще ви е необходим поне инсталиран Python 3.6.
  2. Клонирайте го от Github пример за умения за хороскоп.
  3. Регистрирайте се в Y.Cloud: https://cloud.yandex.ru
  4. Създайте си две кофи Съхранение на обекти, наричайте ги с произволно име {BUCKET NAME} и tgalice-test-cold-storage (това второ име вече е твърдо кодирано main.py моят пример). Първата кофа ще е необходима само за внедряване, втората - за съхраняване на диалогови състояния.
  5. създавам сервизен акаунт, дай му роля editorи вземете статични идентификационни данни за него {KEY ID} и {KEY VALUE} — ще ги използваме, за да запишем състоянието на диалога. Всичко това е необходимо, за да може функция от Ya.Cloud да има достъп до хранилището от Ya.Cloud. Някой ден, надявам се, авторизацията ще стане автоматична, но засега е така.
  6. (По избор) инсталиране интерфейс на командния ред yc. Можете също да създадете функция чрез уеб интерфейса, но CLI е добър, защото в него се появяват всякакви нововъведения по-бързо.
  7. Сега можете действително да подготвите сборката на зависимостите: стартирайте от командния ред от папката с примера за умение make all. В папката ще бъдат инсталирани куп библиотеки (предимно, както обикновено, ненужни). dist.
  8. Изсипете в Object Storage на ръка (в кофата {BUCKET NAME}) архив, получен в предишната стъпка dist.zip. Ако желаете, можете да направите това от командния ред, например с помощта на AWS CLI.
  9. Създайте функция без сървър чрез уеб интерфейса или с помощта на помощна програма yc. За помощната програма командата ще изглежда така:

yc serverless function version create
    --function-name=horoscope
    --environment=AWS_ACCESS_KEY_ID={KEY ID},AWS_SECRET_ACCESS_KEY={KEY VALUE}
    --runtime=python37
    --package-bucket-name={BUCKET NAME}
    --package-object-name=dist.zip
    --entrypoint=main.alice_handler
    --memory=128M
    --execution-timeout=3s

При ръчно създаване на функция всички параметри се попълват по същия начин.

Сега създадената от вас функция може да бъде тествана чрез конзолата за разработчици и след това умението може да бъде подобрено и публикувано.

Създаване на умение за състояние за Alice с помощта на безсървърни функции на Yandex.Cloud и Python

Какво има под капака

Makefile всъщност съдържа доста прост скрипт за инсталиране на зависимости и поставянето им в архив dist.zip, приблизително така:

mkdir -p dist/
pip3 install -r requirements.txt --target dist/ 
cp main.py dist/main.py
cp form.yaml dist/form.yaml
cd dist && zip --exclude '*.pyc' -r ../dist.zip ./*

Останалото са няколко прости инструмента, обвити в библиотека tgalice. Процесът на попълване на потребителски данни е описан от конфигурацията form.yaml:

form_name: 'horoscope_form'
start:
  regexp: 'старт|нач(ать|ни)'
  suggests:
    - Старт
fields:
  - name: 'name'
    question: Пожалуйста, назовите своё имя.
  - name: 'year'
    question: Теперь скажите мне год вашего рождения. Только четыре цифры, ничего лишнего.
    validate_regexp: '^[0-9]{4}$'
    validate_message: Пожалуйста, попробуйте ещё раз. Назовите год вашего рождения - четыре цифры.
  - name: 'month'
    question: Замечательно! Теперь назовите месяц вашего рождения.
    options:
      - январь
     ...
      - декабрь
    validate_message: То, что вы назвали, не похоже на месяц. Пожалуйста, назовите месяц вашего рождения, без других слов.
  - name: 'day'
    question: Отлично! Наконец, назовите мне дату вашего рождения - только число, всего одна или две цифры.
    validate_regexp: '[0123]?d$'
    validate_message: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

Работата по анализирането на тази конфигурация и изчисляването на крайния резултат се поема от класа Python

class CheckableFormFiller(tgalice.dialog_manager.form_filling.FormFillingDialogManager):
    SIGNS = {
        'январь': 'Козерог',
        ...
    }

    def handle_completed_form(self, form, user_object, ctx):
        response = tgalice.dialog_manager.base.Response(
            text='Спасибо, {}! Теперь мы знаем: вам {} лет, и вы {}. n'
                 'Вот это вам, конечно, повезло! Звёзды говорят вам: {}'.format(
                form['fields']['name'],
                2019 - int(form['fields']['year']),
                self.SIGNS[form['fields']['month']],
                random.choice(FORECASTS),
            ),
            user_object=user_object,
        )
        return response

По-точно базовият клас FormFillingDialogManager се занимава с попълването на „формуляра“ и метода на дъщерния клас handle_completed_form й казва какво да прави, когато е готова.

В допълнение към този основен поток от диалог, потребителят трябва също да бъде поздравен, както и да му бъде дадена помощ с помощта на командата „помощ“ и освободен от умението с помощта на командата „изход“. За целта в tgalice Има и шаблон, така че целият диалогов мениджър е съставен от части:

dm = tgalice.dialog_manager.CascadeDialogManager(
    tgalice.dialog_manager.GreetAndHelpDialogManager(
        greeting_message=DEFAULT_MESSAGE,
        help_message=DEFAULT_MESSAGE,
        exit_message='До свидания, приходите в навык "Айтишный гороскоп" ещё!'
    ),
    CheckableFormFiller(`form.yaml`, default_message=DEFAULT_MESSAGE)
)

CascadeDialogManager Работи просто: опитва се последователно да приложи всички свои компоненти към текущото състояние на диалога и избира първия подходящ.

Диалоговият мениджър връща обект на Python като отговор на всяко съобщение. Response, който след това може да бъде преобразуван в обикновен текст или в съобщение в Alice или Telegram - в зависимост от това къде работи ботът; също така съдържа промененото състояние на диалога, което трябва да бъде запазено. Цялата тази кухня се управлява от друг клас, DialogConnector, така че директният скрипт за стартиране на умение на Yandex Functions изглежда така:

...
session = boto3.session.Session()
s3 = session.client(
    service_name='s3',
    endpoint_url='https://storage.yandexcloud.net',
    aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
    region_name='ru-central1',
)
storage = tgalice.session_storage.S3BasedStorage(s3_client=s3, bucket_name='tgalice-test-cold-storage')
connector = tgalice.dialog_connector.DialogConnector(dialog_manager=dm, storage=storage)
alice_handler = connector.serverless_alice_handler

Както можете да видите, по-голямата част от този код създава връзка към S3 интерфейса на Object Storage. Можете да прочетете как тази връзка се използва директно в tgalice код.
Последният ред създава функцията alice_handler — същият, който казахме на Yandex.Cloud да изтегли, когато зададохме параметъра --entrypoint=main.alice_handler.

Това е всичко, всъщност. Makefiles за асемблиране, S3-подобно Object Storage за съхраняване на контекст и библиотека на Python tgalice. В комбинация с безсървърните функции и изразителността на Python, това е достатъчно, за да развиете здрави човешки умения.

Може да попитате защо е необходимо да се създаде tgalice? Целият скучен код, който прехвърля JSON от заявка към отговор и от хранилище към памет и обратно, се намира в него. Има и редовно кодово приложение, функция за разбиране, че „февруари“ е подобно на „февруари“ и други NLU за бедните. Според моята идея това вече трябва да е достатъчно, за да можете да скицирате прототипи на умения в yaml файлове, без да се разсейвате твърде много от технически подробности.

Ако искате по-сериозен NLU, можете да го прикачите към вашето умение Rasa или DeepPavlov, но настройването им ще изисква допълнителни танци с тамбура, особено при сървър без сървър. Ако изобщо не ви се кодира, трябва да използвате визуален конструктор като Aimylogic. Когато създавах tgalice, мислех за някакъв междинен път. Да видим какво ще излезе от това.

Е, сега се присъединете чат за разработчици на умения на alice, Прочети документация, и създайте прекрасни умения!

Източник: www.habr.com

Добавяне на нов коментар