GenUI Chat

Обычное приложение устроено жёстко: разработчик рисует экраны, задаёт переходы и заранее описывает каждое взаимодействие. Всё, что не предусмотрено, просто не поддерживается.

GenUI меняет схему. ИИ-агент собирает путь пользователя на ходу — из тех блоков, которые вы ему дали. Предугадывать каждый сценарий больше не нужно: вы делаете детали, агент решает, когда какая понадобится.

Обычное приложение: пользователь жмёт «Мои заказы» → попадает на OrderDetailPage → видит сведения о заказе, отслеживание и список позиций. Маршрут фиксирован, каждый экран собран заранее.

GenUI: вы делаете OrderSummaryCard, TrackingStatusCard и OrderItemsList отдельными компонентами и getOrderDetails — инструментом. Что показать, решает модель по тому, о чём спросили.

Например, пользователь просит: «покажи мои последние заказы». Вместо текста агент рисует карточки заказов с позициями, суммой и статусом доставки. Следующий вопрос — «где мой последний заказ?» — и агент переключается на карту с текущим положением курьера.

personal-shopper.avif

совет
GenUI — не чат-бот

Внешне это похоже на переписку, но по сути отличается: модель не пишет текст, а рисует настоящие элементы интерфейса — карточки, списки, формы, карты. С ними можно работать, а не только читать.

Речь не о разговоре, а о сборке интерфейса из компонентов вашего приложения.

заметка

Обычный интерфейс это не отменяет. Навигация, дашборды и продуманные сценарии никуда не деваются. GenUI — дополнительный слой для тех редких случаев, под которые никто не станет рисовать отдельный экран.

Основа — A2UI

GenUI — реализация A2UI (Agent-to-UI), открытого проекта Google. Это декларативный протокол, по которому агент описывает интерфейс, а тот отрисовывается нативно на любой платформе — без выполнения произвольного кода.

Три составляющие

1. Каталог компонентов. Вместо текста модель показывает ваши компоненты FlutterFlow: карточки товаров, плитки бронирования, сводки. Пользователь не читает ответ, а работает с интерфейсом.

2. Инструменты. Ваши блоки действий становятся возможностями модели: получить данные, вызвать API, отправить форму, запустить процесс — и сразу использовать результат.

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

three-pillars.avif

Как добавить

Соберём простого помощника по каталогу товаров.

  1. Убедитесь, что пройдена интеграция с Firebase, включая первоначальную настройку и файлы конфигурации.

  2. Откройте Firebase Console > AI Logic и включите его. GenUI работает на Google Gemini через Firebase AI Logic, и оплата идёт по факту использования. Для проб хватит бесплатного тарифа Spark, для продакшена нужен Blaze — расходы зависят от числа запросов и объёма токенов. :::tip Следите за расходом в консоли Firebase и настройте оповещения о бюджете: счёт за ИИ растёт незаметно. :::

  3. Создайте компонент ProductListCard, показывающий картинку, название и описание товара. Он принимает параметр типа Product.

  4. Создайте блок действий getProductDetails, который получает данные одного товара и возвращает их типом Product.

  5. Положите виджет GenUI Chat на страницу или в компонент — как любой другой виджет.

  6. В панели свойств задайте инструкции: что за приложение, каким тоном отвечать, на что обращать внимание. Оставите пустыми — получите универсального помощника, который просто собирает интерфейс по запросу.

    Пример системного запроса: You are a helpful AI shopping assistant for an e-commerce app. Help users discover products, compare options, track orders, and complete purchases.

  7. Отметьте компоненты, которые модели разрешено рисовать. Здесь это ProductListCard из шага 3. Подробности — в разделе про каталог компонентов.

  8. При необходимости добавьте блоки действий, доступные модели. Здесь это getProductDetails из шага 4. Добавить можно только те блоки, что возвращают значение; подробности — в разделе про инструменты.

  9. При необходимости подключите локальные события приложения — см. интеграцию событий.

Оформление

