Moscow travel hack глазами участников, часть 1

в 17:20, , рубрики: api, dialogflow, Moscow travel hack, алиса, Аэроклуб ИТ, аэроэкспресс, голосовой ассистент, голосовые интерфейсы, интерфейсы, хакатон, Хакатоны

Команды Аэроклуб ИТ на Moscow travel hack

Привет! Вы наверняка слышали про первый в России хакатон по теме цифровизации индустрии туризма. Компанию Аэроклуб ИТ представляли на нём сразу две команды, и нам удалось не только отлично провести время, но и разработать прототипы проектов, попробовать силы в необычном для себя формате работы, и пообщаться с другими участниками. Под катом – история одной из наших команд!

При подаче заявки надо было выбрать одну из 10-ти предложенных задач (треков). Это были кейсы таких известных компаний, как «МегаФон», Facebook, PANORAMA 360, MTS Startup Hub, «Аэроэкспресс», Пушкинский музей, парк «Царицыно», Discover Moscow, «Город открытий», и Russpass.

Мы подали заявки на участие сразу двух команд: «Team 73» в треке «Аэроэкспресс», и «New horizons» — в «Царицыно». Первый был выбран потому, что близок к сфере деятельности нашей компании (программные B2B-решения), и в случае победы мы вполне могли бы продолжить сотрудничество и разработку. Второй – ребятами, которые хотели отвлечься от повседневных задач и попробовать что-то новое.

В общем чате мероприятия говорили, что была подана 1241 заявка (как командные, так и индивидуальные), и, как вы уже догадываетесь, мы прошли отбор! Причём обе наши команды!
Дело оставалось за малым – поучаствовать в самом хакатоне.

Хакатон

На площадке было всё как обычно: регистрация, зона с закусками, столы с номерами команд.
В 9:30 состоялось короткое открытие: пара слов от организаторов, торжественный старт хакатона, и началась работа. Далее речь пойдёт от имени участников команды «Team 73», которая взялась за задачу от «Аэроэкспресса».

Вначале мы пообщались с менторами: узнали, что они хотели бы увидеть в решении, какие есть нюансы, и чему отдать предпочтение. Команды были немного удивлены, когда оказалось, что обещанные ресурсы не будут предоставлены. По описанию задачи, мы могли получить API «Аэроэкспресс», хостинг, доменное имя, и сертификат для реализации проекта. Как объяснили менторы, API не могут предоставить из соображений безопасности, но про остальное толком не пояснили. К счастью, у нас был «резервный вариант» — личный хостинг. В итоге, он и спас наше положение.

Решение

Основная проблема, которую требовалось решить – автоматизация продажи билетов на «Аэроэкспресс» для юр. лиц. Мы провели некоторые исследования текущего процесса и были, мягко говоря, в шоке. Как мы узнали из публичной оферты для юридических лиц, сначала от компании-заказчика отправляется письмо-акцепт в качестве запроса на необходимое количество билетов, с указанием реквизитов компании. Далее — оплачивается выставленный счёт и, самое главное, каким-то образом происходит получение билетов в виде запароленного архива. То есть, как вы поняли, минимальный уровень автоматизации.

Мы набросали CJM (customer journey map), выбрали минимально необходимый функционал, подумали над дизайном. В какой-то момент мы рассудили следующим образом: каждая команда, так или иначе, покажет примерно одинаковые решения: регистрация юр. лица, покупка билета, выставление счёта, и так далее. Чтобы как-то выделиться, надо было придумать что-то особенное. Как минимум, нужен хороший дизайн, тогда на общем фоне наше решение будет чуть заметнее. Благо, в другой нашей команде есть дизайнер, и она нам с этим поможет. Но нужно было что-то ещё, что-то совсем необычное для B2B. И тогда мы решили добавить интеграцию с Алисой – той самой, голосовым помощником от Яндекса.

Причин было несколько: основная – у нас есть некоторый опыт работы с ней, чтобы в короткие сроки сделать более-менее полезный прототип. Ещё одна – B2B, как правило, ассоциируется с чем-то скучным и формальным, а получение билетов через говорящую колонку – что-то новенькое. К тому же, у нас два бэкенд-разработчика, и толкаться вдвоём в одном проекте не очень удобно, а так мы параллельно сделаем и основной функционал, и дополнительный.
Начну с основного решения – Портал оптовых продаж Аэроэкспресса. По нашей задумке, он состоит из двух частей: фронтенд и, конечно же, бэкенд.

Фронтенд

