# Agentic Patterns This project demonstrates practical implementations of the workflow patterns for building effective LLM-based systems, as described in [Anthropic's research on building effective agents](https://www.anthropic.com/research/building-effective-agents). ## Overview The project provides concrete implementations of five fundamental workflow patterns that can be used to build effective LLM-based systems. Each pattern is implemented as a separate module with its own specific use cases and benefits. ## Workflow Patterns ### 1. Chain Workflow [chain-workflow/](chain-workflow/) Implements prompt chaining to decompose tasks into a sequence of LLM calls where each step processes the output of the previous one. Ideal for tasks that can be cleanly broken down into fixed subtasks. **When to Use:** - Tasks with clear sequential steps - When you want to trade latency for higher accuracy - When each step builds on the previous step's output **Example Applications:** - Data transformation pipelines - Multi-step text processing - Document generation with structured steps ### 2. Parallelization Workflow [parallelization-worflow/](parallelization-worflow/) Enables concurrent processing of multiple LLM operations with two key variations: - **Sectioning**: Breaking tasks into independent subtasks run in parallel - **Voting**: Running the same task multiple times to get diverse outputs **When to Use:** - Processing large volumes of similar but independent items - Tasks requiring multiple independent perspectives - When processing time is critical and tasks are parallelizable **Example Applications:** - Batch processing of documents - Multi-perspective content analysis - Parallel validation checks ### 3. Routing Workflow [routing-workflow/](routing-workflow/) Implements a classification system that directs input to specialized followup tasks, enabling separation of concerns and optimized processing for different types of input. **When to Use:** - Complex tasks with distinct categories of input - When different inputs require specialized processing - When classification can be handled accurately **Example Applications:** - Customer support ticket routing - Content moderation systems - Query optimization based on complexity ### 4. Orchestrator-Workers [orchestrator-workers/](orchestrator-workers/) Implements a flexible system where a central LLM orchestrates task decomposition and delegates to specialized worker LLMs. **When to Use:** - Complex tasks where subtasks can't be predicted upfront - Tasks requiring different approaches or perspectives - Situations needing adaptive problem-solving **Example Applications:** - Complex code generation tasks - Multi-source research tasks - Adaptive content creation ### 5. Evaluator-Optimizer [evaluator-optimizer/](evaluator-optimizer/) Implements an iterative refinement process where one LLM generates solutions while another provides evaluation and feedback. **When to Use:** - Clear evaluation criteria exist - Iterative refinement provides measurable value - Tasks benefit from multiple rounds of critique **Example Applications:** - Code review and improvement - Content quality optimization - Translation refinement - Complex search tasks ## Implementation Details All workflows are implemented using: - Spring AI for LLM interactions - Spring Boot for application framework - Java 17+ for modern language features Each workflow module contains: - Core workflow implementation - Usage examples - Customization options - Unit tests ## Getting Started 1. Clone the repository 2. Choose the appropriate workflow pattern for your use case 3. See the individual module's README for specific implementation details ## Spring AI Features This project leverages several key features from Spring AI to implement the workflow patterns effectively: 1. **ChatClient Interface**: Core abstraction for interacting with LLM models - Consistent API across different LLM providers - Fluent interface for prompt construction - Built-in retry and error handling 2. **Model Support**: Wide range of supported LLM providers - OpenAI (GPT models) - Azure OpenAI - Anthropic (Claude models) - Ollama (local models) - And more... 3. **Structured Output**: Type-safe handling of LLM responses - Convert JSON responses to Java objects - Strongly-typed response handling - Validation and error handling 4. **Prompt Management**: Flexible prompt handling - Template-based prompts - System and user message separation - Context management These features provide a robust foundation for building reliable and maintainable LLM-based applications. ### Spring AI Model Portability The workflows in this project are model-agnostic and can work with any of the [chat models supported by Spring AI](https://docs.spring.io/spring-ai/reference/1.0/api/chat/comparison.html). To switch between different models: 1. Replace the model-specific starter dependency in your `pom.xml`: ```xml org.springframework.ai spring-ai-openai-spring-boot-starter org.springframework.ai spring-ai-azure-openai-spring-boot-starter org.springframework.ai spring-ai-anthropic-spring-boot-starter org.springframework.ai spring-ai-ollama-spring-boot-starter ``` 2. Configure the model-specific properties in your `application.properties`: ```properties # OpenAI Configuration spring.ai.openai.api-key=your-api-key spring.ai.openai.model=gpt-3.5-turbo # Azure OpenAI Configuration spring.ai.azure.openai.api-key=your-api-key spring.ai.azure.openai.endpoint=your-endpoint spring.ai.azure.openai.model=gpt-35-turbo # Anthropic Configuration spring.ai.anthropic.api-key=your-api-key spring.ai.anthropic.model=claude-3-opus-20240229 # Ollama Configuration spring.ai.ollama.base-url=http://localhost:11434 spring.ai.ollama.model=llama3.2:latest ``` Detailed configuration options for each model can be found in the [Spring AI Chat Models documentation](https://docs.spring.io/spring-ai/reference/1.0/api/chatmodel.html). ### Spring AI Structured Output Several patterns in this project use Spring AI's [Structured Output Converter](https://docs.spring.io/spring-ai/reference/1.0/api/structured-output-converter.html) to handle structured responses from LLMs. This feature allows for: - Converting LLM responses into strongly-typed Java objects - Ensuring consistent response formats - Type-safe handling of LLM outputs #### Example Usage ```java // Define a record for structured output public record EvaluationResponse(Evaluation evaluation, String feedback) { public enum Evaluation { PASS, NEEDS_IMPROVEMENT, FAIL } } // Use the entity() method to convert response to your type EvaluationResponse response = chatClient.prompt(prompt) .call() .entity(EvaluationResponse.class); // Access typed fields if (response.evaluation() == Evaluation.PASS) { // Handle passing evaluation } ``` #### Implementation Examples The feature is used in several workflow patterns: 1. **Evaluator-Optimizer Workflow**: Structures evaluation responses with pass/fail status and feedback ```java record EvaluationResponse(Evaluation evaluation, String feedback) ``` 2. **Routing Workflow**: Structures routing decisions with reasoning and selection ```java record RoutingResponse(String reasoning, String selection) ``` 3. **Chain Workflow**: Structures intermediate transformation results ```java record TransformationResult(String output, List steps) ``` ## References - [Building Effective Agents (Anthropic Research)](https://www.anthropic.com/research/building-effective-agents) - [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/1.0/api/chatclient.html) - [Spring AI Chat Models](https://docs.spring.io/spring-ai/reference/1.0/api/chatmodel.html) - [Spring AI Structured Output](https://docs.spring.io/spring-ai/reference/1.0/api/structured-output-converter.html)