Вид чата настраивается в панели свойств:

  • Раскладка и контейнер — фон, скругление, отступы, расстояние между сообщениями, максимальная ширина сообщения.
  • Шапка — показывать ли, заголовок, цвет фона и текста.
  • Аватары — показывать ли, размер, картинки для пользователя и модели.
  • Пузыри сообщений — цвета фона и текста, скругление, отдельно для пользователя и модели.
  • Поле ввода — текст-заглушка, фон, скругление, отступы.
  • Кнопка отправки — значок и оформление.
  • Приветственный экран — показывать ли, заголовок и подзаголовок для пустого чата.
  • Прокрутка — автопрокрутка к новым сообщениям и длительность анимации.
  • Сообщение размышления — что показывать, пока модель отвечает.

Что включено по умолчанию:

  • шапка показывается;
  • аватары включены;
  • автопрокрутка включена;
  • заглушка поля ввода — «Type a message…»;
  • сообщение размышления — «Thinking…»;
  • приветственный экран показывается, пока сообщений нет.

Примеры

1. Поддержка пользователей

Обычный подход: справочный центр с вопросами и ответами, форма обращения и бот, подбирающий готовые ответы по ключевым словам.

Подход GenUI:

  • Компоненты каталога: TicketStatusCard, FAQArticle, EscalationForm, SatisfactionSurvey, AgentContactCard.
  • Инструменты: lookupTicket(ticketId), searchKnowledgeBase(query), createTicket(details), getCustomerHistory(customerId).
  • События приложения: NewTicketUpdateEvent с автоответом — когда обращение обновилось на стороне поддержки, модель сообщает об этом сама.

Пользователь описывает проблему своими словами. Модель ищет по базе знаний, находит подходящую статью и показывает её компонентом FAQArticle. Если не помогло — создаёт обращение через createTicket, показывает TicketStatusCard с номером и обещает сообщить об изменениях. Когда поддержка обновляет обращение, срабатывает NewTicketUpdateEvent, и модель показывает обновлённую карточку с решением.

Никакого «экрана поиска по базе знаний» разработчик не делал. Он сделал компоненты и инструменты — маршрут собрала модель.

2. Личный шопер

Обычный подход: страницы каталога, фильтры, поиск, сравнение, корзина, оформление заказа.

Подход GenUI:

  • Компоненты каталога: ProductCard, ComparisonTable, PriceHistoryChart, ReviewSummary, CartSummary, PromoCodeBanner.
  • Инструменты: searchProducts(query,filters), getProductDetails(productId), getReviews(productId), addToCart(productId,quantity), applyPromoCode(code), getPriceHistory(productId).
  • События приложения: CartUpdatedEvent для внедрения контекста — модель знает, что уже в корзине; FlashSaleEvent с автоответом — сообщает о срочных скидках.

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

Ни страницы результатов, ни панели фильтров, ни кнопки «сравнить». Модель собрала это из того, что ей дали.

Ограничения

  • Единственный поддерживаемый бэкенд — Firebase AI Logic.
  • Слушать можно только локальные события приложения.
  • У компонентов каталога не может быть параметров-действий.
  • Аватары задаются только сетевыми адресами; путь к локальному ресурсу не подходит.
  • На одной поверхности рисуется ровно один корневой компонент каталога.

Что стоит учесть

Описывайте всё

Модель читает описания компонентов и параметров и по ним решает, что рисовать и с какими значениями. Качество ответов упирается ровно в качество описаний.

  • Имена компонентов: ProductCard, а не Card1.
  • Имена параметров: estimatedDeliveryDate, а не date.
  • Описания параметров: «цена товара в долларах», а не «цена».
  • Описания блоков действий: «ищет товары в каталоге и возвращает совпадения с ценами и наличием», а не «поиск».

Модель настолько сообразительна, насколько внятен словарь, который вы ей дали.

Проектируйте под сборку

  • Инструмент плюс компонент. getOrderDetails() возвращает OrderStruct, OrderStatusCard принимает OrderStruct — модель просто передаёт одно в другое.
  • Мелкое лучше крупного. ProductCard, ReviewSummary и PriceChart дают модели три варианта. Один ProductDetailPage — ни одного.
  • Одинаковые типы. Если searchProducts возвращает ProductStruct, пусть ProductCard его и принимает.

События дают чувство времени

