$npx -y skills add rrezartprebreza/spring-boot-skills --skill spring-ai-integrationUse when integrating LLMs, chat clients, embeddings, RAG pipelines, or AI agents into Spring Boot. Covers Spring AI ChatClient, prompt templates, embeddings, vector stores, and structured output. Use when user mentions Spring AI, LLM, ChatGPT, Claude, RAG, embeddings.
| 1 | # Spring AI Integration |
| 2 | |
| 3 | ## Dependencies |
| 4 | |
| 5 | ```xml |
| 6 | <dependencyManagement> |
| 7 | <dependencies> |
| 8 | <dependency> |
| 9 | <groupId>org.springframework.ai</groupId> |
| 10 | <artifactId>spring-ai-bom</artifactId> |
| 11 | <version>1.0.0</version> |
| 12 | <type>pom</type> |
| 13 | <scope>import</scope> |
| 14 | </dependency> |
| 15 | </dependencies> |
| 16 | </dependencyManagement> |
| 17 | |
| 18 | <dependencies> |
| 19 | <!-- Choose your model provider — 1.0 GA renamed every starter to spring-ai-starter-* --> |
| 20 | <dependency> |
| 21 | <groupId>org.springframework.ai</groupId> |
| 22 | <artifactId>spring-ai-starter-model-anthropic</artifactId> |
| 23 | </dependency> |
| 24 | <!-- OR --> |
| 25 | <dependency> |
| 26 | <groupId>org.springframework.ai</groupId> |
| 27 | <artifactId>spring-ai-starter-model-openai</artifactId> |
| 28 | </dependency> |
| 29 | |
| 30 | <!-- For RAG / vector search --> |
| 31 | <dependency> |
| 32 | <groupId>org.springframework.ai</groupId> |
| 33 | <artifactId>spring-ai-starter-vector-store-pgvector</artifactId> |
| 34 | </dependency> |
| 35 | </dependencies> |
| 36 | ``` |
| 37 | |
| 38 | > **Watch the artifact names.** 1.0 GA dropped the old `spring-ai-<x>-spring-boot-starter` |
| 39 | > coordinates. The pattern is now `spring-ai-starter-model-<provider>` (e.g. `-model-anthropic`, |
| 40 | > `-model-openai`) and `spring-ai-starter-vector-store-<store>`. Agents trained on pre-GA Spring AI |
| 41 | > will emit the dead names — they resolve to nothing in Maven Central. |
| 42 | |
| 43 | ## ChatClient — Basic Usage |
| 44 | |
| 45 | ```java |
| 46 | @Service |
| 47 | @RequiredArgsConstructor |
| 48 | public class DocumentSummaryService { |
| 49 | |
| 50 | private final ChatClient chatClient; |
| 51 | |
| 52 | public String summarize(String content) { |
| 53 | return chatClient.prompt() |
| 54 | .user(u -> u.text("Summarize the following document in 3 bullet points:\n\n{content}") |
| 55 | .param("content", content)) |
| 56 | .call() |
| 57 | .content(); |
| 58 | } |
| 59 | |
| 60 | // With system prompt |
| 61 | public String analyzeFinancial(String document, String language) { |
| 62 | return chatClient.prompt() |
| 63 | .system("You are a financial analyst. Respond in {language}.") |
| 64 | .system(s -> s.param("language", language)) |
| 65 | .user(document) |
| 66 | .call() |
| 67 | .content(); |
| 68 | } |
| 69 | } |
| 70 | ``` |
| 71 | |
| 72 | ## ChatClient Bean Configuration |
| 73 | |
| 74 | ```java |
| 75 | @Configuration |
| 76 | public class AiConfig { |
| 77 | |
| 78 | @Bean |
| 79 | public ChatMemory chatMemory() { |
| 80 | // 1.0 GA: InMemoryChatMemory is GONE. Use MessageWindowChatMemory — |
| 81 | // it caps history to a sliding window and defaults to an in-memory repository. |
| 82 | return MessageWindowChatMemory.builder() |
| 83 | .maxMessages(20) |
| 84 | .build(); |
| 85 | } |
| 86 | |
| 87 | @Bean |
| 88 | public ChatClient chatClient(ChatClient.Builder builder, ChatMemory chatMemory) { |
| 89 | return builder |
| 90 | .defaultSystem("You are a helpful assistant for an e-commerce platform.") |
| 91 | .defaultAdvisors( |
| 92 | MessageChatMemoryAdvisor.builder(chatMemory).build(), // GA: builder, not new(...) |
| 93 | new SimpleLoggerAdvisor() // logs prompts/responses |
| 94 | ) |
| 95 | .build(); |
| 96 | } |
| 97 | } |
| 98 | ``` |
| 99 | |
| 100 | ## Prompt Templates (externalized) |
| 101 | |
| 102 | ```java |
| 103 | // src/main/resources/prompts/analyze-order.st |
| 104 | // Analyze this order and identify any anomalies: |
| 105 | // Customer: {customer} |
| 106 | // Items: {items} |
| 107 | // Total: {total} |
| 108 | // Flag any unusual patterns. |
| 109 | |
| 110 | @Service |
| 111 | public class OrderAnalysisService { |
| 112 | |
| 113 | @Value("classpath:prompts/analyze-order.st") |
| 114 | private Resource promptTemplate; |
| 115 | |
| 116 | public String analyzeOrder(Order order) { |
| 117 | return chatClient.prompt() |
| 118 | .user(u -> u.text(promptTemplate) |
| 119 | .param("customer", order.getCustomerEmail()) |
| 120 | .param("items", order.getItems().toString()) |
| 121 | .param("total", order.getTotal())) |
| 122 | .call() |
| 123 | .content(); |
| 124 | } |
| 125 | } |
| 126 | ``` |
| 127 | |
| 128 | ## Structured Output |
| 129 | |
| 130 | ```java |
| 131 | // Define the target record |
| 132 | public record OrderClassification( |
| 133 | String category, |
| 134 | String priority, |
| 135 | List<String> tags, |
| 136 | boolean requiresManualReview |
| 137 | ) {} |
| 138 | |
| 139 | @Service |
| 140 | public class OrderClassifier { |
| 141 | |
| 142 | public OrderClassification classify(String orderDescription) { |
| 143 | return chatClient.prompt() |
| 144 | .user("Classify this order: " + orderDescription) |
| 145 | .call() |
| 146 | .entity(OrderClassification.class); // Spring AI handles JSON parsing |
| 147 | } |
| 148 | } |
| 149 | ``` |
| 150 | |
| 151 | ## RAG Pipeline |
| 152 | |
| 153 | ```java |
| 154 | @Configuration |
| 155 | public class RagConfig { |
| 156 | |
| 157 | // No manual VectorStore bean — the spring-ai-starter-vector-store-pgvector |
| 158 | // starter auto-configures one. Just inject it. (The old `new PgVectorStore(...)` |
| 159 | // constructor is removed in GA; if you must build one, use PgVectorStore.builder(...).) |
| 160 | |
| 161 | @Bean |
| 162 | public ChatClient ragChatClient(ChatClient.Builder builder, VectorStore vectorSt |