На каждой технической конференции в последнее время обязательно звучит слово «агенты». Они преподносятся по разному: и как следующая ступенька после RAG, и как серебряная пуля для всех проблем, и как абсолютная замена всех классических пайплайнов. А кто еще не использует агентов — безнадежно отстал от прогресса.
Но так ли это на самом деле? Данная статья вдохновлена видением компании Anthropic на применение LLM в процессах и на построение агентов, поэтому давайте попробуем во всем разобраться.
Поговорим про Data Pipelines, LLM Workflows и LLM Agents, а так же сравним их между собой.
Антропиков читать нужно всегда, потому что компания находится на переднем крае развития LLM и часто своими техрепортами задает вектор развития всей индустрии вообще.
Сейчас есть некоторая путаница в определении «агентов». Кто-то называет агентами только полностью автономные системы, работающие самостоятельно длительное время и использующие внешние инструменты выполнения задач. Кто-то называет просто последовательный вызов LLM с разными промптами, а если очень нужна модная строчка в резюме и новые палки на погоны, то агентом становится вообще любой процесс, куда варварским способом воткнули LLMку и которая там вообще изначально была не нужна.
Anthropic выделяет два основных архитектурных подхода:
Workflows (рабочие процессы) — подходы, где LLM и инструменты используются и оркестрируются предопределенными способами
Agents (агенты) — подходы, где LLM динамически управляют собственными процессами и использованием инструментов
Так как эта статья не является просто переводом, а неким более общим сравнением, то я к этому добавлю еще один англицизм Data Pipelines, который в своём чистом значении не совсем идеально вписывается в компанию терминов выше, но здесь будет неким обобщением привычных нам классических алгоритмов и процессов, в которых вообще нет LLM.
При разработке приложений всегда надо искать максимально простое и надежное решение, и увеличивать сложность только при необходимости. «Простота» здесь означает предсказуемое поведение, низкое потребление ресурсов, хорошую управляемость и поддерживаемость процесса. А это автоматически делает неуместным использование агентов, чтобы под ними не подразумевалось.
Агентные системы в определенных ситуациях работают лучше, но они медленнее и дороже. Поэтому важно понять, действительно ли нужна такая сложность — агенты лучше справляются только там, где нужно адаптировать свое поведение и гибко подстраиваться под ситуацию.
Небольшой пример:
Возьмем типичный процесс в ритейле: каждый час собираем данные с касс, считаем выручку по категориям, ищем аномалии и шлем отчет. Можно ли сюда добавить LLM-агента для «умного» анализа причин и написания рекомендаций? Конечно. Но нужно ли это? Это хороший вопрос, у которого, как говорится, большой trade-off между стоимостью, ответственностью, работой ради работы и здравым смыслом.
Не стоит от агентов и LLM в целом ожидать моментального решения всех задач, это — инструменты. Агент LLM придет и порядок наведет — это миф, который никак не избавляет от качественной работы с вашими данными. Потому что иначе будет как в меме:
А еще есть важный момент.
Как только в нашей цепочке вообще появляется LLM – неважно какая: дистиллированная или квантизованная, специализированная или нет – в эту цепочку сразу же требуется добавлять механизмы защиты (то, что называют guardrails) на вход и выход, потому что из модели может вылететь то, чего нам не хотелось бы. И хорошо, если это будет просто галлюцинация, а не слив чужой персухи или странных предоставлений о прекрасном из чужого претрейна.
Приведу таблицу сравнения трех подходов (без LLM, с LLM и агенты) и оптимальные места их применения. А после — будет по большей части авторский (не дословный) перевод видения антропиков на архитектуры с использованием LLM.
Характеристика | Data Pipelines | LLM Workflows | LLM Agents |
---|---|---|---|
Поток выполнения | Предопределённый и линейный | Предопределённые шаги с возможными условиями | Динамический, определяется самой моделью |
Принятие решений | На основе жёстких правил и условий | На основе предопределённых правил и LLM | Автономное, на основе контекста и цели |
Обработка ошибок | Очереди, ретраи, try/catch | Предопределённые обработчики ошибок | Самостоятельное восстановление и поиск альтернативных путей |
Масштабирование | Горизонтальное, через параллелизм | Вертикальное (более мощные модели) и горизонтальное | Преимущественно вертикальное (улучшение способностей агента) |
Мониторинг | Метрики производительности | Метрики качества ответов, время выполнения шагов | Метрики автономности, качества решений, использования ресурсов |
Предсказуемость | Высочайшая | Средняя | Низкая |
Гибкость | Низкая (требует переписывания при изменении) | Средняя (в рамках предопределённых шагов) | Высокая (может адаптироваться к новым ситуациям) |
Использование ресурсов | Предсказуемое, заданное | Умеренное, зависит от сложности шагов | Высокое, непредсказуемое |
Сложность разработки | Любая, зависит от задачи | Средняя или высокая | Высокая |
Отладка | Прямолинейная, обычный анализ логов | Возможна на каждом шаге | Сложная, требует специальных инструментов |
Время разработки | Среднее | Высокое | Очень высокое |
Требования к данным | Структурированные | Структурированные + частично неструктурированные | Любые типы данных |
Автономность | Нет | Частичная | Высокая |
Стоимость в работе | Низкая до средней | Средняя | Очень высокая |
Скорость разработки | Быстрая для стандартных задач | Средняя | Медленная |
Переиспользование в других задачах | Низкое в целом, высокое для схожих задач | Среднее | Низкое (требует адаптации) |
Документация | Стандартная техническая | Требует описания шагов и промптов | Требует детального описания возможностей и ограничений |
Тестирование | Любые тесты | Unit tests + тесты промптов | Сложное тестирование поведения |
Версионирование | Стандартное (код + конфиги) | Код + промпты + модели | Сложное (включая версии знаний) |
Data Pipelines:
ETL процессы
Обработка больших объемов структурированных данных
Регулярные, повторяющиеся задачи
Критичные к производительности процессы
Критичные к предсказуемости и безопасности процессы
LLM Workflows:
Структурированные задачи с элементами NLP
Процессы с предсказуемыми шагами, но требующие более сложного понимания контекста на каком-либо из них
Задачи, где важен баланс между автоматизацией и контролем
Процессы с четкими правилами и ограничениями
LLM Agents:
Сложные задачи, требующие принятия самостоятельных решений
Исследовательские задачи
Задачи с неопределенным количеством шагов и автономностью в них
Процессы, требующие адаптации к новым ситуациям
Ну а далее передаю слово Anthropic с моей легкой адаптацией.
Существует множество фреймворков, которые упрощают реализацию агентных систем, включая:
LangGraph от LangChain;
AI Agent фреймворк от Amazon Bedrock;
Rivet — конструктор LLM-процессов с графическим интерфейсом;
Vellum — инструмент с графическим интерфейсом для создания и тестирования сложных рабочих процессов.
Эти фреймворки облегчают старт, упрощая стандартные низкоуровневые задачи, такие как вызов LLM, вызов дополнительных инструментов и объединение вызовов в цепочки. Однако фреймворки часто создают дополнительные слои абстракции, которые могут скрывать базовые промпты и ответы, усложняя отладку. Они также могут подталкивать к добавлению сложности там, где хватило бы более простого решения.
Важная рекомендация — начинать с прямого использования LLM API: многие штуки можно реализовать всего несколькими строками кода. Но если вы что-то начали использовать, то стоит понимать глубже как оно работает, так как неправильные предположения о том, что происходит под капотом фреймворка — частая причина ошибок и отсутствия ожидаемого результата работы.
Переходим непосредственно к разбору архитектур, которые предлагают нам исследователи, начиная с простых и заканчивая всеми любимыми агентами.
Основным строительным блоком агентных систем является LLM, дополненная такими расширениями, как поиск, инструменты и память.
В идеале, чтобы эти дополнения были сразу встроенные у нужной модели (так пишут в оригинале), но, в принципе, ничего не мешает сделать их на нашей стороне, если нужно.
В примерах дальше будем предполагаться, что каждый вызов LLM имеет доступ к этим расширенным возможностям.
В случае базового блока рекомендуется сосредоточиться на двух ключевых аспектах: адаптацию этого блока под свою задачу и обеспечение хорошо задокументированного протокола работы с ним. Сами Anthropic недавно выпустили готовый протокол под такие случаи (Model Context Protocol), который позволяет интегрироваться с общей экосистемой сторонних инструментов.
Подход, в котором задача разбивается на последовательность шагов, в котором каждый вызов LLM обрабатывает выход предыдущего. Для того, чтобы убедиться, что процесс выполняется верно, можно добавить разные проверки (см. «gate» на схеме ниже). Ну и, соответственно, сложность и длина цепочки зависит только от нашей задачи.
Когда использовать цепочку промптов: идеально, когда исходную задачу можно легко и четко разбить на фиксированные подзадачи. Основная цель — пожертвовать скоростью ради повышения точности, поручая LLM в каждом вызове одну простую задачу.
Подход, в котором входные данные сначала классифицируются, а затем отправляются на более заточенный и специализированной под это промпт. То есть, вместо того, чтобы обрабатывать все подряд LLMкой, мы по смыслу разбиваем входные задачи, подготавливаем под каждую свой промпт и затем распределяем куда нужно.
Когда использовать маршрутизацию: роутинг хорошо работает для задач, где есть четкие категории, которые лучше обрабатывать отдельно. Здесь очень критично правильно определить нужную категорию: это можно сделать либо самой LLM, либо по возможности обычными средствами NLP.
Примеры, где маршрутизация полезна:
Разные типы запросов в службу поддержки (общие вопросы, запросы на возврат денег, ипотечные вопросы и так далее)
Направление простых и однозначных вопросов к более легкой LLM, а сложных к более мощной
Несколько LLM иногда могут работать над задачей одновременно, а финальное решение принимается через объединение или агрегацию их ответов.
Собственно, здесь это два подхода:
Разделение: задача разбивается на независимые подзадачи, выполняемые параллельно, а затем все собирается воедино
Голосование: задача выполняется несколькими запросами параллельно, а затем усредняется единый ответ
Когда использовать распараллеливание: подход эффективен, когда задачу можно разрезать и выполнить независимо параллельно, либо когда требуется комплексный ответ. Для сложных задач со множеством аспектов, языковые модели обычно работают лучше тогда, когда каждый аспект обрабатывается отдельным вызовом модели, так как именно он остается в фокусе.
Примеры, где распараллеливание полезно:
Разделение:
Защитные механизмы, где один экземпляр модели обрабатывает запросы пользователей, а другой в это время проверяет его на безопасность
Оценка чего-либо по нескольким разным параметрам одновременно
Голосование:
Проверка кода на уязвимости, где несколько различных запросов с разными промптами проверяют код
Оценка неприемлемого контента, где множественные запросы оценивают различные аспекты или требуют различных пороговых значений голосов для балансировки ложноположительных и ложноотрицательных результатов
В данном подходе LLM динамически разбивает задачи, делегирует их языковым моделям-исполнителям и затем синтезирует их результаты.
Когда использовать оркестрацию: хотя топографически это похоже на распараллеливание, ключевое отличие заключается в его гибкости — подзадачи не предопределены, а определяются оркестратором на основе конкретного входного запроса. Соответственно, это неплохо подходит для сложных задач, где невозможно предсказать необходимые подзадачи во всех случаях.
Примеры, где оркестратор-исполнители полезны:
Написание кода, которое может потребовать изменения в нескольких файлах
Поисковые задачи, включающие сбор и анализ информации из нескольких источников
Подход, в котором ответ LLM отправляется на вход другой LLM и пока они не договорятся между собой, итогового ответа не будет. То есть, ответ первой LLM итеративно улучшается на основе обратной связи (оценки) от второй, пока не достигнет допустимого порогового значения.
Это чем-то отдаленно похоже на GAN, только здесь нет соревнования и никто не пытается никого обмануть и обе роли играют на общий результат с позитивной обратной связью. Гораздо более близкая аналогия — автор и его добрый рецензент.
Примеры, где оценщик-оптимизатор полезен:
Улучшение перевода или написания литературного текста
Сложные поисковые задачи, требующие нескольких раундов поиска и анализа для сбора всесторонней информации, где оценщик решает, нужны ли дальнейшие поиски
Вот мы и добрались до того, что хардкорные ребята и называют агентами.
Агенты получают распространение по мере того, как языковые модели совершенствуются в ключевых возможностях — понимании сложных входных данных, рассуждении и планировании, надёжном использовании инструментов и восстановлении после ошибок. Агенты начинают свою работу либо с готовой команды от человека-пользователя, либо с интерактивного обсуждения задачи с ним. Когда задача становится понятной, агенты планируют и действуют самостоятельно, при необходимости обращаясь к человеку за дополнительной информацией.
Во время выполнения для агентов критически важно получать «истинное положение дел» из окружающей среды на каждом шаге (например, результаты вызова инструментов или выполнения кода) для оценки своего прогресса. Затем агенты могут приостанавливаться для получения обратной связи от человека на контрольных точках или при столкновении с препятствиями. Остановкой работы является либо успешное завершение задачи, либо определенное число неуспешных попыток эту задачу решить.
Технически агентская схема на основе LLM выглядит так: это языковые модели, работающие в цикле с инструментами и получающие обратную связь от окружающей среды. Однако успешное и безопасное внедрение требует регулярного внимания к деталям и глубокого понимания и проработки многих аспектов: от проектирования защиты и предотвращения утечек данных до создания механизмов мониторинга, логирования и экстренной остановки.
И потому кажущаяся простота базовой реализации на самом деле скрывает за собой вагон проблем — как, собственно, и всегда.
Когда использовать агентов: агентов стоит использоваться для открытых задач, где сложно или невозможно предсказать необходимое количество шагов, и где нельзя жёстко зафиксировать последовательность шагов. Языковая модель потенциально будет работать в течение многих итераций, и вы должны иметь определённый уровень доверия к её принятию решений. Автономность агентов делает их идеальными для масштабирования задач в доверенных средах.
Автономная природа агентов означает более высокие затраты и возможность накопления ошибок, поэтому рекомендуется использовать и тестировать их сначала в закрытом контуре со всей возможной защитой.
Примеры, где агенты полезны:
Агент для программирования, который может вносить необходимые правки в большое количество файлов
Фича с «использованием компьютера», когда агенту доступ к компьютеру и задачу, а дальше он сам пытается найти решение поставленной задачи
Все данные подходы являются лишь попыткой систематизации архитектур с LLM и не предполагают того, что это легко решит поставленную задачу. В реальной жизни часто встречаются комбинации подходов и что-то хорошо работающее появляется только при итеративном и регулярном улучшении заданных нами метрик.
И да, авторы очень расстраиваются, когда что-то простое пытаются решить более сложными способами.
Успех заключается не в создании самой сложной системы. Успех заключается в создании правильной системы для решения нашей задачи. Агенты не нужны там, где можно справиться без них. LLM не нужны там, где можно справиться без них.
Начинаем с простого и постепенно улучшаемся, добавляя новые уровни сложности только тогда, когда это уместно и когда простые решения вот точно не справляются.
А вот три главных принципа при построении агентов:
Поддерживать простоту в архитектурном дизайне вашего агента
Отдавать приоритет прозрачности, явно показывая шаги планирования агента
Тщательно прорабатывать интерфейс взаимодействия агента, основательно все документируя и тестируя результат
Фреймворки могут помочь быстро начать, но для прод-решения стоит сделать все более низкоуровнево и в этом нет ничего плохого, так как позволит получить большую управляемость и прозрачность.
В оригинале статьи есть еще два практических примера агентов у самих авторов: это агент клиентской поддержки, неплохо справляющийся с обращениями, и агент для написания кода, а также дополнительная рекомендация тщательнее продумывать интерфейсы агентов и чаще их тестировать.
И пользуясь случаем, хочется закончить шутеечкой, сказав дополнительное спасибо компании Anthropic, что позволила придумать моё фамильное лого (см. мою фамилию в нике).
Спасибо!