История написания навыков для Алисы и тестилок для них.
Предыстория
В chords-viewer была одна фича: голосовой поиск через браузерный API. Так я наступил в голосовые интерфейсы. Начиналось лето 2018.
Я написал простой список, который можно заполнять голосом - voice-list.
Потом написал список, который умеет отвечать на вопросы что где лежит (речь о вкусах жижи для есиг в разноцветных бутыльках) - voice-whatis.
И тут я вспомнил, что Яндекс запустил возможность обучать Алису в марте и решил, что это неплохая идея для навыка.
Yandex Dialogs SDK - фреймворк для Node.js
Писать с нуля я не люблю, первым делом пошёл на Github искать готовые проекты и либы.
Я сразу нашёл yandex-dialogs-sdk, другого тогда ничего не было в нормальном качестве.
Мы с автором пару месяцев сотрудничали: он писал SDK, учитывая мои хотелки. Трудно представить себе нужные в SDK фичи в вакууме, а я имел боевой навык, покрытый автотестами, который быстро выявлял проблемы в SDK и просил обновлений платформы.
Навык “Вторая память”
Про навык есть отдельный пост.
Колонка с Алисой
В декабре я решил, что раз я пишу навыки для Алисы, надо купить соответствующий девайс. Взял Irbis A, в общем понравилось. Я бы и до этого взял, но был только один вариант за 10 000 рублей, меня жаба душила.
Покупка колонки открыла все удобства и недостатки навыка, после этого было много правок с учётом особенности работы на колонке.
Интерфейс навыка - Алиса, то есть у него нет никакого UI, это называется VUI (Voice User Interface). Но для тестирования это не подходит…
Yandex Dialogs Client - инструмент для тестирования навыков
yandex-dialogs-client написал параллельно с разработкой первого навыка, потому что понял, что нужны автотесты, чтобы прогонять разные сценарии.
Настройки
- Использовать прокси - галочка для отправки запроса с сервера. Плюс: обходит ограничения CORS, если они не обойдены в навыке. Минус: запрос будет отправлен с машины, на которой крутится тестилка, то есть чтобы потестить localhost навык с чужого (или моего) инстанса тестилки, он должен разрешать CORS. Доступно на https://dialogs.home.popstas.ru/ с серверной частью, недоступно на статическом https://dialogs.popstas.ru/
- Использовать /scenarios.yml - после первого запроса к навыку будет запрошен соответствующий файл с вебхука. Навык должен уметь вернуть yaml по этому запросу, иначе тестилка работать не будет при включенной галочке.
- Показывать тесты внизу - закрепляет список тестов на экране
- Показывать JSON в консоли - код запросов и ответов посчитал второстепенным, можно включить его вывод в консоль браузера
- Макс. кол-во сообщений в чате - установлен разумный предел, при большом кол-ве сообщений тесты начинают тормозить
- Макс. кол-во сообщений при открытии страницы - история сообщений хранится в Local Storage браузера, но чистится
- Макс. время ответа - чтобы тестить ограничение на время. Временами я тестил с дебагером и ставил время ответа 60 сек
- Последние URL навыков - здесь сохраняются все вебхуки, которые вводили через
use:
Не выходить в интернет
Я хотел делать всё локально, а стандартная тестилка навыка предполагает, что навык открыт для всех. Поэтому перед написанием навыка я сделал свою тестилку yandex-dialogs-client. Потом я захотел автотесты (сценарии диалогов с проверкой ответов навыка), сделал их, позже они породили yandex-dialogs-tester, который умеет прогонять те же тесты в терминале.
Сейчас для этого я бы взял что-то готовое, тогда тестилок ещё нормальных не написали.
Моя - далеко не единственная.
Прикинуться настоящим
Я хотел сделать максимально похоже на дизайн Алисы в официальных приложениях. Официальная тестилка почему-то этого не хотела и выглядела как поделка начинающего верстальщика. Сейчас выглядит уже хорошо.
Технически это Vue.js с Element UI.
Проверить все сценарии
Этой фичи до сих пор у других не видел.
Идея была в том, чтобы написать все возможные диалоги в файле, который будет автоматически воспроизводиться в навыке и проверять, соответствуют ли ответы ожидаемым.
Тесты можно запускать по одному или все вместе. Для этого внизу чата они выводятся в виде кнопочек.
Тесты прогоняются прямо визуально, просто скрипт пишет в чат сообщения боту.
После прохождения всех тестов будет сводка: сколько тестов прошло, сколько упало, перезапустить все упавшие или один.
Кнопочки раскрашиваются в цвет результата последнего прохождения.
Сообщения от самой тестилки в чате помечаются цветной полосой.
Синтаксис scenarios.yml
Пример одного теста в файле:
"где в конце": # название теста
- "" # пустая строка в запросе
- Привет
- спортзал находится на этаже
- на этаже находится спортзал, поняла # полное соответствие
- где спортзал
- tests: [
{ contains: на этаже }, # содержит строку
{ not_contains: 'на улице' } # не содержит строку
]
- спасибо
- tests:
- one_of: # один из вариантов
- Пожалуйста
- Всегда пожалуйста
- Не за что
- Обращайся!
- удали банан
- tests: [ contains: "" ] # пройдёт любой ответ
В итоге в первом навыке получилось 73 диалога. Все сценарии навыка.
На боевом навыке у меня тестирование 73 диалогов (404 реплики) проходит примерно за 30 секунд, на локалке за 15 секунд.
Я покрыл все сценарии тестовыми диалогами, так я мог не боясь рефакторить код и обновлять версию SDK, сразу сообщая автору, в каких местах что сломалось (а ломалось каждый раз в разных).
Вручную тоже
Для ручного тестирования тоже есть пара фич:
- стрелки вверх-вниз ходят по истории отправленных сообщений, как в терминале
- у исходящих сообщений есть кнопка повторной отправки
Картинки и карточки я не делал, поэтому в тестилке их нет.
Yandex Dialogs Tester - Continous Integration
Потом захотелось прикрутить Travis CI, чтобы там гонялись те же тесты, что и в WebUI. так появился yandex-dialogs-tester, там та же система тестов, но в виде отдельной либы.
Больше об этом проектике нечего сказать, быстрый, но неудобный.
Навык “Список покупок”
Когда я подавал навык на премию Алисы в феврале, мне посоветовали выделить часть, которая касается списка покупок в отдельный навык. Так появился “Вкусный список".
По сути всё уже было готово, я за вечер выбросил всё лишнее, переписал справку и запустил.
Название было такое, потому что “Список покупок” занял какой-то киберсквоттер, но навык он не сделал, там была просто заглушка.
Через какое-то время мне отдали нормальное название “Список покупок”.
Уменьшившийся упростил жизнь как мне, так и пользователю. Например, стало можно сказать просто “добавь картошку”, а не “добавь картошку в список покупок” и т.п.
Сделал возможность добавлять и удалять помногу, защиту от двойного добавления и прочие мелочи.
В итоге оказалось, что навыком действительно удобно пользоваться. На телефоне список выглядел как список, при нажатии на каждый продукт он удалялся из списка, легко было идти по списку и “вычёркивать”.
Навыком начали пользоваться человек 50 в день, я тоже им пользовался, натурально наговаривал список, глядя в холодильник и смотрел в телефон в магазине.
Были косяки, которые меня не парили, а пользователи жаловались. Список хотелок юзеров в какое-то время превысил мои возможности. Например, я надиктовываю сразу группами: “добавь масло, сгущёнку и сыр”, при этом навык должен определить 3 продукта и действие “добавить”. Самое сложное, что я добавлял - “соевый соус”, его я научился определять как один продукт, определяя прилагательное + существительное.
А пользователь хотел “добавить приправу для плова”, можно было через “для” определить связку, но…
Я устал, я ухожу
Под конец простых регулярок перестало хватать для понимания запроса юзера, я начал прикручивать к навыку Томита-парсер для какого-то понимания смысла услышанного (никакого машинного обучения), но всё остановилось на прототипе tomita-parser-test, т.к. навыком я сам пользовался редко, поднадоело.
Вообще я навыки делал в первую очередь для себя, “Вторая память” оказалась бесполезной даже для меня, списком покупок я пользовался несколько месяцев, пока Яндекс не сделал официальный список покупок, он в чём-то хуже (не продуман механизм быстрого удаления в магазине), но в основном он конечно лучше. А больше я не знаю что писать )
Ещё была неудача с премией: Яндекс проводит ежемесячные премии Алисы, где награждает авторов лучших навыков, я ни с одним из 2 навыков не был удостоен. “Ачивки”, которуе я получил от Яндекса: название “Список покупок” и размещение “Второй памяти на главной странице на несколько дней (это подняло посещаемость с 10 до 500 юзеров в день).
К весне 2019 я наигрался с разработкой навыков, поэтому мои тулзы тоже застыли. Я всего 2 навыка сделал и помогал немного в развитии yandex-dialogs-sdk, автору которого надоело ещё раньше меня.