Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents
absoluteUrltrue

Общее описание

Сценарии позволяют описывать диалоги  системы autoFAQ с пользователями. Диалог может включать в себя переписку с пользователем, обращение к данным во внешних системах и обогащение ответов.

Система позволяет создавать сценарии произвольной сложности и прикреплять их напрямую к документам в базах знаний или событиям в работе над диалогами. В случае когда база знаний по запросу пользователя определяет документ, содержащий вместо ответа сценарий, бот начнет вести с пользователем описанный в сценарии диалог.  

Описание сценариев в системе ведется при помощи языка DSL autoFAQ. Тело сценария состоит из последовательных операций. Каждая операция располагается в отдельной строке, для связи со следующей операцией в конце строки требуется указание символа "+". Некоторые операции могут содержать 1 или несколько опциональных модификаторов. 

...

Системные переменные

Для работы с контекстом в сценариях доступны следующие системные переменные:

Code Block
{userFullName} - имя пользователя

{userLogin} - логин пользователя

{userEmail} - электронная почта пользователя

{userPayload.<название_даных>} - дополнительные данные о пользователе, полученные при идентификации пользователя во внешней системе

{platformInMessageQuery} - текст запроса пользователя

{http_code} - переменная содержит код статуса последнего запроса к API

Пользовательские переменные

В сценариях возможно создавать и использовать для хранения данных любые пользовательские переменные. Значение переменной будет потеряно после завершения сценария. 

Code Block
{userSaidYes} - пример пользовательской переменной 

Списки

Переменная attachments[]  хранит не одно значение, а список значений, при записи новых значений в данную переменная они будут дописаны в конец списка.

Code Block
запроситьФайл("Приложите файл").сохранитьРезультат("file")+    -   полученные данные перезапишут значение переменной
запроситьФайл("Приложите файл").сохранитьРезультат("files[]")+ -   полученные данные будут дописаны в список

...

Порядок выполнения шагов сценария 

Anchor
order
order
Все шаги сценария выполняются последовательно с первой до последней строки. Если вы хотите временно исключить одну из строк из процесса выполнения сценария - установите в начале данной строки символ //

Code Block
breakoutModewide
сообщениеПользователю.сШаблоном("Привет")+						- шаг будет выполнен
//сообщениеПользователю.сШаблоном("Привет, {userFullName}")+ 	- шаг не будет выполнен

В конце сценария обязательно размещение одного из шагов завершения сценария:

Code Block
breakoutModewide
languagepy
завершить - завершение сценария
завершитьСШаблоном("Пока!") - завершение сценария с выводом сообщения пользователю
завершитьСНовымЗапросом("Новый запрос") - завершение сценария и одновременный запуск в работу нового сообщения
завершитьИПеревестиНаОператора - звершение сценария и перевод диалога в очередь оператору
завершитьИЗакрытьДиалог() - завершение сценария и закрытие диалога, следующая реплика пользователя начнет новый диалог

Если в условии сценария применен один из шагов завершения, то сценарий может завершить работу досрочно:

Code Block
breakoutModewide
если("{http_code} != 200").то(
  комментарий("Данные пользователя не обновлены")+
  завершитьИПеревестиНаОператора 
)+
комментарий("Обовлены данные пользователя. Новые данные отправлены в CRM")+
завершить

Шаги переписки с пользователями 

сообщениеПользователю.сШаблоном(*args)  

Шаг отправки текстового сообщения пользователю без ожидания ответной реакции. В качестве аргумента шаг принимает текст сообщения или переменную, которая содержит такой текст. Сообщения без текста не будут отправлены.

Текст сообщения может содержать HTML теги для форматирования сообщения. Текст сообщения также может включать в себя вставку значений из переменных. Система самостоятельно проверит форматирование сообщения на соответствие требованиям канала. 

Пример вывода простого текстового сообщения:

Code Block
breakoutModewide
сообщениеПользователю.сШаблоном("Спасибо и всего хорошего") +	
...

Пример вывода текстового сообщения с переменой:

Code Block
breakoutModewide
сообщениеПользователю.сШаблоном("Сообщение от {userFullName}") +
...

Пример вывода текстового сообщения с HTML форматированием ссылки:

Code Block
breakoutModewide
сообщениеПользователю.сШаблоном("Пройдите по <a href='https://yandex.ru'>ссылке</a>") +
...

.сФайлами(*args)

Модификатор шага, который позволяет отправить пользователю вместе с сообщением файлы из текущего документа. В качестве аргумента принимаетя список идентификаторов файлов в документе.

Code Block
breakoutModewide
сообщениеПользователю.сФайлами(523).сШаблоном("Высылаю файл") - отправка файла с идентификатором 523 пользователю вместе с сопровождающим текстом
сообщениеПользователю.сФайлами(523, 524, 525).сШаблоном("Высылаю файл") - отправка нескольких файлов пользователю
сообщениеПользователю.сФайлами(523).сШаблоном("") - отправка файла пользователю без сопровождающего текста

Идентификатор файла копируется из формы прикладывания файла к документу.

...

Info

Передача файлов пользователю поддерживается только для сценариев в документах баз знаний и не поддерживается для сценариев приветствия и интеграций.

...

задатьПользователюВопрос(*args).сохранитьРезультат(*args)  

