SES. Руководство пользователя: различия между версиями
Материал из Флора AI
| (не показано 128 промежуточных версий 3 участников) | |||
| Строка 1: | Строка 1: | ||
===== '''Общее описание''' ===== | |||
Сервис предназначен для создания сценарных машин и обеспечения их работы. | |||
===== '''Термины и определения''' ===== | |||
Script engine service (SES) - сервис обеспечения работы и создания сценарных машин. Swagger UI – интерактивная веб-консоль с кратким описанием методов API и возможностью выполнять запросы к сервису SES в реальном времени | |||
===== '''Скрипты интеграции''' ===== | |||
Для взаимодействия со сторонними сервисами используются скрипты интеграции на языке python. Скрипт интеграции должен содержать функцию '''handler'''(data={}, session_id=None, channel='default'). | Для взаимодействия со сторонними сервисами используются скрипты интеграции на языке python. Скрипт интеграции должен содержать функцию '''handler'''(data={}, session_id=None, channel='default'). | ||
Пример данных на входе можно посмотреть в методе ses GET/ses/session/{robot_id}/{session_id} | Пример данных на входе можно посмотреть в методе ses GET/ses/session/{robot_id}/{session_id} | ||
Функция должна исходя из полученных данных запросить ответ у стороннего сервиса. Запрос необходимо выполнить в блоке try/except. Скрипт не должен выдавать ошибку в основное приложение, все исключения должны быть обработаны внутри скрипта. Для отправки запроса рекомендуется использовать функцию ''' | Функция должна исходя из полученных данных запросить ответ у стороннего сервиса. Запрос необходимо выполнить в блоке try/except. Скрипт не должен выдавать ошибку в основное приложение, все исключения должны быть обработаны внутри скрипта. | ||
------- | |||
====== '''''Функция apiRequest''''' ====== | |||
'''''Для отправки запроса рекомендуется использовать функцию apiRequest.''''' Функция сделает все необходимые записи в лог интеграции. Пример: | |||
<code>from app.tools import apiRequest</code> | <code>from app.tools import apiRequest</code> | ||
| Строка 37: | Строка 43: | ||
* '''answered''' - получен ли ответ (True или False) | * '''answered''' - получен ли ответ (True или False) | ||
Если в скрипте интеграции не используются запросы к api стороннего сервиса через http, необходимо предусмотреть запись в лог (запись в лог встроена в функцию '''apiRequest''' и при ее использовании отдельно писать в лог не надо). Для этого необходимо импортировать библиотеку: | Если в скрипте интеграции не используются запросы к api стороннего сервиса через http, необходимо предусмотреть запись в лог (запись в лог встроена в функцию '''apiRequest''' и при ее использовании отдельно писать в лог не надо). Для этого необходимо импортировать библиотеку: | ||
from app.tools import apiLog | from app.tools import apiLog | ||
------- | |||
====== '''''Функция apiLog''''' ====== | |||
'''''Если в скрипте интеграции не используются запросы к api, по окончании работы функции handler вызвать функцию записи лога:''''' | |||
'''apiLog'''(data=data,name="",url="",request={},reply_code=200,reply=None,request_datetime=None,reply_datetime=None) | '''apiLog'''(data=data,name="",url="",request={},reply_code=200,reply=None,request_datetime=None,reply_datetime=None) | ||
| Строка 60: | Строка 68: | ||
* '''request_datetime''' - время перед запросом, без учета таймзоны, получить лучше так request_datetime=datetime.now(timezone.utc) | * '''request_datetime''' - время перед запросом, без учета таймзоны, получить лучше так request_datetime=datetime.now(timezone.utc) | ||
* '''reply_datetime''' - время сразу по получению ответа, также без учета таймзоны.<br /> Внимание - не используйте '''apiRequest или apiLog''' для данных содержащих пароли в открытом виде, чтобы они не попали в лог | * '''reply_datetime''' - время сразу по получению ответа, также без учета таймзоны.<br /> <span style="color:red">Внимание - не используйте '''apiRequest или apiLog''' для данных содержащих пароли в открытом виде, чтобы они не попали в лог</span> | ||
------- | |||
====== '''''Функция getData''''' ====== | |||
'''''Для упрощения поиска информации можно использовать функцию getData''''' (''from app.tools import getData''), нужна для извлечения конкретных данных из сессии, можно отправить либо всю переменную сессии, либо 'data' из сессии. Пример поиска цифрового кода заявления, выявленного моделью see 'number', поиск только в последнем сообщении диалога: | |||
<code><small>for j in getData(data=data,filter={'type':'see','model':'number'},depth=1):</small></code> | |||
<code><small>kod_zayavl=str(int(j['param']))</small></code> | |||
<code><small>break</small></code> | |||
Параметры функции | |||
* '''data''' - или 'data' из сессии или переменная сессии | |||
* '''filter''' - словарь ключевых полей и их значений - поиск сработает если все данные совпадут | |||
* '''depth''' - отвечает за глубину поиска в истории, по умолчанию 1, т.е. искать только в последнем сообщении. Возвращает список всех найденных данных, добавляя в каждый элемент depth, т.е. где именно он нашелся | |||
------- | |||
====== '''''Выполнение длительных процедур''''' ====== | |||
Код, который будет выполняться дольше нескольких секунд лучше запускать отдельным потоком. В этом случает есть возможность сообщить результат в канал даже после завершения основного диалога. Пример ожидания и отправки файла после паузы: | |||
<br /><small>from app.interactions import connectors | |||
def do_sleep(params, session_id, channel): | |||
time.sleep(params['sleep_time']) | |||
message="выполнено" | |||
connectors.sendMessage(channel=channel,session=session_id,answers=[{'messages':[message]}],files={'document':(filetame, open(file_path,'rb'))})</small> | |||
<small>def handler(data={}, session_id=None, channel='default'): | |||
params={} #чтото передадим в функцию | |||
params['sleep_time']= 100 | |||
Thread(target=do_sleep,name='do_sleep'+str(uuid.uuid4()),args=(params, session_id, channel) ).start() | |||
return { 'text': "запустил задание, ждем результат", 'answered': False }, {}</small> | |||
------- | |||
======'''''Отложенные задания'''''====== | |||
Для выполнения отложенных заданий необходимо | |||
#получить ссылку на базу данных текущего робота | |||
#в таблицу "crons" внести внести время и python код который должен выполниться в указанное время. | |||
Пример отложенного сообщения в телеграм:<br /> <small># Формируем задачу в крон</small> | |||
<small> error, db = get_db(data['robot'])</small> | |||
<small> if error:</small> | |||
<small> return { 'text': 'А я тебе ошибку базы данных привез: '+str(db), 'answered': False }, {}</small> | |||
<small> dt = int(datetime.strptime(date['date']+' '+date['time'],'%Y-%m-%d %H:%M').timestamp())</small> | |||
<small> </small> | |||
<small> # А вот тут создадим код для выполнения задачи</small> | |||
<small> url = f'<nowiki>https://api.telegram.org/bot{token}/sendMessage'</nowiki></small> | |||
<small> data = json.dumps({'chat_id': chat_id, 'text': message})</small> | |||
<small> data = base64.b64encode(data.encode("utf-8")).decode("utf-8")</small> | |||
<small> code = """</small> | |||
<small> import requests, json, base64</small> | |||
<small> try:</small> | |||
<small> data=\"{1}\"</small> | |||
<small> data=base64.b64decode(data.encode('utf-8')).decode('utf-8')</small> | |||
<small> requests.post(\"{0}\", data=json.loads(data), timeout = (5, 10))</small> | |||
<small> except Exception as error:</small> | |||
<small> logging.error(traceback.format_exc())</small> | |||
<small> </small> | |||
<small> """.format(url,data).replace(" ","")</small> | |||
<small> error, result = db.create(table='crons',data={</small> | |||
<small> 'id': str(uuid.uuid4()),</small> | |||
<small> 'name':'Задача-напоминание для '+username,</small> | |||
<small> 'datetime': dt,</small> | |||
<small> 'code': code })</small> | |||
------- | |||
======'''''Пользовательские таблицы базы данных'''''====== | |||
В составе большинства продуктов используется служебная файловая [https://wiki.connect2ai.net/index.php/UPS._%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE_%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B0#%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%D1%8F_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85 база данных]. В SES возможно использование служебной базы в скриптах интеграции. Для этого нужно: | |||
'''Импортировать функцию''' получения объекта БД (<code>from app.db import get_db</code>) | |||
'''Получить объект БД'''<br /> <small>error, db = get_db(data['robot'])</small> | |||
<small>if error: </small> | |||
<small>return { 'text': 'ошибка базы данных: '+str(db), 'answered': False }, {}</small> | |||
'''Объявить структуру''' пользовательской таблицы, создав запись в таблице структур (если еще не объявляли)<br /> <small>search_data={ | |||
"id":"new_table_name" | |||
} | |||
try: | |||
error, search_result = db.select('structures',data=search_data,sort=None,md5clean=True) | |||
if not search_result: | |||
struct_data = { | |||
"id":"new_table_name", | |||
"name": "new_table_name", | |||
"fields": { | |||
"string":"", | |||
"integer":0, | |||
"float":0.0, | |||
"именованный массив":{}, | |||
"неименованный массив":[], | |||
"bool":True | |||
} | |||
} | |||
error, str_id = db.create(table='structures', data=struct_data)</small> | |||
'''Сделать запись''' в базе<br /> <small>new_data={ | |||
"string":"пример строки\n", | |||
"integer":100500, | |||
"float":20.0004, | |||
"именованный массив":{'ключ1':'значение1'}, | |||
"неименованный массив":['запись1','запись2',], | |||
"bool":True | |||
}</small> | |||
<small>error, id = db.create(table="new_table_name", data=new_data) | |||
if error: | |||
return { 'text': 'ошибка создания: '+str(db), 'answered': False }, {}</small> | |||
Если при создании структуры не указывать в структуре id то база сама создаст id, вернет его в ответ. В дальнейшем тогда имя новой таблицы будет в id и запись/поиск в базе только по нему. Пример поиска в 'structures' подходит для поиска в пользовательской таблице. | |||
Создание, редактирование и просмотр пользовательской таблицы в базе возможно и с интерфейса UPS. | |||
====='''Подписка на сессию'''===== | |||
Позволяет просмотреть в реальном времени ход любого диалога. Для подписки в виджете отладчика необходимо активировать соответствующую кнопку и настроить фильтр. Используется для отладки сессий. Если сессий удовлетворяющих фильтру не найдено, виджет отладчика работает в режиме ожидания. | |||
Сессии ассистента можно просматривать не только через отладчик, но и через виджет ассистента. Виджет подключается к ассистенту, встраивается в веб‑страницу и использует параметры авторизованного пользователя для фильтрации сессий (номер телефона из настроек пользователя). | |||
====='''Робот - ассистент'''===== | |||
Предназначен для сопровождения диалога с оператором без вмешательства в него. Возможен только для типа коннектора "freeswitch" (телефонный канал). Робот - ассистент (суфлер) классифицирует и обрабатывает запросы от абонента, но не передает ответ в канал, а оставляет в своей сессии. На эту сессию может '''"подписаться"''' оператор, и в виджете ассистента получать подсказки и информацию от робота. | |||
====== '''''Запуск ассистента''''' ====== | |||
* Опция «Автостарт ассистента» включается в настройках коннектора робота, на который поступает звонок от абонента. | |||
* При каждом звонке ассистент автоматически запускается и сопровождает новую сессию. | |||
* Если вызов перенаправляется оператору, в параметр ''destination'' подставляется "номер для перевода звонка" (указан в настройках коннектора). | |||
* Оператор с таким номером (настроенным в UPS) сможет просмотреть сессию в виджете ассистента. | |||
====== '''''Запуск через API''''' ====== | |||
Используется метод: | |||
<code><small>GET /ses/assistant/{session_id}/{destination}</small></code> | |||
* После вызова метода значение переменной ''destination'' в сессии заменяется на переданное в запросе. | |||
* Это значение должно соответствовать идентификатору или номеру оператора, настроенному в UPS. | |||
* Оператор должен быть авторизован в UPS и обладать нужными правами доступа. | |||
====== '''''Возможные сценарии работы''''' ====== | |||
# абонент -> робот -> оператор (после перевода на оператора) В этом случае основной робот принимает звонок, затем передаёт сессию ассистенту после перевода. В виджете отображаются обе части диалога — до и после трансфера. | |||
# абонент -> оператор Здесь робот-ассистент сразу переводит звонок оператору (согласно настройкам коннектора FreeSWITCH) и не говорит ничего в канал.Если суфлирование не запущено, робот не обрабатывает аудио и не использует ресурсы. | |||
====== '''''Важные настройки''''' ====== | |||
* В блоках «События» и «Исключения» следует отключить действие «Завершить диалог», чтобы ассистент не закрывал свою сессию преждевременно. | |||
* Режим работы (робот или ассистент) и телефон оператора для ассистента задаются в настройках коннектора FreeSWITCH. | |||
* Один и тот же робот может быть ассистентом для одного коннектора и основным — для другого. | |||
====='''Описание методов API'''===== | |||
Запросы осуществляются по протоколу HTTP 1.1 на адрес сервера с доступным сервисом SES. По умолчанию используется порт 6189/tcp. | Запросы осуществляются по протоколу HTTP 1.1 на адрес сервера с доступным сервисом SES. По умолчанию используется порт 6189/tcp. | ||
| Строка 72: | Строка 255: | ||
Содержимое документа зависит от результата выполнения запроса. При наличии ошибки в качестве ответа вернется переменная error=1 и описание в переменной message. Для удобства проверки методов по ссылке http://АДРЕС:6190 будет отображен интерфейс swagger со всеми методами с возможностью их проверки. | Содержимое документа зависит от результата выполнения запроса. При наличии ошибки в качестве ответа вернется переменная error=1 и описание в переменной message. Для удобства проверки методов по ссылке http://АДРЕС:6190 будет отображен интерфейс swagger со всеми методами с возможностью их проверки. | ||
======'''''Методы API'''''====== | |||
{| class="wikitable" style="width: 110%" | {| class="wikitable" style="width: 110%" | ||
|- | |- | ||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses</big>''' | ! colspan="3" style="text-align: center" |'''<big>Группа методов ses</big>''' | ||
| Строка 108: | Строка 293: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''text''' - текст запроса</small> | *<small>'''text''' - текст запроса</small> | ||
* <small>'''channel''' - id канала</small> | *<small>'''channel''' - id канала</small> | ||
* <small>''' | *<small>'''connector''' - имя коннектора</small> | ||
* <small>''' | *<small>'''session''' - uuid сессии, если это не первый запрос в сессии</small> | ||
* <small>''' | *<small>'''tts''' - вернуть результат синтеза (1- вернуть, 0 - не выполнять синтез)</small> | ||
* <small>''' | *<small>'''variables''' - словарик с переменными {"переменная1":"значение","переменнаяN":"значение"}</small> | ||
* <small>'''robot_id''' - id робота</small> | *<small>'''handler''' - python скрипт для изменения ответов метода под требования внешних систем, подробнее в следующем разделе. в поле имя файла без расширения.</small> | ||
*<small>'''restartClosed''' - перезагрузить сессию при её закрытии с новым id (1 - перезагрузить, 0 - не перезагружать)</small> | |||
*<small>'''audio''' - аудиофайл с запросом, текст запроса будет получен распознаванием audio</small> | |||
*<small>'''document''' - документ для последующей обработки</small> | |||
*<small>'''robot_id''' - id робота</small> | |||
*<small>'''endpoint''' - id точки, в которую передать управление диалогом (необязательный параметр, используется для исходящих оповещений)</small> | |||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
<small> "question": "Вопрос",</small> | <small> "question": "Вопрос",</small> | ||
<small> "answer": [</small> | |||
<small> { "messages": [</small> | |||
<small> "ответ" ],</small> | |||
<small> "voice": "",</small> | |||
<small> "interruptible": true/false,</small> | |||
<small> " | <small>"file": "" } ],</small> | ||
<small> "session": "",</small> | |||
<small>"uuid": "" }</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/assistant/{session_id}/{destination}''' | |||
! colspan="3" style="width: 85%" |Запуск робота - суфлера для выбранной сессии | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
* <small>'''robot_id''' - id робота суфлера</small> | |||
<small> | * <small>'''session_id''' - сессия для которой нужен суфлер</small> | ||
<small> | * <small>'''destination''' - номер назначения (номер оператора на которого ушел звонок)</small> | ||
| colspan="2" style="width: 50%" |<small>{ "error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/hostname''' | |||
! colspan="3" style="width: 85%" |Получение имени хоста на котором запущен сервис | |||
|- | |||
| colspan="2" style="width: 50%" |<small>Входные параметры отсутствуют</small> | |||
| colspan="2" style="width: 50%" |<small>{ "error": 0,</small> | |||
<small> | <small>"message": "success",</small> | ||
<small> | <small>"hostname": "kotobot-gpu-04"}</small> | ||
|- | |- | ||
! style="color:green;width: 15%" |'''POST/ses/log''' | ! style="color:green;width: 15%" |'''POST/ses/log''' | ||
| Строка 139: | Строка 360: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''date''' - начальная дата в формате %Y-%m-%d</small> | *<small>'''date''' - начальная дата в формате %Y-%m-%d</small> | ||
| style="width: 50%" |<small>{ "error": 0, "message": "success",</small> | | style="width: 50%" |<small>{ "error": 0, "message": "success",</small> | ||
<small> "log": [</small> | <small> "log": [</small> | ||
<small> {"id": ",.....",</small><small> "session": "</small><small>......</small><small>",</small> <small>"robot": "</small><small>.....</small><small>",</small> | <small> {"id": ",.....",</small> <small> "session": "</small><small>......</small><small>",</small> <small>"robot": "</small><small>.....</small><small>",</small> <small>"channel": "......",</small><small> </small> | ||
<small> | <small>"</small><small>unknown": true/false,</small> <small>"</small><small>closed": true</small><small>/false</small><small>,</small><small> </small> <small>"endpoint":</small> <small>"....."</small><small>,</small> | ||
<small> "variables": {},</small> | <small> "answered": true/false, "models": [....], "variables": {}, "current": {.......},</small> | ||
<small> "request": {.......</small><small>},</small><small> | <small> "request": {.......</small><small>},</small><small> </small> <small>"reply": { .....</small> <small>}, "robot_id": "", "endpointName": "", "endpointType": "" },</small> | ||
<small> .....</small><small> ] }</small> | <small> .....</small><small> ] }</small> | ||
| Строка 158: | Строка 379: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot_id''' - id робота</small> | *<small>'''robot_id''' - id робота</small> | ||
* <small>'''session_id''' - id незакрытой сессии</small> | *<small>'''session_id''' - id незакрытой сессии</small> | ||
| style="width: 50%" |<small>{ "started": " | | style="width: 50%" |<small>{ "started": "",</small><small> "modified": "",</small> | ||
<small>" | <small> "robot": "",</small> | ||
<small>" | <small> "session": "",</small> | ||
<small>" | <small> "channel": "",</small> | ||
<small> | <small> "connector": "",</small> | ||
<small> | <small> "unknown": true/false,</small> | ||
<small>" | <small> "current": {"id": "", "qas": "", "answered": true/false, "category": "",</small> | ||
<small>" | <small> "nearest": "", "entry": [.....], "missingRunData": [],</small> | ||
<small> | <small> "passedRunData": [.....], "waitingRunData": null,</small> | ||
<small> " | <small> "border": int, "preborder": int, "lastreply": ""},</small> | ||
<small> | <small> "models": [.....],</small> | ||
<small> | <small> "scripts": [.....],</small> | ||
<small> | <small><nowiki> "data": [{"request": {.....}, "reply": {.....}}],</nowiki></small> | ||
<small> "timers": [],</small> | |||
<small> "variables": {},</small> | |||
<small> "error": "",</small> | |||
<small> "events": {.....},</small> | |||
<small> "closed": "" }</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/widget/config''' | |||
! colspan="2" style="width: 85%" |Отдает конфигурацию виджета скрипту виджета | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''token''' - ключ виджета</small> | |||
| style="width: 50%" |<small>На выходе содержимое настроек web канала из конфигурационного файла</small> | |||
|- | |- | ||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/<big>''' | ! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/<big>''' | ||
| Строка 193: | Строка 431: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''name''' - имя нового робота</small> | *<small>'''name''' - имя нового робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 202: | Строка 440: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 211: | Строка 449: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 220: | Строка 458: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 229: | Строка 467: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 235: | Строка 473: | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/export/{id}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/export/{id}''' | ||
! colspan="2" style="width: 85%" |Выгрузка робота в архив. | ! colspan="2" style="width: 85%" | Выгрузка робота в архив. | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>zip файл с именем = идентификатор робота</small> | | style="width: 50%" |<small>zip файл с именем = идентификатор робота</small> | ||
|- | |- | ||
| Строка 245: | Строка 483: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 266: | Строка 504: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''zip -''' файл с архивом робота</small> | *<small>'''zip -''' файл с архивом робота</small> | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 288: | Строка 526: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с новыми настройками робота</small> | *<small>'''data''' - json строка с новыми настройками робота</small> | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 298: | Строка 536: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор робота</small> | *<small>'''id''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 309: | Строка 547: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами элемента данных</small> | *<small>'''data''' - json строка с параметрами элемента данных</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 320: | Строка 558: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор элемента данных</small> | *<small>'''id''' - идентификатор элемента данных</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 328: | Строка 566: | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/data/get/{robot}/{id}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/data/get/{robot}/{id}''' | ||
! colspan="2" style="width: 85%" |Получение настроек элемента данных | ! colspan="2" style="width: 85%" |Получение настроек элемента данных | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''id''' - идентификатор элемента данных</small> | *<small>'''id''' - идентификатор элемента данных</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ | | style="width: 50%" |<small>{ "error": 0,</small><small> "data": {</small> | ||
<small> "id": ".....", "name": ".....", "comment": "", "type": "smc",</small> | |||
<small> "rtype": "report", "model": ".....", "param": ".....",</small> | |||
<small> "script": "", "weight": int, "slaveData": [],</small> | |||
<small> " | <small> "getOnlyAsNearest": true/false, "injectToMessage": true/false,</small> | ||
<small> " | <small> "longWaiting": true/false, "dataWaiting": [],</small> | ||
<small>" | <small><nowiki> "actions": {}, "exceptions": {}}}</nowiki></small> | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/data/list/{robot}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/data/list/{robot}''' | ||
| Строка 346: | Строка 590: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | * <small>'''robot''' - идентификатор робота (id)</small> | ||
| style="width: 50%" |<small>[ { | | style="width: 50%" |<small>[ { </small> <small>"id": "3ebfe38b-95bf-4927-a662-17f6e5da22ea",</small><small> "name": "pve", "type": "smc", "rtype": "report",</small> | ||
<small> "name": "pve",</small> | |||
<small> " | <small> "weight": 3, "hasNearestAction": false</small> <small>} ]</small> | ||
|- | |- | ||
! style="color:green;width: 15%" |'''POST/ses/robot/data/modify/{robot}/{id}''' | ! style="color:green;width: 15%" |'''POST/ses/robot/data/modify/{robot}/{id}''' | ||
| Строка 357: | Строка 599: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами элемента данных</small> | *<small>'''data''' - json строка с параметрами элемента данных</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
* <small>'''id''' - идентификатор элемента данных</small> | *<small>'''id''' - идентификатор элемента данных</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 371: | Строка 613: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами конечной точки</small> | *<small>'''data''' - json строка с параметрами конечной точки</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 379: | Строка 621: | ||
|- | |- | ||
! style="color:red;width: 15%" |'''DELETE/ses/robot/endpoint/delete/{robot}/{id}''' | ! style="color:red;width: 15%" |'''DELETE/ses/robot/endpoint/delete/{robot}/{id}''' | ||
! colspan="2" style="width: 85%" |Удаление конечной точки. | ! colspan="2" style="width: 85%" |Удаление конечной точки. | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
* <small>'''id''' - идентификатор конечной точки</small> | *<small>'''id''' - идентификатор конечной точки</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 392: | Строка 634: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
* <small>'''id''' - идентификатор конечной точки</small> | *<small>'''id''' - идентификатор конечной точки</small> | ||
| style="width: 50%" |<small>{ | | style="width: 50%" |<small>{ "error": 0,</small><small> "data": {</small> | ||
<small> "id": "...", "name": "...", "comment": "",</small> | |||
<small> "entryType": "conditions",</small> | |||
<small> " | <small> "entry": [{ "conditions": [{ "type": "...", "depth": 5, "id": "...", "operation": "...", "value": ""}], "run": []}],</small> | ||
<small> " | <small> "run": [],</small> | ||
<small> | <small> "actions": { "default": [{ "action": "...", "voice": "", "type": "...", "interruptible": true/false}]},</small> | ||
<small> | <small><nowiki> "type": "report"}}</nowiki></small> | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/endpoint/list/{robot}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/endpoint/list/{robot}''' | ||
! colspan="2" style="width: 85%" |Получение списка конечных точек робота | ! colspan="2" style="width: 85%" |Получение списка конечных точек робота | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>[ { "id": " | | style="width: 50%" |<small>[{ "error": 0,</small><small> "data": {</small> | ||
<small> "id": "...", "name": "...", "comment": "",</small> | |||
<small> " | <small> "entryType": "conditions",</small> | ||
<small> "entry": [] | <small> "entry": [{ "conditions": [{ "type": "...", "depth": 5, "id": "...", "operation": "...", "value": ""}], "run": []}],</small> | ||
<small> | <small> "run": [],</small> | ||
<small> " | <small> "actions": { "default": [{ "action": "...", "voice": "", "type": "...", "interruptible": true/false}]},</small> | ||
<small> " | <small><nowiki> "type": "report"}}]</nowiki></small> | ||
|- | |- | ||
! style="color:green;width: 15%" |'''POST/ses/robot/endpoint/modify/{robot}/{id}''' | ! style="color:green;width: 15%" |'''POST/ses/robot/endpoint/modify/{robot}/{id}''' | ||
| Строка 425: | Строка 673: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами элемента данных</small> | *<small>'''data''' - json строка с параметрами элемента данных</small> | ||
* <small>'''id''' - идентификатор элемента данных</small> | *<small>'''id''' - идентификатор элемента данных</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
<small> "message": "success"}</small> | <small> "message": "success"}</small> | ||
|- | |||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/archive<big>''' | |||
|- | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/archive/audio/{uuid}''' | |||
! colspan="2" style="width: 85%" |Получение аудио-файла из архива диалогов | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''uuid''' - идентификатор диалога</small> | |||
| style="width: 50%" |<small>аудио-файл с расширением opus</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/archive/dialog/{uuid}''' | |||
! colspan="2" style="width: 85%" |Получение диалога из архива | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''uuid''' - идентификатор диалога</small> | |||
| style="width: 50%" |<small>{ "error": 0,</small><small> "message": "success",</small> | |||
<small> "dialog": [{"id": "...", "robot": "...", "channel": "...",</small> | |||
<small> "unknown": true/false, "closed": true/false, "endpoint": "...",</small> | |||
<small> "answered": true/false, "models": [...], "variables": {}, "current": {</small> | |||
<small> "id": "...", "qas": "", "category": "...", "entry": [...],</small> | |||
<small> "nearest": "...", "missingRunData": [...], "waitingRunData": "...",</small> | |||
<small> "answered": true/false, "lastreply": "..."},</small> | |||
<small> "request": {"datetime": "...", "message": "", "data": [...]},</small> | |||
<small> "reply": {"answers": [{"messages": [...], "voice": "...",</small> | |||
<small> "interruptible": true/false, "file": null}],</small> | |||
<small><nowiki> "datetime": "...", "answered": true/false}}]}</nowiki></small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/archive/list''' | |||
! colspan="2" style="width: 85%" |Получение списка диалогов из архива | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''uuid''' - идентификатор диалога</small> | |||
*<small>'''startdate''' - начало временного интервала в формате date %Y-%m-%d %H:%M</small> | |||
*<small>'''enddate''' - конец временного интервала в формате date %Y-%m-%d %H:%M</small> | |||
*<small>'''phone''' - номер телефона</small> | |||
*<small>'''variable''' - переменная в формате variable=value</small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''text''' - фрагмент текста в любом сообщении</small> | |||
*<small>'''data''' - id элемента данных</small> | |||
*<small>'''channel''' - название канала (коннектора)</small> | |||
| style="width: 50%" |<small>[{"uuid": "...", "datetime": "...","phone": "",</small><small> "channel": [...], "robot": ["..."]}]</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/archive/waveform/{uuid}''' | |||
! colspan="2" style="width: 85%" | Служебный метод для визуализации полученного из архива диалогов аудио-файла, содержит пики сигнала. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''uuid''' - идентификатор диалога</small> | |||
| style="width: 50%" |<small>[0.016,</small> | |||
<small>0.015,</small> | |||
<small>0.01</small><small>]</small> | |||
|- | |- | ||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/script<big>''' | ! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/script<big>''' | ||
| Строка 438: | Строка 749: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами скрипта</small> | *<small>'''data''' - json строка с параметрами скрипта</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 445: | Строка 756: | ||
|- | |- | ||
! style="color:red;width: 15%" |'''DELETE/ses/robot/script/delete/{robot}/{id}''' | ! style="color:red;width: 15%" |'''DELETE/ses/robot/script/delete/{robot}/{id}''' | ||
! colspan="2" style="width: 85%" |Удаление скрипта | ! colspan="2" style="width: 85%" |Удаление скрипта | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
* <small>'''id''' - идентификатор скрипта</small> | *<small>'''id''' - идентификатор скрипта</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
| Строка 455: | Строка 766: | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/script/get/{robot}/{id}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/script/get/{robot}/{id}''' | ||
! colspan="2" style="width: 85%" |Получение текста скрипта | ! colspan="2" style="width: 85%" |Получение текста скрипта | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
* <small>'''id''' - идентификатор скрипта</small> | *<small>'''id''' - идентификатор скрипта</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" | | ||
<small>{ "error": 0,</small> | |||
<small> "data": {</small> | <small> "data": {</small> | ||
<small> "id": "6a9f91b6-9634-4079-ac2b-60a944922c61",</small> | <small> "id": "6a9f91b6-9634-4079-ac2b-60a944922c61",</small> | ||
<small> "type": "Тип скрипта",</small> | |||
<small> "name": "Наименование скрипта",</small> | <small> "name": "Наименование скрипта",</small> | ||
| Строка 473: | Строка 787: | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/robot/script/list/{robot}''' | ! style="color:blue;width: 15%" |'''GET/ses/robot/script/list/{robot}''' | ||
! colspan="2" style="width: 85%" |Получение списка скриптов | ! colspan="2" style="width: 85%" |Получение списка скриптов | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>[ { "id": "9b9d83b7-d5c3-49e6-9bd4-a123a9047939",</small> | | style="width: 50%" |<small>[ { "id": "9b9d83b7-d5c3-49e6-9bd4-a123a9047939",</small> | ||
<small> "name": "наименование1"</small> <small>},</small> | <small> "name": "наименование1",</small> | ||
<small> "type": "Тип скрипта"},</small> | |||
<small> { "id": "48b508ba-a32b-4ada-bcc3-66ce26d81c6a",</small> | <small> { "id": "48b508ba-a32b-4ada-bcc3-66ce26d81c6a",</small> | ||
<small> "name": "наименование2"</small> <small>}]</small> | <small> "name": "наименование2",</small> | ||
<small> "type": "Тип скрипта"}]</small> | |||
|- | |- | ||
! style="color:green;width: 15%" |'''POST/ses/robot/script/modify/{robot}/{id}''' | ! style="color:green;width: 15%" |'''POST/ses/robot/script/modify/{robot}/{id}''' | ||
| Строка 489: | Строка 807: | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''data''' - json строка с параметрами элемента данных</small> | *<small>'''data''' - json строка с параметрами элемента данных</small> | ||
* <small>'''id''' - идентификатор скрипта</small> | *<small>'''id''' - идентификатор скрипта</small> | ||
* <small>'''robot''' - идентификатор робота</small> | *<small>'''robot''' - идентификатор робота</small> | ||
| style="width: 50%" |<small>{ "error": 0,</small> | | style="width: 50%" |<small>{ "error": 0,</small> | ||
<small> "message": "success"}</small> | <small> "message": "success"}</small> | ||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/script/test/{robot}/{id}''' | |||
! colspan="2" style="width: 85%" |Тестирование скрипта. <small>Формат '''data''' как в ответе метода '''GET/ses/session/{robot_id}/{session_id}'''</small> | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''data''' - json строка с параметрами сессии</small> | |||
*<small>'''id''' - идентификатор скрипта</small> | |||
*<small>'''robot''' - идентификатор робота</small> | |||
| style="width: 50%" |<small><nowiki>{"error": 0, "message": "success", "result": {.....}, "variables": {}}</nowiki></small> | |||
|- | |||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/files<big>''' | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/robot/files/download/{robot}/{id}''' | |||
! colspan="2" style="width: 85%" | Получение файла. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота</small> | |||
*<small>'''id''' - идентификатор файла</small> | |||
| style="width: 50%" |<small>файл</small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/files/upload/{robot}''' | |||
! colspan="2" style="width: 85%" |Отправка файла. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота</small> | |||
*<small>'''file''' - файл</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success", "id": "Id файла"}</small> | |||
|- | |- | ||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/testapi''' ''[https://wiki.connect2ai.net/index.php/SES._%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE_%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B0#:~:text=%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F%20%D0%BF%D0%B0%D0%BF%D0%BA%D0%B0-,%D0%AD%D0%BC%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F%20%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2%20%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D0%B8,-%5B%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%7C для отладки скриптов интеграции]'' | ! colspan="3" style="text-align: center" |'''<big>Группа методов ses/testapi''' ''[https://wiki.connect2ai.net/index.php/SES._%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE_%D0%B0%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B0#:~:text=%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F%20%D0%BF%D0%B0%D0%BF%D0%BA%D0%B0-,%D0%AD%D0%BC%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F%20%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2%20%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D0%B8,-%5B%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%7C для отладки скриптов интеграции]'' | ||
| Строка 509: | Строка 854: | ||
|- | |- | ||
! style="color:green;width: 15%" |'''POST/ses/testapi/{request}''' | ! style="color:green;width: 15%" |'''POST/ses/testapi/{request}''' | ||
! colspan="2" style="width: 85%" |Получение ответа эмулятора сервиса интеграции | ! colspan="2" style="width: 85%" |Получение ответа эмулятора сервиса интеграции | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''request''' - запрос вида <service1></small> | *<small>'''request''' - запрос вида <service1></small> | ||
| style="width: 50%" |<small> "ответ эмулятора"</small> | | style="width: 50%" |<small> "ответ эмулятора"</small> | ||
|- | |- | ||
! style="color:blue;width: 15%" |'''GET/ses/testapi/{request}''' | ! style="color:blue;width: 15%" |'''GET/ses/testapi/{request}''' | ||
! colspan="2" style="width: 85%" |Получение ответа эмулятора сервиса интеграции | ! colspan="2" style="width: 85%" |Получение ответа эмулятора сервиса интеграции | ||
|- | |- | ||
| colspan="2" style="width: 50%" | | | colspan="2" style="width: 50%" | | ||
* <small>'''request''' - запрос вида <service1></small> | *<small>'''request''' - запрос вида <service1></small> | ||
| style="width: 50%" |<small> "ответ эмулятора"</small> | | style="width: 50%" |<small> "ответ эмулятора"</small> | ||
| | |||
|- | |||
! colspan="3" style="text-align: center" |'''<big>Группа методов ses/robot/userdata<big>''' | |||
|- | |||
! style="color:blue;width: 15%" |'''POST/ses/robot/userdata/data/add/{robot}/{structure}''' | |||
! colspan="2" style="width: 85%" |Добавление записи в пользовательский справочник. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''data''' - json строка в формате <code>{"колонка 1": "значение 1","колонка n":"значение n"}</code></small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>{"error": 0, "id": "id записи"}</small> | |||
|- | |||
! style="color:red;width: 15%" |'''DELETE/ses/robot/userdata/data/delete/{robot}/{structure}/{id}''' | |||
! colspan="2" style="width: 85%" |Удаление записи из пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
*<small>'''id''' - идентификатор записи (id)</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/robot/userdata/data/list/{robot}/{structure}''' | |||
! colspan="2" style="width: 85%" |Получение данных из пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>[{ "колонка 1": "значение 1",</small> <small> "колонка n": "значение n",</small> <small> "id": "id записи"}]</small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/userdata/data/modify/{robot}/{structure}''' | |||
! colspan="2" style="width: 85%" |Массовое изменение данных в пользовательском справочнике. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''list''' - json строка в формате <code>[{"колонка 1": "значение 1","колонка n": "значение n", "id": "id строки"}]</code></small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/userdata/data/modify/{robot}/{structure}/{id}''' | |||
! colspan="2" style="width: 85%" |Изменение одной записи пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''data''' - json строка в формате <code>{"колонка 1": "значение 1","колонка n":"значение n"}</code></small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
*<small>'''id''' - идентификатор записи (id)</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/userdata/data/put/{robot}/{structure}''' | |||
! colspan="2" style="width: 85%" |Добавление данных с заменой в пользовательском справочнике. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''list''' - json строка в формате <code>[{"колонка 1": "значение 1","колонка n": "значение n", "id": "id строки"}]</code> Поле "id" опционально, при его добавлении данные в строке будут заменены.</small> | |||
*<small>'''replace''' - замена всех данных в справочнике новыми данными. Возможные значения: yes/no. По-умолчанию - yes.</small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''structure''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/userdata/structure/add/{robot}''' | |||
! colspan="2" style="width: 85%" |Добавление пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''data''' - json строка в формате <code><nowiki>{"id": "id справочника", "name": "справочник", "fields": {"колонка 1": "значение по умолчанию","колонка n":"значение по умолчанию"}}.</nowiki></code> Поле "id" опционально.</small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
| style="width: 50%" |<small>{"error": 0, "id": "id справочника"}</small> | |||
|- | |||
! style="color:red;width: 15%" |'''DELETE/ses/robot/userdata/structure/delete/{robot}/{id}''' | |||
! colspan="2" style="width: 85%" |Удаление пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''id''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
! style="color:blue;width: 15%" |'''GET/ses/robot/userdata/structure/list/{robot}''' | |||
! colspan="2" style="width: 85%" |Получение списка пользовательских справочников. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
| style="width: 50%" |<small><nowiki>[{"id": "id справочника", "name": "справочник", "fields": {"колонка1": "значение по умолчанию"}}]</nowiki></small> | |||
|- | |||
! style="color:green;width: 15%" |'''POST/ses/robot/userdata/structure/modify/{robot}/{id}''' | |||
! colspan="2" style="width: 85%" |Модификация структуры пользовательского справочника. | |||
|- | |||
| colspan="2" style="width: 50%" | | |||
*<small>'''data''' - json строка в формате <code><nowiki>{"name": "справочник", "fields": {"колонка 1": "значение по умолчанию","колонка n":"значение по умолчанию"}}.</nowiki></code></small> | |||
*<small>'''robot''' - идентификатор робота (id)</small> | |||
*<small>'''id''' - идентификатор пользовательского справочника</small> | |||
| style="width: 50%" |<small>{"error": 0, "message": "success"}</small> | |||
|- | |||
|} | |||
======'''''Постобработка методов api'''''====== | |||
Для метода '''POST/ses/ask/{robot_id}''' можно изменить формат данных ответа. | |||
Для этого необходимо подготовить скрипт на python в папке /opt/ses/handlers/api/ask/ . Скрипт должен содержать функцию handler(reply={}), Функция должна вернуть переформатированный ответ. Чтобы воспользоваться скриптом необходимо его имя без разрешения указать в поле "<small>'''handler'''</small>" при запросе метода. | |||
Аналогично и для метода ask websocket протокола - файл положить в /opt/ses/handlers/websockets/ask/ . Далее в любом запросе указать обработчик <code><nowiki>{тут всё, что ты и так отправляешь, 'handlers': { 'ask': '__telegram' }} }</nowiki></code> . начиная с этого запроса обработчик будет действовать в течение сессии пока не отправишь 'handlers': {} . Для других полей запросов в канале websocket аналогично. | |||
В составе поставки ses есть файл примера <code>__telegram.py</code> (префикс 2 подчеркивания - такой файл будет переписан при обновлении, любой другой, останется после обновления) | |||
===== '''Websockets сервер''' ===== | |||
Работа с программным продуктом возможна с использованием встроенного websockets сервера. Подключение производится по порту 6191, без SSL. При необходимости работать по SSL перед SES ставится nginx в режиме прокси, и SSL поднимается на nginx. Подробнее см. документацию по nginx. | |||
В таблице ниже приведены форматы сообщений для работы с сервером. В каждом сообщении (за исключением бинарных), присутствует переменная path (формат сообщений - JSON), которая определяет алгоритм обработки сообщения. Подключение к серверу возможно в следующих вариантах: | |||
# ws://адрес:6191 | |||
# ws://адрес:6191/session[/chunk] | |||
Первый вариант подходит только для текстовых сообщений, в данном случае передача переменной session (uuid текущей сессии) должна производиться в теле сообщения. | |||
Второй вариант подходит и для текстового и для голосового общения с роботом. В данном случае session передается в пути подключения к websockets-серверу. Для каждой новой сессии нужно открывать новое соединение, chunk в пути подключения нужен в том случае, если передаются не готовые части аудио, предварительно сформированные, а сплошной поток аудио, кусками по 20 мс. | |||
{| class="wikitable" style="width: 110%" | |||
|- | |||
! colspan="3" style="text-align: center" |'''<big>Входящие сообщения''' | |||
|- | |||
! style="color:green;width: 15%" |'''path:ask''' | |||
! colspan="2" style="width: 85%" |Вопрос роботу | |||
|- | |||
| colspan="2" style="width: 50%" |<small>{</small> | |||
<small> "path": "ask",</small> | |||
<small> "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf",</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5", ''# Необязательный параметр, если не будет отправлен, будет создана новая сессия и в ответе придет сгенерированный session''</small> | |||
<small> "channel": "default",</small> | |||
<small> "link": 1, ''# Необязательный параметр, отдает ссылки на аудио, если 1.''</small> | |||
<small> "format": "wav", ''# Необязательный параметр, формат возвращаемого аудио, если channel=voice''</small> | |||
<small>"document": {"name":"название","base64":"тело документа в base64"}, ''# необязательный параметр''</small> | |||
<small>"handlers": {"ask": "название хэндлера"}, ''# Необязательный параметр, см. [[SES. Руководство администратора|описание обработчиков]]''</small> | |||
<small> "text": "привет", </small> | |||
<small>или</small> | |||
<small>"audio": "base64 строка",</small> | |||
<small>}</small> | |||
| style="width: 50%" |Для текстовых ответов (канал не voice) | |||
<small>{</small><small> "error": 0,</small> | |||
<small> "question": "привет",</small> | |||
<small> "answer": [</small> | |||
<small> {</small> | |||
<small> "messages": [</small> | |||
<small> "Здравствуйте! Как я могу вам помочь сегодня?"</small> | |||
<small> ],</small> | |||
<small> "voice": "Валера",</small> | |||
<small> "interruptible": false,</small> | |||
<small> "file": null</small> | |||
<small> }</small> | |||
<small> ],</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5",</small> | |||
<small> "uuid": "83722305-645d-4674-8c5d-952e02f595f9",</small> | |||
<small> "path": "ask"</small> | |||
<small>}</small> | |||
Для голосовых ответов, канал voice, дополнительно идет отправка N сообщений с аудио | |||
<small>{</small><small> "</small><small>audio</small><small>":</small> <small>"ссылка или base64 закодированное аудио"</small><small>,</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5",</small> | |||
<small> "uuid": "83722305-645d-4674-8c5d-952e02f595f9",</small> | |||
<small> "status": "listening | asking" ''# Требование к клиенту выставить статус.''</small> | |||
<small>}</small> | |||
|- | |||
!'''path:session''' | |||
! colspan="2" |Статус сессии | |||
|- | |||
| colspan="2" |<small>{</small> | |||
<small> "path": "session",</small> | |||
<small> "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf",</small> | |||
<small> "session": "548cd1ca-a24a-4a9a-ab4f-8363aa32c3c2"</small> | |||
<small>}</small> | |||
|<small>{</small><small> "started": "2025-07-08 07:39:24",</small> | |||
<small> "modified": "2025-07-08 07:39:26",</small> | |||
<small> "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf",</small> | |||
<small> "session": "548cd1ca-a24a-4a9a-ab4f-8363aa32c3c2",</small> | |||
<small> "channel": "default",</small> | |||
<small> "connector": "web",</small> | |||
<small> "unknown": false,</small> | |||
<small> "current": {</small> | |||
<small> "id": null,</small> | |||
<small> "qas": "",</small> | |||
<small> "category": null,</small> | |||
<small> "entry": [],</small> | |||
<small> "nearest": null,</small> | |||
<small> "missingRunData": [],</small> | |||
<small> "waitingRunData": null,</small> | |||
<small> "answered": false,</small> | |||
<small> "lastreply": "Здравствуйте! Как я могу вам помочь сегодня?"</small> | |||
<small> },</small> | |||
<small> "models": [</small> | |||
<small> "smc:Рыжик",</small> | |||
<small> "see:Серверы",</small> | |||
<small> "see:fio"</small> | |||
<small> ],</small> | |||
<small> "scripts": [],</small> | |||
<small> "data": [</small> | |||
<small> {</small> | |||
<small> "request": {</small> | |||
<small> "datetime": "2025-07-08T07:39:24.706771",</small> | |||
<small> "message": "привет",</small> | |||
<small> "data": []</small> | |||
<small> },</small> | |||
<small> "reply": {</small> | |||
<small> "answers": [</small> | |||
<small> {</small> | |||
<small> "messages": [</small> | |||
<small> "Здравствуйте! Как я могу вам помочь сегодня?"</small> | |||
<small> ],</small> | |||
<small> "voice": "Валера",</small> | |||
<small> "interruptible": false,</small> | |||
<small> "file": null</small> | |||
<small> }</small> | |||
<small> ],</small> | |||
<small> "datetime": "2025-07-08T07:39:26.269201",</small> | |||
<small> "answered": false</small> | |||
<small> }</small> | |||
<small> }</small> | |||
<small> ],</small> | |||
<small> "timers": [],</small> | |||
<small> "variables": {},</small> | |||
<small> "error": "",</small> | |||
<small> "events": {</small> | |||
<small> "not found": {</small> | |||
<small> "counter": 1</small> | |||
<small> },</small> | |||
<small> "no data": {</small> | |||
<small> "id": null,</small> | |||
<small> "counter": 0</small> | |||
<small> },</small> | |||
<small> "silence": {</small> | |||
<small> "id": null,</small> | |||
<small> "counter": 0</small> | |||
<small> }</small> | |||
<small> },</small> | |||
<small> "path": "session"</small> | |||
<small>}</small> | |||
|- | |||
!'''path:status''' | |||
! colspan="2" |Установка статуса клиентской части. <small>Используется в голосовом канале, для установки текущего статуса клиентской части. В случае использования режима активного слушания в момент речи робота, необходимо выставлять на клиентской части статус asking.</small> | |||
|- | |||
| colspan="2" |<small>{</small> | |||
<small> "path": "status",</small> | |||
<small> "value": "listening | asking",</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5"</small> | |||
<small>}</small> | |||
|<small><nowiki>{ "error": 0, "message": "success", "value": "listening | asking", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" }</nowiki></small> | |||
|- | |||
!'''path:interrupted''' | |||
! colspan="2" |Уведомление о прерывании текущего сообщения робота пользователем. | |||
|- | |||
| colspan="2" |<small>{</small> | |||
<small> "path": "interrupted",</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5"</small> | |||
<small>}</small> | |||
| | |||
|- | |||
!'''path:subscribe''' | |||
! colspan="2" |Подписка на сессию. | |||
|- | |||
| colspan="2" |<small>{</small> | |||
<small> "path": "subscribe",</small> | |||
<small> "token": "токен_авторизации_пользователя"</small> | |||
<small> "variable": "имя_переменной_по_которой_идет_поиск_сессий"</small> | |||
<small> "value": "значение_переменной_variable"</small> | |||
<small> "robot": "id_робота_который_подключается_к_сессиям"</small> | |||
<small>}</small> | |||
| | |||
|- | |||
!'''path:hangup''' | |||
! colspan="2" |Завершение сессии с роботом. | |||
|- | |||
| colspan="2" |<small>{</small> | |||
<small> "path": "hangup",</small> | |||
<small> "value": "user | robot",</small> | |||
<small> "session": "77f1af87-6da7-487b-96d2-4e2684704ad5"</small> | |||
<small>}</small> | |||
|<small><nowiki>{ "error": 0, "message": "success", "value": "user | robot", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" }</nowiki></small> | |||
|} | |} | ||
Со стороны сервера возможны самостоятельные сообщения типов ask и hangup в формате, аналогичном приведенному в таблице выше. | |||
Работа с сервером возможна с поточной передачей аудио в сторону сервера. В данном режиме ответы от сервера будут со ссылками на аудио, которое должно быть воспроизведено на стороне клиента (см. таблицу выше). Формат принимаемого потока аудио: pcm, 8кГц, 16 бит, размер куска аудио - 20 мс. | |||
Аудио отправляется бинарным сообщением по ссылке ws://адрес/код сессии/chunk. | |||
Текущая версия от 10:54, 13 ноября 2025
Общее описание
Сервис предназначен для создания сценарных машин и обеспечения их работы.
Термины и определения
Script engine service (SES) - сервис обеспечения работы и создания сценарных машин. Swagger UI – интерактивная веб-консоль с кратким описанием методов API и возможностью выполнять запросы к сервису SES в реальном времени
Скрипты интеграции
Для взаимодействия со сторонними сервисами используются скрипты интеграции на языке python. Скрипт интеграции должен содержать функцию handler(data={}, session_id=None, channel='default').
Пример данных на входе можно посмотреть в методе ses GET/ses/session/{robot_id}/{session_id}
Функция должна исходя из полученных данных запросить ответ у стороннего сервиса. Запрос необходимо выполнить в блоке try/except. Скрипт не должен выдавать ошибку в основное приложение, все исключения должны быть обработаны внутри скрипта.
Функция apiRequest
Для отправки запроса рекомендуется использовать функцию apiRequest. Функция сделает все необходимые записи в лог интеграции. Пример:
from app.tools import apiRequest
status, reply = apiRequest(name="наименование скрипта",method='get',sessiondata=data,url=url,timeout=(1,10))
- status, reply - http код ответа (например 200) и ответ без изменений и сериализации.
- name = название вызываемого метода, для отчетности
- sessiondata - это data в handler, которая туда прилетает
- method - метод запроса-ответа
после этих параметров в функцию apiRequest отправить все нужные параметры, как при вызове requests, они будут переданы один к одному.
Из функции handler можно передать или изменить переменную (в рамках текущей сессии): data['variables']={'new_var': 'новое_значение'}
Функция handler должна возвращать ответ в виде return { "text": "Текст ответа.", 'answered': True}, {}
- text - текст ответа
- answered - получен ли ответ (True или False)
Если в скрипте интеграции не используются запросы к api стороннего сервиса через http, необходимо предусмотреть запись в лог (запись в лог встроена в функцию apiRequest и при ее использовании отдельно писать в лог не надо). Для этого необходимо импортировать библиотеку:
from app.tools import apiLog
Функция apiLog
Если в скрипте интеграции не используются запросы к api, по окончании работы функции handler вызвать функцию записи лога:
apiLog(data=data,name="",url="",request={},reply_code=200,reply=None,request_datetime=None,reply_datetime=None)
- data - тот же массив который был на входе
- name - наименование или короткое описание скрипта
- url - адрес запроса к стороннему сервису (если есть)
- request - текст запроса
- reply_code - код ответа (стандартный код http)
- reply - необработанный ответ стороннего сервиса
- request_datetime - время перед запросом, без учета таймзоны, получить лучше так request_datetime=datetime.now(timezone.utc)
- reply_datetime - время сразу по получению ответа, также без учета таймзоны.
Внимание - не используйте apiRequest или apiLog для данных содержащих пароли в открытом виде, чтобы они не попали в лог
Функция getData
Для упрощения поиска информации можно использовать функцию getData (from app.tools import getData), нужна для извлечения конкретных данных из сессии, можно отправить либо всю переменную сессии, либо 'data' из сессии. Пример поиска цифрового кода заявления, выявленного моделью see 'number', поиск только в последнем сообщении диалога:
for j in getData(data=data,filter={'type':'see','model':'number'},depth=1):
kod_zayavl=str(int(j['param']))
break
Параметры функции
- data - или 'data' из сессии или переменная сессии
- filter - словарь ключевых полей и их значений - поиск сработает если все данные совпадут
- depth - отвечает за глубину поиска в истории, по умолчанию 1, т.е. искать только в последнем сообщении. Возвращает список всех найденных данных, добавляя в каждый элемент depth, т.е. где именно он нашелся
Выполнение длительных процедур
Код, который будет выполняться дольше нескольких секунд лучше запускать отдельным потоком. В этом случает есть возможность сообщить результат в канал даже после завершения основного диалога. Пример ожидания и отправки файла после паузы:
from app.interactions import connectors
def do_sleep(params, session_id, channel):
time.sleep(params['sleep_time'])
message="выполнено"
connectors.sendMessage(channel=channel,session=session_id,answers=[{'messages':[message]}],files={'document':(filetame, open(file_path,'rb'))})
def handler(data={}, session_id=None, channel='default'):
params={} #чтото передадим в функцию
params['sleep_time']= 100
Thread(target=do_sleep,name='do_sleep'+str(uuid.uuid4()),args=(params, session_id, channel) ).start()
return { 'text': "запустил задание, ждем результат", 'answered': False }, {}
Отложенные задания
Для выполнения отложенных заданий необходимо
- получить ссылку на базу данных текущего робота
- в таблицу "crons" внести внести время и python код который должен выполниться в указанное время.
Пример отложенного сообщения в телеграм:
# Формируем задачу в крон
error, db = get_db(data['robot'])
if error:
return { 'text': 'А я тебе ошибку базы данных привез: '+str(db), 'answered': False }, {}
dt = int(datetime.strptime(date['date']+' '+date['time'],'%Y-%m-%d %H:%M').timestamp())
# А вот тут создадим код для выполнения задачи
url = f'https://api.telegram.org/bot{token}/sendMessage'
data = json.dumps({'chat_id': chat_id, 'text': message})
data = base64.b64encode(data.encode("utf-8")).decode("utf-8")
code = """
import requests, json, base64
try:
data=\"{1}\"
data=base64.b64decode(data.encode('utf-8')).decode('utf-8')
requests.post(\"{0}\", data=json.loads(data), timeout = (5, 10))
except Exception as error:
logging.error(traceback.format_exc())
""".format(url,data).replace(" ","")
error, result = db.create(table='crons',data={
'id': str(uuid.uuid4()),
'name':'Задача-напоминание для '+username,
'datetime': dt,
'code': code })
Пользовательские таблицы базы данных
В составе большинства продуктов используется служебная файловая база данных. В SES возможно использование служебной базы в скриптах интеграции. Для этого нужно:
Импортировать функцию получения объекта БД (from app.db import get_db)
Получить объект БД
error, db = get_db(data['robot'])
if error: return { 'text': 'ошибка базы данных: '+str(db), 'answered': False }, {}
Объявить структуру пользовательской таблицы, создав запись в таблице структур (если еще не объявляли)
search_data={
"id":"new_table_name"
}
try:
error, search_result = db.select('structures',data=search_data,sort=None,md5clean=True)
if not search_result:
struct_data = {
"id":"new_table_name",
"name": "new_table_name",
"fields": {
"string":"",
"integer":0,
"float":0.0,
"именованный массив":{},
"неименованный массив":[],
"bool":True
}
}
error, str_id = db.create(table='structures', data=struct_data)
Сделать запись в базе
new_data={
"string":"пример строки\n",
"integer":100500,
"float":20.0004,
"именованный массив":{'ключ1':'значение1'},
"неименованный массив":['запись1','запись2',],
"bool":True
}
error, id = db.create(table="new_table_name", data=new_data)
if error:
return { 'text': 'ошибка создания: '+str(db), 'answered': False }, {}
Если при создании структуры не указывать в структуре id то база сама создаст id, вернет его в ответ. В дальнейшем тогда имя новой таблицы будет в id и запись/поиск в базе только по нему. Пример поиска в 'structures' подходит для поиска в пользовательской таблице.
Создание, редактирование и просмотр пользовательской таблицы в базе возможно и с интерфейса UPS.
Подписка на сессию
Позволяет просмотреть в реальном времени ход любого диалога. Для подписки в виджете отладчика необходимо активировать соответствующую кнопку и настроить фильтр. Используется для отладки сессий. Если сессий удовлетворяющих фильтру не найдено, виджет отладчика работает в режиме ожидания.
Сессии ассистента можно просматривать не только через отладчик, но и через виджет ассистента. Виджет подключается к ассистенту, встраивается в веб‑страницу и использует параметры авторизованного пользователя для фильтрации сессий (номер телефона из настроек пользователя).
Робот - ассистент
Предназначен для сопровождения диалога с оператором без вмешательства в него. Возможен только для типа коннектора "freeswitch" (телефонный канал). Робот - ассистент (суфлер) классифицирует и обрабатывает запросы от абонента, но не передает ответ в канал, а оставляет в своей сессии. На эту сессию может "подписаться" оператор, и в виджете ассистента получать подсказки и информацию от робота.
Запуск ассистента
- Опция «Автостарт ассистента» включается в настройках коннектора робота, на который поступает звонок от абонента.
- При каждом звонке ассистент автоматически запускается и сопровождает новую сессию.
- Если вызов перенаправляется оператору, в параметр destination подставляется "номер для перевода звонка" (указан в настройках коннектора).
- Оператор с таким номером (настроенным в UPS) сможет просмотреть сессию в виджете ассистента.
Запуск через API
Используется метод:
GET /ses/assistant/{session_id}/{destination}
- После вызова метода значение переменной destination в сессии заменяется на переданное в запросе.
- Это значение должно соответствовать идентификатору или номеру оператора, настроенному в UPS.
- Оператор должен быть авторизован в UPS и обладать нужными правами доступа.
Возможные сценарии работы
- абонент -> робот -> оператор (после перевода на оператора) В этом случае основной робот принимает звонок, затем передаёт сессию ассистенту после перевода. В виджете отображаются обе части диалога — до и после трансфера.
- абонент -> оператор Здесь робот-ассистент сразу переводит звонок оператору (согласно настройкам коннектора FreeSWITCH) и не говорит ничего в канал.Если суфлирование не запущено, робот не обрабатывает аудио и не использует ресурсы.
Важные настройки
- В блоках «События» и «Исключения» следует отключить действие «Завершить диалог», чтобы ассистент не закрывал свою сессию преждевременно.
- Режим работы (робот или ассистент) и телефон оператора для ассистента задаются в настройках коннектора FreeSWITCH.
- Один и тот же робот может быть ассистентом для одного коннектора и основным — для другого.
Описание методов API
Запросы осуществляются по протоколу HTTP 1.1 на адрес сервера с доступным сервисом SES. По умолчанию используется порт 6189/tcp.
Авторизация запросов не требуется. HTTP-запросы должны содержать заголовок "accept: application/json"
Ответ сервиса представляет собой JSON или текстовый документ в кодировке UTF-8, или двоичный файл.
Содержимое документа зависит от результата выполнения запроса. При наличии ошибки в качестве ответа вернется переменная error=1 и описание в переменной message. Для удобства проверки методов по ссылке http://АДРЕС:6190 будет отображен интерфейс swagger со всеми методами с возможностью их проверки.
Методы API
| Группа методов ses | |||
|---|---|---|---|
| для некоторых путей, где используется {robot_id} - это обращение к версии черновика, чтобы обращаться r продовой версии - нужен постфикс "_prod", для бэкапа "_backup"
актуально для методов - получения данных робота GET/ses/robot/get/{id} - применение настроек робота GET/ses/robot/commit/{id} - экспорт робота GET/ses/robot/export/{id} - список скриптов GET/ses/robot/script/list/{robot} - получение скрипта GET/ses/robot/script/get/{robot}/{id} - список ЭД GET/ses/robot/data/list/{robot} - получение ЭД GET/ses/robot/data/get/{robot}/{id} - список КТ GET/ses/robot/endpoint/list/{robot} - получение КТ GET/ses/robot/endpoint/get/{robot}/{id} - метода ask (отладчика) POST/ses/ask/{robot_id} - данные сессии (отладчика) GET/ses/session/{robot_id}/{session_id} | |||
| POST/ses/ask/{robot_id} | Получение ответа на запрос пользователя. Метод для отладки робота | ||
|
{ "error": 0,
"question": "Вопрос", "answer": [ { "messages": [ "ответ" ], "voice": "", "interruptible": true/false, "file": "" } ], "session": "", "uuid": "" } | ||
| GET/ses/assistant/{session_id}/{destination} | Запуск робота - суфлера для выбранной сессии | ||
|
{ "error": 0, "message": "success"} | ||
| GET/ses/hostname | Получение имени хоста на котором запущен сервис | ||
| Входные параметры отсутствуют | { "error": 0,
"message": "success", "hostname": "kotobot-gpu-04"} | ||
| POST/ses/log | Получение лога всех сессий начиная с date. В логе error, message и массив сессий log (log содержит информацию о каждой сессии и запросы с ответами) | ||
|
{ "error": 0, "message": "success",
"log": [ {"id": ",.....", "session": "......", "robot": ".....", "channel": "......", "unknown": true/false, "closed": true/false, "endpoint": ".....", "answered": true/false, "models": [....], "variables": {}, "current": {.......}, "request": {.......}, "reply": { ..... }, "robot_id": "", "endpointName": "", "endpointType": "" }, ..... ] } | ||
| GET/ses/session/{robot_id}/{session_id} | Выдает параметры сессии. Для отображения на боковой панели тестирования в UPS. Основные блоки результата: | ||
|
{ "started": "", "modified": "",
"robot": "", "session": "", "channel": "", "connector": "", "unknown": true/false, "current": {"id": "", "qas": "", "answered": true/false, "category": "", "nearest": "", "entry": [.....], "missingRunData": [], "passedRunData": [.....], "waitingRunData": null, "border": int, "preborder": int, "lastreply": ""}, "models": [.....], "scripts": [.....], "data": [{"request": {.....}, "reply": {.....}}], "timers": [], "variables": {}, "error": "", "events": {.....}, "closed": "" } | ||
| GET/ses/widget/config | Отдает конфигурацию виджета скрипту виджета | ||
|
На выходе содержимое настроек web канала из конфигурационного файла | ||
| Группа методов ses/robot/ | |||
| POST/ses/robot/add | Создание нового робота. На выходе id созданного робота или сообщение об ошибке | ||
|
{ "error": 0,
"id": "2fd2f909-2069-4b20-a725-3a598c83f886"} | ||
| GET/ses/robot/apply/{id} | Применение робота. Переводит черновик робота в статус prod. Если до этого был prod вариант - становится backup. | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/cleardraft/{id} | Обнуление черновика рабочей версией робота | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/commit/{id} | Применение текущих изменений настроек робота. Применимо ко всем версиям (черновик, рабочая, резервная копия) | ||
|
{ "error": 0,
"message": "success"} | ||
| DELETE/ses/robot/delete/{id} | Удаление всех версий робота | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/export/{id} | Выгрузка робота в архив. | ||
|
zip файл с именем = идентификатор робота | ||
| GET/ses/robot/get/{id} | Выгрузка основных настроек робота | ||
|
{ "error": 0,
"data": { "id": ".....", "name": ".....","description": "", "voice": "", "session": { "lifetime": 600 }, "models": {},"servicedata": {},"exceptions": {},"actions": {}, "holidays": [], "timeintervals": { "name": {"weekdays": [ ..... ], "dates": [ ..... ], "months": [.....], "days": "all", "intervals": [ [ 0, 1440 ] ] }}}} | ||
| POST/ses/robot/import/{id} | Загрузка архива робота в черновик существующего робота | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/list | Получение списка роботов | ||
| Входные параметры отсутствуют | [ { "id": "9fd7f6f1-2cac-4f0f-a121-75c40f2b5e78",
"name": "test", "hasProd": true, "hasBackup": true } ] | ||
| POST/ses/robot/modify/{id} | Изменение основных настроек робота. Формат data как в ответе метода GET/ses/robot/get/{id} | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/restore/{id} | Откат рабочей версии из бэкапа. Резервная копия становится рабочей, и удаляется, а черновик остается без изменений | ||
|
{ "error": 0,
"message": "success"} | ||
| Группа методов ses/robot/data | |||
| POST/ses/robot/data/add/{robot} | Добавление элемента данных | ||
|
{ "error": 0,
"message": "success"} | ||
| DELETE/ses/robot/data/delete/{robot}/{id} | Удаление элемента данных | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/data/get/{robot}/{id} | Получение настроек элемента данных | ||
|
{ "error": 0, "data": {
"id": ".....", "name": ".....", "comment": "", "type": "smc", "rtype": "report", "model": ".....", "param": ".....", "script": "", "weight": int, "slaveData": [], "getOnlyAsNearest": true/false, "injectToMessage": true/false, "longWaiting": true/false, "dataWaiting": [], "actions": {}, "exceptions": {}}} | ||
| GET/ses/robot/data/list/{robot} | Получение списка элементов данных | ||
|
[ { "id": "3ebfe38b-95bf-4927-a662-17f6e5da22ea", "name": "pve", "type": "smc", "rtype": "report",
"weight": 3, "hasNearestAction": false } ] | ||
| POST/ses/robot/data/modify/{robot}/{id} | Изменение элемента данных. Формат data как на выходе метода GET/ses/robot/data/get/{robot}/{id} | ||
|
{ "error": 0,
"message": "success"} | ||
| Группа методов ses/robot/endpoint | |||
| POST/ses/robot/endpoint/add/{robot} | Создание конечной точки. Формат data как на выходе метода GET/ses/robot/endpoint/get/{robot}/{id} | ||
|
{ "error": 0,
"id": "8576593b-b0d8-4b03-a623-74f3132356ea"} | ||
| DELETE/ses/robot/endpoint/delete/{robot}/{id} | Удаление конечной точки. | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/endpoint/get/{robot}/{id} | Получение настроек конечной точки | ||
|
{ "error": 0, "data": {
"id": "...", "name": "...", "comment": "", "entryType": "conditions", "entry": [{ "conditions": [{ "type": "...", "depth": 5, "id": "...", "operation": "...", "value": ""}], "run": []}], "run": [], "actions": { "default": [{ "action": "...", "voice": "", "type": "...", "interruptible": true/false}]}, "type": "report"}} | ||
| GET/ses/robot/endpoint/list/{robot} | Получение списка конечных точек робота | ||
|
[{ "error": 0, "data": {
"id": "...", "name": "...", "comment": "", "entryType": "conditions", "entry": [{ "conditions": [{ "type": "...", "depth": 5, "id": "...", "operation": "...", "value": ""}], "run": []}], "run": [], "actions": { "default": [{ "action": "...", "voice": "", "type": "...", "interruptible": true/false}]}, "type": "report"}}] | ||
| POST/ses/robot/endpoint/modify/{robot}/{id} | Изменение конечной точки. Формат data как на выходе метода GET/ses/robot/endpoint/get/{robot}/{id} | ||
|
{ "error": 0,
"message": "success"} | ||
| Группа методов ses/archive | |||
| GET/ses/archive/audio/{uuid} | Получение аудио-файла из архива диалогов | ||
|
аудио-файл с расширением opus | ||
| GET/ses/archive/dialog/{uuid} | Получение диалога из архива | ||
|
{ "error": 0, "message": "success",
"dialog": [{"id": "...", "robot": "...", "channel": "...", "unknown": true/false, "closed": true/false, "endpoint": "...", "answered": true/false, "models": [...], "variables": {}, "current": { "id": "...", "qas": "", "category": "...", "entry": [...], "nearest": "...", "missingRunData": [...], "waitingRunData": "...", "answered": true/false, "lastreply": "..."}, "request": {"datetime": "...", "message": "", "data": [...]}, "reply": {"answers": [{"messages": [...], "voice": "...", "interruptible": true/false, "file": null}], "datetime": "...", "answered": true/false}}]} | ||
| GET/ses/archive/list | Получение списка диалогов из архива | ||
|
[{"uuid": "...", "datetime": "...","phone": "", "channel": [...], "robot": ["..."]}] | ||
| GET/ses/archive/waveform/{uuid} | Служебный метод для визуализации полученного из архива диалогов аудио-файла, содержит пики сигнала. | ||
|
[0.016,
0.015, 0.01] | ||
| Группа методов ses/robot/script | |||
| POST/ses/robot/script/add/{robot} | Добавление нового скрипта. Формат data как в ответе метода GET/ses/robot/script/get/{robot}/{id} | ||
|
{ "error": 0,
"message": "success"} | ||
| DELETE/ses/robot/script/delete/{robot}/{id} | Удаление скрипта | ||
|
{ "error": 0,
"message": "success"} | ||
| GET/ses/robot/script/get/{robot}/{id} | Получение текста скрипта | ||
|
{ "error": 0, "data": { "id": "6a9f91b6-9634-4079-ac2b-60a944922c61", "type": "Тип скрипта", "name": "Наименование скрипта", "code": "Текст скрипта" } } | ||
| GET/ses/robot/script/list/{robot} | Получение списка скриптов | ||
|
[ { "id": "9b9d83b7-d5c3-49e6-9bd4-a123a9047939",
"name": "наименование1", "type": "Тип скрипта"}, { "id": "48b508ba-a32b-4ada-bcc3-66ce26d81c6a", "name": "наименование2", "type": "Тип скрипта"}] | ||
| POST/ses/robot/script/modify/{robot}/{id} | Изменение скрипта.Формат data как в ответе метода GET/ses/robot/script/get/{robot}/{id} | ||
|
{ "error": 0,
"message": "success"} | ||
| POST/ses/robot/script/test/{robot}/{id} | Тестирование скрипта. Формат data как в ответе метода GET/ses/session/{robot_id}/{session_id} | ||
|
{"error": 0, "message": "success", "result": {.....}, "variables": {}} | ||
| Группа методов ses/robot/files | |||
| GET/ses/robot/files/download/{robot}/{id} | Получение файла. | ||
|
файл | ||
| POST/ses/robot/files/upload/{robot} | Отправка файла. | ||
|
{"error": 0, "message": "success", "id": "Id файла"} | ||
| Группа методов ses/testapi для отладки скриптов интеграции | |||
| GET/ses/testapi/list | Получение списка эмуляторов сервисов интеграции | ||
| Входные параметры отсутствуют | [ "service1",
"service2", "serviceN"] | ||
| POST/ses/testapi/{request} | Получение ответа эмулятора сервиса интеграции | ||
|
"ответ эмулятора" | ||
| GET/ses/testapi/{request} | Получение ответа эмулятора сервиса интеграции | ||
|
"ответ эмулятора" | ||
| Группа методов ses/robot/userdata | |||
| POST/ses/robot/userdata/data/add/{robot}/{structure} | Добавление записи в пользовательский справочник. | ||
|
{"error": 0, "id": "id записи"} | ||
| DELETE/ses/robot/userdata/data/delete/{robot}/{structure}/{id} | Удаление записи из пользовательского справочника. | ||
|
{"error": 0, "message": "success"} | ||
| GET/ses/robot/userdata/data/list/{robot}/{structure} | Получение данных из пользовательского справочника. | ||
|
[{ "колонка 1": "значение 1", "колонка n": "значение n", "id": "id записи"}] | ||
| POST/ses/robot/userdata/data/modify/{robot}/{structure} | Массовое изменение данных в пользовательском справочнике. | ||
|
{"error": 0, "message": "success"} | ||
| POST/ses/robot/userdata/data/modify/{robot}/{structure}/{id} | Изменение одной записи пользовательского справочника. | ||
|
{"error": 0, "message": "success"} | ||
| POST/ses/robot/userdata/data/put/{robot}/{structure} | Добавление данных с заменой в пользовательском справочнике. | ||
|
{"error": 0, "message": "success"} | ||
| POST/ses/robot/userdata/structure/add/{robot} | Добавление пользовательского справочника. | ||
|
{"error": 0, "id": "id справочника"} | ||
| DELETE/ses/robot/userdata/structure/delete/{robot}/{id} | Удаление пользовательского справочника. | ||
|
{"error": 0, "message": "success"} | ||
| GET/ses/robot/userdata/structure/list/{robot} | Получение списка пользовательских справочников. | ||
|
[{"id": "id справочника", "name": "справочник", "fields": {"колонка1": "значение по умолчанию"}}] | ||
| POST/ses/robot/userdata/structure/modify/{robot}/{id} | Модификация структуры пользовательского справочника. | ||
|
{"error": 0, "message": "success"} | ||
Постобработка методов api
Для метода POST/ses/ask/{robot_id} можно изменить формат данных ответа.
Для этого необходимо подготовить скрипт на python в папке /opt/ses/handlers/api/ask/ . Скрипт должен содержать функцию handler(reply={}), Функция должна вернуть переформатированный ответ. Чтобы воспользоваться скриптом необходимо его имя без разрешения указать в поле "handler" при запросе метода.
Аналогично и для метода ask websocket протокола - файл положить в /opt/ses/handlers/websockets/ask/ . Далее в любом запросе указать обработчик {тут всё, что ты и так отправляешь, 'handlers': { 'ask': '__telegram' }} } . начиная с этого запроса обработчик будет действовать в течение сессии пока не отправишь 'handlers': {} . Для других полей запросов в канале websocket аналогично.
В составе поставки ses есть файл примера __telegram.py (префикс 2 подчеркивания - такой файл будет переписан при обновлении, любой другой, останется после обновления)
Websockets сервер
Работа с программным продуктом возможна с использованием встроенного websockets сервера. Подключение производится по порту 6191, без SSL. При необходимости работать по SSL перед SES ставится nginx в режиме прокси, и SSL поднимается на nginx. Подробнее см. документацию по nginx.
В таблице ниже приведены форматы сообщений для работы с сервером. В каждом сообщении (за исключением бинарных), присутствует переменная path (формат сообщений - JSON), которая определяет алгоритм обработки сообщения. Подключение к серверу возможно в следующих вариантах:
- ws://адрес:6191
- ws://адрес:6191/session[/chunk]
Первый вариант подходит только для текстовых сообщений, в данном случае передача переменной session (uuid текущей сессии) должна производиться в теле сообщения.
Второй вариант подходит и для текстового и для голосового общения с роботом. В данном случае session передается в пути подключения к websockets-серверу. Для каждой новой сессии нужно открывать новое соединение, chunk в пути подключения нужен в том случае, если передаются не готовые части аудио, предварительно сформированные, а сплошной поток аудио, кусками по 20 мс.
| Входящие сообщения | ||
|---|---|---|
| path:ask | Вопрос роботу | |
| {
"path": "ask", "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5", # Необязательный параметр, если не будет отправлен, будет создана новая сессия и в ответе придет сгенерированный session "channel": "default", "link": 1, # Необязательный параметр, отдает ссылки на аудио, если 1. "format": "wav", # Необязательный параметр, формат возвращаемого аудио, если channel=voice "document": {"name":"название","base64":"тело документа в base64"}, # необязательный параметр
или "audio": "base64 строка", } |
Для текстовых ответов (канал не voice)
{ "error": 0, "question": "привет", "answer": [ { "messages": [ "Здравствуйте! Как я могу вам помочь сегодня?" ], "voice": "Валера", "interruptible": false, "file": null } ], "session": "77f1af87-6da7-487b-96d2-4e2684704ad5", "uuid": "83722305-645d-4674-8c5d-952e02f595f9", "path": "ask" }
{ "audio": "ссылка или base64 закодированное аудио", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5", "uuid": "83722305-645d-4674-8c5d-952e02f595f9", "status": "listening | asking" # Требование к клиенту выставить статус. } | |
| path:session | Статус сессии | |
| {
"path": "session", "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf", "session": "548cd1ca-a24a-4a9a-ab4f-8363aa32c3c2" } |
{ "started": "2025-07-08 07:39:24",
"modified": "2025-07-08 07:39:26", "robot": "f296a3a9-593c-4ed5-a1d3-5d4d46d331bf", "session": "548cd1ca-a24a-4a9a-ab4f-8363aa32c3c2", "channel": "default", "connector": "web", "unknown": false, "current": { "id": null, "qas": "", "category": null, "entry": [], "nearest": null, "missingRunData": [], "waitingRunData": null, "answered": false, "lastreply": "Здравствуйте! Как я могу вам помочь сегодня?" }, "models": [ "smc:Рыжик", "see:Серверы", "see:fio" ], "scripts": [], "data": [ { "request": { "datetime": "2025-07-08T07:39:24.706771", "message": "привет", "data": [] }, "reply": { "answers": [ { "messages": [ "Здравствуйте! Как я могу вам помочь сегодня?" ], "voice": "Валера", "interruptible": false, "file": null } ], "datetime": "2025-07-08T07:39:26.269201", "answered": false } } ], "timers": [], "variables": {}, "error": "", "events": { "not found": { "counter": 1 }, "no data": { "id": null, "counter": 0 }, "silence": { "id": null, "counter": 0 } }, "path": "session" } | |
| path:status | Установка статуса клиентской части. Используется в голосовом канале, для установки текущего статуса клиентской части. В случае использования режима активного слушания в момент речи робота, необходимо выставлять на клиентской части статус asking. | |
| {
"path": "status", "value": "listening | asking", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" } |
{ "error": 0, "message": "success", "value": "listening | asking", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" } | |
| path:interrupted | Уведомление о прерывании текущего сообщения робота пользователем. | |
| {
"path": "interrupted", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" } |
||
| path:subscribe | Подписка на сессию. | |
| {
"path": "subscribe", "token": "токен_авторизации_пользователя" "variable": "имя_переменной_по_которой_идет_поиск_сессий" "value": "значение_переменной_variable" "robot": "id_робота_который_подключается_к_сессиям" } |
||
| path:hangup | Завершение сессии с роботом. | |
| {
"path": "hangup", "value": "user | robot", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" } |
{ "error": 0, "message": "success", "value": "user | robot", "session": "77f1af87-6da7-487b-96d2-4e2684704ad5" } | |
Со стороны сервера возможны самостоятельные сообщения типов ask и hangup в формате, аналогичном приведенному в таблице выше.
Работа с сервером возможна с поточной передачей аудио в сторону сервера. В данном режиме ответы от сервера будут со ссылками на аудио, которое должно быть воспроизведено на стороне клиента (см. таблицу выше). Формат принимаемого потока аудио: pcm, 8кГц, 16 бит, размер куска аудио - 20 мс.
Аудио отправляется бинарным сообщением по ссылке ws://адрес/код сессии/chunk.