How to Integrate OpenAI Into a Spring Boot Application Using Spring AI
A step-by-step guide to creating an AI language assistant using Spring AI
In this tutorial, you will learn the basic concepts of Spring AI and how to implement it in your project. We’ll create an AI assistant in a Spring Boot application that helps students practice a foreign language. 😎
Let’s get started! 🦾
Demo Project
Idea💡
Imagine you’re a foreign language student who wants to practice new vocabulary and grammar. If you’re learning by yourself, you can think about a situation you want to describe. For example, what did I eat for breakfast this morning, what did I do yesterday, and you name it.
However, you might become bored practicing the same scenario all over again. It’s challenging to think about new situations to practice a conversation alone. It would be helpful if someone started a story you can continue, wouldn’t it?
Let’s say you’ve just finished a lesson about clothes, and you want to put that new vocabulary into practice with a fun scenario. That’s where the AI assistant steps up. It’s got a vivid imagination and can whip up all sorts of stories for you to continue. ✨
Technology background 💻
What’s Spring AI?
Spring AI simplifies the development of applications that incorporate AI functionality. It provides a handy set of abstractions for AI models and services in Spring applications.
Spring AI use-cases
Spring AI can help in developing chatbots for natural language interactions, content generation and summarization, data analysis with visualizations, image recognition, and natural language processing.
It’s great at recommending things personalized for you, predicting when machines might break to avoid problems, and quickly spotting fraud while improving security.
Project setup 🛠
- I’m using Maven for this demo. You’ll need the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>0.7.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Note that the spring-ai
dependency is available through the Milestones
and Snapshots
repositories. Add this to your repositories
section in the pom.xml
:
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
2. You’ll need an OpenAI api-key for this project. If you don’t have one already, please follow the instructions.
3. Once you have your key generated, add it to the application.yml
in your project:
spring:
ai:
openai.api-key: YOUR_KEY
That’s everything you need to get started. Let’s continue with the coding part!
4. Create a RestController
:
@RestController
@RequiredArgsConstructor
public class PromptController {
private final PromptService promptService;
@PostMapping("/starter")
public ResponseEntity<String> generateSentenceStarter(@RequestBody Map<String, String> params) {
String language = params.get("language");
String topic = params.get("topic");
return ResponseEntity.ok(promptService.generateSentences(language, topic));
}
}
The generateSentenceStarter
method accepts incoming POST
requests via the /starter
endpoint. The student will provide a topic they want to practice about and the studied language.
5. Here is the code for our PromptService
:
@Service
@RequiredArgsConstructor
public class PromptService {
private final AiClient aiClient;
public String generateSentences(String language, String topic) {
String userText = """
Start a sentence in {language} about this topic {topic} and ask the student to think about continuing the story to practice grammar and new words.
If the sentence is in Japanese,
always write back in Hiragana and provide the Romaji equivalent in brackets.
Also, translate it into English.
""";
PromptTemplate userPromptTemplate = new PromptTemplate(userText);
Message userMessage = userPromptTemplate.createMessage(Map.of("language", language, "topic", topic));
String systemText = """
You are a helpful AI assistant that helps students in practicing foreign languages. Respond in the style of an encouraging teacher.
""";
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
Message systemMessage = systemPromptTemplate.createMessage();
Prompt prompt = new Prompt(List.of(userMessage, systemMessage));
return aiClient.generate(prompt).getGeneration().getText();
}
}
Basic concepts
The AiClient
is the abstract interface that enables generative AI API usage. Currently, it has two implementations — OpenAI and Azure OpenAI.
In Spring AI, a Prompt
tells the AI what output to generate.
The PromptTemplate
uses a model object to fill in placeholders in the template. We provide the rendered string to the AI model as a prompt.
Roles
refer to specific parts within a prompt that play different functions in crafting the final response. These roles help structure the information provided to the AI model and allow for more tailored and meaningful outputs.
Roles in AI prompts include:
- System Role: Guides the AI’s behavior by setting interpretation and response style rules.
- User Role: Represents the user’s input, forming the AI response basis.
- Assistant Role: The AI’s response maintains conversation flow and context.
- Function Role: Focuses on specific tasks, like calculations or data fetching, going beyond conversation to provide practical assistance when needed.
Different implementations of the Message
interface align with the message categories an AI model can handle. Message categories are differentiated based on conversational roles in models. This distinction is facilitated by the MessageType
.
That was the theory part. 😌Let’s test the app.
Test the application🧪
Start the app and send a POST request using curl
with similar parameters:
curl -X POST -H "Content-Type: application/json" -d '{"language": "japanese", "topic": "clothes"}' http://localhost:8080/starter
Here’s the generated response:
あなたは明日友達とショッピングに行く予定です。何を着て行く予定ですか?
(Anata wa ashita tomodachi to shoppingu ni iku yotei desu. Nani o kite iku yotei desu ka?)
Translation: You are planning to go shopping with your friend tomorrow. What are you planning to wear?
I’m currently studying Japanese, and the response looks correct based on my humble knowledge. This is a great sentence starter.😉
Let’s try out another Role
. This time, the student wants feedback for their text.
Include this method in the PromptService
:
public String provideFeedback(String userText) {
Message userMessage = new UserMessage("Is this sentence correct: " + userText);
String instructions = """
You are a helpful AI assistant that helps students in practicing foreign languages.
You should provide feedback to the students to correct the grammar and make the sentence in the foreign language sound native.
Check and correct the user text {text}. Tell the student if the sentence is correct. If the sentence is in Japanese,
always write back in Hiragana and provide the Romaji equivalent in brackets.
""";
AssistantPromptTemplate assistantPromptTemplate = new AssistantPromptTemplate(instructions);
Message assistantPromptTemplateMessage = assistantPromptTemplate.createMessage(Map.of("text", userText));
Prompt prompt = new Prompt(List.of(userMessage, assistantPromptTemplateMessage));
return aiClient.generate(prompt).getGeneration().getText();
}
As you can see, it uses the Assistant role.
Add the new endpoint to the RestController
:
@PostMapping("/feedback")
public ResponseEntity<String> provideFeedback(@RequestBody Map<String, String> params) {
String text = params.get("text");
return ResponseEntity.ok(promptService.provideFeedback(text));
}
The application will listen to the /feedback
endpoint and send the student’s text to the AI assistant. It will return the corrected answer.
Let’s try it out!
curl -X POST -H "Content-Type: application/json" -d '{"text": "Kirei dzubon o kaimashita. Murasakiiro no sukaato mo kaimashita. Kono sukaato wa kirei da ga takai desu."}' http://localhost:8080/feedback
Here is what the AI replies:
The sentence you provided is mostly correct. Here is the corrected version:
きれいなズボンを買いました。紫色のスカートも買いました。このスカートはきれいだが高いです。
(Kirei na zubon o kaimashita. Murasakiiro no sukāto mo kaimashita. Kono sukāto wa kirei da ga takai desu.)
Translation: I bought a nice pair of pants. I also bought a purple skirt. This skirt is beautiful, but expensive.
Well done! Your sentence is grammatically correct and the vocabulary usage is appropriate. Keep up the good work!
It understood what I was trying to say. It also corrected my mistakes. This is impressive! 😲
But of course, we should be cautious with the feedback because the AI might be wrong.😉 It’s always a good idea to double-check the answers.
Conclusion
In this tutorial, you learned how to get started with Spring AI. You also became familiar with specific terms, such as Prompt
, Role
, Message
, and PromptTemplate
.
You can now create your own application using Spring AI according to your needs. Feel free to drop a comment and share your latest project idea— I’m curious! 🚀👩💻
As usual, the complete code for this project can be found in my GitHub repo.
I hope you’ve enjoyed this article. Thanks for reading, and happy coding!