|
Professor Seleznov
|
Представьте внутреннего AI-агента, который помогает компании искать общие документы и управлять ими. Он работает. До тех пор, пока 12–15% запросов не начинают падать. Агент возвращает не тот документ, редактирует не тот файл, молча падает или уверенно ссылается на файл, которого не существует. Поиск по фото отказывает с той же частотой. Ошибки размазаны равномерно по пользователям, фичам и запросам. Первое инстинктивное действие — поменять модель. Opus 4.5, GPT 5.5 или что там сейчас в топе лидерборда. Меняете. Счет за инференс растет в 4–5 раз, а общая доля ошибок снижается с 12% до 9%. Пользователи пишут о тех же проблемах. Бюджет следующего квартала сгорает за пару недель ради улучшения в 3 процентных пункта — и вы по-прежнему не понимаете, что именно было не так в системе и как улучшать ее дальше. Эта статья — о том, почему смена модели обычно разочаровывает и куда стоит смотреть в первую очередь. Большинство сбоев AI-систем живет в слое обвязки — orchestration, retrieval, tool definitions, retries, context management, — а не в самой модели. Дальше — метод, как отличить проблемы обвязки от проблем модели, кейс, в котором одно исправление в обвязке подняло completion rate с 26% до 88% без смены модели, и чек-лист, который поможет найти такие сбои в вашей собственной системе. Если вы никогда не делали подобной диагностики — вероятнее всего, вы обнаружите хотя бы одну проблему, которую стоит починить. Почему «слабая модель» — обычно ложный диагноз В AI-системах модели живут внутри обвязки. Общая производительность системы складывается мультипликативно из производительности модели и обвязки вокруг нее. Сильная обвязка + слабая модель часто побеждает слабую обвязку + передовую модель — пока вы не упретесь в потолок возможностей модели. В обвязку AI-агента входят: слой оркестрации, ретраи (к провайдеру API и во внутренних рутинах обвязки), retrieval, описания инструментов, менеджмент контекста, валидация вывода. Далеко не только промпт-инжениринг. Хотя обвязка критична, есть три сигнала, что узкое место — действительно модель:
- Ошибки не сдвигаются при итерации промпта, ретраях или смене механизмов retrieval (например, многошаговый retrieval с постепенным ослаблением строгости).
- Характер ошибки указывает на известный capability gap (например, планирование на большом горизонте, глубокое рассуждение в узкой нише).
- Контролируемый A/B-тест между моделями на одной обвязке показывает явное улучшение.
И три сигнала, что дело в обвязке:
- Ошибки кластеризуются вокруг конкретных инструментов / сценариев / состояний.
- Поведение ретраев делает ошибки менее наблюдаемыми и склонно маскировать их.
- Та же модель на другой обвязке показывает существенно отличающиеся результаты на тех же входных данных.
Где ломается обвязка Дальше — диагностический чек-лист. Прогоните по нему свою систему. Примерно в 8 из 10 продакшен-AI-систем, с которыми я работал, сбой принадлежал одной из этих категорий . Если вам удастся обнаружить его здесь — фикс будет стоить N часов инженерного времени, а не удвоенного счета за инференс.
- Оркестрация, поток управления:
- Agent loop не знает, когда остановиться.
- Плохие или отсутствующие терминальные условия.
- Рекурсия в вызовах инструментов.
- Ретраи и обработка ошибок:
- Тихие ретраи, не информирующие остальную систему.
- Ретраи на неретраябельных операциях.
- Нет различия между transient ошибками и структурными ошибками.
- Retrieval:
- Неправильно настроенный баланс между релевантностью и точностью.
- Чанки, смешивающие несвязанный контент.
- Нет реранкинга.
- Загрязнение контекста между ходами.
- Описания инструментов:
- Описания, которые модель читает неверно.
- Пересекающаяся семантика / ответственность инструментов.
- Недоспецифицированные параметры.
- Отсутствующие примеры использования.
- Управление контекстом:
- Нет стратегии сжатия контекста (compact).
- Накопление шума между ходами.
- Утечка контекста между сессиями.
- Валидация вывода:
- Отсутствующая или плохая проверка структурированного вывода.
- Тихие падения парсеров на валидации.
Кейс из продакшена Выше я изложил таксономию. Теперь — кейс из Kismet — AI-агента, которого я разрабатываю для автоматизации генерации кода на визуальном скриптом языке Unreal Engine (Blueprints), а также Material и Niagara-графов. Разберу один кейс подробно. Ландшафт сбоев меняется от системы к системе.

