模擬類似 DeepSeek 的對話

以下是一個完整的 JavaScript 數據流式獲取實現方案,模擬類似 DeepSeek 的對話式逐段返回效果。包含前端實現、后端模擬和詳細注釋:

在這里插入圖片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>流式對話演示</title><style>#output {border: 1px solid #ccc;padding: 20px;margin: 20px;min-height: 200px;font-family: monospace;white-space: pre-wrap;}.loading {display: none;color: #666;}</style>
</head>
<body><button onclick="startStream()">開始對話</button><div id="output"></div><div id="loading" class="loading">思考中...</div><script>// 流式對話核心邏輯class StreamDialog {constructor() {this.output = document.getElementById('output');this.loading = document.getElementById('loading');this.controller = null;  // 用于中止請求}// 開始流式對話async start() {try {this.showLoading();this.output.textContent = '';// 創建中止控制器this.controller = new AbortController();// 發起 fetch 請求const response = await fetch('/stream', {signal: this.controller.signal,headers: {'Content-Type': 'application/json'}});if (!response.ok) throw new Error(response.statusText);if (!response.body) throw new Error("ReadableStream not supported");// 創建讀取器const reader = response.body.getReader();const decoder = new TextDecoder();// 持續讀取流數據while (true) {const { done, value } = await reader.read();if (done) break;// 解析數據塊const chunk = decoder.decode(value);const lines = chunk.split('\n').filter(line => line.trim());for (const line of lines) {try {const event = JSON.parse(line.replace('data: ', ''));this.appendContent(event.content);} catch (e) {console.error('解析錯誤:', e);}}}} catch (error) {if (error.name !== 'AbortError') {this.appendContent('\n[對話異常終止]');}} finally {this.hideLoading();this.controller = null;}}// 中止對話abort() {if (this.controller) {this.controller.abort();}}// 添加內容到輸出區appendContent(text) {// 模擬打字機效果let currentIndex = 0;const animate = () => {if (currentIndex < text.length) {this.output.textContent += text[currentIndex];currentIndex++;requestAnimationFrame(animate);this.output.scrollTop = this.output.scrollHeight; // 自動滾動}};animate();}showLoading() {this.loading.style.display = 'block';}hideLoading() {this.loading.style.display = 'none';}}// 初始化對話實例const dialog = new StreamDialog();// 啟動對話function startStream() {dialog.start();}// 中止對話function stopStream() {dialog.abort();}</script>
</body>
</html>

后端 Node.js 實現(Express):

const express = require('express');
const app = express();
const port = 3000;// 允許跨域
app.use((req, res, next) => {res.header('Access-Control-Allow-Origin', '*');next();
});// 流式端點
app.get('/stream', (req, res) => {// 設置流式響應頭res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive'});// 模擬的對話數據const responseText = ["你好!我是 DeepSeek 的智能助手。","我正在分析您的問題...","根據現有數據,建議如下:\n","1. 首先檢查網絡連接\n","2. 驗證 API 密鑰有效性\n","3. 查看服務狀態面板\n","\n需要更詳細的幫助嗎?"];// 發送流式數據let index = 0;const sendChunk = () => {if (index < responseText.length) {const chunk = {content: responseText[index],finished: index === responseText.length - 1};// SSE 格式要求res.write(`data: ${JSON.stringify(chunk)}\n\n`);index++;setTimeout(sendChunk, 500); // 控制發送速度} else {res.end();}};sendChunk();// 處理客戶端斷開連接req.on('close', () => {console.log('客戶端斷開連接');res.end();});
});app.listen(port, () => {console.log(`服務運行在 http://localhost:${port}`);
});

核心實現原理:

  1. 前端實現:
  • 使用 Fetch API + ReadableStream 處理流式數據
  • 支持請求中止(AbortController)
  • 實現打字機動畫效果
  • 自動滾動保持內容可見
  • 加載狀態指示
  1. 后端實現:
  • 使用 Server-Sent Events (SSE) 協議
  • 分塊發送 JSON 格式數據
  • 模擬真實響應延遲(500ms/塊)
  • 支持客戶端斷開檢測
  1. 數據格式:
{"content": "當前內容片段","finished": false
}

優化擴展建議:

  1. 性能優化:
// 添加節流控制
const throttle = (func, limit) => {let lastFunc;let lastRan;return function(...args) {if (!lastRan) {func.apply(this, args);lastRan = Date.now();} else {clearTimeout(lastFunc);lastFunc = setTimeout(() => {if ((Date.now() - lastRan) >= limit) {func.apply(this, args);lastRan = Date.now();}}, limit - (Date.now() - lastRan));}};
};// 在 appendContent 中使用
this.appendContent = throttle(this.appendContent, 50);
  1. 錯誤處理增強:
// 前端添加錯誤處理
async start() {try {// ...原有邏輯...} catch (error) {if (error.name === 'AbortError') {this.appendContent('\n[對話已中止]');} else {this.appendContent(`\n[錯誤: ${error.message}]`);console.error('Stream Error:', error);}}
}// 后端添加錯誤模擬
app.get('/stream', (req, res) => {// 10% 概率模擬錯誤if (Math.random() < 0.1) {res.writeHead(500);res.end();return;}// ...原有邏輯...
});
  1. 功能擴展:
// 添加 Markdown 支持
appendContent(text) {// 簡單 Markdown 解析const parsed = text.replace(/#{3}/g, '<h3>').replace(/#{2}/g, '<h2>').replace(/#{1}/g, '<h1>').replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');// 使用 DocumentFragment 優化渲染const fragment = document.createDocumentFragment();const span = document.createElement('span');span.innerHTML = parsed;fragment.appendChild(span);this.output.appendChild(fragment);
}

這個實現方案完整展示了:

  1. 前后端流式通信的全流程
  2. 實時內容渲染優化技巧
  3. 完整的錯誤處理機制
  4. 可擴展的架構設計
  5. 用戶體驗優化細節

實際部署時,建議:

  1. 使用 WebSocket 替代 SSE 實現雙向通信
  2. 添加 JWT 鑒權
  3. 實現速率限制(Rate Limiting)
  4. 部署到支持 HTTP/2 的服務器
  5. 添加前端緩存策略

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/73393.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/73393.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/73393.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【訓練細節解讀】文本智能混合分塊(Mixtures of Text Chunking,MoC)引領RAG進入多粒度感知智能分塊階段

RAG系統在處理復雜上下文時,傳統和語義分塊方法的局限性,文本分塊的質量限制了檢索到的內容,從而影響生成答案的準確性。盡管其他算法組件有所進步,但分塊策略中的增量缺陷仍可能在一定程度上降低整體系統性能。如何直接量化分塊質量?如何有效利用大型語言模型(LLMs)進行…

IMA+DeepSeekR1+本地知識庫撰寫NOIP2008普及組T3【傳球游戲】題解

目錄 一、提問詞 二、DeepSeekR1回復 題目描述 解題思路 實現代碼 代碼說明 三、說明 【IMADeepSeekR1本地知識庫】撰寫NOIP2008普及組復賽題解系列 1、IMADeepSeekR1本地知識庫撰寫NOIP2008普及組T1【ISBN 號碼】題解-CSDN博客 2、IMADeepSeekR1本地知識庫撰寫NOIP200…

Nginx正向代理HTTPS配置指南(僅供參考)

要使用Nginx作為正向代理訪問HTTPS網站&#xff0c;需通過CONNECT方法建立隧道。以下是操作詳細步驟&#xff1a; 1. 安裝Nginx及依賴模塊 需要模塊&#xff1a;ngx_http_proxy_connect_module&#xff08;支持CONNECT方法&#xff09;。 安裝方式&#xff1a;需重新編譯Nginx…

Python 實現機器學習的 房價預測回歸項目

項目目標&#xff1a; 基于房屋特征&#xff08;如房間數、地理位置等&#xff09;預測加州地區的房價中位數。 使用 Python 實現機器學習的 房價預測回歸項目&#xff08;使用 California Housing 數據集&#xff09; 環境準備 # 安裝必要庫&#xff08;若未安裝&#xff09…

聚力·突破·共贏|修飾組學服務聯盟正式成立,共啟協同發展新篇章

2025年3月13日&#xff0c;上海——由中科新生命、杭州微米生物、廣科安德、承啟生物、派森諾生物、胡珀生物等十余家行業標桿企業共同發起的“修飾組學服務聯盟”成立儀式在上海紫竹新興產業技術研究院隆重舉行。聯盟以“聚力突破共贏”為主題&#xff0c;致力于整合修飾組學全…

【Docker項目實戰】使用Docker部署serverMmon青蛇探針(詳細教程)

【Docker項目實戰】使用Docker部署serverMmon青蛇探針 一、serverMmon介紹1.1 serverMmon 簡介1.2 主要特點二、本次實踐規劃2.1 本地環境規劃2.2 本次實踐介紹三、本地環境檢查3.1 檢查Docker服務狀態3.2 檢查Docker版本3.3 檢查docker compose 版本四、下載serverMmon鏡像五、…

力扣刷題(數組篇)

日期類 #pragma once#include <iostream> #include <assert.h> using namespace std;class Date { public:// 構造會頻繁調用&#xff0c;所以直接放在類里面&#xff08;類里面的成員函數默認為內聯&#xff09;Date(int year 1, int month 1, int day 1)//構…

【通縮螺旋的深度解析與科技破局路徑】

通縮螺旋的深度解析與科技破局路徑 一、通縮螺旋的形成機制與惡性循環 通縮螺旋&#xff08;Deflationary Spiral&#xff09;是經濟學中描述價格持續下跌與經濟衰退相互強化的動態過程&#xff0c;其核心邏輯可拆解為以下鏈條&#xff1a; 需求端萎縮&#xff1a;居民消費信…

單一責任原則在Java設計模式中的深度解析

在軟件開發中&#xff0c;設計模式提供了一種解決特定問題的思路。在眾多的設計原則中&#xff0c;單一責任原則&#xff08;Single Responsibility Principle&#xff0c;SRP&#xff09;是一個非常重要的概念。它主要強調一個類應該只有一個責任&#xff0c;也就是說&#xf…

開源后臺管理系統推薦

前言 在當今數字化時代&#xff0c;企業和組織對于管理和運營資源的需求日益增加。開源后臺管理系統應運而生&#xff0c;為用戶提供了一個靈活、可定制化的管理平臺。本文將介紹開源后臺管理系統的概念和優勢&#xff0c;探討常見的開源后臺管理系統&#xff0c;以及如何選擇…

原生微信小程序實現導航漫游(Tour)

效果&#xff1a; 小程序實現導航漫游 1、組件 miniprogram/components/tour/index.wxml <!--wxml--> <view class"guide" wx:if"{{showGuide}}"><view style"{{guideStyle}}" class"guide-box"><view class&quo…

Docker容器命令速查表

這是 Docker 的快速參考備忘單。 你可以在這里找到最常見的 Docker 命令。 安裝 curl -sSL https://get.docker.com/ | sh sudo chmod 777 /var/run/docker.sock在后臺創建和運行容器 $ docker run -d -p 80:80 docker/getting-started-d - 以分離&#xff08;后臺&#xff0…

Qt QML實現鼠標自由選擇不規則區域進行截圖

背景 不規則區域進行截圖是一種常見的應用場景&#xff0c;通常用于程序截圖工具或者圖像處理軟件中。主要是為了讓用戶可以自由選擇任意形狀的區域進行截圖&#xff0c;而不僅僅局限于矩形區域。這樣用戶可以更靈活地進行截圖操作&#xff0c;特別是對于需要截取特定形狀區域…

SpringDataRedis存儲Redis的數據序列化

在使用Spring Data Redis存儲數據至Redis時&#xff0c;選擇合適的序列化策略至關重要。它不僅影響數據存儲的效率和空間利用率&#xff0c;還關系到跨語言兼容性和系統的擴展性。適當的序列化方式可以確保數據正確無誤地被存儲和讀取&#xff0c;提升系統的穩定性和維護性&…

交易系統【三】網關

第二章本來是要講消息總線&#xff0c;審核說是過度宣傳&#xff0c;就放棄了&#xff0c;不糾結&#xff0c;先跳過。 網關和消息總線的底層技術都和網絡相關&#xff0c;兩者也有很重要的差別。消息總線主要用于內網&#xff0c;受交換機和網卡影響比較大&#xff0c;網絡狀…

eNSP中路由器的CON/AUX接口、GE Combo接口、Mini USB接口、USB接口、WAN側uplink接口、FE接口、GE接口介紹

路由器常見接口的詳細介紹及其應用示例&#xff1a; 1. CON/AUX 接口 全稱&#xff1a;Console/Auxiliary&#xff08;控制臺/輔助接口&#xff09;作用&#xff1a; CON&#xff08;Console&#xff09;&#xff1a;通過命令行界面&#xff08;CLI&#xff09;直接配置路由器…

iOS底層原理系列04-并發編程

在移動應用開發中&#xff0c;流暢的用戶體驗至關重要&#xff0c;而并發編程是實現這一目標的關鍵技術。本文將深入探討iOS平臺上的并發編程和多線程架構&#xff0c;幫助你構建高性能、響應迅速的應用程序。 1. iOS線程調度機制 1.1 線程本質和iOS線程調度機制 線程是操作…

Vmware下的openEuler

1.下載openEuler操作系統鏡像 https://repo.openeuler.org/openEuler-20.03-LTS/ISO/ 2.在VM新建虛擬機 3.虛擬機聯網 我是出現了沒有網絡&#xff0c;ping不通的問題 參考&#xff1a;https://blog.csdn.net/FHY26828/article/details/140941234 修改文件&#xff1a; 在…

帶寬管理配置實驗

一、實驗拓撲 配置流程&#xff1a; 1、帶寬通道&#xff1a;整體帶寬、每個用戶帶寬、連接數、優先級信息 2、帶寬策略 3、策略通道&#xff0c;引用 4、配置接口出入帶寬 二、實驗需求和配置 1、基礎配置 接口配置 [dianxin]interface GigabitEthernet 0/0/0 [dianxin-G…

【STM32】從新建一個工程開始:STM32 新建工程的詳細步驟

STM32 開發通常使用 Keil MDK、STM32CubeMX、IAR 等工具來創建和管理工程。此處是 使用 Keil MDK5 STM32CubeMX 創建 STM32 工程的詳細步驟。 新建的標準庫工程文件已上傳至資源中&#xff0c;下載后即可直接使用。 標準庫新建 STM32 工程的基本目錄結構&#xff1a;STD_STM…