Шаг отправки пользователю вопроса пользователю и ожидания ответа.

В качестве аргумента для задатьПользователюВопрос принимается текст вопроса или переменную, которая содержит такой текст. Сообщения без текста не будут отправлены. Текст вопроса может содержать HTML теги для форматирования сообщения. Текст сообщения также может включать в себя вставку значений из переменных. Система самостоятельно проверит форматирование сообщения на соответствие требованиям канала.

В качестве аргумента для сохранитьРезультат принимается название переменной, в которую сценарий поместит ответ пользователя. Если указанная переменная ранее не была определена в сценарии - сценарий создаст её.

Пример простого вопроса пользователю:

Code Block
breakoutModewide
задатьПользователюВопрос("На какую дату нужен пропуск ?").сохранитьРезультат("whatDay") +
...

Пример сценария с вопросом и разбором результатов:

Code Block
breakoutModewide
задатьПользователюВопрос("Как дела?").сохранитьРезультат("what") +
если("{what} != Хорошо").то(
  комментарий("А дела то не хорошо") +
  завершитьИПеревестиНаОператора 
) +
комментарий("Все отлично") +
завершить

Время ожидания ответа от пользователя устанавливается таймером сценариев, значение которого можно указать в разделе Настройки - Сценарии. Если ответ от пользователя не поступит в указанное время, сценарий будет завершен. После завершения сценарий по таймеру система отправит пользователю соотвествующее служебное сообщение, текст которого можно указать в разделе Настройки - Сценарии.

Дополнительные модификаторы для данного шага включают в себя возможность указания вариантов ответа и правила проверки ответа по шаблону.

.сВариантамиОтвета(варианты) 

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

Code Block
breakoutModewide
задатьПользователюВопрос("На какую дату нужен пропуск ?").сВариантамиОтвета("Сегодня", "Завтра").сохранитьРезультат("whatDay") +
...

.проверитьФормат(формат, сообщение)

Модификатор шага проверяет полученные от пользователя данные на соответствие шаблону. Шаблон задается регулярным выражением. В случае соответствия ответной реплики пользователя шаблону шаг передает данные далее, в обратном случае - выводит текст сообщения и ожидает получения корректной информации без ограничений по количеству попыток ввода.

Code Block
breakoutModewide
//  выражение для проверки, что введенная строка соотвествует формату даты вида 02.12.2021
задатьПользователюВопрос("Укажите дату").проверитьФормат("(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.](19|20)\\d\\d", "Не понял вас, повторите пожалуйста.").сохранитьРезультат("day")+

//  выражение для проверки, что введенная строка содержит адрес электронной почты
задатьПользователюВопрос("Напишите email").проверитьФормат("^\\S+@\\S+\\.[a-z]{2,}$", "Пожалуйста, введите корректный email").сохранитьРезультат("_email")+

запроситьФайл(*args).сохранитьРезультат(переменная)

Шаг запроса файла  у пользователя и записи его в переменную. В качестве аргумента шаг принимает текст просьбы или переменную с таким текстом. Файл будет сохранен в хранилище файлов диалога и будет доступен в указанной переменной.

Code Block
breakoutModewide
запроситьФайл("Приложите файл").сохранитьРезультат("file")+ +

Дополнительные модификаторы шага включает опцию пропуска отправки файла

.можноПропустить(сообщение) - функция позволяет пользователю пропустить отправку файла

Code Block
breakoutModewide
запроситьФайл("Приложите файл").можноПропустить("Пропустить")+

...

Шаги работы с внешними сервисами  

Шаги обращения к внешним сервисам и разбора полученных данных. В настоящее время поддерживается API вызовы REST и SOAP сервисов, планируется подключение к почтовым, FTP и прочим сервисам.

Функции операции:

вызвать.внешнийСервис(адрес, тип).сохранитьРезультат(*args)

Шаг вызова REST API сервисов. Данный шаг ожидает получение ответа в формате плоского JSON. Для работы с SOAP сервисами используется данный шаг с модификаторам, которые будут указаны ниже.

В качестве аргументов для вызвать.внешнийСервис принимаются адрес ендпонта и тип вызова. Поддерживаются основные типы вызовов - GET, POST, PUT, DELETE. В качестве адреса ендпойнта принимается строка с адресом или переменная, которая содержит данную строку.

В качестве аргументов для сохранитьРезультат принимается список пар из названия поля в полученном JSON и названия переменной, в которую сценарий сохранит полученное значение.

Пример GET запроса, из ответа которого будет выбрано 1 поле result

Code Block
breakoutModewide
вызвать.внешнийСервис("https://api.autofaq.ai/v1/ping","GET").сохранитьРезультат(("result", "answer_code")) +

Пример POST запроса с указанием адреса вызова из переменной, телом запроса и разбором двух полей из ответа - message и code

Code Block
breakoutModewide
установитьПеременную("post_url", "https://api.autofaq.ai/v1/ping") +
...
вызвать.внешнийСервис("{post_url}", "POST").сТеломСообщения("{query}").сохранитьРезультат(("message", "response_message"),("code", "response_code")) +
...

Модификаторы шага позволяют указать URL параметры запроса, заголовки, тело сообщения или сохранить ответ со сложной структурой для дальнейшего разбора.

