In 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:
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.beans.factory.annotation.Value;
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;
import java.io.FileInputStream;
import java.security.KeyStore;
@Configuration
public class SpringOpenAIConfig {
@Value("${cacerts.secret}")
private String cacertsSecret;
@Bean
public RestTemplate secureRestTemplate(RestTemplateBuilder builder) throws Exception {
// FIXME Path to the default cacerts file in your Java installation (I'm using the JDK 17, on Windows)
String cacertsPath = System.getenv("JAVA_HOME") + "\\lib\\security\\cacerts";
// Load the default cacerts truststore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream fis = new FileInputStream(cacertsPath)) {
keyStore.load(fis, cacertsSecret.toCharArray());
}
// Build the SSLContext using the default cacerts
final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
final SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(keyStore, acceptingTrustStrategy)
.build();
final SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
final Registry socketFactoryRegistry =
RegistryBuilder. 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 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 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.