Команда 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 реализует обсуждаемые ниже паттерны.
Агентные системы
Публикация исследования вводит важное архитектурное различие между двумя типами агентных систем:
-
Workflows: системы, в которых LLM и инструменты оркеструются через предварительно заданные пути в коде (например, директивная система)
-
Агенты (Agents): Системы, где LLM динамически направляют свои процессы и использование инструментов
Ключевой вывод состоит в том, что в то время как полностью автономные агенты могут казаться привлекательными, workflows часто предоставляют лучшую предсказуемость и стабильность для хорошо определенных задач. Это наилучшим образом сочетается с требованиями, предъявляемыми крупным бизнесом, где надежность и поддерживаемость являются решающими факторами.
Давайте посмотрим, как Spring AI реализует эти концепции через пять фундаментальных паттернов, каждый их которых помогает решению определенного набора кейсов:
Паттерн 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; } }
Эта реализация демонстрирует несколько ключевых принципов:
-
Каждый шаг фокусируется на своей зоне ответственности
-
Вывод одного шага становится вводом другого
-
Цепочка легко расширяется и поддерживается
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 );
Этот пример демонстрирует параллельную обработку анализа ситуации с держателями акций, при этом каждая группа держателей акций анализируется отдельно в многопоточном режиме.
Паттерн 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:
<!-- Easy model switching through dependencies --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>
// Type-safe handling of LLM responses EvaluationResponse response = chatClient.prompt(prompt) .call() .entity(EvaluationResponse.class);
-
Один и тот же интерфейс для разных 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 и всего, что с ним связано.
ссылка на оригинал статьи https://habr.com/ru/articles/877196/
Добавить комментарий