Ужасами Хэллоуина могут стать не только приведения за окном и страшные костюмы, в которых пришли коллеги. Для истинного интроверта — это будет общение с толпами людей во время праздника, да и не только. В прошлом году я участвовала в создании бота Ады Лавлейс, первой в мире женщины-программиста. В течение года я периодически болтала с ней и мечтала сделать её более совершенной. Приглашаю под кат почитать о новых возможностях, которые мы добавили: цитаты самой Ады, математические задачи от неё и распознавание изображений.



Недавно у нас проходил хакатон для студентов-партнеров Microsoft, на котором одна из команд взялась за идею улучшить предыдущую версию бота Ады Лавлейс. Давайте посмотрим, что получилось.


Как учила Ада


Бот Ады Лавлейс построен на Microsoft Bot Framework, что позволяет его деплоить не только в Telegram, но и в другие каналы, такие как Skype, Slack, Facebook Messenger, Web Chat, Cortana, SMS, etc. Ребята постарались воссоздать бота, взяв за основу реальные цитаты Ады Лавлейс. Довольно интересно, о чём думала в тот момент девушка – сильный математик и первый программист.


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


Вот пример одной из задач, которые вас попросит решить Ада.

По вечерам я люблю засиживаться на веранде, пополняя свой дневник все новыми и новыми исследованиями в области математики. Но однажды, я заметила, мой сосед – Мистер Сандерс по вечерам постоянно ходит в соседний сад. Мне стало интересно. Дождавшись полуночи, когда белый туман, освещенный лунным светом, окутывает просторы сада, я решилась узнать его тайну. Обойдя фонтан со всех сторон в еле видном лунном свете, я заметила странный рисунок на дне фонтана. На нем были изображены четыре отдельно расположенные надписи: «1010», «1100», «10010», «1111». Наверное, это какие цифры в десятичной системе исчисления. Интересно, если мои предположения верны, какие числа там были закодированы? Какую тайну скрывал Мистер Сандерс? У тебя есть предположения? Введи ответ целостно ниже». Или к примеру: «Утром, после завтрака я очень люблю засиживаться в отцовском кабинете и читать исследования отца. В очередной раз, читая его дневник, я обнаружила потертые записи какого-то математического вычисления. В этом математическом вычислении было число, которое инкрементировалось (+) или декрементировалось (-) определенным другим числом. Данное вычисление завершалось только тогда, когда сумма достигала определенного значения, которое мы задавали сами. Такое повторение я решила назвать "Цикл". Для практического подтверждение правильности определения своего термина, я решила провести простое математическое вычисление. Через сколько действий цикл прекратится, при условии: стартовое число равно 5, значение инкремента равно 3, пороговое число для прекращения цикла равно 35.


Некоторые из задач снабжены подсказками, если человек не может решить с первого раза, он получит подсказку, а если ошибется 3 раза, ему скажут ответ. Как только собеседник заводит разговор про математику или программирование, Ада может предложить ему решить задачку.


Задачи собеседнику бот будет выдавать с помощью обертки диалогов IDialog. Рандом будет случайно выбирать момент, когда следует дать пользователю задачу. Далее будет создаваться диалог, в котором будет заданы задачки из json файла с Blob на Microsoft Azure.


Код здесь.
        public async System.Threading.Tasks.Task MessageRecieveAsync(IDialogContext context, IAwaitable<IActivity> result)

        {

            IActivity message = await result;

            string reply = "";

            if (tasks.Unreaded)

            {

                reply = "Я знаю несколько интересных задач и предлагаю вам решить парочку из них";

                await context.PostAsync(reply);

                reply = tasks.Tasks[tasks.Number].Condition;

                await context.PostAsync(reply);

                tasks.Unreaded = false;

                context.Wait(MessageRecieveAsync);

            }

            else if (Helpers.NumParser(message.AsMessageActivity().Text) == tasks.Tasks[tasks.Number].Answer)

            {

                reply = "Это верный ответ!";

                await context.PostAsync(reply);

                tasks.Tasking = false;

                context.Done(this);

                return;

            }

            else

            {

                reply = "Неверно. Но я могу подсказать. \n\n\u200C" + tasks.Tasks[tasks.Number].Explanation + "\n\n\u200CВ следующий раз будь внимательнее";

                await context.PostAsync(reply);

                context.Done(this);

                return;

            }

        }

Как видела Ада


Помимо того, что Ада научилась задавать собеседникам задачи, она еще научилась видеть. Если вы отправите ей какую-нибудь картинку, то Ада увидит её и сможет сказать, что на ней изображено. Зрение Ада получила благодаря Microsoft Cognitive Services. Для реализации зрения Ады мы использовали Vision API. Если на картинке будут присутствовать люди, она сможет оценить эмоциональное настроение людей на картинке.


