类ChatGPT聊天应用流式响应优化:实时渲染与性能平衡咨询
类ChatGPT聊天应用实时渲染优化方案求助
我正在开发一款类ChatGPT的聊天应用,目前需要优化实时消息渲染的技术方案。之前尝试过两种渲染策略,但都存在问题:
- 策略1:当消息缓冲区字符数超过50时更新Redux状态触发UI重渲染,但会出现响应卡顿。
- 策略2:仅在收到完整响应的message.id时更新状态,减少了重渲染次数,但用户需要等待完整内容加载完成,期间只能看到占位符。
我希望实现类似ChatGPT的实时逐段/逐字显示效果,同时保证响应速度,避免频繁重渲染带来的性能损耗。以下是相关代码:
SocketService 代码
import { addMessage, modifyLatestMessage, removeLatestMessage, setError, setStatus, store, } from "@/store"; import { io, Socket } from "socket.io-client"; const messageChunkSize = 50; class SocketService { private socket: Socket | null = null; private messageBuffer = ""; connectSocket = (sessionToken: string) => { if (!this.socket) { this.socket = io("https://sakkarai-backend.azurewebsites.net", { path: "/sockets/v1", auth: { token: sessionToken }, transports: ["websocket"], // 优先使用WebSocket传输 reconnectionAttempts: 5, timeout: 10000, }); this.socket.on("connect", () => { console.log("Socket connected"); store.dispatch(setStatus("CONNECTED")); }); this.socket.on("disconnect", () => { console.log("Socket disconnected"); store.dispatch(setStatus("DISCONNECTED")); }); this.socket.on("receiveMessage", (message) => { console.log("Message received at:", new Date().toISOString(), message); let updateMessage = false; let payload: any = {}; if (message.message) { this.messageBuffer += message.message; // if (this.messageBuffer.length >= messageChunkSize) { // store.dispatch( // modifyLatestMessage({ message: this.messageBuffer }) // ); // this.messageBuffer = ""; // } } if (message.id) { store.dispatch( modifyLatestMessage({ message: this.messageBuffer, id: message.id }) ); this.messageBuffer = ""; } if (message.commit) { store.dispatch(modifyLatestMessage({ commit: message.commit })); } }); this.socket.on("error", (error: any) => { console.error("Socket error:", error); store.dispatch(setStatus("IDLE")); if (error.code === "insufficient-quota") { store.dispatch(removeLatestMessage("assistant")); store.dispatch(removeLatestMessage("user")); store.dispatch(setError(error.message)); } }); } }; emitMessage = (message: string) => { if (this.socket && this.socket.connected) { store.dispatch( addMessage({ content: message, createdAt: new Date(), role: "user", canCommit: false, user: null, }) ); store.dispatch( addMessage({ content: "", createdAt: new Date(), role: "assistant", canCommit: false, user: null, }) ); this.socket.emit("sendMessage", { message }); store.dispatch(setStatus("STREAMING")); } else { console.error("Socket is not connected!"); } }; disconnect() { if (this.socket) { this.socket.disconnect(); this.socket = null; store.dispatch(setStatus("DISCONNECTED")); } } } export const socketService = new SocketService();
chatSlice 代码
export const chatSlice = createSlice({ name: "chat", initialState, reducers: { setMessages: (state, action) => { state.messages = action.payload; }, addMessage: (state, action: { payload: Message }) => { console.log("Adding Message", action.payload) state.messages.unshift(action.payload); }, setStatus: (state, action) => { state.status = action.payload; }, modifyLatestMessage: ( state, action: { payload: { id?: string; message?: string; commit?: boolean }; } ) => { if (state.messages.length > 0) { if (action.payload.message) { state.status = "STREAMING"; state.messages[0].content += action.payload.message; } if (action.payload.commit) { state.messages[0].canCommit = action.payload.commit; } if (action.payload.id) { state.status = "IDLE"; if (state.messageBuffer.length > 0) { state.messages[0].content += state.messageBuffer; state.messageBuffer = ""; } state.messages[0].id = action.payload.id; } } }, removeLatestMessage: (state, action: { payload: string }) => { const role = action.payload; const lastUserMessageIndex = state.messages.findIndex( (msg) => msg.role === role ); if (lastUserMessageIndex !== -1) { state.messages.splice(lastUserMessageIndex, 1); } }, resetChat: (state) => { state.messages = []; state.metadata = undefined; }, setError: (state, action) => { state.error = action.payload; }, clearError: (state) => { state.error = null; }, }, extraReducers: (builder) => { builder.addCase(fetchMessages.pending, (state) => { state.status = "LOADING_MESSAGES"; }); builder.addCase(fetchMessages.fulfilled, (state, action) => { state.messages.push(...action.payload.data); state.metadata = action.payload.metadata; state.status = "IDLE"; }); builder.addCase(fetchMessages.rejected, (state) => { state.status = "IDLE"; }); // builder.addCase(sendMessage.pending, (state) => { // state.status = "STREAMING_MESSAGE"; // }); // builder.addCase(sendMessage.fulfilled, (state) => { // if (commitmentParser.test(state.messages[0].content)) { // state.messages[0].canCommit = true; // } // state.status = "IDLE"; // }); // builder.addCase(sendMessage.rejected, (state, action) => { // state.status = "IDLE"; // state.messages.shift(); // if (action.payload === "insufficient-quota") { // state.error = "You have exceeded your message quota."; // } // }); builder.addCase(clearConversation.pending, (state) => { state.status = "CLEARING_CHAT"; }); builder.addCase(clearConversation.fulfilled, (state) => { state.status = "IDLE"; }); builder.addCase(clearConversation.rejected, (state) => { state.status = "IDLE"; }); }, });
内容的提问来源于stack exchange,提问作者Hamza10
相关产品推荐
相关产品推荐

