
Содержание статьи
автор Рафаэль Фиол
И зачем тебе такое делать

Существует два способа реализовать свои навыки для Alexa.
Первый является самым распространенным и рекомендованным Amazon. Используйте AWS Lambda, компьютерную службу без сервера. Нет статей и учебных пособий по теме. Это не один из них.
Второй способ встречается гораздо реже. Это размещение конечной точки с помощью веб-службы HTTPS, которую вы управляете. Несколько сложнее найти хорошие примеры такого подхода. В этой статье мы попытаемся сделать именно это и использовать Spring Boot как основу для реализации.

Но прежде чем прыгнуть в какдавайте поговорим о почему:
- Почему бы вам не использовать AWS Lambda?
- Почему игнорировать рекомендацию Amazon?
Эти вопросы важны. Вы найдете множество замечательных примеров и документации по созданию навыков с помощью Lambda, и не так много для альтернативы. Также важно, если вы соглашаетесь, что я делаю, что мир будет без серверов. Это замечательная статья по этой теме Джеймса Бесвика. Переход по маршруту HTTPS приведет вас в одиночку, но иногда это нормально.
Вот несколько причин, почему вы можете захотеть или потребовать пойти по этому одинокому пути.
- Вы можете написать свои веб-сервисы Alexa с помощью любого языка программирования.
- Если вы уже развернули существующие сервисы RESTful, и вы хотите использовать эту инфраструктуру/инвестиции.
- Если ваш CISO не позволяет использовать инфраструктуру вне помещения или облака.
- Если ты любишь одинокие тропы.
В моем случае я решил исследовать путь без лямбда прежде всего, потому что у меня уже был существующий уровень услуг, который я хотел использовать. Имеются POJO и методы, которые я хотел использовать повторно, не открывая новые конечные точки. Конечно, я мог бы создать Lambdas, которые просто предшествовали эти службы, и это действительный шаблон. Но я не хотел добавлять еще один уровень сценариев развертывания, тестирования и мониторинга.
Наверняка у вас есть свои причины. Если бы я создавал новое программное обеспечение, я, вероятно, пошел бы по пути Лямбда.
Предпосылки
Вы будете использовать консоль разработчика Alexa, чтобы зарегистрировать свои навыки, определить намерения и выражения и проверить их. Я предполагаю, что вы уже создали аккаунт разработчика, и что вы можете настроить новый специальный навык на консоли.
Навык Alexa Spring Boot
Остальная статья покажет вам, как легко добавить Alexa Skill к вашим существующим приложениям Spring Boot. Чтобы продемонстрировать это, мы создадим навык, который будет искать интересные факты об определенном году или случайном году. Вы сможете взаимодействовать с нашими навыками, произнося такие вещи, как:
Alexa, ask my demo app to tell me trivia about a random year.Alexa, ask my demo app, what happened in the year 1984?
Ладно, да, это довольно бесполезный навык. Но он продемонстрирует все важные аспекты программы Alexa, в частности:
- специальная обработка намерений
- использование слотов, управление сессиями
- встроенная обработка намерений
Чтобы достичь этого, наш пример навыков будет вызывать бесплатный посторонний API для поиска информации о мелочах, используя отличный NumbersAPI. Большое спасибо Дэвиду и Маку за создание этого веселого сервиса.
Начинаем
В первую очередь. Добавьте пакет SDK Alexa Skills Kit в файл «pom.xml». На момент написания статьи последняя версия SDK – 1.8.1.
<dependency> <groupId>com.amazon.alexa</groupId> <artifactId>alexa-skills-kit</artifactId> <version>1.8.1</version></dependency>
Пакет SDK содержит специальный сервлет с ним. SpeechletServlet
, который вам нужно будет скачать как часть загрузки приложения. Это действительно очень легко сделать.
Сервлет – это рабочая лошадка. Он обрабатывает все беспорядочные требования для размещения навыков, например проверку запроса Alexa, проверку подписи и проверку отметки времени. К нашему счастью, нам не приходится сталкиваться ни с одной из этих головных болей. Нам просто нужно скачать сервлет. Вот как мы это делаем:
Просто. Вы можете видеть выше, что мы создали конфигурационный класс, который загружает наш сервлет. В строке 10 это видно SpeechletServlet
создается экземпляр, а затем в строке 13 он регистрируется в Spring.
Это почти все, что вам нужно сделать, чтобы скачать сервлет.
Как я отмечал, сервлет берет на себя все сложные коммуникации рукопожатия из Alexa. И после того, как это сделает, сервлет делегирует реальную бизнес-логику взаимодействия. Speechlet, который вы должны реализовать. Вы можете увидеть в строке 11 этот Speechlet, который я назвал HandlerSpeechlet
, назначается сервлетом. Этот Speechlet будет вызываться при каждом взаимодействии с Alexa.
Speechlet – это просто POJO, соответствующий интерфейсу SpeechletV2, определенному в Alexa Skills SDK. Вот как смотрится интерфейс.
Ваша работа – реализовать эти четыре метода.
Все они важны, но большинство работы происходит у них OnIntent()
, который вызывается, когда пользователь говорит что-нибудь значимое. Если вы новичок в словарном запасе программирования Alexa, вам следует прочесть Намерения, высказывания и слоты: новый словарь, необходимый для развития голоса.
Определение намерений
Выделите консоль разработчика Alexa. Настройте новый специальный навык в консоли – эта часть очень проста. Я назвал свой навык «MyDemoApp», а в меню «Вызов» установил «Название вызова навыка» на «моя демонстрационная программа».
Напомним, ранее в этой статье я говорил, что вы можете взаимодействовать с нашими навыками, произнося такие вещи, как:
Alexa, ask my demo app to tell me trivia about a random year.Alexa, ask my demo app, what happened in the year 1984?
Вы можете видеть, что каждое из приведенных выше предложений начинается со слова пробуждения (Alexa) и названия вызова навыков (моя демонстрационная программа).
Alexa, ask my demo app ...
Все после имени вызова навыка известно как an высказывания. Ваша работа состоит в том, чтобы перечислить высказывания на консоли разработчика и сопоставить их с намерением. Одно намерение обычно содержит множество высказываний, представляющих варианты, которые может сказать пользователь. Например, все следующие высказывания по существу одинаковы:
tell me trivia about a random year.say something about any year.pick a random year.tell me some trivia.say anything about any year.
Все эти высказывания означают одно и то же, и потому могут отражаться в одном умысле. В своей заявке я назвал это RandomYearIntent. Вот как это смотрится на консоли разработчика.