Наш фронтендер – адепт Angular, отсюда и выбор именно этого фреймворка. Angular «из коробки» даёт хорошее стартовое окружение, в котором не надо заморачиваться с конфигурацией, роутингом, и подключением к бэкенду– то, что надо для хакатона. Так же наш разработчик давно работает с ним и накопил несколько своих библиотек, с которыми можно сэкономить немного времени на хакатоне.

В результате у нас получился вот такой фронтенд:

Внешний вид мы старались сделать современным, стильным, выдерживая цвета «Аэроэкспресса».

Здесь у нас был реализован следующий функционал:

  1. Поиск названия компании по ИНН
  2. Регистрация компании и контактного лица с указанием примерного объёма продаж билетов в месяц.
  3. Авторизация сотрудника компании
  4. Заказ билета
  5. Количество предстоящих поездок
  6. История заказов
  7. Личный кабинет менеджера со стороны «Аэроэкспресса»

Мы постарались сделать максимально простую регистрацию компании на портале: её представителю достаточно знать ИНН юр. лица, и ввести его в соответствующем поле. Если появившееся название подходит – можно продолжать. Регистрация на портале – это одновременно заявка на сотрудничество с компанией «Аэроэкспресс». Менторы подсказали, что им будет проще рассматривать такие заявки, если представители будут указывать примерный объём продаж билетов в месяц, для этого мы добавили соответствующее поле.

На первый взгляд может показаться, что сделано не так уж и много, но у нашего решения очень красивый и проработанный дизайн. Его сделали с нуля, не используя никаких готовых шаблонов. По предыдущему опыту, в хакатонах зачастую побеждали решения, которые были не столь хорошо проработаны, но «завёрнуты в красивую упаковку», и в этот раз мы решили сделать ставку именно на красивый внешний вид. Забегая вперёд, скажу, что менторы были в восторге от нашего дизайна, но оценивали решения именно по количеству реализованных функций и по дальнейшей перспективе применения решения (которую некоторые команды хорошо продумали).

Бэкенд

