Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 39)
Даже идеально сбалансированный по латентности конвейер упирается в узкое место, если несколько стадий конкурируют за один сериализованный ресурс: общий инструмент с лимитом запросов, единый writer состояния (см. главу 41), внешний API с квотой, один человек-аппрувер на стадии одобрения. Такой ресурс сериализует поток независимо от того, насколько параллельны сами стадии. Классический случай — стадия одобрения человеком: сколь угодно быстрый конвейер, упирающийся в одного оператора, который физически просматривает один артефакт за раз, имеет пропускную способность этого оператора и никакую больше (см. главу 96 об усталости оператора). Узкое место конвейера часто лежит не внутри агентной стадии, а на разделяемом ресурсе, к которому стадии обращаются, — и эту точку нужно искать отдельно от анализа латентности стадий.
Падение одной стадии в чистом линейном конвейере останавливает весь поток — конвейер настолько надёжен, насколько надёжна его наименее надёжная стадия, перемноженная по цепочке. Если каждая из шести стадий доступна с вероятностью порядка 0,99, конвейер целиком доступен с вероятностью порядка 0,94 — заметно хуже любой отдельной стадии. Это произведение надёжностей — структурная плата за последовательность.
Конвейер защищают теми же средствами, что и любую распределённую цепочку (детально — главы 70–72): тайм-аут на каждую стадию, чтобы зависшая стадия не блокировала поток бесконечно; повтор стадии при сбое — но только если стадия идемпотентна (см. главу 43), иначе повтор продублирует побочные эффекты; и сохранение промежуточного артефакта на каждой границе, чтобы при отказе стадии можно было перезапустить её с входа, а не гнать поток с самого начала. Последнее — checkpoint на границах стадий — для агентного конвейера особенно ценно: переделка стадии стоит токенов, и возможность возобновиться с последней успешной границы напрямую экономит деньги. Конвейер без сохранения промежуточных артефактов при любом сбое теряет всю оплаченную работу до точки отказа.
Два отказа возникают на стыке устойчивости и семантики доставки (см. главу 29). Первый: если стадия имеет побочный эффект (записала в БД, отправила во внешнюю систему, потратила квоту) и её повторили после неясного сбоя, побочный эффект может продублироваться. Защита — идемпотентность стадии и ключи идемпотентности на границах. Второй: при репликации стадии или при асинхронной передаче между стадиями элементы потока могут прийти на следующую стадию не в том порядке, в каком вышли с предыдущей. Если последующая стадия зависит от порядка (например, собирает разделы документа по номерам), нарушение порядка испортит сборку. Защита — либо явная нумерация элементов и пересортировка на входе порядко-зависимой стадии, либо отказ от репликации порядко-зависимых стадий вовсе.
Перечисленные отказы объединяет то, что без приборного учёта по стадиям их нельзя ни обнаружить, ни локализовать. Конвейер требует наблюдаемости иного рода, чем один агент (детально — часть XI): измерять нужно не систему целиком, а каждую границу. Минимальный набор того, что регистрируется на стыках:
— Латентность каждой стадии — без неё узкое место находят гадая, а не измеряя.
— Длина очереди перед каждой стадией — растущая очередь сигнализирует о приближающемся переполнении и указывает на узкое место раньше, чем оно станет отказом.
— Размер артефакта на каждой границе — внезапный рост или схлопывание артефакта между стадиями часто и есть видимый след дрейфа или потери контекста.
— Идентификатор исходной задачи на всём пути — сквозной task_id позволяет восстановить траекторию одного элемента через все стадии и связать финальный артефакт с исходной постановкой (трассировка, см. главу 77).
— Результат валидатора на каждой границе — отклонения валидатором локализуют, какая именно стадия начала производить артефакты вне контракта.
Без сквозного идентификатора ретроспективный разбор конвейерного инцидента (см. главу 82) сводится к угадыванию, на какой стадии всё пошло не так; с ним — к чтению трассы. Это делает сквозную идентификацию элемента не удобством, а условием отлаживаемости конвейера.
Конвейер — не универсальная топология, и значительная часть его failure modes возникает оттого, что его применяют там, где он не подходит. Решение применять конвейер — это решение принять его налог: передачи контекста, накопление дрейфа, произведение надёжностей и латентность длины цепочки.
Конвейер оправдан, когда выполняется большинство условий:
— Задача естественно разбивается на фазы с ясными границами, и эти фазы качественно разные (исследование — это не то же, что ревью), так что специализация стадий даёт реальную выгоду.
— Есть поток однотипных задач, а не единственная задача, — тогда конвейерный параллелизм окупает передачи.
— Границы между фазами можно оформить проверяемой схемой, а не только свободным текстом, — иначе дрейф съест выигрыш специализации.
— Промежуточные артефакты имеет смысл сохранять (для возобновления, аудита, переиспользования).
Конвейер вреден или избыточен, когда:
— Задача единственная и не повторяется — тогда конвейер добавляет латентность и дрейф, не давая параллелизма; один агент, проходящий фазы по очереди, проще и часто точнее, потому что не теряет контекст на границах.
— Фазы сильно связаны и плохо разделяются — искусственное разрезание сильносвязанной задачи на стадии порождает толстые, хрупкие границы, через которые приходится протаскивать почти весь контекст, и выгода специализации обнуляется стоимостью передачи.
— Задача требует глобального взгляда на каждом шаге, который нельзя локализовать в одной стадии, — конвейер по построению даёт каждой стадии только локальный срез, и задачи, где каждое решение зависит от всего сразу, ему противопоказаны.
— Стоимость дрейфа критична, а проверяемой схемы на границах построить нельзя — например, тонкая стилистическая или смысловая работа, где «почти то же самое» означает «не то».
Сравнение с соседними топологиями помогает выбрать осознанно.
Свойство | Конвейер | Оркестратор и воркеры (гл. 8) | Иерархия (гл. 9)
Тип разбиения | По фазам (последовательно) | По данным (параллельно) | По уровням делегирования
Ускоряет одну задачу | Нет | Да (с поправкой Амдала) | Частично
Ускоряет поток задач | Да (pipelining) | Да | Зависит от структуры
Распространение ошибки | Вниз по цепочке, аккумулируется | Изолируется по воркерам | Вверх и вниз по дереву
Главный риск | Дрейф и узкое место | Сборка и согласование | Глубина и потеря контекста при делегировании
Где живёт контекст задачи | В проходящем артефакте | У оркестратора | У родителя
Эти топологии не исключают друг друга. Реальные системы — гибриды (см. главу 14): конвейер, одна из стадий которого внутри устроена как fan-out; иерархия, где лист — это короткий конвейер; конвейер с обратной связью, образующий цикл ревью. Чистый конвейер — это базовая форма для рассуждения, а не предписание строить системы строго линейными.
Сведём ключевые архитектурные развилки конвейера и цену каждого выбора — это и есть предмет инженерного решения при проектировании.
Модель данных: потоковая или накопительная. Потоковая экономит токены и изолирует стадии, но теряет контекст и ускоряет дрейф. Накопительная сохраняет контекст, но раздувает его линейно с числом стадий и переносит ранние ошибки во все поздние. Распространённый компромисс — передавать стабильное ядро (исходная задача плюс ключевые артефакты) накопительно, а рабочие черновики — потоково.
Глубина конвейера. Каждая стадия добавляет специализацию, но и границу: латентность передачи, точку дрейфа, множитель в произведении надёжностей. Глубокий конвейер — не признак зрелости, а накопленная стоимость. Правило: минимальное число стадий, при котором фазы остаются качественно разными.
Жёсткость границ. Свободный текст на границе дёшев в разработке и дорог в эксплуатации (дрейф, отсутствие валидации). Строгая схема дорога в разработке и дёшева в эксплуатации. Для долгоживущего конвейера в production схема почти всегда окупается.
Обратная связь. Циклы ревью-правка повышают качество, но вводят риск незавершения. Любой цикл обязан иметь предел итераций и поведение по умолчанию при его достижении (принять как есть либо эскалировать). Цикл без предела — это спроектированный livelock.
Размещение проверок. Проверка в конце ловит дрейф, но дорого — после того, как ошибка прошла весь конвейер. Проверка на каждой границе дороже в сумме, но ловит ошибку у источника, где откат дешевле. Для конвейеров с дорогими поздними стадиями ранняя проверка окупается.
Checkpoint на границах. Сохранение промежуточных артефактов стоит хранилища и усложняет систему, но превращает отказ стадии из «переделать весь конвейер» в «возобновить с последней границы». Для агентного конвейера, где переделка измеряется в деньгах за токены, это решение почти всегда в пользу сохранения.
— Конвейер разбивает задачу по фазам, а не по данным: добавление стадий не ускоряет отдельную задачу, а удлиняет её путь; выигрыш конвейерного параллелизма проявляется только на потоке однотипных задач и ограничен самой медленной стадией.