Команда Spring АйО перевела статью, в которой рассказывается про разработку эффективных агентов с помощью Spring AI. Исследование Anthropic "Building effective agents" подчеркивает важность простоты и модульности в разработке LLM-агентов.

В статье рассматривается, как эти принципы реализуются в Spring AI через пять ключевых паттернов: Chain Workflow, Parallelization Workflow, Routing Workflow, Orchestrator-Workers и Evaluator-Optimizer.


В недавней публикации своего исследования: Building effective agents, Anthropic поделился ценными взглядами на разработку эффективных LLM агентов (Large Language Model - большая языковая модель). Что делает это исследование особенно интересным, так это то, что оно акцентирует простоту и пригодность к компоновке, ставя их в приоритет по отношению к комплексным фреймворкам. Давайте посмотрим на то, как эти принципы транслируются в практические реализации с использованием Spring AI.

В то время как описания паттернов и диаграмм взяты нами из оригинальной публикации от Anthropic, мы сосредоточимся на том, как реализовать эти паттерны с использованием возможностей Spring AI в части переносимости моделей и структурированного вывода. Мы рекомендуем сначала прочитать оригинальную публикацию.

Проект agentic-patterns реализует обсуждаемые ниже паттерны.

Агентные системы

Публикация исследования вводит важное архитектурное различие между двумя типами агентных систем:

  1. Workflows: системы, в которых LLM и инструменты оркеструются через предварительно заданные пути в коде (например, директивная система) 

  2. Агенты (Agents): Системы, где LLM динамически направляют свои процессы и использование инструментов 

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

Давайте посмотрим, как Spring AI реализует эти концепции через пять фундаментальных паттернов, каждый их которых помогает решению определенного набора кейсов:

1. Chain Workflow

Паттерн Chain Workflow является примером разбиения сложных задач на более простые, более управляемые, чтобы иметь возможность выполнять их по шагам.

Когда используется:

  • Задачи с четкими последовательными шагами

  • Когда вы готовы пожертвовать latency ради более высокой точности 

  • Когда каждый шаг использует результаты предыдущего 

Приведем практический пример из реализации Spring AI:

public class ChainWorkflow {
    private final ChatClient chatClient;
    private final String[] systemPrompts;

    // Processes input through a series of prompts, where each step's output
    // becomes input for the next step in the chain.     
    public String chain(String userInput) {
        String response = userInput;
        for (String prompt : systemPrompts) {
            // Combine the system prompt with previous response
            String input = String.format("{%s}\n {%s}", prompt, response);
            // Process through the LLM and capture output
            response = chatClient.prompt(input).call().content();
        }
        return response;
    }
}

Эта реализация демонстрирует несколько ключевых принципов:

  • Каждый шаг фокусируется на своей зоне ответственности 

  • Вывод одного шага становится вводом другого 

  • Цепочка легко расширяется и поддерживается

2. Parallelization Workflow

LLM могут одновременно работать над задачами и агрегировать их вывод программным путем. Параллелизация workflow проявляется в двух ключевых вариантах:

  • Разбиенте на секции: задачи разбиваются на несколько независимых подзадач для параллельной обработки 

  • Голосование: несколько инстансов одной и той же задачи запускаются одновременно ради консенсуса

Когда используется:

  • Обработка больших количеств похожих, но независимых объектов 

  • Задачи, требующие многочисленных независимых подходов 

  • Когда время обработки имеет решающее значение, а задачи можно выполнять параллельно 

Паттерн Parallelization Workflow демонстрирует эффективную многопоточную обработку многочисленных LLM операций. Этот паттерн особенно полезен для сценариев, требующих параллельного выполнения вызовов LLM с автоматизированной агрегацией вывода. 

Приведем базовый пример использования паттерна Parallelization Workflow:

List<String> parallelResponse = new ParallelizationWorkflow(chatClient)
    .parallel(
        "Analyze how market changes will impact this stakeholder group.",
        List.of(
            "Customers: ...",
            "Employees: ...",
            "Investors: ...",
            "Suppliers: ..."
        ),
        4
    );

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

3. Routing Workflow

Паттерн Routing реализует умное распределение задач, позволяя обрабатывать различные типы входных данных по-разному.

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

Когда используется:

  • Сложные задачи с четко определенными категориями входных данных 

  • Когда разные входные данные требуют специализированной обработки 

  • Когда классификацию можно выполнить достаточно точно 

Приведем базовый пример использования Routing Workflow:

@Autowired
private ChatClient chatClient;

// Create the workflow
RoutingWorkflow workflow = new RoutingWorkflow(chatClient);

// Define specialized prompts for different types of input
Map<String, String> routes = Map.of(
    "billing", "You are a billing specialist. Help resolve billing issues...",
    "technical", "You are a technical support engineer. Help solve technical problems...",
    "general", "You are a customer service representative. Help with general inquiries..."
);

// Process input
String input = "My account was charged twice last week";
String response = workflow.route(input, routes);

4. Orchestrator-Workers

Этот паттерн демонстрирует, как реализовывать более сложное агентоподобное поведение, при этом полностью сохраняя контроль:

  • Центральная LLM оркестрирует декомпозицию задач 

  • Специализированные обработчики обрабатывают специфические подзадачи 

  • Четкие границы поддерживают надежность системы

