Spring AI Example Tutorial

Prompts and prompt engineering are crucial in generative AI, significantly influencing the effectiveness of the AI's output. A well-designed prompt can lead to more accurate and relevant responses. This tutorial will walk you through creating an AI poet using Spring AI and demonstrate the use of simple prompts, prompt templates, and roles to enhance AI interactions.
  1. Prompts: Instructions given to the AI model to generate responses.
  2. Prompt Templates: Structured prompts with placeholders that can be dynamically replaced with actual data at runtime.
  3. Roles: Different roles (system, user, assistant, function) help manage the context and behavior of AI interactions.
Let's create a Spring Boot project, integrate Spring AI, and generate content using OpenAPI for the poet prompts.

Setting Up the Project

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
  • 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>

Configuring Spring AI

Step 1: Add API Key to Configuration

Add your OpenAI API key to application.properties or application.yml.

For application.properties:

openai.api.key=your_openai_api_key

For application.yml:

openai:
  api:
    key: your_openai_api_key

Step 2: Configure Spring Beans

Create a configuration class to set up the necessary Spring beans, including the OpenAiClient and ChatClient.

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;
import org.springframework.ai.prompts.PromptTemplate;

@Configuration
public class AppConfig {

    @Bean
    public OpenAiClient openAiClient() {
        return new OpenAiClient();
    }

    @Bean
    public ChatClient chatClient(OpenAiClient openAiClient) {
        return new OpenAiChatClient(openAiClient);
    }

    @Bean
    public PromptTemplate poetPromptTemplate() {
        return new PromptTemplate("Write a {adjective} poem about {topic}");
    }
}

Creating and Using Prompts

Step 1: Simple Prompt

Create a service to interact with the AI using a simple prompt.

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 PoetService {

    private final ChatClient chatClient;

    @Autowired
    public PoetService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public String generateSimplePoem(String adjective, String topic) {
        String prompt = "Write a " + adjective + " poem about " + topic;
        ChatMessage userMessage = new ChatMessage("user", prompt);

        ChatRequest request = new ChatRequest();
        request.setMessages(List.of(userMessage));

        ChatResponse response = chatClient.sendMessage(request);
        return response.getReply();
    }
}

Step 2: Prompt Template

Create a service to use the PromptTemplate for generating prompts.

package com.example.demo.service;

import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.prompts.PromptTemplate;
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.Map;

@Service
public class PoetService {

    private final ChatClient chatClient;
    private final PromptTemplate poetPromptTemplate;

    @Autowired
    public PoetService(ChatClient chatClient, PromptTemplate poetPromptTemplate) {
        this.chatClient = chatClient;
        this.poetPromptTemplate = poetPromptTemplate;
    }

    public String generateTemplatePoem(String adjective, String topic) {
        String prompt = poetPromptTemplate.create(Map.of("adjective", adjective, "topic", topic));
        ChatMessage userMessage = new ChatMessage("user", prompt);

        ChatRequest request = new ChatRequest();
        request.setMessages(List.of(userMessage));

        ChatResponse response = chatClient.sendMessage(request);
        return response.getReply();
    }
}

Step 3: Using Roles

Enhance the service to use roles to manage the context and behavior of the AI interaction.

package com.example.demo.service;

import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.prompts.PromptTemplate;
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;
import java.util.Map;

@Service
public class PoetService {

    private final ChatClient chatClient;
    private final PromptTemplate poetPromptTemplate;

    @Autowired
    public PoetService(ChatClient chatClient, PromptTemplate poetPromptTemplate) {
        this.chatClient = chatClient;
        this.poetPromptTemplate = poetPromptTemplate;
    }

    public String generateRoleBasedPoem(String adjective, String topic) {
        String prompt = poetPromptTemplate.create(Map.of("adjective", adjective, "topic", topic));

        ChatMessage systemMessage = new ChatMessage("system", "You are a poetic assistant.");
        ChatMessage assistantMessage = new ChatMessage("assistant", "I will help you write a beautiful poem.");
        ChatMessage userMessage = new ChatMessage("user", prompt);

        ChatRequest request = new ChatRequest();
        request.setMessages(List.of(systemMessage, assistantMessage, userMessage));

        ChatResponse response = chatClient.sendMessage(request);
        return response.getReply();
    }
}

Exposing the Services via REST

Create a Controller to Expose the Services

Create a controller to expose endpoints for generating poems using simple prompts, prompt templates, and role-based interactions.

package com.example.demo.controller;

import com.example.demo.service.PoetService;
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 PoetController {

    private final PoetService poetService;

    @Autowired
    public PoetController(PoetService poetService) {
        this.poetService = poetService;
    }

    @GetMapping("/generateSimplePoem")
    public String generateSimplePoem(@RequestParam String adjective, @RequestParam String topic) {
        return poetService.generateSimplePoem(adjective, topic);
    }

```java
    @GetMapping("/generateTemplatePoem")
    public String generateTemplatePoem(@RequestParam String adjective, @RequestParam String topic) {
        return poetService.generateTemplatePoem(adjective, topic);
    }

    @GetMapping("/generateRoleBasedPoem")
    public String generateRoleBasedPoem(@RequestParam String adjective, @RequestParam String topic) {
        return poetService.generateRoleBasedPoem(adjective, topic);
    }
}

Testing the Integration

Step 1: Run the Application

Run your Spring Boot application. Ensure the application starts without errors.

Step 2: Access the Endpoints

Use Postman, curl, or your browser to test the endpoints.

  1. Generate Simple Poem:

    http://localhost:8080/generateSimplePoem?adjective=beautiful&topic=nature
    
  2. Generate Template Poem:

    http://localhost:8080/generateTemplatePoem?adjective=melancholic&topic=autumn
    
  3. Generate Role-Based Poem:

    http://localhost:8080/generateRoleBasedPoem?adjective=inspiring&topic=the universe
    

You should receive responses generated by the AI model based on the provided prompts, templates, and roles.

Conclusion

This tutorial demonstrated how to set up and use Spring AI to create an AI poet. You learned how to configure Spring AI and create and use simple prompts, prompt templates, and role-based prompts to interact with the AI model. This setup allows you to create structured and contextually relevant prompts, enhancing the capabilities of your AI applications. 

Explore further customization and enhancements to leverage the full potential of prompts and roles in your Spring Boot projects.

Comments