If you are an Artificial Intelligence enthusiast and want to learn how to create an intelligent chat application using Spring AI and OpenAI, you are in the right place! In this tutorial, we'll walk you step-by-step through the process of developing a chat application using Spring AI and OpenAI's Chat Completion API.
Project configuration
Before starting, we invite you to follow the first chapter of our guide on Spring AI which explains how to create a project from scratch. Once the project is initialized, you should have your Spring Boot application ready with Maven dependencies on your OpenAI and Spring Web modules imported:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
API Key generation for OpenAI
The first thing to do is to set an API Key to authenticate to the OpenAI API by setting the “spring.ai.openai.api-key” property in the application.properties file. If you want to avoid pasting the clear key into the file you can refer to an environment variable as in the example below:
spring.ai.openai.api-key=${SPRING_AI_OPENAI_API_KEY}
In case the name of the environment variable is exactly the same as SPRING_AI_OPENAI_API_KEY
the property is optional because Spring reads the variable with this name by default. If the name of the variable is different then it is essential to specify the property.
To generate the API Key you need to access the OpenAI console and select the “API Keys” item from the side menu:
By clicking on “+ Create new secret key” and following the guided procedure you can create the key in just a few clicks.
Creating a REST Controller
To test the integration we will implement a REST Controller in our application as in the example below:
package com.example.aidemo.controller;
import java.util.Map;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.openai.OpenAiChatModel;
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 OpenAiRestController {
private final ChatModel chatModel;
@Autowired
public OpenAiRestController(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", chatModel.call(message));
}
}
As you can see the controller is very simple and simply exposes a GET endpoint “/ai/generate” where you can pass a “message” parameter in query string. Example:
http://localhost:8080/ai/generate?message=Where is New York City located?
By starting the server and connecting to the endpoint via browser you can easily test the result:
{
"generation": "New York City is located in the state of New York in the United States."
}
API Stream
As an alternative to the previous method, OpenAI also allows API Stream type communication.
When we talk about a “stream API,” we’re referring to an API that allows you to receive data continuously rather than in a single transaction. In practice, the use of the “stream API” allows you to maintain a persistent connection with the server by receiving data continuously throughout the duration of the session. This allows for a smoother, more responsive interaction without having to wait for a single, definitive response.
To define an endpoint of this type with Spring AI you can refer to this example:
@GetMapping("/ai/stream")
public Flux<ChatResponse> stream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return chatModel.stream(prompt);
}