背景
要集成chatGpt參考我上一篇文章即可,但是,如果要實作官網一樣的效果,逐字輸出,難度就提升了不少了,經過在官網的研究發現它應該是采用了SSE技術,這是一種最新的HTTP互動技術,SSE(Server-Sent Events):通俗解釋起來就是一種基于HTTP的,以流的形式由服務端持續向客戶端發送資料的技術,相比較WebSocket更加輕量了,有了SSE,我們就可以實作,一次HTTP請求,可以逐步獲取后端內容并及時輸出展示,也就可以實作ChatGpt官網的效果了,下面給出簡單的實作代碼
后端核心代碼
@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; } }
前端核心代碼
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 =https://www.cnblogs.com/hdwang/p/ 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) });
效果圖

完整專案代碼
https://github.com/hdwang123/GptTest
感想
在調研這個技術的時候,遇到很多挑戰,雖然艱難好在最終都克服了,主要有以下幾個方面的問題:
1. SSE技術僅支持GET請求,這個查了相關文章有第三方庫可以實作POST,由于我這里只是做個簡單的例子,所以不想再去弄什么第三方庫,于是終于想到了辦法,就是在后端進行訊息暫存:先用POST請求將資料提交到后端,回傳一個訊息ID,然后再用使用SSE技術提交訊息ID建立連接,
2. SSE向前端send的訊息總是一把輸出,并沒有實作逐字輸出效果,折騰了半天終于從SSE原始碼中看到了解決方案,那就是GetMapping控制器方法必須及時回傳,要做到這一點,send訊息方法的呼叫必須在新的執行緒中進行呼叫,我用@Async解決了
3.SSE向前端輸出英文的時候丟失空格,所有英文單詞擠在一起了,哎!這個我一開始是直接發送訊息內容的,發現英文單詞前面的空格丟失了,沒辦法,改成現在發送json物件字串的方式,保證了空格不丟失,
4. 前端樣式調整問題,主要遇到了滾動條自動滾動到div底部失效問題,scrollTop設定值始終為0,看了好多文章,也找不到解決方案,后來看到別人寫的是兩個div,靈感來了,我也用兩個div,父div設定滾動,子div設定內容,這樣就搞定了!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554743.html
標籤:Java
上一篇:Java物件中轉換空值的欄位
下一篇:返回列表
