Головна / Статті / За межами поля чату: архітектура AI-агента WhatsApp на Google ADK

За межами поля чату: архітектура AI-агента WhatsApp на Google ADK

Як асистент WhatsApp у продакшені поєднує спеціалістів Google ADK, технологію RAG, детерміністичні інструменти, стан сесії, передачу обов’язків людині та оцінку на основі траєкторії.

2371 слів

Більшість демонстрацій ШІ — це текстове поле, підключене до моделі: вводиться запит, отримується зрозуміла відповідь, і аудиторія задоволена. Продукт, від якого залежать справжні клієнти, має значно довший перелік вимог. Він має пам’ятати хід розмови, працювати з актуальними даними компанії, виконувати дії, переживати збої та передавати клієнта людині, коли автоматизації недостатньо.

У цій статті розглядається архітектура допоміжного сервісу, який працює всередині WhatsApp для ринку зарядки електромобілів у Шрі-Ланці. Він обслуговує водіїв електромобілів, власників нерухомості, які можуть розміщувати зарядні пристрої, та людей, які просто хочуть дізнатися про зарядку електромобілів. До кінця ви отримаєте конкретний план елементів, які оточують модель, та набір правил проектування, які можна використовувати знову у власному агенті, незалежно від каналу, у якому він працює.

Чому канал впливає на продукт

Команда обрала WhatsApp, щоб нікому не доводилося встановлювати ще один додаток лише для того, щоб поставити запитання. Цільові користувачі вже перебувають у WhatsApp: вони знають, як надсилати повідомлення, ділитися місцезнаходженням, зберігати контакти та відповідати на конкретне повідомлення в чаті. Зустрічаючись з користувачами там, можна повністю уникнути проблем з адаптацією. Замість того, щоб навчати людей користуватися продуктом з ШІ, асистент з’являється у інструменті, який вони вже розуміють.

Цей вибір також створює обмеження, з якими ніколи не стикається веб-чат-бот:

  • Відповіді мають бути короткими, адже довгі відповіді ускладнюють користування на телефоні.
  • Повідомлення мають надходити у природному темпі, а не як один великий блок тексту.
  • Запити на місцезнаходження мають використовувати вбудований інтерфейс для обміну місцезнаходженням у WhatsApp.
  • Контактні дані мають надходити у вигляді справжньої картки контакта, а не як вставлений текст.

Метою є розмова, яка відчувається як природна для WhatsApp, а не чат-бот на комп’ютері, втиснутий у додаток для повідомлень. Пам’ятайте про це для будь-якого каналу: конвенції інтерфейсу платформи є частиною специфікації, а не декором.

Шлях запиту від webhook до відповіді

Бекенд написаний на Python за допомогою Google’s Agent Development Kit (ADK) та FastAPI. ADK може створити готовий сервер API для агента з вбудованою підтримкою запуску агентів, керування сеансами та передачі результатів у вигляді подій. Цей сервер API працює на FastAPI та Uvicorn, що полегшує додавання власного WhatsApp webhook та кінцевих точок, специфічних для бізнесу.

