要实现一个 Spring Boot + SSE (Server-Sent Events) 服务端,通过调用 OpenAI API 获取数据并解析后返回给前端,你可以分为几个步骤来完成。具体来说,前端会通过 SSE 连接到 Spring Boot 后端,然后后端会调用 OpenAI API(比如 ChatGPT API),解析返回的数据,并通过 SSE 实时推送给前端。
步骤概述
- 搭建 Spring Boot 项目:
创建一个 Spring Boot 项目,添加相关依赖。 - 调用 OpenAI API:
使用 HTTP 客户端(如RestTemplate
或WebClient
)向 OpenAI API 发起请求,获取返回的数据。 - 解析返回数据:
解析 OpenAI API 返回的 JSON 数据。 - 通过 SSE 向前端推送数据:
使用 Spring Boot 的SseEmitter
实现 Server-Sent Events,将解析的数据推送到前端。 - 前端接收数据:
使用 JavaScript 的EventSource
接收从后端推送的事件数据,并在页面上实时显示。
1. 创建 Spring Boot 项目
使用 Spring Initializr 或 IDE 创建一个新的 Spring Boot 项目,添加以下依赖:
- Spring Web
- Spring Boot DevTools
- Jackson (默认包含)
- Spring Boot Starter JSON
pom.xml
示例依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- OpenAI API RestClient -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
2. 配置 OpenAI API
你需要申请 OpenAI API 密钥并将其保存到项目的配置文件中。
在 application.properties
或 application.yml
中添加 OpenAI API 密钥:
openai.api.key=YOUR_OPENAI_API_KEY
3. 调用 OpenAI API
Spring 提供了 RestTemplate
或 WebClient
来进行 HTTP 请求,我们选择 WebClient
(异步方式)来进行 OpenAI API 调用。
首先,配置 WebClient
bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
4. 调用 OpenAI API 的服务
创建一个 OpenAIService
类来封装与 OpenAI API 的交互:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
@Service
public class OpenAIService {
@Value("${openai.api.key}")
private String apiKey;
private final WebClient.Builder webClientBuilder;
public OpenAIService(WebClient.Builder webClientBuilder) {
this.webClientBuilder = webClientBuilder;
}
public Mono<String> callOpenAI(String prompt) {
String apiUrl = "https://api.openai.com/v1/completions";
return webClientBuilder.baseUrl(apiUrl)
.defaultHeader("Authorization", "Bearer " + apiKey)
.defaultHeader("Content-Type", "application/json")
.post()
.bodyValue("{\"model\":\"text-davinci-003\", \"prompt\":\"" + prompt + "\", \"max_tokens\":100}")
.retrieve()
.bodyToMono(String.class);
}
}
callOpenAI()
方法会发起一个 POST 请求,传递用户的提示语(prompt
)给 OpenAI API,并获取模型返回的结果。
5. 使用 SSE 实时推送数据
在控制器中,使用 SseEmitter
来实现 SSE 功能,将数据实时推送到前端。
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Mono;
@RestController
public class OpenAIController {
private final OpenAIService openAIService;
public OpenAIController(OpenAIService openAIService) {
this.openAIService = openAIService;
}
@GetMapping("/openai-sse")
public SseEmitter streamOpenAIResponse(@RequestParam String prompt) {
SseEmitter emitter = new SseEmitter();
openAIService.callOpenAI(prompt)
.doOnTerminate(emitter::complete)
.subscribe(response -> {
try {
emitter.send(response, MediaType.APPLICATION_JSON);
} catch (Exception e) {
emitter.completeWithError(e);
}
});
return emitter;
}
}
- 通过
@GetMapping("/openai-sse")
,客户端可以通过该端点访问数据流。 SseEmitter
用于将响应数据实时推送到前端。
6. 前端接收 SSE 数据
在前端,使用 EventSource
API 来接收从后端推送的 SSE 数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenAI SSE Example</title>
</head>
<body>
<h1>OpenAI Response:</h1>
<div id="response"></div>
<script type="text/javascript">
const prompt = "Tell me a joke"; // Example prompt
const eventSource = new EventSource(`/openai-sse?prompt=${encodeURIComponent(prompt)}`);
eventSource.onmessage = function(event) {
const newElement = document.createElement("div");
newElement.textContent = `Response: ${event.data}`;
document.getElementById("response").appendChild(newElement);
};
eventSource.onerror = function(event) {
console.error("Error occurred:", event);
eventSource.close();
};
</script>
</body>
</html>
7. 测试和调试
- 启动 Spring Boot 应用,访问前端页面,前端页面会通过 SSE 接收到从 OpenAI API 返回的实时数据。
- 调试过程包括检查 OpenAI 请求是否成功返回,并确保 SSE 数据流正常推送。
总结
- 后端:
- 使用
WebClient
调用 OpenAI API,获取模型响应。 - 使用
SseEmitter
将数据实时推送给前端。
- 使用
- 前端:
- 使用
EventSource
API 接收 SSE 数据流,并实时展示返回结果。
- 使用
通过这种方式,你可以实现 Spring Boot 后端与 OpenAI API 的集成,并使用 SSE 向前端实时推送数据。
发表回复