Spring AI is an innovative framework that integrates artificial intelligence (AI) capabilities into the Spring ecosystem. This tutorial will cover the core concepts, APIs, features, integration with Spring Boot, prompt templates, roles, output parsers, and a real-world example to help you get started with Spring AI.
Table of Contents for Spring AI Tutorial
-
What is Spring AI?
- Definition and Purpose
-
Spring AI Concepts
- AI Models
- Prompts and Responses
- Output Parsers
- Roles
-
Spring AI API
- Key Components: ChatClient, ChatRequest, ChatResponse, PromptTemplate
-
Spring AI Features
- Integration
- Extensible Architecture
- Ease of Use
-
Spring AI Integration with Spring Boot
- Create Project
- Add Dependencies
- Configure API Key
- Configure Beans
- Service and Controller Setup
-
Spring AI Prompt Templates
- Usage and Examples
-
Spring AI Roles
- System, User, Assistant, Function Roles
- Examples
-
Spring AI Output Parsers
- BeanOutputParser
- MapOutputParser
- ListOutputParser
-
Real-World Example
- Customer Support Chatbot
-
Conclusion
What is Spring AI?
Spring AI is a framework designed to simplify the integration of AI and machine learning models into Spring Boot applications. It leverages the strengths of the Spring ecosystem, providing tools and libraries that make it easier to incorporate AI functionalities such as natural language processing, image recognition, and more into your applications.
Spring AI Concepts
AI Models
Spring AI supports various AI models, including pre-trained models from providers like OpenAI and custom models developed by users. These models can perform tasks such as text generation, sentiment analysis, and image classification.
Prompts and Responses
In Spring AI, interaction with AI models is managed through prompts and responses. Prompts are the inputs provided to the AI model, and responses are the outputs generated. This structure allows for building conversational agents and other interactive AI applications.
Output Parsers
Spring AI includes output parsers that process and format the responses from AI models into usable data structures like beans, maps, and lists, making it easier to handle the data within Spring applications.
Roles
Roles in Spring AI help manage the context and behavior of AI interactions:
- System Role: Sets the parameters and rules for how the AI interprets and responds to input.
- User Role: Represents the user’s input.
- Assistant Role: The AI’s response to the user’s input.
- Function Role: Carries out specific tasks or operations during the interaction.
Spring AI API
Spring AI provides a simplified API for interacting with AI models. This API abstracts the complexity involved in working with AI models, making it accessible to developers with varying levels of expertise in AI and machine learning.
Key API Components
- ChatClient: Manages the interaction between the application and the AI model.
- ChatRequest: Represents a request sent to the AI model.
- ChatResponse: Represents the response received from the AI model.
- PromptTemplate: Allows the creation of structured prompts with placeholders that can be dynamically replaced with actual data at runtime.
Spring AI Features
Seamless Integration
Spring AI integrates seamlessly with the Spring ecosystem, allowing developers to use familiar tools and methodologies to incorporate AI capabilities into their applications.
Extensible Architecture
The architecture of Spring AI is designed to be extensible, enabling developers to add support for new AI models and providers easily.
Ease of Use
Spring AI provides a simplified API for interacting with AI models, making it accessible to developers with varying levels of expertise in AI and ML.
Spring AI Integration with Spring Boot
To get started with Spring AI in a Spring Boot application, follow these steps:
Step 1: Create a New Spring Boot Project
Use Spring Initializr to create a new Spring Boot project. Include dependencies for Spring Web and Spring AI.
Using Spring Initializr:
- Go to start.spring.io
- Select:
- Project: Maven Project
- Language: Java
- Spring Boot: 3.0.0 (or latest)
- Dependencies: Spring Web, Spring AI
- Generate the project and unzip it.
Step 2: Add Dependencies
In your project’s pom.xml
, add the necessary dependencies for Spring AI.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Step 3: Configure API Key
Add your OpenAI API key to application.properties
.
openai.api.key=your_openai_api_key
Step 4: Configure Spring Beans
Create a configuration class to set up the necessary Spring beans.
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.openai.OpenAiClient;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.ChatClient;
@Configuration
public class AppConfig {
@Bean
public OpenAiClient openAiClient() {
return new OpenAiClient();
}
@Bean
public ChatClient chatClient(OpenAiClient openAiClient) {
return new OpenAiChatClient(openAiClient);
}
}
Step 5: Create a Service to Interact with AI Models
Create a service to handle interactions with the AI model.
package com.example.demo.service;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ChatGPTService {
private final ChatClient chatClient;
@Autowired
public ChatGPTService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String getChatGPTResponse(String userMessage) {
ChatMessage userMsg = new ChatMessage("user", userMessage);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(userMsg));
ChatResponse response = chatClient.sendMessage(request);
return response.getReply();
}
}
Step 6: Create a Controller to Expose the Service
Create a controller to expose an endpoint for the chatbot.
package com.example.demo.controller;
import com.example.demo.service.ChatGPTService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ChatbotController {
private final ChatGPTService chatGPTService;
@Autowired
public ChatbotController(ChatGPTService chatGPTService) {
this.chatGPTService = chatGPTService;
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatGPTService.getChatGPTResponse(message);
}
}
Spring AI Prompt Templates
Spring AI provides PromptTemplate
to create structured prompts with placeholders that can be dynamically replaced with actual data at runtime. This is useful for generating dynamic prompts based on user input or other contextual information.
package com.example.demo.service;
import org.springframework.ai.prompts.PromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class PromptService {
private final PromptTemplate poetPromptTemplate;
@Autowired
public PromptService() {
this.poetPromptTemplate = new PromptTemplate("Write a {adjective} poem about {topic}");
}
public String createPoemPrompt(String adjective, String topic) {
return poetPromptTemplate.create(Map.of("adjective", adjective, "topic", topic));
}
}
Spring AI Roles
Roles in Spring AI help manage the context and behavior of AI interactions:
- System Role: Guides the AI’s behavior and response style.
- User Role: Represents the user’s input.
- Assistant Role: The AI’s response to the user’s input.
- Function Role: Carries out specific tasks or operations during the interaction.
Example of Using Roles
package com.example.demo.service;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class RoleBasedChatService {
private final ChatClient chatClient;
@Autowired
public RoleBasedChatService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String chatWithRoles(String userMessage) {
ChatMessage systemMessage = new ChatMessage("system", "You are a helpful assistant.");
ChatMessage userMessageObj = new ChatMessage("user", userMessage);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(systemMessage, userMessageObj));
ChatResponse response = chatClient.sendMessage(request);
return response.getReply();
}
}
Spring AI Output Parsers
Spring AI includes several output parsers to process and format the responses from AI models into usable data structures like beans, maps, and lists.
Example of Output Parsers
BeanOutputParserExample.java
package com.example.demo.service;
import com.example.demo.model.Product;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.ai.output.BeanOutputParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BeanOutputParserExample {
private final ChatClient chatClient;
@Autowired
public BeanOutputParserExample(ChatClient chatClient) {
this.chatClient = chatClient;
}
public Product parseResponseToBean(String userMessage) {
ChatMessage userMsg = new ChatMessage("user", userMessage);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(userMsg));
ChatResponse response = chatClient.sendMessage(request);
BeanOutputParser<Product> parser = new BeanOutputParser<>(Product.class);
return parser.parse(response.getReply());
}
}
MapOutputParserExample.java
package com.example.demo.service;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.ai.output.MapOutputParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class MapOutputParserExample {
private final ChatClient chatClient;
@Autowired
public MapOutputParserExample(ChatClient chatClient) {
this.chatClient = chatClient;
}
public Map<String, Object> parseResponseToMap(String userMessage) {
ChatMessage userMsg = new ChatMessage("user", userMessage);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(userMsg));
ChatResponse response = chatClient.sendMessage(request);
MapOutputParser parser = new MapOutputParser();
return parser.parse(response.getReply());
}
}
ListOutputParserExample.java
package com.example.demo.service;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.ai.output.ListOutputParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ListOutputParserExample {
private final ChatClient chatClient;
@Autowired
public ListOutputParserExample(ChatClient chatClient) {
this.chatClient = chatClient;
}
public List<String> parseResponseToList(String userMessage) {
ChatMessage userMsg = new ChatMessage("user", userMessage);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(userMsg));
ChatResponse response = chatClient.sendMessage(request);
ListOutputParser<String> parser = new ListOutputParser<>(String.class);
return parser.parse(response.getReply());
}
}
Creating Controllers to Expose the Services
Create controllers to expose endpoints for each output parser example.
BeanOutputParserController.java
package com.example.demo.controller;
import com.example.demo.model.Product;
import com.example.demo.service.BeanOutputParserExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BeanOutputParserController {
private final BeanOutputParserExample parserExample;
@Autowired
public BeanOutputParserController(BeanOutputParserExample parserExample) {
this.parserExample = parserExample;
}
@GetMapping("/parseToBean")
public Product parseToBean(@RequestParam String message) {
return parserExample.parseResponseToBean(message);
}
}
MapOutputParserController.java
package com.example.demo.controller;
import com.example.demo.service.MapOutputParserExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class MapOutputParserController {
private final MapOutputParserExample parserExample;
@Autowired
public MapOutputParserController(MapOutputParserExample parserExample) {
this.parserExample = parserExample;
}
@GetMapping("/parseToMap")
public Map<String, Object> parseToMap(@RequestParam String message) {
return parserExample.parseResponseToMap(message);
}
}
ListOutputParserController.java
package com.example.demo.controller;
import com.example.demo.service.ListOutputParserExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ListOutputParserController {
private final ListOutputParserExample parserExample;
@Autowired
public ListOutputParserController(ListOutputParserExample parserExample) {
this.parserExample = parserExample;
}
@GetMapping("/parseToList")
public List<String> parseToList(@RequestParam String message) {
return parserExample.parseResponseToList(message);
}
}
Spring AI Real-World Example
Scenario: Building a Customer Support Chatbot
In this example, we will build a simple customer support chatbot using Spring AI. The chatbot will be able to respond to common customer queries.
Step 1: Define the Model
Create a model to represent customer queries and responses.
package com.example.demo.model;
public class CustomerQuery {
private String question;
private String answer;
// Getters and setters
}
Step 2: Create the Service
Create a service to interact with the AI model and handle customer queries.
package com.example.demo.service;
import com.example.demo.model.CustomerQuery;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.ai.output.BeanOutputParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CustomerSupportService {
private final ChatClient chatClient;
@Autowired
public CustomerSupportService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public CustomerQuery getResponse(String question) {
ChatMessage userMessage = new ChatMessage("user", question);
ChatRequest request = new ChatRequest();
request.setMessages(List.of(userMessage));
ChatResponse response = chatClient.sendMessage(request);
BeanOutputParser<CustomerQuery> parser = new BeanOutputParser<>(CustomerQuery.class);
return parser.parse(response.getReply());
}
}
Step 3: Create the Controller
Create a controller to expose the customer support service.
package com.example.demo.controller;
import com.example.demo.model.CustomerQuery;
import com.example.demo.service.CustomerSupportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CustomerSupportController {
private final CustomerSupportService customerSupportService;
@Autowired
public CustomerSupportController(CustomerSupportService customerSupportService) {
this.customerSupportService = customerSupportService;
}
@GetMapping("/support")
public CustomerQuery getSupport(@RequestParam String question) {
return customerSupportService.getResponse(question);
}
}
Step 4: Run and Test the Application
Run your Spring Boot application and test the customer support chatbot using a tool like Postman or a web browser.
Example URL:
http://localhost:8080/support?question=What is your return policy?
Expected Response:
{
"question": "What is your return policy?",
"answer": "Our return policy allows you to return items within 30 days of purchase. Please visit our website for more details."
}
Conclusion
Spring AI simplifies the integration of AI capabilities into Spring applications, providing a robust and flexible framework for building intelligent systems. By leveraging the core concepts, models, and features of Spring AI, developers can create applications that leverage the power of artificial intelligence to deliver enhanced functionality and user experiences. Whether you’re building conversational agents, performing data analysis, or incorporating machine learning models, Spring AI provides the tools and infrastructure needed to succeed.