Оба наших бэк-разработчика – матёрые шарписты (пишут на C#), поэтому и бэк основан на .net core. Была выбрана версия 2.1, поскольку приложения на нём точно поднимаются на резервном хостинге, а экспериментировать на хакатоне опасно – можно потерять время и остаться без решения. У нас получилось обычное web-api, с блэк-джэком и DI.
Здесь мы сделали всё необходимое для «фронта»:

  1. Поиск информации о компании по ИНН
  2. Регистрация компании и его контактного лица
  3. Аутентификация по логину-паролю
  4. Авторизация по Bearer-токену
  5. Получение информации о пользователе
  6. Получение списка сотрудников компании текущего пользователя
  7. Создание заказа
  8. Отправление билета на почту после создания заказа
  9. Отправка билета на почту запрошенному пользователю (для внешней интеграции)
  10. Получение информации о всех билетах компании
  11. Вывод списка заказов
  12. Вывод списка зарегистрированных компаний

Из интересного – интеграция с поиском организации по ИНН или ОГРН в Dadata, для лёгкой регистрации юр. лица. Если кратко – бэкенд получает запрос «найди компанию» с переданным ИНН, и отправляет эту информацию в API сервиса. В ответ, если компания найдена, получаем информацию о ней: краткое название (отдаём в ответе), и реквизиты. Полученные данные полезно где-то сохранить, потому что они пригодятся при формировании счетов: пользователю будет достаточно проверить их корректность, что гораздо проще, чем «вбивать» самостоятельно.

Навык для голосового помощника

Навыки для ассистентов – это, как правило, веб-сервисы, которые работают с определённым протоколом запросов и ответов. Как уже говорил, мы выбрали интеграцию с Алисой в качестве дополнения к основному решению. Подробнее о протоколе работы с ней вы можете узнать из документации, а ещё в свежей статье про навыки. В нашем случае веб-сервис навыка тоже был основан на .net core.

Пользователю должно быть комфортно взаимодействовать с навыком, как если бы он разговаривал со своим близким приятелем. Для этого, как минимум, необходимо поддерживать контекст разговора, понимать, о каком объекте говорит пользователь, и отвечать по теме. Если же пользователь отклоняется от цели диалога, нужно уметь вернуть его в нужное русло. И всё это должно происходить не дольше 3х секунд – именно столько времени платформа Яндекс-диалогов даёт навыку на ответ. Если ответ не будет получен за отведённое время – диалог прекратится, а пользователю скажут, что навык не отвечает, и в него вряд ли захотят вернуться снова.

Справиться с такой задачей можно при помощи различных сервисов, предназначенных для поддержания диалога с пользователем. У нас уже был кое-какой опыт работы с Dialogflow от Google, поэтому выбрали его. Как минимум, для него есть альтернатива из России – Aimylogic от JustAI, но с ним пока ещё не приходилось работать.

В нашем случае предполагается достаточно простой диалог: пользователь просит отправить ему билет, и если он сразу назвал свои ФИО – отправляем. Если нет – уточняем ФИО, и тогда уже отправляем.

Уточнение имени пользователя любой ценой

Уточнение имени пользователя любой ценой

На наш взгляд, самое сложное в этой задаче – получить ФИО пользователя. Если они не будут названы, надо каким-то образом получить их от пользователя, и только после этого выполнить нужное действие. К счастью, DF (Dialogflow) позволяет делать такое «из коробки».
Для этого в намерении (Intent), в котором предполагается получение ФИО, нужно добавить тренировочные фразы, содержащие полное имя, и разметить их таким образом, чтобы эта информация попадала в соответствующий параметр намерения. Если ФИО будут распознаны, то параметр будет содержать это значение.

Размеченные тренировочные фразы

Размеченные тренировочные фразы

Параметры намерения

Параметры намерения

В противном случае надо получить эти параметры любой ценой. Для этого надо пометить параметр с ФИО как обязательный (галочка в колонке «Required»), и задать для него уточняющие фразы («Prompts»). Теперь, если нужно, в ответ DF будет отдавать именно их. А если ФИО распознаны – то обычные ответы для этого намерения, а также действие («Action»).

Уточняющие фразы

Уточняющие фразы

Обычные ответы

Обычные ответы

Дальше всё просто: если получено название действия и в ответе DF есть все необходимые параметры – выполняем это действие, и передаём ответ пользователю. Если же нет – отправляем текст уточнения.

Для отправки билетов навык должен выполнить запрос к бэкенду нашего портала с заголовком авторизации и ФИО пользователя в теле. По заголовку будет определена компания, а по ФИО легко найти нужного пользователя. В жизни заголовок может быть получен путём авторизации в навыке, но на хакатоне мы его просто «захардкодили», для экономии времени. С полным именем чуть сложнее.

Можно воспользоваться ФИО, распознанными в DF, но есть небольшая проблема: если пользователь назовёт себя не в именительном падеже, то и в параметре будет записано такое значение. На бэкенде имена пользователей записаны в нормальной форме (в именительном падеже), и несоответствие написания затруднит поиск.

И тут мы обратили внимание, что в запросе от Алисы приходят распознанные ФИО, нормализованные и записанные в отдельные поля!

Распознанное ФИО

Распознанное ФИО

К сожалению, NLU Яндекс-диалогов не очень хорошо справляется с более сложными именами, например Мамедов Полад Муртуза оглы, но для демонстрации на хакатоне подойдёт и этот вариант.

В итоге, получилась вот такая цепочка:

Диаграмма запросов

Диаграмма запросов

К концу хакатона у нас уже были готовы все три части нашего решения, которые мы и показали менторам. По их реакции сложно было сказать, нравится им наша разработка или нет, но, как мы позже узнали из личной беседы, демонстрация интеграции с Алисой однозначно оказала ожидаемый вау-эффект.

Во время работы также проходила техническая комиссия: каждая команда должна была предоставить доступы к своим репозиториям, и не реже одного раза в час делать в них «коммиты». Также к нам иногда приходили представители комиссии, обсуждали разрабатываемое решение. Кстати, их впечатление о хакатоне можете узнать вот здесь.

Победители

После выступлений приглашённых спикеров начались финальные питчи команд, победивших в той или иной задаче. В треке «Аэроэкспресс» выиграла команда «AeroTeam». Как позже нам рассказали менторы (они же — жюри), именно у этой команды была наиболее продуманная концепция дальнейшего развития решения, и ребята учли и проработали некоторые моменты, о которых даже сами заказчики не задумывались (к сожалению, не упомянули, какие именно). Нам же для победы не хватало некоторых деталей, который по-настоящему интересны менторам с точки зрения бизнеса. Они выбрали решение, которое достаточно проработано для того, чтобы начать его разработку «прямо сейчас», а значит были весьма объективны в своём решении, и это здорово.

Как мы потом узнали из беседы с участниками «AeroTeam», они собрались в команду достаточно сумбурно: узнали о хакатоне из совершенно разных источников, так или иначе попали в общий чат мероприятия, и там уже объединились. Всего в «AeroTeam» было три человека. В какой-то момент им предлагали ещё и UX-дизайнера, но они отказались, и вполне хорошо справились без этой роли. Никаких особых предпосылок к победе у ребят не было (например, в виде каких-то наработок), и им удалось проделать настолько мощную работу, которая, на мой взгляд, по праву заслужила победу.

Другая наша команда, к сожалению, тоже не выходила на сцену с питчем, а значит – не выиграла в своём треке, но эту историю мы расскажем в другой раз. А пока – кто же стал суперпобедителем хакатона? Эту номинацию отдали команде, которая, по мнению жюри, сделала самое лучше решение среди всех победителей в той или иной категории — «Голден ПСЖ». Они работали над задачей от смотровой площадки «Панорама 360». По заданию предполагалось, что посетители площадки будут фотографироваться на фоне «хромакея» (однотонного полотна), выбирать вместо него другой красочный фон, и сразу же печатать фотографию. Ребята же пошли дальше, и их решение позволяет удалять любой фон (а программно выполнить это гораздо сложнее, чем убирать одинаковый цвет) вокруг основного объекта (человека), и заменять его другим. На наш взгляд, это решение также достойно победы.

Сами участники – студенты бюджетного отделения ИТМО. Как ребята рассказали в личной беседе, они всё время были на площадке, ночью никуда не разъезжались, и «пахали» почти 26 часов из 30-ти (с перерывами, конечно же). У них уже был опыт участия в хакатонах, но приз забирают впервые.

Выводы

В первую очередь, стоит уделять больше времени реализации основного решения, чтобы жюри могли «потрогать» его, увидеть вживую на прототипе, а не на макетах и словах. Также стоит продумать дальнейшие перспективы развития проекта. При прочих равных, судьи могут отдать предпочтение решению, которое выполняет не только текущую задачу, но и сопутствующие цели заказчика.

Тем не менее, если есть возможность как-то выделиться — сделать красивый дизайн, или реализовать необычную идею, этим однозначно стоит воспользоваться. По опыту участия в других соревнованиях, это может помочь выиграть если не в основной, то хотя бы в дополнительной номинации — например, получить «приз зрительских симпатий», если такие предусмотрены. Или просто запомниться участникам и судьям необычным подходом.

До мероприятия стоит провести некоторые исследования бизнеса заказчика, чтобы лучше узнать его «боль» и придумать что-то для её устранения. Идеи и небольшие наработки не являются «готовым решением», так что правила хакатона не будут нарушены, и будет больше времени на самом соревновании.

Ещё не стоит полагаться на предоставление ресурсов со стороны заказчика, даже если это прописано в задаче. И вообще, к хакатону всегда следует хорошо готовиться: поднять минимально необходимую инфраструктуру, продумать публикацию проекта, исследовать API нужных сервисов, и тому подобное. Обязательно стоит предусмотреть решение такого вопроса, как собственный доступ в интернет, поскольку на большинстве подобных мероприятий с этим возникают трудности. Здесь, например, большую часть времени не было стабильного подключения. Ирония ещё заключается в том, что символом хакатона был оффлайновый динозавр, которого можно увидеть в Chrome, когда у вас нет интернета.Moscow travel hack глазами участников, часть 1 - 9

Хотелось бы отдельно отметить организацию хакатона: в целом, она была на высоте. Каждый этап проходил вовремя, на самой площадке тоже был полный порядок: еды хватало всем, закусок было много. На публичную часть во второй день, по идее, можно было прийти после предварительной регистрации, но, в итоге, туда мог попасть любой желающий. Небольшая вечеринка с музыкальной группой и фуршетом тоже удалась! Мы выражаем благодарность и уважением организаторам. Наша оценка – четыре зелёных динозавра из пяти – чтобы было к чему стремиться!

Таким был для нас Moscow travel hack: что-то в нашем решении было плохо, а что-то – хорошо. В любом случае, мы учтём свои ошибки и будем помнить их на следующем соревновании. Вообще, участвовать в хакатоне, особенно в команде коллег – это здорово! Для нас это был не только золотой опыт, но и лучший тимбилдинг. Мы очень круто сыгрались, творили безумные вещи без сна и отдыха. Убедились, что можем продуктивно работать над сложными задачами в сжатые сроки и в стрессовой ситуации. Главное — это наслаждаться процессом!

Если интересны технические детали реализации нашего решения — напишите в комментариях, с радостью расскажем.
Не прощаемся, увидимся на хабре!
Команда «Team 73», Аэроклуб ИТ

Команды Аэроклуб ИТ на Moscow travel hack

Автор: Степан

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js