Вернуться к написанию кода
Когда наше первое намерение определено, пора вернуться в нашу программу Spring и написать некоторый код. Давайте отредактируем наш HandlerSpeechlet. На данный момент давайте пропустим onSessionStarted
и onLaunch
методов Speechlet, и перейти прямо в onIntent
метод.
Поскольку наша программа будет обрабатывать несколько намерений, нам сначала нужно определить, какое намерение вызывается.
В строке 10 мы теперь называем название намерения. В нашем примере пока это должно быть RandomYearIntent
. В этот момент у вас может возникнуть соблазн написать кучу if-else
высказывания против названия умысла, но давайте попробуем что-нибудь умнее.
Убедившись, что наши намерения соблюдают определенную конвенцию по именам, мы можем использовать некоторую магию Spring для загрузки и вызова специализированных обработчиков для каждого намерения. Дальше не является чем-то специфическим для Alexa Skills SDK. Это просто мой способ обработки нескольких намерений. Есть много способов воплотить эту логику. Вот мой.
Давайте начнем с определения интерфейса, который мы будем использовать для всех наших обработчиков. Давайте творить IntentHandler
как:
Далее для каждого намерения мы создадим класс, реализующий этот интерфейс. Мы также будем осторожны называть наши классы так же, как имя умысла, с добавлением слова Handler. Например, для намерения «RandomYearIntent» мы создадим класс с именем RandomYearIntentHandler
.
Ладно, пока оставим это нереализованным. Мы вернемся к нашему «HandlerSpeechlet» чтобы добавить код, который передаст управление нашему новому RandomYearIntentHandler. Основная стратегия состоит в том, чтобы полагаться на наше соглашение об именовании IntentName + Handler.
Я удалил некоторые детали и обработки ошибок из кода ниже, чтобы мы могли сосредоточиться на важных частях. В конце этой статьи вы можете найти ссылку на мой репозиторий GitHub с полным кодом.
Просмотрите строки 12 и 13 ниже, формирующие имя класса, а затем попросите Spring найти зарегистрированный bean с таким названием. Затем, наконец, в строке 17 мы передаем управление этому обработчику.
RandomYearIntentHandler
Теперь у нас есть сантехника, чтобы вызвать наших специализированных менеджеров. Давайте вернемся к реализации нашего RandomYearIntentHandler. Это конкретное намерение просто. Вот полная реализация.
Просто! Вы уловили аннотацию в строке 1? Это @Component
annotation – это крутой маленький трюк, который скажет Spring создать экземпляр этого класса как Bean. Вот как мы можем получить доступ к обработчику в нашем Speechlet, используя beanFactory.getBean(handlerBeanName)
.
В строке 11 мы создаем случайное число между 1900 и текущим годом. Затем мы вызываем Numbers API, чтобы получить информацию о том году.
В строках 14 и 15 создаем a Card
и а Speech
. The Card
это то, что отображается в вашем мобильном приложении Alexa или на экране в Echo Show. Язык – это то, что произносится пользователю.
AlexaUtils
это простой класс, который я создал. Я не буду вдаваться в детали здесь, но вы можете просмотреть это на GitHub.
Это было легко — а как насчет слотов?
Слоты в основном переменные в высказываниях. Посмотрите на два намерения в нашей программе. Второе намерение, которое я буду называть SpecificYearIntent, позволяет пользователю сказать любой год. Например:
Alexa, ask my demo app, what happened in the year 1984?
В приведенном выше высказывании год очень изменчив. Мы не хотим определить высказывания для каждого возможного года. Вместо этого мы определим это высказывание, используя слот, как:
Alexa, ask my demo app, what happened in the year {Year}?
{Year} – число. Вернувшись к нашей консоли разработчика, мы настроим новое намерение SpecificYearIntent со связанными с ним высказываниями следующим образом:

