Building a Generative AI Application with Spring AI

Bradley Clemson
Version 1
Published in
5 min readJan 12, 2024

In this tutorial, we will explore the practical application of generative AI in a Spring Boot application with Spring AI.

AI-powered code analysis and documentation — Decipher | Version 1

Put simply, Spring AI provides abstractions that streamline the development of AI applications. These abstractions have various implementations and enable developers to customise artificial intelligence functionality without unnecessary complexity.

From the AiClient to EmbeddingClient and Vector Database implementation, the Spring AI API is a comprehensive toolkit for crafting AI applications. Gracefully, as tasks for the API become more intricate, Spring AI integrates with other projects in the Spring Ecosystem, such as Spring Integration, Spring Batch, and Spring Data.

The Spring AI Documentation covers the most recent releases, updates to the Spring AI project, and delivers in-depth insights into fundamental AI concepts such as models, prompts, and beyond.

One of the features introduced by Spring AI is the AiClient interface. It acts as a uniform interface for interacting with various AI Models, including implementations for OpenAI and Azure OpenAI. The interface manages the complexity of request preparation and response parsing, offering a direct and simplified API interaction. Let’s demonstrate how this streamlines adding generative AI to our application…

Dependencies required in pom.xml

To use Spring AI, define the following repository.

 <repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>

When implementing OpenAI (what we will use in this tutorial), you can specify the following dependency:

  <dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>0.2.0-SNAPSHOT</version>
</dependency>

To implement Azure OpenAI instead of OpenAI, you can use the following dependency:

<dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
<version>0.2.0-SNAPSHOT</version>
</dependency>

Create OpenAI API Key

To initiate a connection with OpenAI and make use of its models, it is essential to sign up and obtain an OpenAI API key here.

Add API Key and OpenAI Image Generator URL in application. properties file:

spring.ai.openai.apikey=REPLACE_WITH_YOUR_API_KEY
spring.ai.openai.imageUrl=https://api.openai.com/v1/images/generations

Project Structure :

Create SpringAIService under services package:

@Service
public class SpringAIService {

@Autowired
AiClient aiClient;

@Value("${spring.ai.openai.apikey}")
private String apiKey;

@Value("${spring.ai.openai.imageUrl}")
private String openAIImageUrl;


public String getJoke(String topic){
PromptTemplate promptTemplate = new PromptTemplate("""
Crafting a compilation of programming jokes for my website. Would you like me to create a joke about {topic}?
""");
promptTemplate.add("topic", topic);
return this.aiClient.generate(promptTemplate.create()).getGeneration().getText();
}

public String getBook(String category, String year) {
PromptTemplate promptTemplate = new PromptTemplate("""
I would like to research some books. Please give me a book about {category} in {year} to get started?
But pick the best best you can think of. I'm a book critic. Ratings are great help.
And who wrote it? And who help it? Can you give me a short plot summary and also it's name?
But don't give me too much information. I don't want any spoilers.
And please give me these details in the following JSON format: category, year, bookName, author, review, smallSummary.
""");
Map.of("category", category, "year", year).forEach(promptTemplate::add);
AiResponse generate = this.aiClient.generate(promptTemplate.create());
return generate.getGeneration().getText();
}


public InputStreamResource getImage(@RequestParam(name = "topic") String topic) throws URISyntaxException {
PromptTemplate promptTemplate = new PromptTemplate("""
I am really bored from online memes. Can you create me a prompt about {topic}.
Elevate the given topic. Make it sophisticated.
Make a resolution of 256x256, but ensure that it is presented in json.
I want only one image creation. Give me as JSON format: prompt, n, size.
""");
promptTemplate.add("topic", topic);
String imagePrompt = this.aiClient.generate(promptTemplate.create()).getGeneration().getText();

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + apiKey);
headers.add("Content-Type", "application/json");
HttpEntity<String> httpEntity = new HttpEntity<>(imagePrompt,headers);

String imageUrl = restTemplate.exchange(openAIImageUrl, HttpMethod.POST, httpEntity, GeneratedImage.class)
.getBody().getData().get(0).getUrl();
byte[] imageBytes = restTemplate.getForObject(new URI(imageUrl), byte[].class);
assert imageBytes != null;
return new InputStreamResource(new java.io.ByteArrayInputStream(imageBytes));
}




}

There are three methods —

1.getJoke takes a topic as a parameter and returns a joke based on the topic.

2.getBook takes category and year as parameters, returning an appropriate book recommendation.

3.getImagetakes a topic as a parameter and requests an image related to that topic.

Let’s unpack how the methods work…

Dependency Injection: At the top level, using the @Autowired annotation, the class injects an instance of the AiClient interface that communicates with the OpenAI service.

Prompt: A key component for prompt templating in Spring AI is the PromptTemplate class. The class is designed to facilitate the creation of structured prompts that are then sent to the AI model for processing. Using the method Prompt create() we generate a predefined prompt in each of our our three methods.

Response: The AiResponse class holds the OpenAI AI Model’s output. The AiResponse class can also carry a map of key-value pairs providing metadata about the AI Model’s response.

Generation: Finally, the Generation class contains a String that represents the output text and a map that provides metadata about the response. In the case of our getImage method, the resulting image URL is obtained. The image is then fetched from the URL and converted into an InputStreamResource for further processing.

Create GeneratedImage entity under models package:

public class GeneratedImage {
private List<ImageUrl> data;

public List<ImageUrl> getData() {
return data;
}

public void setData(List<ImageUrl> data) {
this.data = data;
}

public static class ImageUrl {
private String url;

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}
}
}

Create SpringAIController under controllers package:

@RestController
@RequestMapping("/api/v1")
public class SpringAIController {

@Autowired
SpringAIService aiService;

@GetMapping("/joke")
public String getJoke(@RequestParam String topic) {
return aiService.getJoke(topic);
}

@GetMapping("/book")
public String getBook(@RequestParam(name = "category") String category, @RequestParam(name = "year") String year) {
return aiService.getBook(category, year);
}

@GetMapping(value = "/image", produces = "image/jpeg")
public ResponseEntity<InputStreamResource> getImage(@RequestParam(name = "topic") String topic) throws URISyntaxException {
return ResponseEntity.ok().body(aiService.getImage(topic));
}
}

There are three endpoints in the controller class

  1. /api/v1/joke : It will tell a joke based on the topic you provide.

2. /api/v1/book : It will give you details of a book recommendation based on the category and year you provide.

3. /api/v1/image : It will generate an image for you related to your description.

Spring AI is magnificent. Hopefully, this tutorial has shown how it makes simple work of integrating a Spring application with AI. It is safe to say, that if you’re a developer who is familiar with Spring, and want to build generative AI in your applications, then Spring AI is indispensable.

About the author

Bradley Clemson is a Java Developer here at Version 1.

--

--