.сПараметрами()

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

Code Block
breakoutModewide
установитьПеременную("user_token", "1234567890abcd") +
...
вызвать.внешнийСервис("{url}","GET").сПараметрами(("query","order"),("token","{user_token}")).сохранитьРезультат(("result", "answer_code")) +
...

.сЗаголовками()

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

Code Block
breakoutModewide
установитьПеременную("user_token", "1234567890abcd") +
...
вызвать.внешнийСервис("{url}", "POST").сЗаголовками(("Content-Type", "application/json"),("charset", "utf-8"),("Authorization","Bearer {user_token}")).сохранитьРезультат(("result", "answer_code")) +
...

.сТеломСообщения()

Модификатор шага вызова сервиса для передачи тела запроса.

Поддерживаются форматы x-www-form-urlencoded и json. JSON передается кодированный в строку. Названия и значения параметров принимаются строкой или переменной, которая содержит эту строку.

Code Block
breakoutModewide
// передача JSON 
вызвать.внешнийСервис("{url}", "POST").сЗаголовками(("Content-Type", "application/json")).сТеломСообщения("{\"name\":\"new document\", \"question\":\"new question\"}").сохранитьРезультат(("result", "answer_code")) +
// передача x-www-form-urlencoded
вызвать.внешнийСервис("{url}", "POST").сЗаголовками(("Content-Type", "application/x-www-form-urlencoded")).сТеломСообщения("name=new document, question=new question").сохранитьРезультат(("result", "answer_code")) +

.сСоставнымТеломСообщения()

...

Модификатор шага вызова сервиса для передачи multipart тела запроса для передачи файлов. При передаче файла можно указать либо полное название файла либо идентификатор файла в файловом хранилище диалога.

Code Block
breakoutModewide
// передача файла через указание пути
вызвать.внешнийСервис("

...

{url}", "POST").сСоставнымТеломСообщения(("content" -> "C:/docker.yml")).сохранитьРезультат((

...

"result", "answer_code")) +
// передача файла через идентификатор файла в хранилище
вызвать.внешнийСервис("{

...

url}", "POST").сЗаголовками(("apikey","{apikey_var}")).сСоставнымТеломСообщения(("content" -> "{fileId}"),("type" -> "addAttach")).

...

сохранитьРезультат(("result", "answer_code")) +

.сохранитьРезультатКакСтроку()

...

Модификатор шага вызова сервиса для сохранения полученныго ответа как сериализованную строку в переменную сценария. В качестве аргумента принимается название переменной, в которую будет сохранен ответ сервиса.

Ответ может быть разобран далее по ходу сценария.

Code Block
breakoutModewide
// запрос и сохранение результата в строку
вызвать.внешнийСервис("{

...

url}", "POST").сТеломСообщения("{query}").сохранитьРезультатКакСтроку("answer")+
// разбор ответа в JS коде (рассмотрено ниже)
выполнитьJs("""
  try {
    var answerParsed = JSON.parse(answer);
  } catch(err) {
    var answerParsed = {'results':[]};
  }
   
  var resultsLength = answerParsed.results.length;
  var exit = {'resultsLength ':resultsLength};
  exit;
""") +
...

...

Шаги установки переменных

установитьПеременную(переменная, значение)

...

Шаг установки создания и установки значения переменной в сценарии. Если переменная существовала к моменту вызова шага, то ее старое значение будет затерто новым. При указании значения допускается использование переменных.

...

Созданная таким шагом переменная будет доступна только в рамках

...

текущего сценария.

Code Block
breakoutModewide
установитьПеременную("date", "Сегодня {new_date}")+

...

установитьПеременнуюВДиалог(*

...

args)

Операция установки переменной для всего текущего диалога. При указании значения допускается использование переменных. Переменная диалога сохраняет свое значение на протяжении всего диалога, может быть создана и прочтена в рамках любого сценария. В новом диалоге будет отсутствовать.

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

Code Block
breakoutModewide
установитьПеременнуюВДиалог(
    ключ = "priority",                  - системное название задаваемой переменной, любой текст
    значение = "[\"v1\", \"v2\"]",      - значение, может быть пустым 
    название = "Выберите критичность",  - название, которое будет отображаться в интерфейсе, строка
    редактируемое = true,               - является ли поле редактируемым или нет, true/false
    показыватьОператору = true,         - показывать ли оператору в боковой панели, true/false
    обязательное = true,                - является ли обязательным для заполнения при закрытии диалога, true/false
    множественныйВыбор = true,          - можно ли выбрать несколько вариантов, применимо только для выпадающего списка, true/false
    тип = "Выпадающий список",          - тип задаваемой переменной, возможные значения в таблице ниже
    варианты = "{\"v1\": \"High\", \"v2\": \"Medium\"}" - список возможных значений, применимо только для выпадающего списка, можно задать как с помощью другой переменной, так и напрямую
)+

Список возможных типов с примерами использования:

Тип

Пример использования

Текст

Code Block
установитьПеременнуюВДиалог(
	ключ = "NonEditabletext",
    значение = "Нередактируемый текст",
    название = "Примечание",
    показыватьОператору = true,
    редактируемое = false,
    обязательное = false,
    тип = "Текст"
)
Code Block
установитьПеременнуюВДиалог(
    ключ = "textField",
    значение = "г.Москва Ул.Тверская",
    название = "Адрес",
    показыватьОператору = true,
    редактируемое = true,
    обязательное = true,
    тип = "Текст"
)

