Разработчик игр, который впервые берётся за голосового агента, часто слышит одно и то же: «Это другая область, начинай с нуля». В моём случае вышло иначе. Пять с лишним лет в Unity — фриланс, AR для пожарных, клинический XR, кроссплатформенный C# SDK — дали не знание движка, а набор привычек. Почти все они оказались про другое: про системы, которые работают в реальном времени, перед человеком, который не станет ждать, и на датчиках, которые врут.
Вот честное разделение: что переносится почти без потерь и что пришлось выбросить. Второй список — там, где были дорогие уроки.
Что переносится
Бюджет кадра — это бюджет задержки. В Unity быстро узнаёшь, что время — жёсткий ресурс. При 60 fps у тебя около 16 мс на кадр. На автономном VR-шлеме — ближе к 11 мс. Дисциплина, которая из этого вырастает, звучит не как «сделай быстро», а как «знай, что именно лежит на критическом пути». Профилируешь, а не гадаешь. Убираешь работу с главного потока. Раскидываешь дорогие задачи по кадрам. И перестаёшь верить средним: игрок чувствует худший кадр, а не медианный.
У голосового агента та же геометрия. Звонящий замечает самый медленный ответ, а не средний. Работа та же: найти, что реально блокирует ответ; вынести записи в CRM и уведомления в автоматизацию после звонка; прикрыть неизбежное ожидание речью, а не тишиной; мерить хвост задержки. Порог другой: 16 мс превращаются примерно в 800 мс. Психология та же — после порога система перестаёт ощущаться живой.
Всё реальное время — это конечный автомат, и баги живут в переходах. Игровой разработчик живёт в автоматах: контроллеры персонажей, UI-потоки, графы анимации. Опыт быстро показывает, что баги почти никогда не сидят внутри состояния. Они живут в переходах, особенно в тех, которые никто не описал. Игрок, который открывает инвентарь в прыжке во время загрузки кат-сцены, находит щель.
С разговором то же самое. Узлы сценария писать легко. Выживаемость агента решают условия выхода: что считается завершением? Что делать, если звонящий отвечает на вопрос, который вы не задавали? Куда он попадает, когда всё развалилось? Выходы я теперь пишу раньше счастливого пути — привычка прямо из контроллеров персонажей.
Датчики врут, поэтому дизайн строят вокруг вранья. Это переносится неожиданно прямо. Location-based AR работает на GPS и магнитометре, и оба врут не случайно и не одинаково. В геопространственном AR иллюзию обычно ломал не градус позиции, а ошибка курса. В клиническом XR весь продукт был измерением по неидеальному сигналу eye-tracking, на который потом опирался врач.
Распознавание речи — такой же вход. Это шумный датчик со структурными отказами, и структуру можно выучить. Хуже всего он работает на значениях без избыточности: имена, почтовые индексы, регистрационные номера, адреса почты. Целые предложения выживают. Когда принимаешь, что у каждого показания есть подразумеваемая уверенность, строишь иначе:
- проверяешь форму значения ниже по потоку, а не доверяешь сырому;
- перечитываешь важные значения небольшими кусками;
- хранишь уверенность рядом со значением;
- даёшь пути исправления конец, чтобы он не зацикливался.
AR научил не доверять числу только потому, что его выдало устройство. Транскрипт — это число, которое выдало устройство.
Плейтест — это состязательный QA. Любой, кто видел, как незнакомый человек впервые играет в его игру, знает: тесты такого не рассказывают. Люди не идут по пути. Они входят в стену, жмут все кнопки в туториале и отвечают на вопрос, который вы не задавали.
Звонящие — тоже игроки. Перебивают, выдают два факта сразу, замолкают, посреди записи спрашивают что-то вне задач агента. Геймдев вырабатывает привычку тестировать на сложном пользователе, а не на сговорчивом. Агент, который пережил идеального звонящего, не доказывает ничего. Как и игра, которая выживает только под своим разработчиком.
Релиз через привратника, которому нет дела до тебя. Магазины приложений учат отдельной производственной дисциплине: отправка, ревью, отказ, воспроизводимая сборка и план отката, о котором стоило подумать до того, как он понадобился. «У меня работает» описывает место, где работает. Это не защита.
У голосовых агентов свои привратники, и они менее снисходительны, чем кажутся: операторы связи, A2P-регистрация, правила согласия на запись, медицинские и privacy-ограничения. Правила другие, поза та же. Что-то вне вашего контроля может не пустить к пользователям — значит, это планируют на первой неделе, а не за день до запуска.
Что не переносится
Звонок нельзя переиграть. Игры достаточно детерминированы, чтобы их перезапускать. Тот же seed, те же входы, тот же баг — сколько нужно раз. Живой звонок не повторяется: другой звонящий, другой шум, модель не выдаст тот же ответ дважды. По нему не пройтись по шагам.
Поэтому наблюдаемость строят заранее, потому что отладчика нет: транскрипты, записи, структурированные данные после звонка, полный трейс вызовов инструментов. Вы делаете форензику постфактум, а не шагаете по кадрам. Задача — собрать достаточно доказательств в момент звонка, чтобы потом восстановить картину.
Игру видно, агента — нет. Почти любой визуальный баг в Unity сам о себе заявляет. Смотришь на сцену — что-то не на месте. Отказы голосового агента тихие и выглядят как успех. Звонок завершён, транскрипт читается нормально, а клиент так и не получил письмо, потому что адрес почты распознали неверно. Ничего не падает. Пришлось заменить рассматривание чтением и завести привычку читать неудачные звонки целиком, а не выборочно.
Движок твой, модель — нет. Unity — зависимость, которую можно понять, декомпилировать, обойти и в конце концов узнать полностью. Языковая модель — зависимость, которая меняет поведение без changelog, и пропатчить её нельзя. Её не чинят, её обходят. Агент держат тонким. Всё, что обязано быть правильным, уводят в детерминированную автоматизацию ниже по потоку, а не доверяют памяти модели. Там, где формулировка несёт риск, ограничивают то, что модели разрешено говорить. Эта архитектурная осторожность — главное реальное изменение в том, как я строю. Из игр оно не пришло.
| Аспект | Игра | Голосовой агент |
|---|---|---|
| Бюджет времени | 16 мс на кадр при 60 fps, около 11 мс на автономном VR-шлеме | Примерно 800 мс до того, как ответ перестаёт ощущаться живым |
| Отладка | Перезапуск с тем же seed и входом | Повтор невозможен; транскрипты, записи, трейс инструментов |
| Вход | Датчики врут предсказуемо | Речь врёт структурно: имена, индексы, номера, почта |
| Тестирование | Незнакомый игрок ломает сценарий | Сложный звонящий ломает сценарий |
| Релиз | Магазин приложений, ревью, откат | Операторы, A2P, согласие на запись, privacy |
Если вы переходите
Стек добирается за недели. Дольше всего люди учатся не промптам, а интуиции по задержке, дизайну состояний, терпимости к ненадёжному входу, состязательному тестированию и релизной дисциплине. У игрового разработчика это уже есть.
- Сразу закладывайте наблюдаемость: транскрипт, запись, данные после звонка, трейс вызовов. Без этого первый сложный баг станет нераскручиваемым.
- Определите худший допустимый хвост задержки и мерьте его, а не среднее.
- Вынесите всё, что должно быть правильным, в детерминированный код после звонка: запись в CRM, уведомления, письма.
- Пишите выходы из сценария до счастливого пути. Особенно аварийный.
- Тестируйте на звонках, которые ломаются: перебивания, два факта сразу, молчание, вопрос не по теме.
Если ждать, что модель будет вести себя как движок — предсказуемо и с changelog, — будет больно. Если строить агента как тонкую обёртку над промптом и не закладывать наблюдаемость и детерминированный выход, опыт в реальном времени не спасёт. Он даёт привычки, но не заменяет архитектуру.
Стек меняется за недели. Привычка мерить худший кадр, а не средний, и писать выходы раньше входа остаётся. В голосовых агентах она стоит дороже, чем знание Unity.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.