Happy Halloween! Hello, Ada

Сьогодні хеллоуїн! Вважається, що це день, коли душі померлих вільно подорожують по світу живих. Саме сьогодні, поспішайте познайомитися з духом Ади Лавлейс – першого програміста в історії, яка через століття знайшла нове життя в Telegram. Це стало можливим завдяки двом моїм колегам, які провели безсонну ніч, відтворюючи за цитат і історичним текстам віртуальний образ Ади. Для тих же, хто хоче схожим чином оживити когось з інших історичних персонажів, ми підготували детальну інструкцію по створенню бота з допомогою Microsoft Bot Framework і wit.ai, яку ви знайдете під катом.


Disclaimer: Пропонований вашій увазі бот є демонстрацією того, як створювати ботів з допомогою Bot Framework і Wit.ai, і не претендує на проходження тесту Тюрінга або навіть на здатність підтримувати складну розмову. Тому пропоную не лаяти інтелектуальність бота в коментарях. Крім того, створення даного бота не означає, що ми вітаємо та підтримуємо різні технології потойбічного спілкування.

Ми вже писали про те, як почати розробляти свого бота на Microsoft Bot Framework. З тих пір версія Bot Framework трохи оновилася, але принципи залишилися ті ж. Тим не менш, минулого разу ми залишили за межами статті найголовніше питання — як написати інтелектуального бота, здатного спілкуватися на природній мові.

Для цього нам потрібно спочатку навчитися розпізнавати фрази користувача, тобто чого саме він хоче досягти. Такий намір користувача, яке він висловлює своєї фрази, називається интент. Для виділення интентов з природної мови служать спеціальні інструменти, такі, як LUIS (входить до складу Microsoft Cognitive Services або wit.ai. Про використання LUIS ми вже писали, зараз же ми вирішили інтегрувати бота з wit.ai.

Використовуємо wit.ai
Для початку необхідно зареєструватись на сайті wit.ai і створити там додаток.



В рамках програми необхідно перерахувати всі интент, які ми хочемо розпізнавати в діалозі. Интент можуть мати складну природу, різні параметри (наприклад, интент «дізнатися погоду в місті» може мати місце і дату в якості параметрів) і т. д. Однак у нашому випадку для простоти ми обмежимося простими интентами.



Далі необхідно навчити логіку боти, надаючи йому приклади фраз, та вказуючи, яким интенту та чи інша фраза відповідає. Чим більше різних фраз ви дасте в якості прикладів, тим краще буде бот в результаті розуміти вашу мову.

Створюємо бота в bot framework

Для створення бота вам знадобиться:
  1. Microsoft Visual Studio 2015 (з останніми оновленнями).
  2. Bot Application Template (необхідно завантажити цей файл і скопіювати його, не розпаковуючи, у %USERPROFILE%\Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C#).
  3. Bot Framework Channel Emulator.


Далі створюємо нового бота в Visual Studio: Visual Studio -> File — > New -> Project -> Templates -> Visual C# -> Bot Application.



Name: AdaBot -> Ok.
В створеному проекті вже реалізований найпростіший варіант бота, який повторює введені фраза і друкує їх довжину. За логіку бота відповідає вміст папки Controllers.

Запускаємо його в емуляторі, щоб переконатися, що все працює правильно:
  • Debug -> Start Debugging (або клавіша F5), в результаті чого в браузері відкривається веб-сторінка.
  • Запускаємо Bot Framework Channel Emulator, якщо поле Bot URL пусте, копіюємо в нього адресу відкрилася раніше веб-сторінки і додаємо «api/messages».
  • Набираємо текст і відправляємо боту.
  • У відповідь отримуємо повторення відправленої фрази і число символів, з яких вона складається.


Для написання бота залишилося лише поміняти пару рядків, що відповідають за формування відповіді. В
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
за це відповідають рядки:

// calculate something for us to return
int length = (activity.Text ?? string.Empty).Length;


Нам потрібно замість цього розпізнати интент користувача і вибрати у відповідь один з варіантів повідомлень, відповідних цьому интенту.

Для завдання варіантів відповіді додамо в додаток файл
Responses.xml
приблизно такого змісту:



<Responses>
<Response intent="greeting">
<Text>Здрастуй, мій співрозмовник!</Text>
<Text>Вітаю вас!</Text>
<Text>Добрий день.</Text>
<Text>Рада з вами поговорити.</Text>
<Text>Яка зустріч!</Text>
<Text>Рада вас вітати!</Text>
<Text>Дозвольте привітати вас!</Text>
<Text>Добрий день. Холодно сьогодні.</Text>
<Text>Хто ви?</Text>
<Text>Навіщо ви потурбували мене?</Text>
<Text>Здрастуйте! Я жива!</Text>
<Text>Що відбувається?</Text>
</Response>
...
</Responses>


Так потрібно вказати кілька варіантів відповіді для кожного интента, щоб бот радував вас різноманітністю.

Щоб використовувати API wit.ai в нашому проекті, підключимо до нього відповідний пакет nuget Wit.ai.net. В Solution Explorer викликаємо для AdaBot контекстне меню -> Manage NuGet Packages -> вкладка Browse.



Далі необхідно реалізувати логіку бота. У файлі проекту MessagesController.cs підключаємо простору імен:

using com.valgut.libs.bots.Wit;
using System.Text;
using System.Xml.Linq;



Для пошуку интента використовуємо наступний код:
var wit = new WitClient("YOUR WIT SERVER ACCESS TOKEN");
var msg = wit.Converse(activity.From.Id activity.Text);
var intent = string.Empty; double conf = 0;
try
{
var a = msg.entities["intent"];
if (a != null)
{
foreach (var z in msg.entities["intent"])
{
if (z.confidence > conf)
{
conf = z.confidence;
intent = z.value.ToString();
}
}
}
}
catch (System.Collections.Generic.KeyNotFoundException exc)
{

}


Ми бачимо, що wit.ai повертає нам кілька ймовірних интентов і ступеня їх достовірності, тому ми перебираємо їх всі і вибираємо найбільш ймовірний з усіх. До речі, интентов може і не бути зовсім, тоді в змінної intent залишається порожній рядок, і буде обраний відповідь, якому в нашому XML-файлі відповідає порожній интент.

Далі залишилося лише вибрати один з можливих відповідей, відповідних знайденому интенту. Для цього використовуємо LINQ:
string res = "Я вас не розумію...";
var doc = XDocument.Load(System.Web.HttpContext.Current.Request.MapPath("~/Responses.xml"));
var r = (from x in doc.Descendants("Response")
where x.Attribute("intent").Value == intent
select x).FirstOrDefault();
if (r!=null)
{
var arr = (from x in r.Descendants("Text") select x.Value).ToArray();
if (arr!=null && arr.Length>0)
{
var rnd = new Random();
res = arr[rnd.Next(0, arr.Length)];
}
}


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

// return our reply to the user
Activity reply = activity.CreateReply($"You sent {activity.Text} which was {length} characters");

на
Activity reply = activity.CreateReply(res);


Тепер бот вміє розмовляти! Звичайно, якщо ви попередньо натренировали його на розпізнавання великої кількості фраз, і задали безліч відповідей.

Приклад коду ви можете знайти на https://github.com/evangelism/WitAdaBot, правда, без усього розмаїття фраз і без тренувальної вибірки для wit.ai. Це нехай залишиться нашим know how.

Якщо ж ви хочете напередодні хеллоуїна поговорити з самим ботом Ади Лавлейс — використовуйте @Ada_Lovelace_Bot телеграме.

Зі святом!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.