Число

Code Block
установитьПеременнуюВДиалог(
	ключ = "number",
    значение = "",
    название = "Возраст",
    показыватьОператору = true,
    редактируемое = true,
    обязательное = true,
    тип = "Число"
)

Выпадающий список

Code Block
установитьПеременную("priority", "{\"v1\": \"Blocker\", \"v2\": \"Critical\", \"v3\": \"Major\", \"v4\": \"Minor\"}")+
установитьПеременнуюВДиалог(
    ключ = "priority",
    значение = "[\"v1\", \"v2\"]",
    название = "Выберите критичность",
    редактируемое = true,
    показыватьОператору = true,
    обязательное = true,
    множественныйВыбор = true,
    тип = "Выпадающий список",
    варианты = "{priority}"
)
Code Block
установитьПеременнуюВДиалог(
    ключ = "severity",
    значение = "",
    название = "Выберите важность",
    редактируемое = true,
    показыватьОператору = true,
    обязательное = true,
    тип = "Выпадающий список",
    варианты = "{\"v1\": \"High\", \"v2\": \"Medium\", \"v3\": \"Low\"}"
)

Переключатель

Code Block
установитьПеременнуюВДиалог(
	ключ = "switcher",
    значение = "true",
    название = "Активный?",
    показыватьОператору = true,
    редактируемое = true,
    обязательное = true,
    тип = "Переключатель"
)

...

установитьПеременнуюПользователю(переменная, значение)

...

Шаг установки переменной для пользователя. При указании значения допускается использование переменных. Переменная пользователя сохраняет свое значение до тех пор пока не будет очищена. Может быть создана и наполнена в любом сценарии. После создания переменная будет доступна в любом сценарии любого диалога.

Можно установить значение одной из фиксированных переменных пользователя или произвольной переменной в составе payload. Сохранение данных пользователя позволит передавать данные между разными диалогами.

Code Block
// установка фиксированной переменной
установитьПеременнуюПользователю("userEmail", "vasya@mail.ru")+
// установка переменной из payload
установитьПеременнуюПользователю("userPayload.lastLoginTS", "{nowTimeStamp}")+

...

Сервисные шаги

