Java集成ChatGPT在前面的文章中已经讲过了这次带大家实现官网的流式输出效果。首先我们明确的是官网是采用SSE
技术来实现的流式输出,SSE(Server-Sent Events):通俗解释起来就是一种基于HTTP的,以流的形式由服务端持续向客户端发送数据的技术。
看到这里可能有人会说这不是WebSocket一样吗?其实不然,SSE比WebSocket更加的轻量化,更加的易用。
那么让GPT帮我们讲解一下SSE的工作流程吧:
@Controller
@RequestMapping("/chat")
public class ChatController {
/**
* 暂存消息(由于前端EventSource对象仅支持Get请求,故消息通过POST发送到后端后进行中转)
*/
Map<String, String> msgMap = new ConcurrentHashMap<>();
@Autowired
ChatService chatService;
/**
* 发送消息
*
* @param msg 消息
* @return 消息ID
*/
@ResponseBody
@PostMapping("/sendMsg")
public String sendMsg(String msg) {
String msgId = IdUtil.simpleUUID();
msgMap.put(msgId, msg);
return msgId;
}
/**
* 对话
*
* @param msgId 消息ID
* @return SseEmitter
*/
@GetMapping(value = "/conversation/{msgId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter conversation(@PathVariable("msgId") String msgId) {
SseEmitter sseEmitter = new SseEmitter();
String msg = msgMap.remove(msgId);
//调用流式会话服务
chatService.streamChatCompletion(msg, sseEmitter);
//及时返回SseEmitter对象
return sseEmitter;
}
}
sendMsg
方法:
msg
的参数,表示要发送的消息。IdUtil.simpleUUID()
方法生成),然后将消息ID和消息内容存储到 msgMap
中,并返回消息ID。conversation
方法:
@GetMapping
注解进行映射,并指定了返回的内容类型为 MediaType.TEXT_EVENT_STREAM_VALUE
,表明这是一个SSE流式事件的请求。msgId
,表示消息ID。SseEmitter
对象,用于向客户端发送SSE事件。msgMap
中根据消息ID取出对应的消息内容。chatService
的 streamChatCompletion
方法,传递消息内容和 SseEmitter
对象,以便进行后续的流式处理。SseEmitter
对象,以便客户端与服务器建立SSE连接并接收事件流。var eventSource = new EventSource('http://localhost:8080/chat/conversation/'+data)
eventSource.addEventListener('open', function(e) {
console.log("EventSource连接成功");
});
eventSource.addEventListener("message", function(evt){
var data = evt.data;
var json = JSON.parse(data);
var content = json.content ? json.content : '';
content = content.replaceAll('\n','<br/>');
console.log(json)
var outputBody = ('#outputTxt');
outputBody.html(outputBody.html()+content);
var outputCard =('#outputCard');
var scrollHeight = outputCard[0].scrollHeight;
outputCard.scrollTop(scrollHeight);
});
eventSource.addEventListener('error', function (e) {
console.log("EventSource异常:" + e)
});
new EventSource('http://localhost:8080/chat/conversation/'+data)
创建了一个 EventSource 对象,指定了服务器端的 SSE 路径。其中 data
是变量,可能是用于动态构建路径的信息。open
:当连接建立成功时触发。在这里,打印消息 "EventSource连接成功"。message
:当接收到新的消息时触发。在这里,将消息内容解析为 JSON 格式,然后将内容展示到页面上。此处使用了 jQuery 来操作 DOM。error
:当连接发生错误时触发。在这里,打印错误信息。message
事件监听器中,首先解析收到的消息数据,并将其转换为 JSON 格式。<br/>
,以便在页面上正确显示换行。$('#outputTxt')
) 中。powered by kaifamiao