Простой способ создавать сложные сценарии для Яндекс.Алисы
Библиотека разработана сообществом и не является продуктом Яндекса
Эта библиотека позволяет писать многоэтапные сценарии без callback-ов и ручного хранения информации о состоянии диалога. Достаточно использовать условия и циклы:
from alice_scripts import Skill, request, say, suggest
skill = Skill(__name__)
@skill.script
def run_script():
yield say('Добрый день! Как вас зовут?')
name = request.command
yield say('Сколько вам лет?')
while not request.matches(r'\d+'):
yield say('Я вас не поняла. Скажите число')
age = int(request.command)
yield say('Вы любите кошек или собак?',
suggest('Обожаю кошечек', 'Люблю собак'))
while not request.has_lemmas('кошка', 'кошечка',
'собака', 'собачка'):
yield say('У вас только два варианта - кошки или собаки')
loves_cats = request.has_lemmas('кошка', 'кошечка')
yield say(f'Рада познакомиться, {name}! Когда вам '
f'исполнится {age + 1}, я могу подарить '
f'{"котёнка" if loves_cats else "щенка"}!',
end_session=True)
Запустить сценарий можно как обычное Flask-приложение:
pip install alice_scripts
FLASK_APP=hello.py flask run --with-threads
Класс Skill
реализует WSGI-приложение и является наследником класса flask.Flask. Сценарий, соответствующий приложению, регистрируется с помощью декоратора @skill.script
(см. пример выше).
Сценарий запускается отдельно для каждого уникального значения session_id
.
Конструкция yield say(...)
служит для выдачи ответа на запрос и принимает три типа параметров:
-
Неименованные строковые аргументы задают варианты фразы, которую нужно показать и сказать пользователю. При выполнении случайно выбирается один из вариантов:
yield say('Как дела?', 'Как вы?', 'Как поживаете?')
-
Модификаторы (см. ниже) позволяют указать дополнительные свойства ответа. Например, модификатор
suggest
создаёт кнопки с подсказками для ответа:yield say('Как дела?', suggest('Хорошо', 'Нормально', 'Не очень'))
-
Именованные аргументы позволяют использовать те возможности протокола, для которых нет модификаторов:
yield say('Здравствуйте! Это мы, хороводоведы.', tts='Здравствуйте! Это мы, хоров+одо в+еды.')
Переданные пары «ключ-значение» будут записаны в словарь
response
в ответе навыка.
Модификаторы — это функции, возвращающие замыкания. При этом каждое замыкание должно принимать словарь response
из ответа навыка и добавлять туда нужные ключи.
-
suggest(...)
Создаёт кнопки с подсказками для ответа:
yield say('Как дела?', suggest('Хорошо', 'Нормально'))
Так как библиотека находится в стадии proof of concept, других модификаторов пока не реализовано. Используйте именованные параметры в конструкции
yield say(...)
.
Объект request
представляет собой thread-local хранилище, содержащее информацию о последнем действии пользователя в сессии.
-
С объектом
request
можно работать как со словарём, полученным из запроса к навыку:original_utterance = request['request']['original_utterance']
-
request.command
— свойство, содержащее значение поля command, из которого убраны завершающие точки. -
request.matches(pattern, flags=0)
— метод, позволяющий проверить, удовлетворяет ли свойствоrequest.command
регулярному выражениюpattern
(используется функция re.fullmatch). -
request.words
— свойство, содержащее все слова (и числа), найденные в поле command. -
request.lemmas
— свойство, содержащее начальные формы слов из свойстваrequest.words
(полученные с помощью библиотеки pymorphy2). -
request.has_lemmas(...)
— метод, позволяющий проверить, были ли в запросе слова, чьи начальные формы совпадают с начальными формами указанных слов:if request.has_lemmas('нет', 'не'): answer = 'no' elif request.has_lemmas('да', 'ага'): answer = 'yes'
Сценарий можно (и нужно) разбивать на подпрограммы. Каждая подпрограмма должна вызываться с помощью оператора yield from
и может возвращать значение с помощью оператора return
. См. пример.
В этой библиотеке состояние диалога хранится в виде состояния Python-генератора и не может быть сериализовано. В связи с этим:
- Реплики из одной сессии всегда должны обрабатываться одним и тем же процессом.
- Навык не может быть запущен на serverless-платформе.
- При перезапуске приложения все сессии будут разорваны.
Развернуть приложение в production-е можно с помощью gunicorn. Вы можете использовать несколько потоков, но не можете использовать несколько воркеров (иначе gunicorn будет направлять реплики из одной сессии разным процессам).
Если у вашего навыка много пользователей и одного процесса недостаточно, чтобы успевать отвечать на запросы за требуемое время (по протоколу — не более 1,5 сек), можно поступить так:
- Запустите несколько экземпляров gunicorn (в каждом — 1 воркер) на одном или нескольких серверах.
- Настройте nginx таким образом, чтобы он направлял запросы с одним и тем же
session_id
к одному и тому же экземпляру gunicorn.
Пример описанной конфигурации есть в этой папке.
Copyright © Александр Борзунов, 2018
The MIT License (MIT)