Как написать сценарий с Framework
Создание своего сценария
При создании проекта автоматически создаются два сценария: 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
.
{
"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!