Для того, чтобы бот распознавал картинку, мы должны прочесть прикрепленные файлы к сообщению в мессенджере. Сделаем мы это так:


Код здесь.
if (activity.Attachments?.Any() == true)

Если Attachments будут иметь прикрепленный файл, в частности изображение, то сперва создаем http-клиент, по которому у нас будет отправляться фотография. Затем открываем Stream для фото и создаем файл по ссылке. Само распознавание будет происходить по Description, полученному после распознавания картинки.


Код здесь.
private async System.Threading.Tasks.Task StartRecognize(MemoryStream photo)

        {

            try

            {

                \_analysisResult = await \_visionServiceClient.DescribeAsync(photo);

                \_isVision = true;

            }

            catch

            {

            }

        }

        public async Task<string> MakeSomeSummary(MemoryStream photo)

        {

            string result = "nothing";

            await StartRecognize(photo);

            if (\_isVision)

            {

                if (\_analysisResult.Description.Captions.Length > 0)

                {

                    result = \_analysisResult.Description.Captions[0].Text;

                }

            }

            return await Helpers.TranslateText(result, "ru", await Helpers.GetAuthenticationToken("SubKey"));

        }

Для того, чтобы Ада отвечала нам по-русски, Description мы переведем с помощью Translation API.


Код здесь.
public static async Task<string> TranslateText(string inputText, string language, string accessToken)

        {

            string result = "";

            string url = " [http://api.microsofttranslator.com/v2/Http.svc/Translate](http://api.microsofttranslator.com/v2/Http.svc/Translate)";

            string query = $"?text={System.Net.WebUtility.UrlEncode(inputText)}&to={language}&contentType=text/plain";

            using (var client = new HttpClient())

            {

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

                var response = await client.GetAsync(url + query);

                result = await response.Content.ReadAsStringAsync();

                if (!response.IsSuccessStatusCode)

                    return "Hata: " + result;

                var translatedText = XElement.Parse(result).Value;

                return translatedText;

            }

            return result;

        }

        public static async Task<string> GetAuthenticationToken(string key)

        {

            string endpoint = " [https://api.cognitive.microsoft.com/sts/v1.0/issueToken](https://api.cognitive.microsoft.com/sts/v1.0/issueToken)";

            using (var client = new HttpClient())

            {

                client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);

                var response = await client.PostAsync(endpoint, null);

                var token = await response.Content.ReadAsStringAsync();

                return token;

            }

        }

После распознавания мы создаём ответ и проверяем, распознаны ли у нас эмоции. Здесь гораздо интереснее. Ада будет распознавать среднюю эмоциональную активность на всей фотографии, распознавая все лица и определяя, какая эмоция преобладает на картинке. Мы же собираем все эмоции на каждое лицо и находим по среднему арифметическому от каждой эмоции "среднюю температуру по больнице";.


Код здесь.
public async Task<string> MakeAboveEmotion(MemoryStream photo)

        {

            string result = "nothing";

            await StartRecognize(photo);

            if (\_isEmotion)

            {

                double[] aboveEmo = new double[8];

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[0] += x.Scores.Anger;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[1] += x.Scores.Contempt;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[2] += x.Scores.Disgust;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[3] += x.Scores.Fear;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[4] += x.Scores.Happiness;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[5] += x.Scores.Neutral;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[6] += x.Scores.Sadness;

                });

                Emotions.ToList().ForEach(x =>

                {

                    aboveEmo[7] += x.Scores.Surprise;

                });

                int mx = aboveEmo.ToList().IndexOf(aboveEmo.ToList().Max());

                switch (mx)

                {

                    case 0:

                        result = "anger emotions";

                        break;

                    case 1:

                        result = "contempt emotions";

                        break;

                    case 2:

                        result = "disgust emotions";

                        break;

                    case 3:

                        result = "fear emotions";

                        break;

                    case 4:

                        result = "happiness emotions";

                        break;

                    case 5:

                        result = "neutral emotions";

                        break;

                    case 6:

                        result = "sadness emotions";;

                        break;

                    case 7:

                        result = "surprise emotions";

                        break;

                    default:

                        result = "nothing";

                        break;

                }

            }

            return await Helpers.TranslateText(result, "ru", await Helpers.GetAuthenticationToken("SubKey"));

        }

Как говорила Ада


Не стоит забывать и об основном функционале бота. В новой версии ребята постарались расширить базу интентов. Теперь можно услышать цитаты Ады Лавлейс. Например, на один из вопросов вы можете получить ответ, который содержит в себе факты о жизни первого в мире программиста.


Например, вот такую цитату о математике.

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


Надеемся, что вам это поможет погрузиться в мысли великого математика. Разумеется, не обошлось и без расширения базы основных ответов.


Вы можете поговорить с Адой в Telegram: @adalovelacebot_bot


