Skip to main content

Топологии инструментов

Сегодня большинство систем чатботов полагаются на выполнение одного инструмента без планирования. Это имеет смысл: это проще реализовать и имеет меньшую задержку. Если ваша команда разрабатывает свою первую агентную систему, или если этого достаточно для удовлетворения потребностей вашего сценария, то вы можете остановиться после следующего раздела "Выполнение одного инструмента". Однако для многих случаев мы хотим, чтобы наши агенты могли выполнять сложные задачи, требующие множественных инструментов.

Предоставляя агенту достаточный диапазон инструментов, вы можете затем позволить вашему агенту гибко располагать эти инструменты и применять их в правильном порядке для решения более широкого разнообразия проблем. В традиционной разработке программного обеспечения дизайнеры должны были реализовать точный поток управления и порядок, в котором должны выполняться шаги. Теперь мы можем реализовать инструменты и определить топологию инструментов, в которой агент может работать, а затем позволить точной композиции быть спроектированной динамически в ответ на контекст и задачу под рукой.

Выполнение одного инструмента (Single Tool Execution)

Начнем с задач, которые требуют ровно одного инструмента. В этом случае планирование состоит из выбора одного инструмента, наиболее подходящего для решения задачи. Как только инструмент выбран, он должен быть правильно параметризован на основе определения инструмента. Инструмент затем выполняется, и его выход используется как вход при составлении окончательного ответа для пользователя.

Хотя это минимальное определение плана, это основа, на которой мы построим более сложные паттерны.

Рабочий процесс:

  1. Пользовательский запрос передается модели
  2. Модель выбирает подходящий инструмент из набора инструментов
  3. Модель получает выход инструмента
  4. Модель составляет окончательный ответ для пользователя

Хотя этот паттерн выполнения одного инструмента прост, он формирует основу, на которой строятся более сложные стратегии многошагового планирования и оркестрации инструментов в продвинутых агентных системах.

Параллельное выполнение инструментов (Parallel Tool Execution)

Первое увеличение сложности приходит с параллелизмом инструментов. В некоторых случаях может быть стоит предпринять множественные действия на входе. Например, представьте, что вам нужно найти запись для пациента. Если ваш набор инструментов включает множественные инструменты, которые обращаются к множественным источникам данных, то будет необходимо выполнить множественные действия для получения данных из каждого из источников.

Подход:

  1. Извлечь максимальное число инструментов, которые могут быть выполнены — скажем, пять — используя семантический выбор инструментов.
  2. Сделать второй вызов базовой модели с каждым из этих пяти инструментов и попросить её выбрать пять или меньше инструментов, которые необходимы для проблемы, фильтруя до инструментов, необходимых для задачи.
  3. Аналогично, базовая модель может вызываться повторно с дополнительным контекстом того, какие инструменты уже были выбраны, пока она не решит не добавлять больше инструментов.
  4. Как только выбраны, эти инструменты независимо параметризуются и выполняются.
  5. После того, как все инструменты завершены, их результаты передаются базовой модели для составления окончательного ответа для пользователя.

Этот паттерн параллельного выполнения инструментов позволяет агентам эффективно собирать всестороннюю информацию из множественных источников за один шаг. Интегрируя эти результаты перед составлением ответа, агент может предоставить более богатые, более информированные выходы, минимизируя общую задержку.

Цепочки (Chains)

Следующее увеличение сложности приводит нас к цепочкам. Цепочки относятся к последовательностям действий, которые выполняются одно за другим, где каждое действие зависит от успешного завершения предыдущего. Планирование цепочек включает определение порядка, в котором должны выполняться действия для достижения конкретной цели, обеспечивая, чтобы каждое действие вело к следующему без прерывания. Цепочки распространены в задачах, которые включают пошаговые процессы или линейные рабочие процессы.

К счастью, LangChain предлагает декларативный синтаксис, Язык выражений LangChain (LCEL), для построения цепочек путем композиции существующих Runnables, а не ручного подключения объектов Chain. Под капотом LCEL обрабатывает каждую цепочку как Runnable, реализующий тот же интерфейс, поэтому вы можете вызвать invoke(), batch() или stream() любую LCEL цепочку так же, как любой другой Runnable.

Преимущества цепочек:

  • Уменьшение шаблонного кода
  • Продвинутые функции выполнения
  • Краткие и поддерживаемые цепочки

Планирование цепочек требует тщательного рассмотрения зависимостей между действиями, стремясь оркестрировать связный поток активности к желаемому результату. Настоятельно рекомендуется установить максимальную длину для цепочек инструментов, поскольку ошибки могут накапливаться по длине цепочки. Пока задача не ожидается разветвляться на множественные ветвящиеся подзадачи, цепочки обеспечивают отличный компромисс между добавлением планирования для множественных инструментов с зависимостями и поддержанием относительно низкой сложности.

Графы (Graphs)

Для сценариев поддержки с множественными точками принятия решений топология графа моделирует сложные, неиерархические потоки гораздо более выразительно, чем цепочки или деревья. В отличие от линейных цепочек или строго ветвящихся деревьев, структуры графов позволяют вам определять как условные ребра, так и ребра консолидации, так что параллельные пути могут объединяться обратно в общие узлы.

Каждый узел в графе представляет дискретный вызов инструмента (или логический шаг), в то время как ребра — включая add_conditional_edges — объявляют точные условия, при которых агент может переходить между шагами. Консолидируя выходы из множественных ветвей в один нижестоящий узел (например, summarize_response), вы можете сшить вместе находки из отдельных обработчиков в единый ответ клиенту.

Однако полное выполнение графа обычно влечет значительно больше вызовов базовой модели, чем цепочки — добавляя задержку и стоимость — поэтому критично ограничить глубину и фактор ветвления. Кроме того, циклы, недостижимые узлы или конфликтующие слияния состояний вводят новые классы ошибок, которые должны управляться через строгую валидацию и тестирование.

Пример реализации в LangGraph:

  1. Определения узлов: Каждый узел представляет функцию, которая обрабатывает состояние и возвращает обновленное состояние.
  2. Построение графа: Создание StateGraph, добавление узлов и ребер, определение условных переходов.
  3. Выполнение графа: Запуск графа с начальным состоянием и максимальной глубиной.

Графы предлагают максимальную гибкость для моделирования сложных, нелинейных рабочих процессов — позволяя вам ветвиться, объединяться и консолидировать множественные выполнения инструментов в единый процесс. Однако эта выразительность приходит с добавленными накладными расходами: больше вызовов LLM, более глубокая логика маршрутизации и потенциал для циклов или недостижимых путей.

Рекомендации:

  • Начните с цепочки, если ваша задача строго линейна
  • Примите граф только когда вы должны и ветвиться, и позже консолидировать множественные потоки информации
  • На практике сначала набросайте вашу топологию на бумаге
  • Реализуйте инкрементально — ограничьте глубину и фактор ветвления
  • Напишите модульные тесты для каждого маршрутизатора
  • Используйте встроенную трассировку LangGraph для валидации

Выше всего, держите это как можно проще. Каждый дополнительный узел или ребро умножает потенциальные пути выполнения и режимы ошибок. Если более простая цепочка или дерево удовлетворяет вашим потребностям, сохраните паттерны графов для подлинно сложных сценариев.