Вступ до NLP. Як розробити діалогову систему
Привіт, мене звати Ян Бутельський, я NLP-розробник. Уже шостий рік своєї кар’єри займаюся обробкою природної мови, допомагаю машинам зрозуміти людей. Моє знайомство з NLP почалося ще в університеті, але через тодішні методи викладання матеріал здавався мені вкрай нудним. Жодних перспектив у цьому напрямі для себе я тоді не побачив.
Утім після університету доля підкинула мені першу роботу, де NLP стало моєю рутиною. Я збирав, обробляв та анотував великі блоки текстових даних з різних сторінок інтернету. В мене був класичний синдром затятого програміста: практики було багацько, а от теорії бракувало. Згодом я відкрив для себе Coursera і її чудових викладачів.
За півдесятка років, що я в темі, у мене накопичився досвід розробки діалогових систем, який буде корисним усім, хто вже займається обробкою природної мови або хоче спробувати себе у цій галузі.
ChatScript у NLP: ніколи знову
І почну одразу з epic fail story. На старті шляху NLP-інженера я потрапив на проєкт, де NLP-складова була основою продукту (що є рідкістю). Головною фішкою проєкту була якраз діалогова система, для розробки якої замовник обрав платформу ChatScript. На той час вона мала репутацію авангарду NLP, вирішувала купу проблем із діалоговими системами й узагалі була привабливою інвестицією. Вишенькою на торті стала премія Льобнера (присуджена найбільш «людиноподібним» програмам), яку ChatScript неодноразово вигравав.
Та саме на цьому моменті я мушу застерегти всіх, хто хоче розпочати працювати з ChatScript. Якщо коротко: не треба. Якщо трохи розгорнутіше: не треба, будь ласка. Річ у тім, що під капотом ChatScript не відбувається жодної магії — вона містить лишень просунутий набір if’ок і регулярних виразів. Про машинне навчання чи просунуті алгоритми розпізнавання природної мови годі й говорити. Їх немає. Враховуючи те, що у ChatScript немає потужних інструментів для побудови чат-ботів, мені видається, що єдина людина, яка виграє з ChatScript щорічну «льобнерівку» — це сам творець платформи.
Створюємо архітектуру: логіка та принцип роботи
Відокремившись від застарілих технологій, NLP-спеціаліст стикається із наступним викликом — самостійним вибором архітектурного рішення для діалогової системи (і відповідальністю за його імплементацію). На щастя, у часи дилеми з ChatScript я бачив на ринку непогані аналоги — Siri, Google Assistant, Microsoft Cortana та Amazon Alexa. Їхня потужність охайно загорнута в простоту: надіслати повідомлення, подзвонити, знайти локацію тощо можна було без танців з бубном.
Перше, на що програмістові варто звернути увагу — архітектурна схожість усіх вищеназваних діалогових систем. Якщо дуже просто: запит обробляється через пайплайн з модулів. Ключова мета — розпізнавання наміру, тобто intent’у користувача — відтворюється за допомогою стандартної
Принцип роботи multiclass classification простий — вона збирає корпус даних і маркує їх відповідними намірами людини. Так натренована
Оскільки людське мовлення і мова — це майже завжди різниця між сказаним і почутим, обробка природної мови є складнішою за пошук true/false-збігів. Відповідь на фразу «де тут „Криївка“?» залежатиме від (1) вашої локації, (2) бажаного виду транспорту, (3) годин роботи закладу і (4) дорожнього трафіку. Саме тому intent є формою, що складається з кількох слотів. Аби виконалася певна дія, ця форма має бути заповненою. До прикладу, ми — процесор, а по той бік екрана — тремтячий від холоду турист, який призабув, що столичне метро вже не працює. Коли він питає про те, як дістатися звідси до готелю, ми відтворюємо його намір як nav.directions, який складатиметься з двох частин — @from i @to, тобто точок А і Б. Під капотом діалогової системи це матиме такий вигляд.
Користувач: Give me directions to Hotel Grand Budapest
- Intent classifier: nav.directions
- Slot tagger: @to{HotelGrandBudapest}
- Dialogue manager: all slots are filled, here’s the route
Асистент: Here’s the route
Звісно ж, розпізнавання слотів — теж нелегка справа, для якої треба тренувати окрему модель. Незалежно від ступеня складності, я раджу використовувати стандарт BIO/IOB (скор. beginning-inside-outside). Це загальний формат позначення тегів для маркування тексту в NLP. Текст розбивається на токени, а маркуються лише ті з них, які цікавлять конкретного користувача з конкретним наміром (і процесор, який на нього батракує). Префікс B- відповідає за початок слоту, I- — середину, а O- за сам слот. На виході отримуємо токени, промарковані тегами. Їх модель буде використовувати як лейбл під час тренування.
Працюємо з архітектурою: лікнеп із модулів
Наступним кроком у вашій роботі з архітектурою буде розробка і налаштування окремих модулів. На ілюстрації нижче зображено весь пайплайн діалогового менеджера, і розуміння роботи з кожним модулем — ключ до налагодженої роботи NLP-інженера. Як бачимо, сама схема проста: модуль ASR перетворює людське мовлення на текст, після чого NLP-алгоритм структурує і маркує його, а діалоговий менеджер інтерпретує його в команди та диригує усією системою. На виході користувач отримує очікуваний результат, що супроводжується згенерованим текстом, аудіоповідомленням, посиланням чи зображенням.
А тепер я зазирну до кожного модуля окремо і простими словами поясню, навіщо вони тут і як працюють.
Automatic Speech Recognition — зчитує усну мову користувача і переробляє її у текстовий формат для подальшої обробки. Важливо пам’ятати, що з отриманого тексту системі необхідно витягнути якомога більше фіч, особливо для коректної роботи наступного модуля.
Natural Language Understanding — тренує отримані моделі й на основі цього створює додатковий шар логіки, який керує роботою усієї архітектури та стає фундаментом модуля Dialogue Manager.
Dialogue Manager — локомотив діалогової системи, який ухвалює рішення про виконання чи ігнорування запиту користувача (зверніть увагу на ілюстрацію з попереднього розділу). Він тісно пов’язаний з бекенд-процесами, які можуть звернутися до third-party сервісів або баз даних. До прикладу, на запит про Львівську ратушу бекенд паралельно тягнутиме інформацію з Вікіпедії та Google Maps, аби видати дві релевантні відповіді.
Natural Language Generation — останній бастіон у спробі машини зрозуміти намір людини й видати остаточний результат. Зібравши необхідну інформацію від усіх попередніх модулів, він генерує релевантну до запиту відповідь людською мовою.
Підсумок
Шлях від «хей, Сірі» до бажаного результату хоча й бентежний, але не настільки складний, як може здаватися. Архітектура діалогового рішення складається із чіткої послідовності незалежних модулів, кожен з яких долає конкретну сходинку в обробці тексту: зчитування, маркування, інтерпретація тощо. Успішність цілої системи залежить не лише від натренованості моделі, а й від чіткості роботи кожного модуля.
Майбутнім і нинішнім NLP-інженерам, окрім декомпозиції системи на модулі, стане в пригоді ще кілька ресурсів, завдяки яким я навчився краще і швидше будувати окремі модулі та поєднувати їх в архітектуру діалогової системи. Основа основ — це книга від O’Reilly Natural Language Processing with Python. Автори простими словами розповідають про NLTK для Python, побудову словника та парсинг текстів. Любителям онлайн-навчання рекомендую класичний Coursera-курс з обробки мови. Не менш вдалим, на мій погляд, є Стенфордський курс з корисною документацією із теми.
Сподіваюся, що ця публікація допоможе NLP-інженерам глибше зрозуміти діалогові системи, а найкращим продовженням буде дружня дискусія про особливості різних платформ для NLP. Хтозна, можливо, існує людина, яка успішно використовує ChatScript для серйозних алгоритмів обробки тексту, а мої застереження — приховане невігластво.
Якщо стаття буде цікавою товариству, обіцяю у майбутньому зробити докладний опис кожного зі складників пайплайну діалогової системи та поділитися best practices щодо їхньої побудови. Дякую за приділений час!