Integrate Spring With Open AI
Learn how to easily integrate your Spring application with Open AI features and be ready to use the ChatGPT on your Java project.
Join the DZone community and get the full member experience.
Join For FreeIn this article, I will discuss in a practical and objective way the integration of the Spring framework with the resources of the OpenAI API, one of the main artificial intelligence products on the market.
The use of artificial intelligence resources is becoming increasingly necessary in several products, and therefore, presenting its application in a Java solution through the Spring framework allows a huge number of projects currently in production to benefit from this resource.
All of the code used in this project is available via GitHub. To download it, simply run the following command: git clone https://github.com/felipecaparelli/openai-spring.git
or via SSL git clone
.
Note: It is important to notice that there is a cost in this API usage with the OpenAI account. Make sure that you understand the prices related to each request (it will vary by tokens used to request and present in the response).
Assembling the Project
1. Get API Access
As defined in the official documentation, first, you will need an API key from OpenAI to use the GPT models. Sign up at OpenAI's website if you don’t have an account and create an API key from the API dashboard.
- Going to the API Keys page, select the option Create new secret key.
- Then, in the popup, set a name to identify your key (optional) and press Create secret key.
- Now copy the API key value that will be used in your project configuration.
2. Configure the Project Dependencies
The easiest way to prepare your project structure is via the Spring tool called Spring Initializr. It will generate the basic skeleton of your project, add the necessary libraries, the configuration, and also the main class to start your application. You must select at least the Spring Web dependency. In the Project type, I've selected Maven, and Java 17. I've also included the library httpclient5
because it will be necessary to configure our SSL connector.
Follow the snipped of the pom.xml generated:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>br.com.erakles</groupId>
<artifactId>spring-openai</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-openai</name>
<description>Demo project to explain the Spring and OpenAI integration</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M1</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. Basic Configuration
On your configuration file (application.properties), set the OpenAI secret key in the property openai.api.key
. You can also replace the model version on the properties file to use a different API version, like gpt-4o-mini
.
spring.application.name=spring-openai
openai.api.url=https://api.openai.com/v1/chat/completions
openai.api.key=YOUR-OPENAI-API-KEY-GOES-HERE
openai.api.model=gpt-3.5-turbo
A tricky part about connecting with this service via Java is that it will, by default, require your HTTP client to use a valid certificate while executing this request. To fix it we will skip this validation step.
3.1 Skip the SSL validation
To disable the requirement for a security certificate required by the JDK for HTTPS requests you must include the following modifications in your RestTemplate bean, via a configuration class:
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
@Configuration
public class SpringOpenAIConfig {
@Bean
public RestTemplate secureRestTemplate(RestTemplateBuilder builder) throws Exception {
// This configuration allows your application to skip the SSL check
final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
final SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
final SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
final Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
final BasicHttpClientConnectionManager connectionManager =
new BasicHttpClientConnectionManager(socketFactoryRegistry);
HttpClient client = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
return builder
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory(client))
.build();
}
}
4. Create a Service To Call the OpenAI API
Now that we have all of the configuration ready, it is time to implement a service that will handle the communication with the ChatGPT API. I am using the Spring component RestTemplate
, which allows the execution of the HTTP requests to the OpenAI endpoint.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class JavaOpenAIService {
@Value("${openai.api.url}")
private String apiUrl;
@Value("${openai.api.key}")
private String apiKey;
@Value("${openai.api.model}")
private String modelVersion;
private final RestTemplate restTemplate;
public JavaOpenAIService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
/**
* @param prompt - the question you are expecting to ask ChatGPT
* @return the response in JSON format
*/
public String ask(String prompt) {
HttpEntity<String> entity = new HttpEntity<>(buildMessageBody(modelVersion, prompt), buildOpenAIHeaders());
return restTemplate
.exchange(apiUrl, HttpMethod.POST, entity, String.class)
.getBody();
}
private HttpHeaders buildOpenAIHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + apiKey);
headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);
return headers;
}
private String buildMessageBody(String modelVersion, String prompt) {
return String.format("{ \"model\": \"%s\", \"messages\": [{\"role\": \"user\", \"content\": \"%s\"}]}", modelVersion, prompt);
}
}
5. Create Your REST API
Then, you can create your own REST API to receive the questions and redirect it to your service.
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import br.com.erakles.springopenai.service.SpringOpenService;
@RestController
public class SpringOpenAIController {
private final SpringOpenService springOpenService;
SpringOpenAIController(SpringOpenService springOpenService) {
this.springOpenService = springOpenService;
}
@GetMapping("/chat")
public ResponseEntity<String> sendMessage(@RequestParam String prompt) {
return ResponseEntity.ok(springOpenService.askMeAnything(prompt));
}
}
Conclusion
These are the steps required to integrate your web application with the OpenAI service, so you can improve it later by adding more features like sending voice, images, and other files to their endpoints.
After starting your Spring Boot application (./mvnw spring-boot:run
), to test your web service, you must run the following URL http://localhost:8080/ask?promp={add-your-question}.
If you did everything right, you will be able to read the result on your response body as follows:
{
"id": "chatcmpl-9vSFbofMzGkLTQZeYwkseyhzbruXK",
"object": "chat.completion",
"created": 1723480319,
"model": "gpt-3.5-turbo-0125",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Scuba stands for \"self-contained underwater breathing apparatus.\" It is a type of diving equipment that allows divers to breathe underwater while exploring the underwater world. Scuba diving involves using a tank of compressed air or other breathing gas, a regulator to control the flow of air, and various other accessories to facilitate diving, such as fins, masks, and wetsuits. Scuba diving allows divers to explore the underwater environment and observe marine life up close.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 90,
"total_tokens": 102
},
"system_fingerprint": null
}
I hope this tutorial helped in your first interaction with the OpenAI and makes your life easier while diving deeper into your AI journey. If you have any questions or concerns don't hesitate to send me a message.
Opinions expressed by DZone contributors are their own.
Comments