Spring AI Tutorial

Spring AI Tutorial

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

  1. What is Spring AI?

    • Definition and Purpose
  2. Spring AI Concepts

    • AI Models
    • Prompts and Responses
    • Output Parsers
    • Roles
  3. Spring AI API

    • Key Components: ChatClient, ChatRequest, ChatResponse, PromptTemplate
  4. Spring AI Features

    • Integration
    • Extensible Architecture
    • Ease of Use
  5. Spring AI Integration with Spring Boot

    • Create Project
    • Add Dependencies
    • Configure API Key
    • Configure Beans
    • Service and Controller Setup
  6. Spring AI Prompt Templates

    • Usage and Examples
  7. Spring AI Roles

    • System, User, Assistant, Function Roles
    • Examples
  8. Spring AI Output Parsers

    • BeanOutputParser
    • MapOutputParser
    • ListOutputParser
  9. Real-World Example

    • Customer Support Chatbot
  10. 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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top