Как написать свой сценарий


Создание своего сценария

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

Служебный сценарий – run_app

run_app – это служебный интент, который означает запуск смартапа без особого контекста. Сценарий для этого интента находится в <ИМЯ_ПРОЕКТА>/static/references/scenarios/run_app.json.

Ниже представлен пример сценария, который служит для перенаправления пользователя в сценарий приветствия при запуске смартапа. У сценария ниже нет явного указания типа, так как это базовый сценарий без формы.

Поле Описание
run_app Имя текущего сценария
actions: type Тип действия. Например, run_scenario - тип, который запускает другой сценарий
actions: scenario Имя сценария, который будет запущен. Например, hello_scenario - это сценарий приветствия

Пример:

{
    "run_app": {
        "actions": [
            {
                "type": "run_scenario",
                "scenario": "hello_scenario"
            }
        ]
    }
}

Сценарий приветствия - hello_scenario

Ниже представлен сценарий другого типа – form_filling. Это означает, что сценарий будет выполнен только после заполнения формы с обязательными полями. При создании такого сценария вводится дополнительная сущность - форма (Form).

Данный сценарий можно поместить в отдельный файл или объявить рядом с уже существующим.

Поле Описание
hello_scenario Имя текущего сценария
type Тип сценария. Например, form_filling - тип сценария с формой
form Имя формы
actions: type Тип действия. Например, string - тип, который возвращает строку
actions: command Название действия, которое будет совершено. В примере ниже - это выдача ответа пользователю
actions: nodes: pronounceText Ответ, который будет выдан пользователю.В данном параметре используется шаблон Jinja. Фреймворк передает в окружение этого шаблона параметры, собираемые классом BasicParametrizer: входящее сообщение, формы, id текущего сценария, а также переменные и счётчики из actions. При выполнении сценария ниже, на любое входящее сообщение будет отправляться ответ: "Привет user_id!"

Пример:

{
    "hello_scenario": {
        "type": "form_filling",
        "form": "hello_form",
        "actions": [
            {
                "type": "string",
                "command": "ANSWER_TO_USER",
                "nodes": {
                    "pronounceText": "Привет {{main_form.name}}!"
                }
            }
        ]
    }
}

Формы, по аналогии со сценариями, находятся в специальной директории - <ИМЯ_ПРОЕКТА>/static/references/forms/. Формы состоят из полей, а поля - из филлеров. Филлеры могут находить в тексте имена, числа, даты, города и прочие объекты. В примере ниже филлер user_id получает из сообщения id пользователя.

{
    "hello_form": {
        // имя формы
        "fields": {
            // словарь с полями
            "name": {
                // имя поля
                "filler": {
                    // параметр с филлером внутри
                    "type": "user_id" // тип филлера
                }
            }
        }
    }
}

Сценарий приветствия - hello_form

Следующий пример - это создание сценария, который меняет способ приветствия в зависимости от возраста пользователя:

  • если пользователь моложе 50 лет, то приветствие идет через "Привет";
  • если пользователь старше 50 лет, то приветствие идет через "Здравствуйте".

Данный сценарий можно поместить в отдельный файл или объявить рядом с уже существующим. В сценарий можно попасть только из предыдущего сценария - hello_scenario:

{
    "hello_scenario": {
        /*"type": "form_filling" ... */
    },
    "gentle_hello_scenario": {
        "actions": [
            {
                "type": "string",
                "command": "ANSWER_TO_USER",
                "nodes": {
                    "pronounceText": "Здравствуйте {{main_form.name}}!"
                }
            }
        ]
    }
}

Узнать возраст пользователя можно через расширение уже существующей формы - hello_form.

Поле Описание
questions: type Тип действия.
filler: type Тип филлера. Например, number_first - берет первую встречную цифру в тексте
{
    "hello_form": {
        "fields": {
            "name": {
                "filler": {
                    "type": "user_id"
                }
            },
            "age": {
                "questions": [
                    {
                        "type": "string",
                        "command": "ANSWER_TO_USER",
                        "nodes": {
                            "pronounceText": "Сколько вам лет?"
                        }
                    }
                ],
                "filler": {
                    "type": "number_first"
                }
            }
        }
    }
}

Теперь необходимо добавить в hello_scenario новую сущность - Requirement. Через эту сущность задается условие на переход в другой сценарий.

{
    "hello_scenario": {
        "type": "form_filling",
        "form": "hello_form",
        "actions": [
            {
                "type": "else", // тип actions с условием
                "requirement": {
                    // объект Requirement
                    "type": "template",
                    "template": "{{main_form.age >= 50}}" // шаблон Jinja
                },
                "action": {
                    // действие при успешном прохождении условия
                    "type": "run_scenario",
                    "scenario": "gentle_hello_scenario"
                },
                "else_action": {
                    "type": "string",
                    "command": "ANSWER_TO_USER",
                    "nodes": {
                        "pronounceText": "Привет {{main_form.name}}!"
                    }
                }
            }
        ]
    },
    "gentle_hello_scenario": {
        "actions": [
            {
                "type": "string",
                "command": "ANSWER_TO_USER",
                "nodes": {
                    "pronounceText": "Здравствуйте {{main_form.name}}!"
                }
            }
        ]
    }
}

Особенность slot filling

Запуск сценария с формой происходит только при заполнении всех обязательных полей, поэтому форма всегда пытается заполниться целиком. Но в SmartApp Framework все поля являются опциональными. Из-за этого, если в примере выше не указать возраст в первом сообщении, то уточняющий вопрос никогда не будет задан и это приведет к ошибке сравнения. В итоге поле age будет заполнено None.

> привет
TypeError: '>=' not supported between instances of 'NoneType' and 'int'
> привет, мне тридцать лет
pronounceText: Привет local_testing_1!

Во избежание этой ошибки необходимо сделать поле age обязательным, добавив свойство required: true. В этом случае, если поле будет пустым, то выполнится блок из questions.

> привет
pronounceText: Сколько вам лет?
> 50
pronounceText: Здравствуйте local_testing_1!
> привет 30
pronounceText: Привет local_testing_1!

При этом поле age все еще может быть заполнено первым сообщением. Чтобы поле заполнялось только ответом на заданный вопрос, необходимо выставить флаг available: false.

"age": {
        "required": true,
        "available": false,
        "questions": [
          {
            "type": "string",
            "command": "ANSWER_TO_USER",
            "nodes": {
              "pronounceText": "Сколько вам лет?"
            }
          }
        ],
        "filler": {
          "type": "number_first"
        }
      }
> привет 30
pronounceText: Сколько вам лет?
> 50
pronounceText: Здравствуйте local_testing_1!

Заметили ошибку?

Выделите текст и нажмите Ctrl + Enter, чтобы сообщить нам о ней