Агент ADK складається з чотирьох елементів:

  • Модель, наприклад Gemini.
  • Інструкції, які визначають роль та межі агента.
  • Інструменти, які дозволяють знаходити дані чи виконувати дії.
  • Сесія, яка зберігає історію розмови.
  • Послідовний аналіз одного повідомлення від початку до кінця уточнює концепцію проекту:

    1. Користувач надсилає повідомлення через WhatsApp, і Meta передає його на webhook FastAPI.
    2. Бекенд парсує повідомлення та відображає його у Chatwoot, щоб команда підтримки могла стежити за розмовою.
    3. Бекенд знаходить сесію цього користувача та передає повідомлення до ADK.
    4. ADK запускає координатора, який направляє запити: технічні питання — до агента EV, питання щодо доходів — до агента ціноутворення, пошук станцій — до агента станцій.
    5. Обраний агент або шукає інформацію у базі знань Vertex AI, або використовує інструменти — наприклад, для отримання даних про станції, оцінки доходу, надсилання картки контакту чи запиту про місцезнаходження користувача.
  • Коли відповідь готова, FastAPI форматує її у короткі повідомлення WhatsApp, надсилає їх через API Meta та копіює відповідь у Chatwoot.
  • Зверніть увагу, наскільки мало в цьому процесі пов’язано безпосередньо з самим моделлю. Аналіз, пошук сеансу, маршрутизація, форматування, доставка та відтворення — усе це звичайні завдання бекенду.

    Один координатор, три спеціалісти

    Асистент організований як координатор, який делегує завдання трьом спеціалізованим агентам:

    • Агент інфраструктури електромобілів, який відповідає за типи зарядних пристроїв, їх встановлення та правила.
    • Агент з ціноутворення та бізнесу, який займається економікою хостингу.
    • Агент пошуку станцій, який допомагає знаходити місця для зарядки.

    Єдиною завданням координатора є зрозуміти намір користувача та передати розмову відповідному спеціалісту. Питання про типи зарядних пристроїв надсилається до відділу інфраструктури, запит власника нерухомості щодо потенційного доходу — до відділу ціноутворення, а прохання про станції поблизу Галле — до системи пошуку станцій. Ці передачі залишаються непомітними для користувача, який має враження щодоносної, безперервної розмови з одним асистентом.

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

    Існує витрата, яку варто зазначити. Кожне рішення щодо маршрутизації — це ще один виклик моделі, який може зазнати невдачі, тож неправильно спрямоване запит провалюється так, як цього ніколи не сталося б з окремим агентом. Це одна з причин, чому стратегія оцінки, описана далі, перевіряє, який агент та інструмент були обрані, а не лише кінцеву формулювання. Щоб детальніше дізнатися про те, як маршрутизація та спеціалізовані агенти взаємодіють, дивіться спеціалізовані агенти, маршрутизатор ключових слів та функція переривання в LangGraph.

    Основування відповідей у контрольованій базі знань

    Асистент компанії не повинен вигадувати факти, а процес зарядки електромобілів містить багато деталей, які легко можна сплутати: ємність зарядних пристроїв, часи зарядки, вимоги до встановлення, правила, моделі автомобілів та інформація, специфічна для компанії. Багато з цих елементів змінюються з часом, тож у загального асистента майже немає знань про місцевий ринок.

    Рішенням є генерація з підтримкою пошуку. Ці знання зберігаються у вигляді корпусу даних у двигуні RAG Vertex AI, і перед тим, як відповісти на технічне запитання, агент може здійснити пошук найбільш релевантних фрагментів. Існують два окремі шляхи пошуку: один для загальної інфраструктури зарядки електромобілів, а інший — для запитань про моделі автомобілів та часи зарядки. Такий розподіл корпусу даних дозволяє зосередити результати, адже запитання про те, скільки часу потрібно для зарядки конкретного автомобіля, не конкурує з нормативними документами за перші місця в результатах пошуку.

    Ключовою ідеєю є розподіл праці. Модель все ще формує відповідь, але факти надходять з джерел, якими керує компанія, і їх можна оновлювати без повторної підготовки моделі.

    Перетворення розмови на дію

    Найбільшим кроком уперед було виходження за межі простого відповідання на запитання. Асистент має інструменти, які виконують реальну роботу. Він може:

    • Запитувати бекенд ринку щодо кількості зарядних станцій поблизу певного міста.
    • Надсилати запит на визначення місцезнаходження через WhatsApp.
    • Надсилати візитку компанії.
    • Ділитися адресою офісу у вигляді значка на карті.
    • Оцінювати потенційний дохід для тих, хто розглядає можливість встановлення зарядної станції.
    • Позначати розмову для людини-співробітника, коли це необхідно користувачеві.

    Чому обчислення доходу здійснюється за допомогою звичайного Python

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

    Цей розрахунок здійснюється за допомогою детермінованої Python-мови, а не моделлю мовлення. Моделі є ненадійними у виконанні арифметичних операцій, тому фінансові показники, які показуються потенційному клієнту, мають бути відтворюваними та підлягати перевірці. Модель керує діалогом та збирає вхідні дані; код генерує числа. Результат надсилається через структуровану шаблон WhatsApp, а інформація про клієнта записується у Google Sheets.

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

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

    Стан сесії — це логіка продукту

    Хороша розмова залежить від того, що було до неї. Асистент підтримує окрему сесію для кожного номера WhatsApp, і в цій сесії зберігаються ім’я користувача, номер телефону, вибраний варіант меню, останні повідомлення, інформація про місцезнаходження та ID останнього повідомлення.

    Зберігання ID останнього повідомлення дозволяє системі розуміти відповіді на конкретне повідомлення з меню, що користувачі WhatsApp роблять постійно. Стан сесії також дозволяє багатокроковим процесам продовжуватися природним чином. Наприклад, передача інформації про місцезнаходження відбувається так:

    1. Запитати, чи бажає користувач поділитися своїм місцезнаходженням.
  • Чекайте, поки надійде повідомлення з координатами від WhatsApp.
  • Збережіть координати у сеансі.
  • Відновіть розмову про налаштування з того місця, де вона обірвалась.
  • Без цього стану кожне повідомлення буде розглядатися як початок нової розмови. Пам’ять у агенті — це не додатковий елемент; вона визначає поведінку продукту та заслуговує на таку ж увагу до дизайну, як і будь-яка інша функція.

    Форматування для маленького екрана

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

    Для цього існує спеціальний шар форматування. Він:

    • Перетворює Markdown на власну синтаксис форматування WhatsApp.
    • Виявляє списки, приховані всередині тексту.
  • Перетворює їх на читабельні пункти списку.
  • Розділяє довгі відповіді на кілька коротших повідомлень.
  • Короткі інтервали між частинами дають читачеві час засвоїти кожну ідею. Мета не в тому, щоб імітувати набір тексту людиною, а в контролі темпу. Індикатори набору тексту, які надсилаються через Meta API, показують, що відповідь готується.

    Асистент також реагує на деякі повідомлення емодзі, причому робить це вибірково. Легкий модель, такий як Flash Lite, вирішує, чи заслуговує повідомлення на реакцію, і якщо так, то реакція надсилається через Meta API. Емоційні, захоплюючі, кумедні чи значущі повідомлення можуть отримати емодзі; рутинні повідомлення, такі як „гаразд“, „дякую“ чи прості інструкції, зазвичай їх не отримують. Використання невеликого, дешевого моделю для цього вибіркового рішення знижує затримку та витрати, поки основні агенти обробляють суттєвий зміст. Такі деталі окремо є незначними, але разом вони визначають, чи здається продукт природним.

    Збереження шляху до людини

    Автоматизація ніколи не повинна ставати перешкодою між клієнтами та компанією. Кожна вхідна розмова синхронізується з Chatwoot, і додаються також відповіді асистента, тож команда підтримки завжди бачить саме те, що було сказано.

    Коли користувач просить зв’язатися з реальною особою або проявляє ознаки роздратування, асистент активує процес отримання допомоги від людини, який записує запит разом із питанням користувача для подальшого розгляду командою. Оскільки вся розмова вже відображена, людина, яка бере на себе обов’язки, не повинна просити клієнта повторити свої слова.

    Автоматизація має усувати повторювану роботу, а не перешкоджати доступу до людини.

    Робота над надійністю поза межами розмови

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

    Навколо цього знаходяться ті не надто привабливі функції, які потрібні кожній службі:

    • Усунення дублікатів вхідних повідомлень, адже webhooks можуть доставити одну й ту саму подію кілька разів.
    • Моніторинг стану системи.
    • Обробка оновлення токенів доступу.
    • Контроль CORS для HTTP-ендпоінтів.
    • Розгортання на основі Docker.
    • Відстеження помилок за допомогою Sentry.

    Жоден з цих елементів не справить враження на аудиторію під час демонстрації. Усі вони стають необхідними у ту мить, коли демонстрація перетворюється на сервіс, від якого залежать клієнти.

    Тестування поведінки, а не лише тексту

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

    Тому набір засобів оцінки використовує симульовані розмови, які охоплюють питання інфраструктури, процеси формування цін та розмови між спеціалістами. Перевірки аналізують послідовність використання інструментів, тобто які агенти та інструменти були викликані у якому порядку, а не лише формулювання кінцевої відповіді.

    Зміни запитів обробляються так само. Замість того, щоб вручну редагувати системний запит, команда експериментувала з циклом оптимізації, у якому кандидатські інструкції оцінювалися в рамках фіксованого набору розмов, включаючи оптимізацію запитів на основі GEPA. Кандидатські варіанти протестувалися з питаннями для навчання, а окремий оцінювач на базі Gemini оцінював кожну відповідь за точністю та особливостями стилю. Це перетворює роботу з запитами на щось більш схоже на інженерію: замість того, щоб залишати зміну лише через краще відчуття, можна порівнювати поведінку в рамках повторюваного набору розмов. Існує один застереження щодо будь-якої схеми з використанням моделі як оцінювача: у оцінювача є власні упередження, тому доцільно перевіряти його оцінки порівняно з людським судженням, перш ніж покладатися на нього для важливих рішень.

    Основні висновки

    • Модель є одним компонентом; більша частина інженерних аспектів стосується маршрутизації, пошуку інформації, керування станом, інструментів, форматування, обробки помилок та їх піднесення на вищий рівень.
    • Коли запити та списки інструментів стають складними для аналізу, розділіть зростаючий агент на координатора та спеціалістів, які виконують конкретні завдання, та протестуйте сам процес маршрутизації.
    • Основу фактичних відповідей становте у знаннях, якими ви керуєте, а точні обчислення та іншу роботу зберігайте у детермінованому коді.
    • Вважайте стан сесії та форматування, специфічне для каналу, частиною основної логіки продукту.
    • Завжди зберігайте видимий, простий у використанні шлях до людини-експерта.
    • Оцінюйте траєкторії роботи інструментів у межах фіксованого набору розмов, щоб зміни запитів можна було вимірювати, а не припускати.

    Обгортання запиту навколо виклику API дозволяє створити демонстрацію. Надійний агент — це цілісна система, у якій мовні моделі, дані, інструменти, дизайн продукту та традиційна інженерія бекенду виконують ту роль, у якій вони найкраще справляються.