Если вы хотите поучаствовать в улучшении бота, pull requests are welcome.


Об авторах


  • Разработчик: Максим Еремин. Студент-партнер Microsoft (MSP). Студент 3 курса 8 факультета кафедры "Вычислительной математики и программирования". Практикует создание ботов на Microsoft Bot Framework, разработку приложений, использующих Microsoft Cognitive Services.
  • Автор интентов: Никулкин Андрей. Студент-партнер Microsoft (MSP). Студент 3 курса факультета сервисных технологий кафедры "Информационные системы" ФГБОУ ВО "РГУТИС". Из интересов, ключевой является создание приложений дополненной реальности AR, информационная безопасность в Windows 10, финансовая бизнес-аналитика Power BI.
  • Team Lead, автор задач: Александр Поповкин. Microsoft Student Partners Lead | Microsoft Russia. Считает, что технологии Microsoft могут изменить мир к лучшему.

Комментарии (14)


  1. Aquahawk
    31.10.2017 17:52
    -2

    Я считаю что такое отношение у реально жившему и умершему человеку совершенно неприемлемо. И даже не собираюсь пояснять почему. И даже на хеллоуин.


    1. Milein
      31.10.2017 18:07
      +2

      Глупость какая-то. Анекдоты с участием исторических лиц вы тоже считаете неприемлимыми?


      1. iCpu
        01.11.2017 10:21

        Только если те в ответ не спамят ссылками.


  1. Zenitchik
    31.10.2017 18:44

    Действительно как-то не по себе. Из хорошего человека делать игрушку.


    1. Catharsis96
      31.10.2017 20:07
      +1

      вообще это ключ к бессмертию. Бот был воссоздан по ее настоящим цитатам и соответственным образом обучен.


      1. Arlekcangp
        01.11.2017 01:40

        А в чем тут бессмертие? Что я вижу конкретно в этом так это желание попиариться одной отдельно взятой компании на имени уже мертвого человека. Особенно учитывая заявление из предыдущей статьи что не стоит ожидать что бот пройдет хотя бы тест Тьюринга («хотя бы» потому что этот тест еще не гарантирует интеллекта) Ну т.е. никаких объективных достижений он не демонстрирует, но привлекает внимание. И да я понимаю что это блог компании и пиар тут допустим. Но согласен с людьми которым такой вид рекламы не нравится — это вполне правильно. И оно никак не приближает нас к бессмертию от слова совсем.


        1. General_Failure
          01.11.2017 07:05

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


          1. Arlekcangp
            01.11.2017 22:30

            Расценить можно что и как угодно. Конечно это мое субъективное мнение. Так что вопросы этики можно и в стороне оставить. Однако мне видится что в этой статье рекламы больше, чем чего то полезного. Статья по сути раздувает хайп вокруг того что уже давно существует. А неплохо бы показать что то действительно новое. До певцов честно сказать дела нет — они на хабре рекламных статей пока не пишут.


  1. gaploid
    31.10.2017 20:26

    Код, похоже, прошел через html escape: "Task&-lt;string&-gt" и теперь не код.


    1. EreminMaxim
      31.10.2017 21:10

      Подробнее код можно посмотреть на github. github.com/MaximDmitrievich/WitAdaBot


    1. Catharsis96
      31.10.2017 21:10

      код доступен на github: http://github.com/MaximDmitrievich/WitAdaBot


  1. Alex625000
    31.10.2017 21:10

    Спасибо. Попробовал. Пока эффекта осмысленного диалога не достигнуто. Хотя опыта тоже у меня маловато. Алиса не впечатлила аналогично. Хотелось бы встретить умную, интерактивную, динамичную ботессу для общения и обучения.
    Разработчикам удачи и мои наилучшие.


  1. VovanZ
    01.11.2017 00:58

    Мне она выдаёт всего одну задачу:


    задача

    Утром, после завтрака я очень люблю засиживаться в отцовском кабинете и читать исследования отца. В очередной раз, читая его дневник, я обнаружила потертые записи какого-то математическиого вычисления. В этом математическом вычислении было число, которое инкрементировалось(+) или декрементировалось(-) определенным другим числом. Данное вычисление завершалось только тогда, когда сумма достигала определенного значения, которое мы задавали сами. Такое повторение я решила назвать "Цикл".
    ?
    ? Для практического подтверждение правильности определения своего термина, я решила провести простое математическое вычисление.
    ?
    ? Через сколько действий цикл прекратится, при условии: стартовое число равно 5, значение инкремента равно 3, пороговое число для прекращения цикла равно 35.
    ?
    ? Подсказка: количество повторений цикла отправьте числом.


  1. kost
    01.11.2017 04:15

    POST to halloween_bot failed: POST to the bot's endpoint failed with HTTP status 500