Я определил слот под названием Year, который имеет тип AMAZON.NUMBER. Теперь в своем обработчике я могу легко получить значение слота под названием.
В строке 13 мы определяем год Slot
. Остальное – это стандартный Java-код, который придерживается того же шаблона, что и первое намерение – позвоните в службу NumbersAPI за год и обработайте ответ.
Сессии и состояние
Я не попал в OnSessionStarted
или OnLaunch
методы Speechlet в этой статье, но я включил реализацию для OnLaunch
в примерном проекте на GitHub.
Вы можете использовать Session
объект для хранения переменных, которые сохраняются во время вызовов в режиме разговора. Режим разговора возникает, когда пользователь использует ваш навык, но не говорит распознанного высказывания. Например:
Alex, open my demo app.
>> Hello. Here are some things you can say: Tell me something about a random year. Or, what happened in nineteen eighty-nine?
What happened in the year 1984?
>> 1984 is the year that the European Economic Community makes £1.8 million available to help combat the Ethiopian famine on October 25th.
>> What else can I tell you? Say "Help" for some suggestions.
Cancel.
>> OK. Goodbye.
В моем исходном коде вы заметите, что у меня есть метод с именем setConversationMode
. Он просто устанавливает переменную в сеансе, давая мне знать, что мы в режиме разговора.
Резюме
Написать навыки Alexa с помощью Spring Boot достаточно легко и может являться мощным способом повторного использования существующей инфраструктуры. Загрузите полное приложение с GitHub, чтобы узнать больше.
А если вы находитесь в районе Южной Флориды, вы можете использовать мой Cutler Stew Skill (построен с помощью Spring Boot), чтобы узнать, когда и где моя группа Cutler Stew выступит следующим образом.