- PVSM.RU - https://www.pvsm.ru -
Alice-ktx [1]- это библиотека на Kotlin [2], упрощающая разработку навыков Алисы [3] из Яндекс.Диалогов [4]. В этой статье мы рассмотрим основные возможности библиотеки.
Для начала, добавьте библиотеку в зависимости вашего проекта
dependencies {
implementation("io.github.danbeldev:alice-ktx:0.0.3")
}
fun main() {
skill {
id = "..."
webServer = ktorWebServer {
port = 8080
path = "/alice"
}
dispatch {
message({ message.session.new }) {
response {
text = "Привет!"
}
}
message {
response {
text = message.request.command.toString()
}
}
}
}.run()
}
id
- Уникальный идентификатор скилла, читайте здесь [5].
webServer
- Конфигурация приложение с использованием Ktor.
port
- Порт, на котором будет запущено приложение. В данном случае используется порт 8080.
path
- Путь, по которому приложение будет доступен. В данном случае это /alice.
message({ message.session.new }) {
response {
text = "Привет!"
}
}
Этот блок кода обрабатывает новые сессии. Если сессия новая message.session.new
, то в ответ отправляется текст "Привет!".
message {
response {
text = message.request.command.toString()
}
}
Этот блок кода обрабатывает все остальные сообщения. В ответ отправляется текст запроса пользователя.
Мидлварь - это код, который активируется при каждом событии, полученном от API Алисы.
Внешняя (outer) область - вызывается перед обработкой фильтров (innerMiddleware
).
Внутренняя (inner) область - вызывается после обработки фильтров, но перед обработчиком (outerMiddleware
).
Мидлварь должен всегда возвращать null чтобы передать событие следующему мидлварю/хэндлеру. Если вы хотите завершить обработку события, вы должны вернуть
Response
.
dispatch {
// ...
outerMiddleware {
if(message.session.user?.userId == null)
response { text = "У вас нет аккаунта в Яндексе." }
else
null
}
// ...
}
responseFailure — это расширение для Dispatcher, которое позволяет обрабатывать ошибки, возникающие при выполнении запросов. Оно предоставляет возможность задать обработчики ошибок для различных типов исключений и условий.
responseFailure
должен всегда возвращать null чтобы передать событие следующему хэндлеру. Если вы хотите завершить обработку события, вы должны вернутьResponse
.
Обработка конкретного исключения.
responseFailure(ArithmeticException::class) {
response {
text = "Произошла арифметическая ошибка"
}
}
Общий обработчик исключений.
responseFailure {
response {
text = "Произошла ошибка"
}
}
Обработка ошибок по условию.
responseFailure({ message.session.new }) {
response {
text = "В начале сессии произошла ошибка"
}
}
Чтобы получить, загрузить и удалить загруженные изображения и звуки, надо передать OAuth Token [6] при создании DialogApi
.
skill {
// ...
dialogApi = ktorYandexDialogApi {
oauthToken = "..."
}
// ...
}.run()
Для каждого аккаунта Яндекса на Диалоги можно загрузить не больше 100 МБ
картинок и 1 ГБ
аудио. Чтобы узнать, сколько места уже занято, используйте этот метод.
dialogApi.getStatus()
Все доступные методы API.
interface DialogApi {
suspend fun getStatus(): Response<Status>
suspend fun uploadImage(url: String): Response<ImageUpload>
suspend fun uploadImage(file: File): Response<ImageUpload>
suspend fun getAllImages(): Response<Images>
suspend fun deleteImage(id: String): Response<Unit>
suspend fun uploadSound(file: File): Response<SoundUpload>
suspend fun getAllSounds(): Response<Sounds>
suspend fun deleteSound(id: String): Response<Unit>
}
Все методы API возвращают обёртку Response<>
.
sealed interface Response<T> {
data class Failed<T>(val message: String): Response<T>
data class Success<T>(val data: T): Response<T>
}
Не вся функциональность навыка может быть реализована в одном хэндлере. Если вам нужно получить некоторую информацию от пользователя в несколько шагов или нужно направить его в зависимости от ответа, то вам надо использовать FSM.
Для начала определите возможные состояния в вашем навыке
enum class InfoState {
SET_NAME,
SET_AGE,
SET_INFO
}
Начальное Состояние, когда начинается новая сессия, установите начальное состояние
message({ message.session.new }) {
state.setState(InfoState.SET_NAME.name)
response {
text = "Добро пожаловать в навык, как вас зовут?"
}
}
Условие
: Обрабатывается при начале новой сессии.
Действие
: Устанавливает состояние в SET_NAME
и запрашивает у пользователя имя.
После получения имени от пользователя, сохраняем его и переходим к следующему состоянию.
message({ state == InfoState.SET_NAME.name }) {
val username = message.request.originalUtterance.toString()
state.updateData("name" to username)
state.setState(InfoState.SET_AGE.name)
response {
text = "Рад познакомиться $username, сколько вам лет?"
}
}
Условие
: Обрабатывается, если текущее состояние SET_NAME
.
Действие
: Сохраняет имя в состоянии, устанавливает следующее состояние SET_AGE
, и запрашивает возраст.
После получения возраста от пользователя, сохраняем его и переходим к последнему состоянию.
message({ state == InfoState.SET_AGE.name }) {
val age = message.request.originalUtterance.toString()
state.updateData("age" to age)
state.setState(InfoState.SET_INFO.name)
response {
text = "Супер, расскажите о себе"
}
}
Условие
: Обрабатывается, если текущее состояние SET_AGE
.
Действие
: Сохраняет возраст в состоянии, устанавливает следующее состояние SET_INFO
, и запрашивает дополнительную информацию.
На заключительном этапе, после получения дополнительной информации, формируем окончательный ответ и завершаем сессию.
message({state == InfoState.SET_INFO.name}) {
val info = message.request.originalUtterance.toString()
val data = state.getData()
state.clear()
response {
text = "Вот что мне удалось узнатьnnИмя-${data["name"]}nВозраст-${data["age"]}nИнформация-$info"
endSession = true
}
}
Условие
: Обрабатывается, если текущее состояние SET_INFO
.
Действие
: Формирует текст ответа на основе собранной информации, очищает состояние и завершает сессию.
Использование машины состояний позволяет структурировать взаимодействие с пользователем и управлять процессом сбора информации через последовательные шаги. Это особенно полезно для сложных сценариев, требующих многократного взаимодействия и сохранения состояния между шагами.
Для того чтобы добавить кнопку используйте метод button
.
response {
text = "Выберите тип"
SchedulesType.entries.forEach {
button {
text = it.name
payload = mapOf("schedule_type" to it.name)
}
}
}
Существует три типа альбомов
Card Items List [7].
response {
text = "CARD ITEMS LIST"
cardItemsList {
header = "HEADER"
repeat(10) { index ->
item {
imageId = IMAGE_ID
title = "#${index + 1}"
}
}
footer {
text = "Footer text"
mediaButton {
text = "Click"
}
}
}
}
Card Big Image [8].
response {
cardBigImage {
imageId = IMAGE_ID
title = "CARD BIG IMAGE"
mediaButton {
text = "Open url"
url = "https://ya.ru"
}
}
}
Card Image Gallery [9].
response {
cardImageGallery {
repeat(10) { index ->
item {
imageId = IMAGE_ID
title = "#${index + 1}"
}
}
}
}
Alice-ktx [1]
Документация [10]
Примеры [11]
Автор: danbel
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/yandeks/393257
Ссылки в тексте:
[1] Alice-ktx : https://github.com/danbeldev/alice-ktx
[2] Kotlin: https://kotlinlang.org
[3] навыков Алисы: https://dialogs.yandex.ru/store
[4] Яндекс.Диалогов: https://dialogs.yandex.ru/development
[5] здесь: https://github.com/danbeldev/alice-ktx/blob/master/documentation/%D0%9D%D0%B0%D1%87%D0%B0%D0%BB%D0%BE.md
[6] OAuth Token: https://yandex.ru/dev/direct/doc/start/token.html
[7] Items List: https://yandex.ru/dev/dialogs/alice/doc/ru/response-card-itemslist
[8] Big Image: https://yandex.ru/dev/dialogs/alice/doc/ru/response-card-bigimage
[9] Image Gallery: https://yandex.ru/dev/dialogs/alice/doc/ru/response-card-imagegallery
[10] Документация: https://github.com/danbeldev/alice-ktx/tree/master/documentation
[11] Примеры: https://github.com/danbeldev/alice-ktx/tree/master/examples/src/main/kotlin/com/github/examples
[12] Источник: https://habr.com/ru/articles/834264/?utm_source=habrahabr&utm_medium=rss&utm_campaign=834264
Нажмите здесь для печати.