Небольшой Blueprint-граф в Unreal Engine — домен вывода агента. Типизированные пины, узлы потока управления (здесь — Switch on E_SpawnTeam) и попарные соединения пинов — то, что агент должен порождать и о чем рассуждать. Примечание: проценты из текста ниже взяты из внутренних eval-прогонов Kismet на внутреннем бенчмарке. Они могут не обобщаться на другие AI-системы. Дрейф состояния графа на длинных Blueprint-задачах Симптом. На сложных Blueprint-задачах за пределами ~15–20 операций над нодами completion rate обрушивался. Агент пересоздавал ноды, которые уже создал, пытался соединять пины на несуществующих нодах или объявлял задачу выполненной, когда ключевые соединения flow-control отсутствовали. Первая гипотеза. Лимит рабочего контекста. Модель не вытягивает контекст такого размера — со всеми инструментами, системными промптами, transient выводами тулзов, discovery-итерациями. Пробовал более длинные контекстные окна. Пробовал compact (суммаризацию) в середине. Доля ошибок практически не сдвинулась. Что было на самом деле. Представление модели о Blueprint-графе было trace'ом тулзовых вызовов, а не актуальным состоянием графа. Когда тулзовый вызов отрабатывал частично, когда побочный эффект модификации графа выглядел не так, как модель предсказала, или когда слой ретраев что-то менял, расхождение накапливалось ход за ходом. К 20-му ходу модель планировала, основываясь на представлении о сильно измененном графе, который больше не соответствовал реальности.
 Более сильная модель не помогала, потому что вход на каждом шаге был неправильный. Модель рассуждала корректно — но из испорченного состояния. Фикс. Перед каждым ходом агента я начал инжектить актуальное структурированное состояние графа. Модель планирует из наблюдаемого состояния, а не пытается удерживать намерение в течение 20–30 ходов. Этот фикс не зависит от того, насколько умна модель. Стоит примерно 330 дополнительных токенов за ход (медиана на задачах средней сложности во внутреннем eval-бенчмарке). Это кардинально изменило производительность. Итог. Completion rate на длинных задачах вырос с 26.3% до 87.9%. Ошибки пересоздания нод упали почти до нуля. Галлюцинации пинов и соединений — почти до нуля. Задачи, которые раньше требовали 30+ ходов (большую часть которых агент тратил на восстановление после операций по воображаемому графу), теперь решаются за медианные 7 ходов на задачах средней сложности.
 Этот же тип сбоя проявился в других частях системы. Инструмент connect_pins (формирующий соединения между логическими нодами и собирающий поток выполнения по графу) принимал типы пинов как произвольные строки. Модель могла выдавать «Boolean», «Bool», «bool» вперемешку. Все проходили валидацию; вытекающие type mismatch'и всплывали только на ручном ревью. Система типов Blueprints в UE не согласует именования между семействами узлов, что создает реальную сложность для валидации. Фикс был очевидным — перестать доверять выведенному контракту, отдавать модели на следующем ходе актуальное состояние типов и ограничений, позволить ей самой себя корректировать. В обоих описанных сбоях смена модели потратила бы бюджет инференса ради в лучшем случае небольшого улучшения. Реальные исправления стоят практически ничего в инференсе и специфичны для обвязки. Паттерн: везде, где ваша обвязка stateful — граф, типы, окружение, ретривал, ранжирование — и модель вынуждена выводить, а не наблюдать, у вас появляется кандидат на новый источник ошибок. Большинство таких сбоев проявятся только на масштабе или в экзотических условиях. И все они будут выглядеть как «модель не справляется». Или просто как шум, пока вы не присмотритесь. Замечание перед началом диагностики Перед списком действий — небольшая ремарка про подход к разработке. Все в этой статье предполагает, что у вас есть система, работающая на сильной модели, и вы пытаетесь сделать ее дешевле или надежнее. Когда вы запускаете что-то по-настоящему сложное — берите самую сильную модель, какую можете себе позволить, докажите, что задача в принципе решаема end-to-end, и только потом занижайте модель. Если идти обратным путем — стартовать на дешевой и наращивать, если не работает, — это ловушка. Вы тратите дни, не понимая: это баг обвязки или потолок возможностей модели. Если передовая модель не решает вашу задачу — более слабая не поможет, сколько ни вкладывай в обвязку. Что попробовать до смены модели Большинство шагов ниже стоит пару часов инженерного времени и ноль дополнительной стоимости инференса.
- Логируйте каждый тулзовый вызов, ретрай и терминальное состояние. Если не можете воспроизвести сбой — не сможете и найти проблему.
- В политике ретраев разделите transient ошибки и структурные ошибки.
- Измерьте точность retrieval на маленьком размеченном наборе, прежде чем винить генерацию во всех своих бедах.
- Тестируйте каждое описание инструмента изолированно.
- Добавьте возможность агенту отвечать «не знаю». Это валидный ответ, который большинство обвязок запрещают.
- Зафиксируйте размер контекста. Измерьте качество в строгом контекстном лимите.
- Валидируйте структурированный вывод. Ошибки должны быть verbose. Прокидывайте ошибки обратно агенту на следующий ход.
- Поменяйте модель на следующий тир на той же обвязке. Если разрыв в метриках небольшой — узкое место в обвязке.
Без раздельного наблюдения вы ничего из этого не увидите Каждый шаг чек-листа предполагает, что вы локализуете источники сбоев. Большинство команд этого не делает. У них одна end-to-end метрика — success rate, стоимость токенов и немного продуктовых метрик типа удовлетворенности пользователей (вайбы). Когда эти метрики меняются, обвязка и модель неразличимы. Решение — покомпонентные тесты и эвалы. Критически важно изолировать каждый слой обвязки. Заключение После всего сказанного, смена модели — последнее, что стоит пробовать (если вы изначально стартовали на достаточно сильной модели). Если нет — берите самую способную, какую можете себе позволить, докажите, что задача решаема, и только потом занижайте модель, чтобы оптимизировать счет за инференс. Основной рычаг, которым вы можете влиять на производительность, — обвязка, а не модель.-Источник
|