Когда используется:

  • Сложные задачи, в которых подзадачи нельзя предсказать заранее 

  • Задачи, требующие разных подходов или точек зрения 

  • Ситуации, требующие адаптивного решения проблем 

Реализация использует ChatClient от Spring AI's для интерактивного взаимодействия с LLM и состоит из:

public class OrchestratorWorkersWorkflow {
    public WorkerResponse process(String taskDescription) {
        // 1. Orchestrator analyzes task and determines subtasks
        OrchestratorResponse orchestratorResponse = // ...

        // 2. Workers process subtasks in parallel
        List<String> workerResponses = // ...

        // 3. Results are combined into final response
        return new WorkerResponse(/*...*/);
    }
}

Пример использования:

ChatClient chatClient = // ... initialize chat client
OrchestratorWorkersWorkflow workflow = new OrchestratorWorkersWorkflow(chatClient);

// Process a task
WorkerResponse response = workflow.process(
    "Generate both technical and user-friendly documentation for a REST API endpoint"
);

// Access results
System.out.println("Analysis: " + response.analysis());
System.out.println("Worker Outputs: " + response.workerResponses());

5. Evaluator-Optimizer

Паттерн Evaluator-Optimizer реализует процесс dual-LLM (двойная LLM), где одна модель генерирует ответы, в то время как вторая предоставляет оценку и обратную связь в итерационном цикле, что напоминает процесс работы писателя над текстом. Паттерн состоит из двух главных компонентов:

  • Generator LLM (модель-генератор): Генерирует первоначальный ответ и улучшает его на базе обратной связи 

  • Evaluator LLM (модель-оценщик): Анализирует ответы и предоставляет подробную обратную связь для улучшений 

Когда используется:

  • Существуют четкие критерии оценки 

  • Улучшение в цикле дает измеримое преимущество 

  • Задачи выигрывают от нескольких раундов критической оценки 

Реализация использует ChatClient от Spring AI's для интерактивного взаимодействия с LLM и состоит из:

public class EvaluatorOptimizerWorkflow {
    public RefinedResponse loop(String task) {
        // 1. Generate initial solution
        Generation generation = generate(task, context);
        
        // 2. Evaluate the solution
        EvaluationResponse evaluation = evaluate(generation.response(), task);
        
        // 3. If PASS, return solution
        // 4. If NEEDS_IMPROVEMENT, incorporate feedback and generate new solution
        // 5. Repeat until satisfactory
        return new RefinedResponse(finalSolution, chainOfThought);
    }
}

Пример использования:

ChatClient chatClient = // ... initialize chat client
EvaluatorOptimizerWorkflow workflow = new EvaluatorOptimizerWorkflow(chatClient);

// Process a task
RefinedResponse response = workflow.loop(
    "Create a Java class implementing a thread-safe counter"
);

// Access results
System.out.println("Final Solution: " + response.solution());
System.out.println("Evolution: " + response.chainOfThought());

Преимущества реализаций в Spring AI

Реализации этих паттернов в Spring AI имеют несколько преимуществ, которые соответствуют рекомендациям Anthropic:

  1. Переносимость модели

<!-- Easy model switching through dependencies -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
  1. Структурированный вывод

// Type-safe handling of LLM responses
EvaluationResponse response = chatClient.prompt(prompt)
    .call()
    .entity(EvaluationResponse.class);
  1. Стабильный API

  • Один и тот же интерфейс для разных LLM провайдеров 

  • Встроенная обработка ошибок и повторные попытки 

  • Гибкое управление подсказками

Best Practices и рекомендации

Базируясь как на исследовании от Anthropic, так и на реализациях от Spring AI, можно сформулировать следующие ключевые рекомендации для построения эффективных систем, базирующихся на LLM:

  • Начинайте с простого

    • Начинайте с простых workflows прежде чем добавить большую сложность 

    • Используйте самый простой паттерн из тех, что соответствуют вашим требованиям 

    • Добавляйте сложность только тогда, когда это необходимо 

  • Надежность архитектуры

    • Реализуйте четкую систему обработки ошибок 

    • Используйте типобезопасные ответы, где это возможно 

    • Встраивайте валидацию на каждом шаге 

  • Рассматривайте компромиссы

    • Балансируйте latency и точность 

    • Проводите оценку целесообразности использования многопоточной обработки 

    • Выбирайте между фиксированными workflows и динамическими агентами

Что дальше

В части 2 этой серии статей мы расскажем о том, как использовать Agents, которые сочетают в себе основные паттерны и более комплексные возможности:

Композиции паттернов

  • Комбинирование нескольких паттернов для создания более мощных workflows

  • Построение гибридных систем, которые используют силу каждого паттерна по максимуму

  • Создание гибких архитектур, которые могут адаптироваться к меняющимся требованиям 

Усовершенствованное управление памятью в агенте 

  • Реализация persistent памяти во всех диалогах 

  • Эффективное управление контекстными окнами 

  • Разработка стратегий по долговременному хранению знаний 

Интеграция инструментов и протокола Model-Context (MCP) 

  • Использование внешних инструментов через стандартные интерфейсы 

  • Реализация MCP для расширенного взаимодействия с моделью 

  • Построение расширяемых архитектур агента 

В дальнейшем мы также расскажем о подробностях реализаций и best practices для этих усовершенствованных возможностей.

Заключение

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

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

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм - Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Комментарии (0)