если(*условие).то(*операции

...

Шаг условного выполнения операций. В качестве условия указывается сравнение двух значений. Для оценки условия доступны операции сравнения - равенство (==), больше (>), меньше (<), неравенство (!=).

...

Функции операции:

...

 В качестве сравниваемых значений можно указывать переменные сценарий, текст или числа.

Пример сообщения, отправляемого пользователю при равенстве переменной error единице.

Code Block
breakoutModewide
если("{error} == 1").то(
   сообщениеПользователю.сШаблоном("Система не работает")    
) +
...

Блок операций может состоять из нескольких

...

шагов. В этом случае различные шаги в блоке должны быть соединены знаком “+”,

...

но последний шаг в блоке не

...

должен содержать “+

Code Block
breakoutModewide
если("{when

...

} == 

...

завтра").то(
   задатьПользователюВопрос("

...

Ок! Введи пожалуйста 

...

нужное 

...

время").сохранитьРезультат("

...

time") +
   вызвать.внешнийСервис("

...

{url}", "GET").сПараметрами(("

...

time","{

...

time}")).

...

сохранитьРезультатКакСтроку(

...

"result"))
) +
...

Дополнительные модификаторы шага условных операций включают в себя дополнительные условия для выполнения операций и указание на сочетание условий.

.и(

...

*условие)

Модификатор для указания дополнительного условия, объединененного с основным условием логической операцией И. Итоговый набор шагов будет выполнен только при одновременном выполнении основного и дополнительного условий.

Code Block
breakoutModewide
если("{error} == 0").и("{connection_mistakes} == 0").то(
   сообщениеПользователю.сШаблоном("Система работает")
)+

.или(*условие) -

...

 

Модификатор для указания дополнительного условия, объединененного с основным условием логической операцией ИЛИ. Итоговый набор шагов будет выполнен при выполнении одного из условий - основного или дополнительного.

Code Block
breakoutModewide
если("{error} == 1").или("{connection_mistakes} == 1").то(сообщениеПользователю.сШаблоном("Система не отвечает"))+

...

установитьМетку(*название)

...

Шаг установки метки в коде

...

сценария. Метка используется для перехода из любого места сценария.

Code Block
breakoutModewide
установитьМетку("раз") +
...
перейтиНаМетку("раз")+

...

...

перейтиНаМетку(*метка)

...

Шаг установки метку в

...

коде сценария.

Code Block
breakoutModewide
// перети на метку не более 3 раз, на 4 раз шаг перехода не сработает 
  

...


если("

...

{error} == 0").

...

и("{connection_mistakes} == 0").то(
   // переход на метку без указания лимита переходов, используется значение по-умолчанию 30
   перейтиНаМетку("раз") 
) +
...        

запросВБазыЗнаний(вопрос, переменная)

...

Для ограничения бесконечного зацикливания сценария в шаге установлен лимит на количество переходов равный 30. Для установки другого ограничения количества переходов служит модификатор шага.

.неБольше(*количество)

Модификатор для установки лимита по количеству переходов. При достижении лимита сценарий не перейдет на метку, а продожит работу далее по коду.

Code Block
перейтиНаМетку("раз").неБольше(3) +

комментарий(*сообщение)

Шаг позволяет добавлять комментарий в диалог. Комментарий виден администраторам и операторам системы, пользователь не видит комментарии. Шаг принимает в качестве аргумента текст комментарий. Текст комментария может включать переменные.

Code Block
breakoutModewide

...

комментарий("

...

Сменил 

...

тематику 

...

назначитьТематику(ID базы знаний)

Шаг принудительного указания тематики диалога. Шаг замещает все автоматически определенные тематики и сохраняет значение тематики вне зависимости от того что пишет пользователь.

Для установки тематики требуется указать идентификатор базы знаний.

...

Code Block
назначитьТематику("1234")+
// диалог попадет на скилл группу операторов со специализацией на базе знаний с ID 1234
завершитьИПеревестиНаОператора

Если база знаний с указанным идентификатором не будет найдена шаг не заменит тематику.

назначитьОператора(логин оператора)

Шаг указания оператора для диалога. Требуется указать логин оператора.

Code Block
breakoutModewide
назначитьОператора("vasya@mail.ru")+
//
// Сценарий не обязательно должен завершаться переводом на оператора завершитьИПеревестиНаОператора,
// можно просто завершить - назначенный оператор будет найден когда диалог попадет на операторов 
завершить

...

чата на {newTheme}") +
...

...

выполнитьJs(*скрипт)

Шаг выполнения скрипта на JavaScript. Шаг позволяет реализовать произвольную логику вычислений или разбор сложных объектов. В качестве аргумета шаг принимает текст JS скрипта.

Info

Javascript VM соответствует ECMAScript 5.1

Используйте обычный синтаксис callback function поскольку не поддерживается синтаксис lambda функций ES6

JS скрипт имеет доступ ко всем переменным сценария. Результаты скрипта следует записать в JSON объект и передать его на выход, в DSL сценарии можно будет получить к ним доступ по названиям полей.

Пример JS кода с выводом результата в переменной exit.

Code Block
breakoutModewide
languagejs
выполнитьJs("""
  var uids = JSON.parse(results);
  var ln = uids.length;
  if (ln == 0) {
     var uuid = '';
  } else {
     var uuid = uids[0]["UUID"];
  }
  var exit = {'uuid':uuid, 'numberOfUids':ln};
  exit;
""") +
завершитьСШаблоном("Заявка создана, всего создано полей {numberOfUids}, первый id - {uuid}.")

Внутри JavaScript есть возможность получить данные об операторе для случая, когда запущен сценарий на интеграцию по кнопке. Название объекта - initByOperator.

Пример использования:

Code Block
languagejs
выполнитьJs("""
var initByOperator = JSON.parse(initByOperator);
var initByOperatorLogin = initByOperator.login;
var exit = {'operatorLogin ': initByOperatorLogin, 'operatorFIO': initByOperator.fullName, 'operatorEmail': initByOperator.email};
exit;
""")+
комментарий("ФИО оператора: {operatorFIO}") +
комментарий("Логин оператора: {operatorLogin}") +
комментарий("Email оператора: {operatorEmail}") +

Весь список параметров, к которым можно получить доступ:

id: String, login: String, fullName: Option[String], isActive: Boolean, isNotify: Boolean, serviceId: String, actions: Seq[UserRoleType], email: Option[String], settings: UserSettings = UserSettings()

knowledgeBases: Seq[Long] = Seq.empty, autoAssignEnabled: Boolean = false

...

Шаги управления диалогом

запросВБазыЗнаний(*args)

Шаг проверки наличия у баз знаний автоматического ответа на указанный запрос. В качестве агрументов шаг принимает текст запроса и название переменной, в которую будет помещен результат проверки. Текст запроса может быть указан напрямую в виде текста или в виде переменной, которая сожержит этот текст.

Если в базах знаний есть ответ, который удовлетворяет требованиям по точности, переменной будет присвоено значение true, если ответа нет - false.

Code Block
breakoutModewide
запросВБазыЗнаний("Как купить слона", "botKnows")+
если("{botKnows} == true").то(
  сообщениеПользователю.сШаблоном("Ответ есть")
)+

назначитьТематику(*идентификатор)

Шаг принудительного указания тематики диалога. Шаг замещает все автоматически определенные тематики и сохраняет значение тематики длога вне зависимости от содержания диалога. В качестве аргумента шаг принимает идентификатор базы знаний. Если указан некорректный идентификатор, то установка тематики не происходит.

Получить идентификатор базы знаний можно из списка баз знаний в разделе Базы знаний или из карточки само базы знаний.

...

Code Block
назначитьТематику("119117") +
// диалог будет назначен на операторов со специализацией на базе знаний "Техническая поддержка""
завершитьИПеревестиНаОператора

назначитьОператора(*логин)

Шаг указания оператора для диалога. В качестве аргумента шаг принимает логин оператора.

Code Block
breakoutModewide
назначитьОператора("vasya@company.ru") +
завершитьИПеревестиНаОператора

При попадании такого диалога в процедуру перевода диалога на оператора система в первую очередь попытается назначить диалог на оператора с указанным логином. Если такой оператор существует и удовлетворяет всем требованиям

...

назначения - система назначит диалог на данного оператора. Если оператора с таким логином не существует или он не удовлетворяет требованиям автоназначения система проведет назначение на другого оператора по стандартным правилам.

Info

Для корректного назначения на оператора следует проверить соответствие тематики диалога и специализации оператора. Проще всего установить диалогу нужную тематику через шаг назначитьТематику()

В последующем, данные оператор может перевести диалог на другого оператора или в другую группу - система больше не будет пытаться назначить диалог на него.

комментарий("сообщение")

Команда позволяет добавлять комментарий в диалог. Комментарий виден администраторам и операторам системы, пользователь не видит комментарии.

Code Block
breakoutModewide
комментарий("текст комментария")+

выполнитьJs(скрипт)

Выполнить произвольный скрипт на JavaScript. Шаг позволяет реализовать произвольную логику вычислений или разбор сложных объектов.

Info

Javascript VM соответствует ECMAScript 5.1

Используйте обычный синтаксис callback function поскольку не поддерживается синтаксис lambda функций ES6

JS скрипт имеет доступ ко всем переменным сценария. Результаты скрипта следует записать в JSON объект и передать его на выход, в DSL сценарии можно будет получить к ним доступ по названиям полей.

Code Block
languagejs
выполнитьJs("""
  var uids = JSON.parse(results);
  var ln = uids.length;
  if (ln == 0) {var uuid = '';} else {var uuid = uids[0]["UUID"];}
  var exit = {'uuid':uuid, 'numberOfUids':ln};
  exit;
""") +
завершитьСШаблоном("Заявка создана, всего создано полей {numberOfUids}, первый id - {uuid}.")

Внутри JavaScript есть возможность получить данные об операторе для случая, когда запущен сценарий на интеграцию по кнопке. Название объекта - initByOperator.

Пример использования:

Code Block
languagejs
выполнитьJs("""
var initByOperator = JSON.parse(initByOperator);
var initByOperatorLogin = initByOperator.login;
var exit = {'operatorLogin ': initByOperatorLogin, 'operatorFIO': initByOperator.fullName, 'operatorEmail': initByOperator.email};
exit;
""")+
комментарий("ФИО оператора: {operatorFIO}") +
комментарий("Логин оператора: {operatorLogin}") +
комментарий("Email оператора: {operatorEmail}") +

Весь список параметров, к которым можно получить доступ:

id: String, login: String, fullName: Option[String], isActive: Boolean, isNotify: Boolean, serviceId: String, actions: Seq[UserRoleType], email: Option[String], settings: UserSettings = UserSettings()

knowledgeBases: Seq[Long] = Seq.empty, autoAssignEnabled: Boolean = false

добавитьПолеВФормуОператора(*args)

...

Шаги генерации формы для оператора

При работе оператора над диалогом система позволяет вывести для оператора форму сбора данных.

...

Форма операторов может быть выведена только в сценариях, которые привязаны к событию “Оператор нажал кнопку”. Введенные оператором в форме данные будет доступны в сценарии.

добавитьПолеВФормуОператора(*args)

Шаг для конструирования формы, которая будет показана оператору в момент работы сценария. Шаг добавляет новое поле в форму. Для добавления нескольких полей требуется выполнить этот шаг столько раз, сколько нужно полей. В качестве аргументов шаг принимает именованный список с данными в формате ключ-значение:

Code Block
breakoutModewide
форма: String         // имя формы, должно быть одинаковым для всех полей одной формы
переменная: String    // имя переменнной, в которой далее будет доступен результат заполнения поля
название: String      // название поля на форме
тип: String           // тип поля, доступно указание одного из типов указанного ниже
описание: String      // описание поля на форме, выводится под названием поля
значение: String      // предопределенное значение поля
обязательное: Boolean // обязательность заполнения поля, булево - true или false
варианты: String      // список вариантов, актуально только для выпадающих списков 

Пример добавления текстового поля на форму:

Пример:

...

breakoutModewide
Code Block
breakoutModewide

...

форма: String, - имя формы - обязательный параметр
переменная: String, - имя переменнной, которая пойдет в сценарий и имя в html form - обязательный параметр
название: String - имя на форме,
тип: String - Тип HTML ввода - обязательный параметр, если не задано или неверное -> нередактируемый текст 
описание: String  - описание на форме,
значение: String - предопределенное значение,
обязательное: Boolean - обязательность - по-умолчанию - false,
варианты: String - варианы для выпадающих списков - пример - {\"v1\": \"l1\", \"v2\": \"l2\"}
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Service Desk",
  переменная = "t1",
  название = "Описание заявки",
  тип = "Многострочный редактируемый текст",
  описание = "Опишите вашу проблему",
  обязательное = true
)

Список возможных значений параметра "тип":

  • Нередактируемый текст - вывод нередактируемого текстового сооющения на форме

  • Однострочный редактируемый текст - вывод однострочного поля для ввода

  • Многострочный редактируемый текст - вывод многострочного поля для ввода

  • Целое число - вывод поля для ввода целого числа

  • Выпадающий список - вывод поля для выбора одного значения из выпадающего списка

  • Множественный выбор - вывод поля для выбора нескольких значений из выпадающего списка

  • Переключатель - вывод переключателя, который сохранит булево значение true или false

Для полей типа Выпадающий список или Множественный выбор необходимо указание параметра варианты . Данный парметр должен содержать сериализованное представление списка вариантов в формате ключ-значение.

Code Block
breakoutModewide
варианты: "{\"1\": \"Утро\", \"2\": \"День\", \"3\": \"Вечер\", \"4\": \"Ночь\"}"

Оператор на форме увидит список из значений данного списка. По результату работы формы в переменную будет записан ключ выбранного значения. В значениях полей могут быть использованы переменные.

Code Block
breakoutModewide
установитьПеременную("slots", "{\"1\": \"Утро с 9 до 12\", \"2\": \"День с 12 до 18\", \"3\": \"Вечер с 18 до 21\", \"4\": \"Ночь с 21 до 24\"}") +
...
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Service 

...

Desk",
  переменная = "

...

slot",
  название = "

...

Временной слот",
  тип = "

...

Выпадающий 

...

список",
  описание = "

...

",
 

...

 

...

обязательное 

...

= 

...

true,
  варианты = "{

...

slots}"

...


) 

...

Список возможных значений параметра "тип":

  • "Нередактируемый текст"

  • "Однострочный редактируемый текст"

  • "Многострочный редактируемый текст"

  • "Переключатель"

  • "Целое число"

  • "Выпадающий список"

  • "Множественный выбор"

+
...

показатьФормуОператору(имя = "форма")

...

Шаг отображения формы оператора. Шаг отобразит форму со всеми установленными ранее полями. Сценарий отобразит форму и

...

будет ожидать пока оператор не нажмет на форме кнопку “Отмена” или “Продолжить”. После нажатия кнопки “Отмена” сценарий прекратит свою работу. После нажатия кнопки “Продолжить” сценарий продолжит свою работу со следующего шага. Все заполненные поля будут доступны в сценарии по имени переменной.

Code Block
показатьФормуОператору(имя = "Заведение заявки в Jira") +
если("{slot} == 4").то(
  комментарий("Требуется ночной формат работ") 
) +

...

Шаги работы с группами

определитьИдентификаторГруппы(*args)

Шаг определения текущей группы диалога. В качестве аргумента шаг принимает название переменной куда будет установлен текстовый идентификатор текущей группы диалога.

Code Block
определитьИдентификаторГруппы("chatGroupId") +
если("{chatGroupId} == 1234-abcd-5678").то(
  ...
) +

перевестиНаГруппу(*args).иЗавершить

Шаг перевода диалога на другую группу. Шаг совмещает смену группы и завершение текущего сценария в одном. В качестве аргумента шаг принимает идентификатор группы, в которую надо перевести диалог. Идентификатор каждой группы можно выяснить в разделе Настройки - Группы. Если в сервисе не будет обнаружено группы с таким идентификатором, то перевод на группу будет проигнорирован.

После смены группы диалог продолжит работу с текущего места:

  • если смена группы произошла в сценарии поступления диалога в систему, то после завершения сценария диалог запустит приветствие данной группы, а после переведет запрос в базы знаний;

  • если смена группы произошла в сценарии приветствия, то после зщавершения сценария диалог передаст запрос в базы знаний;

  • если смена группы произошла в сценарии документа из базы знаний, то следующий запрос пользователя будет передан уже в базы знаний указанной группы, а если пользователь ничего не запросит то диалог будет автоматически закрыт в указанной группе.

Code Block
breakoutModewide
задатьПользователюВопрос("Привет! Подскажи кому передать твой запрос?").сВариантамиОтвета("HR", "IT").сохранитьРезультат("UserSaid")+
если("{UserSaid} == HR").то(
	сообщениеПользователю.сШаблоном("Ок, перевожу запрос в HR отдел") +
	перевестиНаГруппу("1b514696-b033-41f4-88cd-91a5649b4f13").иЗавершить
) +
...

перевестиНаГруппу(*args).иЗавершитьСНовымЗапросом(*args)

Шаг перевода диалога на другую группу и передачи запроса в базы знаний этой группы вне зависимости от того где был использован данный шаг.

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

В качестве аргумента для иЗавершитьСНовымЗапросом указывается текст запроса, который необходимо передать в базы знаний, или переменная, которая содержит этот текст.

Code Block
breakoutModewide
задатьПользователюВопрос("Привет! Подскажи что тебя интересует?").сохранитьРезультат("UserSaid")+
перевестиНаГруппу("1b514696-b033-41f4-88cd-91a5649b4f13").иЗавершитьСНовымЗапросом("{UserSaid}")

перевестиНаГруппу(*args).иЗавершитьИПеревестиНаОператора

...

Шаги завершения сценария

завершить

Операция завершения сценария.

Code Block
breakoutModewide
завершить
Code Block
breakoutModewide
вызвать.внешнийСервис("{url}", "POST").сПараметрами(("accessKey", "{accessKey}")).сТеломСообщения("{"email":"{myEmail}"}").сохранитьРезультатКакСтроку("res")+
если("{http_code} > 210").то(
  завершить
)+

...

завершитьСНовымЗапросом("вопрос")

Операция завершения текущего сценария и вызова другого документа по запросу в бота. После завершения этого сценария, но в рамках текущей сессии боту будет передан приведенный запрос. Запрос будет обработан по стандартной процедуре, так как если бы этот запрос написал пользователь. Если результатом поиска по данному запросу будет документ с ответом в виде сценария, то по завершении текущего сценария будет сразу запущен следующий сценарий.

Code Block
breakoutModewide
задатьПользователюВопрос("Что еще вы хотели узнать ?").сохранитьРезультат("what")+
завершитьСНовымЗапросом("{what}")

завершитьИПеревестиНаОператора

Операция завершения текущего сценария и перевода диалога в очередь оператору. Запрос будет обработан по стандартной процедуре, так как если бы этот запрос написал пользователь и он сразу попал в очередь оператору.

Code Block
сообщениеПользователю.сШаблоном("Переключаю диалог на оператора")+
завершитьИПеревестиНаОператора

завершитьИЗакрытьДиалог()

Операция завершения текущего сценария и закрытия всего диалога. Следующая реплика пользователя создаст новый диалог.

Code Block
// проверка валидности пароля
если("{checkPassword} == 0").то(
  комментарий("Пользователь ввел неверный пароль")+
  сообщениеПользователю.сШаблоном("Вам сюда нельзя. Пока.")+
  завершитьИЗакрытьДиалог()
)+
сообщениеПользователю.сШаблоном("Все хорошо, продолжаем")+
завершить


Примеры сценариев

Сценарий с вызовом внешнего сервиса, разбором ответа в JS.

Code Block
установитьПеременную("host_cities", "https://api.autofaq.ai/v1/query") +
установитьПеременную("service_id", "121000") +
установитьПеременную("service_token", "939b8") +
установитьПеременную("other_score", "0.5") +
задатьПользователюВопрос("Уточните ваш город, пожалуйста?").сохранитьРезультат("city")+
вызвать.внешнийСервис("{host_cities}", "POST").сЗаголовками(("Content-Type", "application/json"),("charset", "utf-8")).сТеломСообщения("{\"service_token\": \"{service_token}\",\"service_id\":{service_id},\"query\":\"{city}\"}").сохранитьРезультатКакСтроку("results")+
выполнитьJs("""
var result = JSON.parse(results); var score = 0.0; var answer = '';
if (result.results.length > 0) {
	answer = result.results[0]['answer']; score = result.results[0]['score'];
    answer = answer.replace(/\n/g,'<br>');
} 
var exit = {'answer':answer, 'score':score}; exit;
""") +
если("{http_code} > 210").то(завершитьСШаблоном("Что-то сломалось. Зайдите попозже."))+
если("{score} < {other_score}").то(завершитьСШаблоном("Вот в этом городе у нас ничего нет"))+
сообщениеПользователю.сШаблоном("В указанном городе можно приобрести по адресам: <br>{answer}")+
задатьПользователюВопрос("Все ок?").сВариантамиОтвета("Да", "А мне не выдают").сохранитьРезультат("what")+
если("{what} == Да").или("{what} == да").то(завершитьСШаблоном("ну и отлично. Всего хорошего!"))+
завершитьСНовымЗапросом("Перевести на оператора")

Сценарий для интеграции на событие "Нажатие кнопки оператором"

Code Block
комментарий("Запуск интеграции по кнопке.")+
установитьПеременнуюВДиалог("Поле 2", значение = "Field 2", название = "Поле 2", показыватьОператору = true, обязательное = true, редактируемое = false)+
установитьПеременную("priority", "{\"v1\": \"Blocker\", \"v2\": \"Critical\", \"v3\": \"Major\", \"v4\": \"Minor\"}") +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t1",
  название = "Что вам нужно сделать: ",
  тип = "Нередактируемый текст",
  значение = "Заполните форму"
) +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t2",
  название = "Название заявки",
  тип = "Однострочный редактируемый текст",
  описание = "Введите название заводимой заявки",
  значение = "Введите",
  обязательное = true
) +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t3",
  название = "Критичность",
  тип = "Выпадающий список",
  описание = "Выберите из списка критичность заявки",
  обязательное = true,
  значение = "v3", 
  варианты = "{priority}"
) +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t4",
  название = "Описание",
  тип = "Многострочный редактируемый текст",
  описание = "Опишите вашу проблему",
  обязательное = true
) +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t5",
  название = "Уведомить руководителя?",
  тип = "Переключатель",
  обязательное = false
) +
установитьПеременную("tags", "{\"v1\": \"Teacher\", \"v2\": \"Student\", \"v3\": \"Sales\", \"v4\": \"Tech\"}") +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t6",
  название = "Теги",
  тип = "Множественный выбор",
  описание = "Выберите теги, которыми пометить обращение",
  варианты = "{tags}",
  обязательное = true
) +
добавитьПолеВФормуОператора(
  форма = "Заведение заявки в Jira",
  переменная = "t7",
  тип = "Целое число",
  название = "Частота возникновения проблемы",
  описание = "% пользователей, у которых возникает проблема" 
) +
показатьФормуОператору(имя = "Заведение заявки в Jira") +
комментарий("Вот что у нас получилось: {t2}, {t3}, {t4}")+
комментарий("Конец сценария интеграции!")