Всем привет ???? . Зовут меня Илюша Кр, и сегодня я вам расскажу, как же все-таки попросить ассистента принести чипсов сделать поисковый запрос внутри вашего приложения.
Для начала скажу пару слов о себе: я такой же обычный парень, как и вы, работаю разработчиком под Android в онлайн-кинотеатре PREMIER. Но, когда я взял задачу по внедрению голосового помощника Сбера в приложение, моя жизнь разделилась на «до» и «после». Заинтриговал? Тогда читай дальше!
В этой статье вы узнаете:
Как интегрировать ваше приложение с приставками Сбера и телевизорами;
Как обработать запрос пользователя и взять только нужную информацию;
ответ на загадку Жака ФрескоКак обрабатывать данные от ассистента непосредственно в самом приложении.
Ачо, а всмысле?
Так, давайте определимся с задачей: у Сбер-девайсов на пульте четыре кнопки и они вам не нужны, поскольку есть ГОЛОСОВОЙ ПОМОЩНИК. А это значит, что поиск контента нужно сделать посредством голосового ввода. Если же мы находимся не на экране поиска, откроем этот экран и введем запрос пользователя. Этим мы и займемся!
Подготовка
Начнем с того, что нам необходимо зарегистрировать наше приложение в SberMarket Studio. В личном пространстве нажмите «Создать проект» и выберите пункт SmartApp. В качестве типа смартапа выбираем NativeApp. В настройках проекта добавьте apk-файл. Et voilà, теперь ваше приложение является нэйтив апп и в него можно встроить сберовские примочки.
Само собой все это в доках Сбера есть, но смотреть туда неинтересно. Ведь поэтому вы здесь? Ну что, продолжим!
Для голосового помощника понадобится добавить:
Sdk и логику в приложение;
Скрипт бэкенда, который будет обрабатывать запросы.
Настройка приложения
Начнем, пожалуй, с нашего приложения.
Для начала необходимо добавить sdk (спойлер: на момент написания статьи в доках указана версия 1.0, но найти ее не получится, поскольку не релизнута. А сегодня в завтрашний день не все могут смотреть… Ну вы поняли). А вообще вот вроде ссылки на актуальные версии.
У себя в проекте я не использовал «жирный сдк» из-за ненадобности всех фич (только messaging и appstate).
dependencies {
...
implementation "ru.sberdevices.smartapp.sdk:appstate:1.0-alpha-2"
implementation "ru.sberdevices.smartapp.sdk:messaging:1.0-alpha-2"
}
Создадим инстансы для стейта приложения и обмена сообщениями:
data class SberAppState(
@SerializedName("isOnScreen")
val isOnScreen: Boolean
) : Serializable
data class SberMessage(
@SerializedName("type")@SerializedName("message")
val message: String,
@SerializedName("type")
val type: String
) : Serializable
Данные мы будет передавать обычным Json-объектом.
SberAppState представляет из себя класс всего с одним полем — isOnScreen. Данный параметр определяет, в каком стейте находится наше приложение(либо непосредственно на экране поиска, либо где-то еще).
SberMessage состоит из двух полей: type и message. Параметр type нужен для определения, в каком стейте сейчас находится приложение, а message — запрос пользователя в виде строки.
Ну что, посмотрим на код:
const val LOCAL_SEARCH_TYPE = "LOCAL_SEARCH" // Приложение на экране поиска
const val GLOBAL_SEARCH_TYPE = "GLOBAL_SEARCH" // Приложение НЕ на экране поиска
val listener = object : Messaging.Listener {
override fun onMessage(messageId: MessageId, payload: Payload) {
val sberMessage = Gson().fromJson(
payload.data,
SberMessage::class.java
)
if (sberMessage.type == LOCAL_SEARCH_TYPE) {
// подставим во фрагменте запрос sberMessage.message
}
if (sberMessage.type == GLOBAL_SEARCH) {
// переадресовывем пользователя на экран поиска
}
}
override fun onError(messageId: MessageId, throwable: Throwable) {
// Пришла ошибка: ~~будем плакать~~ обработаем ее
}
}
fun updateAppState(isOnSearchScreen: Boolean) {
appStateHolder.setState(Gson().toJson(SberAppState(isOnSearchScreen)))
}
В функции onMessage обработаем сообщение от ассистента, функция updateAppState в моменты перехода на экран поиска приложение обновляет стейт isOnSearchScreen = true и при уходе - isOnSearchScreen = false соответственно.
Это основная механика обработки запросов в приложении.
Настройка бекенда (написание скрипта)
Взаимодействие пользователя и нашего native app происходит через настроенный нами бэкенд, в котором и закладываем логику обработки фраз пользователя.
В СберМаркет Студио в пространстве приложения на выбор можно создать проект Graph либо Code.
Для данной задачи я выбрал тип Code.
Code — это среда разработки смартаппов на языках JavaScript и SmartApp DSL
Рассмотрим проект. Его структура выглядит следующим образом:
-
src
utils.js
test
caila_import.json
chatbot.yaml
Мы рассмотрим подробно файлы main.sc и utils.js (про остальные можно почитать в доке).
function reply(body, response) {
var replyData = {
type: "raw",
body: body
};
response.replies = response.replies || [];
response.replies.push(replyData);
}
function handleRequest(usersRequest, isOnSearchScreen, response) {
var appType = null
if (isOnSearchScreen) {
appType = 'LOCAL_SEARCH'
} else {
appType = 'GLOBAL_SEARCH'
}
var body = {
items: [
{
command: {
type: 'smart_app_data',
smart_app_data: {
type: appType,
message: usersRequest,
},
},
},
],
};
reply(body, response);
}
Функция reply просто отправляет сообщение в наш native app с данными body.
Функция handleRequest получает на вход три параметра:
usersRequest — то, что мы передадим в поле message;
isOnSearchScreen — параметр, необходимый для разделения логики обработки сообщения в приложении (LOCAL_SEARCH — мы на экране поиска, GLOBAL_SEARCH — мы НЕ на экране поиска);
response — параметр, через который мы отправляем сообщение в native app.
theme: /
state: runApp
q!: $regex</start>
script:
$response.replies = $response.replies || [];
$response.replies.push({
type: 'raw',
body: {
items: [
{
command: {
type: "smart_app_data",
smart_app_data: {
type: "app_action",
message: "запустиприложение"
},
},
auto_listening: true
},
],
},
});
state: UsersSearchRequest
intent!: /UsersRequest
script:
$session.request = $parseTree.text
script: handleRequest($session.request, $jsapi.context().request.rawRequest.payload.meta.current_app.state.isOnScreen, $response)
Need to understand if this state is needed
# Если мы не распознали запрос:
state: Fallback
event!: noMatch
a: Упс, что то пошло не так :(
Данный файл выступает навигационным — каждый стейт отвечает за свое действие:
state runApp — обрабатывает команды открытия и загрузки приложения на устройство;
state UsersSearchRequest — стейт, в который попадает каждый запрос (кроме запуска приложения);
state Fallback — для необработанных запросов(которых не должно быть).
Стейт UsersSearchRequest использует в качестве точки входа интент, для которого тренировочная фраза — регулярное выражение: «+» (любое количество символов не меньше одного). При попадании в этот стейт мы должны отправить в приложение данные с помощью функции handleRequest (в секции скрипта мы просто сохраняем в переменную regexp<.+>».
Тестирование и отладка сценария
Для того, чтобы произвести рефактор сценария, необходимо быть участником пространства, в котором находится приложение.
Для отладки и тестирования сценария необходимо авторизоваться на Сбер-девайсе пользователем, добавленным в пространство тестируемого приложения.
А как быть, если пространство уже есть, а вас там нет? Все просто: просим уважаемого человека с доступом добавить вас на проект. Для этого, находясь в нужном пространстве, нажимаем на красивую иконку шестеренки в правом верхнем углу, далее вкладка «Команда». На этом экране вы можете добавить нового участника, поменять роли у текущих и, само собой, удалить тех, кто сомневается в вашем идеальном коде.
Заключение
Вот и подошло к концу наше увлекательное путешествие по интеграции помощника. Надеюсь, данная статья будет полезна тем, кто только решил завезти похожий функционал и не знает, с чего начать. Также могу дать совет: при создании Code- и Graph-проектов есть возможность выбрать предустановленный темплейт, попробуйте поковыряться в них — там есть полезный код.
На этом я с вами прощаюсь. Жду ваших вопросов и комментов. Живите долго и процветайте.
Комментарии (2)
Chelidonium
22.11.2022 21:22из сбера в такое шоу, посмотрят и будут приходить с бумажными сберкнижками только
Moskus
А что случилось с @dioman648и @arkofom которые тоже писали про Премьер в блоге Газпром-Медиа (в том же стиле с "мемасиками"), которых тоже пригласил @UmaTech Сколько вас там вообще?