Без событий модель знает только то, что ей написали. С событиями — что происходит в приложении.

  • auto_respond: false — для постоянного фона: переходы между экранами, смена настроек, фоновое обновление данных.
  • auto_respond: true — для срочного: предупреждения, завершение задач, превышение порогов, входящие сообщения.

Системный запрос — как вводная новому сотруднику

Опишите:

  • какая у помощника роль;
  • в какой предметной области он работает;
  • что для него важнее всего;
  • чего делать нельзя;
  • каким тоном общаться;
  • какие правила бизнеса соблюдать.

Разница между полезным помощником и обычным ботом обычно именно здесь.

Как это устроено

За моделью стоит Firebase AI Logic с Google Gemini. Цепочка такая:

ваша конфигурация → генерация кода → виджет, работающий на Firebase AI Logic и пакете GenUI.

Вы описываете компоненты, инструменты и события во FlutterFlow, остальное генерируется.

Частые вопросы

Виджет собирается, но модель отвечает только текстом

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

Компонент не добавляется в каталог

Обычные причины:

  • у компонента есть параметр-действие;
  • у обязательного сложного параметра нет значения по умолчанию;
  • компонент удалили или переименовали после настройки.

Блок действий не добавляется как инструмент

Блок должен возвращать значение, а все его параметры и тип результата — поддерживаться сериализатором инструментов.

Не срабатывает подписка на событие

Проверьте:

  • область события — LOCAL;
  • нужное событие действительно объявляется во время работы;
  • значение auto_respond то, которое вы ожидаете.

Почему компонент не проходит проверку?

Обычные причины:

  • есть параметр-действие;
  • компонент настроен в каталоге дважды;
  • у обязательного сложного параметра нет значения по умолчанию;
  • настроенного компонента больше не существует.

Почему модель выбирает не тот компонент?

Как правило, одно из:

  • слишком общие имена;
  • слабые описания параметров;
  • несколько компонентов каталога делают почти одно и то же;
  • системный запрос не объясняет, чему отдавать предпочтение.

Может ли модель нарисовать несколько элементов?

Да, но надёжный способ — один компонент каталога, принимающий список. Рассчитывать, что модель сама соберёт несколько независимых компонентов рядом, не стоит.

Почему модель не вызывает инструмент?

Обычно дело не в коде, а в том, что модель его не «видит»:

  • размытое имя;
  • слабое описание;
  • системный запрос не объясняет, когда инструмент нужен;
  • модели хватает контекста, чтобы ответить без него.

Что происходит при ошибке в инструменте?

Сгенерированный код перехватывает исключение, снимает состояние загрузки и отправляет модели структурированное описание ошибки. Интерфейс при этом не ломается, а модель решает, как объяснить сбой.

Почему не удаётся выбрать событие?

Событие должно иметь область LOCAL и по-прежнему существовать в проекте или зависимости, где оно объявлено.

Почему помощник не ответил сразу?

Проверьте:

  • действительно ли auto_respond равно true;
  • объявляется ли событие;
  • сказано ли в системном запросе, что на такое событие нужно реагировать видимым образом.

И учтите: даже при немедленном обращении к модели видимый ответ появляется не всегда.

Почему помощник реагирует только на следующее сообщение пользователя?

Так и работает `auto_respond: false`: подписка складывает скрытый контекст в очередь, а не запускает отдельное обращение к модели.

Можно ли подписать один виджет GenUI на одно событие дважды?

Нет. Повторная подписка на то же событие в том же виджете отклоняется при проверке.

Сохраняются ли переписки между запусками приложения?

Нет. При закрытии и повторном открытии приложения история сбрасывается.

Можно ли выбрать модель Gemini или задать температуру?

Нет. GenUI работает через Firebase AI Logic, и выбор модели с её параметрами берёт на себя сервис — ни конкретную версию, ни температуру, ни top_p задать нельзя.

Что будет при превышении квоты Firebase AI Logic?

Запросы начнут возвращать ошибку 429 — превышена квота. Обычно это упирается в число запросов в минуту или в предел бесплатного тарифа; иногда в ответе указано, через сколько можно повторить. Тариф Spark годится для проб, но для продакшена нужен платный план и внимание к расходу.

перевод официальной документации FlutterFlow

обновлено

ESC