Голосовой орб, который реально управляет сайтом: архитектура ассистента, а не «говорящего FAQ»

Голосовые ассистенты на сайтах обычно заканчиваются одним из двух: либо это чат-бот, которому приклеили распознавание речи, либо озвучка FAQ. Мы пошли от обратной задачи — сделать голос основным способом управления интерфейсом, а не надстройкой над текстом. Ниже разбор архитектуры и решений, которые пришлось принять.
Задача
Пользователь открывает сложную страницу генерации — видео, картинки, музыка — где есть выбор модели, загрузка референса, промпт, параметры. Новичок теряется. Классический онбординг (тур со стрелочками) люди закрывают на втором шаге. Мы захотели, чтобы можно было просто сказать голосом: «хочу оживить это фото», а ассистент сам подсветил нужную кнопку, объяснил и довёл до результата.
Ключевое отличие от чат-бота: орб видит состояние страницы и действует на ней, а не отвечает текстом «нажмите кнопку X где-то там».
Архитектура: три слоя

• Голосовой тракт. Потоковое распознавание речи → модель → синтез ответа. Требование — низкая задержка и возможность перебивать (barge-in): пользователь начал говорить — ассистент замолкает. Без этого диалог ощущается как рация, а не разговор.
• Мозг. Мы сознательно отвязали «личность» ассистента от конкретной языковой модели: модель настраивается на стороне сервера, так что её можно менять под задачу и стоимость без передеплоя фронта. Ассистент получает не только реплику пользователя, но и машиночитаемый снимок текущей страницы: какие элементы есть, какие кнопки, что уже выбрано.
• Executor на клиенте. Модель возвращает не только текст, но и действия: подсветить элемент, прокрутить к блоку, объяснить поле. Клиент исполняет их поверх реального DOM.
Три грабли, на которые мы наступили
Самое интересное — не happy path, а провалы. Мы разобрали логи реальных диалогов и вынесли корневые правила.
1. Галлюцинация возможностей. Ассистент предлагал модели, которых нет на текущей странице, или путал модель для картинок с моделью для видео. Пользователь справедливо злится: «нет такой модели». Фикс — не полагаться на «знание мира» модели: ассистент может называть и переключать только то, что реально есть в снимке текущей страницы. Это классическая проблема grounding — модель нужно жёстко привязать к состоянию интерфейса, иначе она уверенно врёт.
2. Подсветка не той кнопки. Просят показать «загрузить фото» — подсвечивает «Сгенерировать». Причина — нечёткий маппинг «намерение → элемент». Решение: элементы получают семантические якоря, и ассистент обязан подсветить ровно тот, о котором говорит, а не соседний по смыслу.
3. Навязчивость. Модель уже выбрана — ассистент всё равно лезет её менять; пользователь просит «просто напиши промпт» — а он спорит. Правило: если состояние уже подходит или пользователь явно просит не трогать — не действовать и не спорить, сразу делать то, что просят. Меньше инициативы, больше исполнения.
Вывод, который мы бы дали любому, кто строит агента поверх интерфейса: 90% качества — это не модель, а grounding и дисциплина действий. Модель должна видеть точное состояние и не имеет права выходить за его пределы.
Экономика диалога
Голос дороже текста, поэтому у орба есть бесплатное окно, дальше — оплата по факту разговора. Биллинг привязан к длительности голосового взаимодействия, а не к количеству «сообщений».
Если делаете что-то похожее — интересно сравнить подходы к grounding и barge-in.