Skip to main content

Simple way to create complex scripts for Yandex.Alice

Project description

alice_scripts
=============

Простой способ создавать сложные сценарии для [Яндекс.Алисы](https://dialogs.yandex.ru/)

> Библиотека разработана сообществом и не является продуктом Яндекса

## 🚀 Быстрый старт

Эта библиотека позволяет писать многоэтапные сценарии без callback-ов и ручного хранения информации о состоянии диалога. Достаточно использовать условия и циклы:

> ```
> from alice_scripts import Skill, request, say, suggest
> skill = Skill(__name__)
> ```

```python
@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](http://flask.pocoo.org/)-приложение:

pip install alice_scripts
FLASK_APP=hello.py flask run --with-threads

## Примеры

* [Примеры из документации](examples)
* [Навык «Приложение для знакомств»](https://github.com/FuryThrue/WhoIsAlice/blob/master/app.py)

## 📖 Интерфейс

### Skill

Класс `Skill` реализует WSGI-приложение и является наследником класса [flask.Flask](http://flask.pocoo.org/docs/1.0/api/#flask.Flask). Сценарий, соответствующий приложению, регистрируется с помощью декоратора `@skill.script` (см. пример выше).

Сценарий запускается отдельно для каждого уникального значения `session_id`.

### yield say(...)

Конструкция `yield say(...)` служит для выдачи ответа на запрос и принимает три типа параметров:

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

```python
yield say('Как дела?', 'Как вы?', 'Как поживаете?')
```

- Модификаторы (см. ниже) позволяют указать дополнительные свойства ответа. Например, модификатор `suggest` создаёт кнопки с подсказками для ответа:

```python
yield say('Как дела?', suggest('Хорошо', 'Нормально', 'Не очень'))
```

- Именованные аргументы позволяют использовать те возможности [протокола](https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage/#response), для которых нет модификаторов:

```python
yield say('Здравствуйте! Это мы, хороводоведы.',
tts='Здравствуйте! Это мы, хоров+одо в+еды.')
```

Переданные пары «ключ-значение» будут записаны в словарь `response` в ответе навыка.

### Модификаторы

Модификаторы — это функции, возвращающие [замыкания](https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)). При этом каждое замыкание должно принимать словарь `response` из [ответа](https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage/#response) навыка и добавлять туда нужные ключи.

- `suggest(...)`

Создаёт кнопки с подсказками для ответа:

```python
yield say('Как дела?', suggest('Хорошо', 'Нормально'))
```

> Так как библиотека находится в стадии proof of concept, других модификаторов пока не реализовано. Используйте именованные параметры в конструкции `yield say(...)`.

### request

Объект `request` представляет собой thread-local хранилище, содержащее информацию о последнем действии пользователя в сессии.

- С объектом `request` можно работать как со словарём, полученным из [запроса](https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage/#request) к навыку:

```python
original_utterance = request['request']['original_utterance']
```

- `request.command` — свойство, содержащее значение поля [command](https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage/#request), из которого убраны завершающие точки.

- `request.matches(pattern, flags=0)` — метод, позволяющий проверить, удовлетворяет ли свойство `request.command` регулярному выражению `pattern` (используется функция [re.fullmatch](https://docs.python.org/3/library/re.html#re.fullmatch)).

- `request.words` — свойство, содержащее все слова (и числа), найденные в поле [command](https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage/#request).

- `request.lemmas` — свойство, содержащее начальные формы слов из свойства `request.words` (полученные с помощью библиотеки [pymorphy2](http://pymorphy2.readthedocs.io/en/latest/)).

- `request.has_lemmas(...)` — метод, позволяющий проверить, были ли в запросе слова, чьи начальные формы совпадают с начальными формами указанных слов:

```python
if request.has_lemmas('нет', 'не'):
answer = 'no'
elif request.has_lemmas('да', 'ага'):
answer = 'yes'
```

## Разбиение на подпрограммы

Сценарий можно (и нужно) разбивать на подпрограммы. Каждая подпрограмма *должна* вызываться с помощью оператора `yield from` и может возвращать значение с помощью оператора `return`. См. [пример](examples/guess_number_subgens.py).

## Развёртывание

В этой библиотеке состояние диалога хранится в виде состояния Python-генератора и не может быть сериализовано. В связи с этим:

- Реплики из одной сессии всегда должны обрабатываться одним и тем же процессом.
- Навык не может быть запущен на serverless-платформе.
- При перезапуске приложения все сессии будут разорваны.

Развернуть приложение в production-е можно с помощью gunicorn. Вы можете использовать несколько [потоков](http://docs.gunicorn.org/en/stable/settings.html#threads), но не можете использовать несколько [воркеров](http://docs.gunicorn.org/en/stable/settings.html#workers) (иначе gunicorn будет направлять реплики из одной сессии разным процессам).

## Масштабирование

Если у вашего навыка много пользователей и одного процесса недостаточно, чтобы успевать отвечать на запросы за требуемое время (по протоколу — не более 1,5 сек), можно поступить так:

1. Запустите несколько экземпляров gunicorn (в каждом — 1 воркер) на одном или нескольких серверах.
2. Настройте nginx таким образом, чтобы он направлял запросы с одним и тем же `session_id` к одному и тому же экземпляру gunicorn.

Пример описанной конфигурации есть в [этой папке](examples/scaling).

## Автор

Copyright © Александр Борзунов, 2018

The MIT License (MIT)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for alice-scripts, version 0.2.post1
Filename, size File type Python version Upload date Hashes
Filename, size alice_scripts-0.2.post1.tar.gz (6.8 kB) File type Source Python version None Upload date Hashes View hashes

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page