Главная / Статьи / За пределами чат-бокса: архитектура ИИ-агента WhatsApp на Google ADK

За пределами чат-бокса: архитектура ИИ-агента WhatsApp на Google ADK

Как ассистент WhatsApp в производственной среде объединяет специалистов Google ADK, технологию RAG, детерминистические инструменты, информацию о состоянии сессии, передачу задач человеку и оценку на основе траектории.

2371 слов

Большинство демонстраций ИИ представляют собой текстовое поле, подключенное к модели: вводится вопрос, поступает плавный ответ, и аудитория довольна. У продукта, от которого зависят реальные клиенты, требования гораздо шире. Он должен запоминать ход разговора, работать с актуальными данными компании, принимать действия, выдерживать сбои и передавать клиента человеку, когда автоматизация недостаточна.

В этой статье рассматривается архитектура помощника, работающего внутри WhatsApp для рынка зарядки электромобилей в Шри-Ланке. Он обслуживает водителей электромобилей, владельцев недвижимости, которые могут размещать зарядные устройства, а также тех, кто просто хочет узнать о зарядке электромобилей. К концу вы получите конкретную схему компонентов, окружающих модель, и набор правил проектирования, которые можно будет использовать в собственном агенте, независимо от канала его работы.

Почему канал влияет на продукт

Команда выбрала WhatsApp, чтобы людям не приходилось устанавливать ещё одно приложение только для того, чтобы задать вопрос. Целевые пользователи уже пользуются WhatsApp: они знают, как отправлять сообщения, делиться местоположением, сохранять контакты и отвечать на конкретные сообщения в диалоге. Встреча с пользователями там полностью устраняет проблему адаптации. Вместо того чтобы учить людей пользоваться продуктом с ИИ, ассистент появляется в инструменте, который они уже понимают.

Этот выбор также налагает ограничения, с которыми никогда не сталкивается веб-чат-бот:

  • Ответы должны быть краткими, потому что длинные ответы создают нагрузку на телефон.
  • Сообщения должны поступать в естественном темпе, а не как один длинный блок текста.
  • Запросы на получение местоположения должны использовать встроенный интерфейс WhatsApp для обмена местоположением.
  • Контактная информация должна поступать в виде настоящей карточки контакта, а не в виде вставленного текста.

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

Путь запроса от webhook до ответа

Бэкенд написан на Python с использованием инструментария Google Agent Development Kit (ADK) и FastAPI. ADK позволяет создать готовый сервер API для агента с встроенной поддержкой запуска агентов, управления сессиями и передачи результатов в виде событий. Этот сервер API работает на FastAPI и Uvicorn, что облегчает добавление пользовательского webhook для WhatsApp и конечных точек, специфичных для бизнеса.

Агент 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 позволяет создать демонстрацию. Надежный агент — это целая система, в которой языковые модели, данные, инструменты, дизайн продукта и традиционная инженерия бэкенда выполняют ту работу, в которой они лучше всего справляются.