Живете в Москве и ездите на своем автомобиле? Если да, то как вы оплачиваете парковку? Отправляете SMS? Платите через приложение Парковки Москвы? Используете бот в Telegram? «Это все неудобно» — решил я и создал свой навык для Алисы для оплаты парковки голосом. К тому же, Алиса уже встроена в Яндекс.Навигатор. Теперь можно просто сказать Навигатору что-то типа «Алиса, попроси Парковки Москвы оплатить парковку 3209 на 30 минут».
С чем я столкнулся при разработке навыка?
Сессия
Для того, чтобы запустить навык от стороннего разработчика, Алисе необходимо сказать «Алиса, запусти навык такой-то». Это хорошо и удобно, если предстоит долгое общение с навыком — например, запускается игра. Если же нужно сказать какую-то фразу, получить ответ и всё, то «входить в навык» неудобно — при таком входе, при завершении работы с навыком, потребуется из него «выйти».
Для одной фразы есть решение от разработчиков Алисы — нужно сказать «Алиса попроси навык такой-то сделать то-то». Однако python-пример от разработчиков Алисы такой запуск навыка не поддерживает:
if req['session']['new']:
# что-то делаем
return
Каждый раз, когда запускается навык, в т.ч. и по команде «Алиса попроси навык ...», значение session.new равно True. Потому весь дальнейший код по обработке сделать то-то выполнен не будет. Решение — проверять и текст session.command — он должен быть пустым.
Кстати, если вы «вошли» в навык, то по умолчанию для всех навыков Алиса поддерживает фразы выхода — «Алиса, хватит» и «Алиса, вернись». Если же требуется принудительно завершить сеанс работы с навыком, то необходимо в ответе передать end_session, равное True. Но работает это лишь с Яндекс.Станцией — на других устройствах выход из навыка в этом случае не срабатывает.
Работа с числами
В моем навыке требуется работать с числами — сначала распознать номер телефона пользователя, затем — распознавать номер парковки.
В указанном выше примере от Яндекса используется
req['request']['original_utterance'].lower()
для работы с запросом пользователя. Сначала и я использовал данное поле из запроса. Для того, чтобы распознать номер телефона пользователя, мне приходилось просить пользователя называть отдельно каждую цифру номера — например, «девять один шесть один два три четыре пять шесть семь». А в коде — заменять текстовые значения («девять») на числовые (9). Еще смешнее получалось с кодом парковки — код «3209» я называю как «тридцать два ноль девять», в коде была куча замен типа
s.replace('тридцать два', '32').replace('тридцать один', '31').replace('ноль', '0')
Учитывая то, что на основании текста запроса в коде навыка, я пытался понять что-же пользователь хочет (машина состояний в навыке не используется), это преобразование приходилось делать почти с каждым (!) запросом пользователя.
Выяснилось, что сервера Алисы все уже делают за тебя (и даже больше). Просто вместо request.original_utterance необходимо использовать request.command. Да, об этом сказано в документации. Во всплывающей подсказке в примере к ответу.
Служебное поле: запрос пользователя, преобразованный для внутренней обработки Алисы. В ходе преобразования текст, в частности, очищается от знаков препинания, а числительные преобразуются в числа.
Странно, что в примере от разработчиков Алисы (ссылка выше) используется оригинальный текст (request.original_utterance). На самом деле, в request.command делается даже большее (что не описано в документации). Например, телефонный номер преобразуется в формат (916)123-45-67 — теперь пользователь в моем навыке может называть телефон в любом удобном ему формате. Также вырезаются фразы «Алиса, попроси навык такой-то», обращения «Алиса», исправляются опечатки.
Еще на стороне Алисы отдельные части запросов (числа, имена, адреса, даты) могут преобразовываться в Именованные сущности. Но работает это странно. Запрос 79161234567 1234, в именованных сущностях преобразовался в два числа — 79161234570 и 1234. Почему первое число оказывается другим выяснить так и не удалось — тех. поддержка Яндекс.Диалогов до сих пор думает над ответом.
Время отклика навыка
Алиса ждет ответ от навыка в течение 3-х секунд (у Google этот лимит — 5/10 секунд). Мой навык обращается к сторонним серверам для начала и завершения парковки. Отвечают они неспешно. Иногда за 3 секунды мой навык ответ дать не успевает. В индивидуальном порядке увеличить время для отклика навыка не удалось. Потому в отдельных случаях пришлось пожертвовать удобством — например, при старте парковки навык не запрашивает актуальный автомобиль, указанный в профиле приложения Парковки Москвы, а использует тот, что сохранил у себя при авторизации пользователя.
Ну, и на правах «я пиарюсь» ;) -
Автор: and7ey