当前位置: 首页 > ai >正文

前端接收流式数据demo,并用markdown解析数据,包括EventSource和fetch两种方式

前端接收流式数据demo

可以直接复制代码

如上视频,要实现类似deepseek和chatgpt的效果,用传统的方式接受数据根本行不通,必须使用SSE, Server-Sent Events(SSE)功能,允许服务端推送数据到客户端,通常叫数据推送。当数据源有新数据,它马上发送到客户端,不需要再等待客户端请求。
这里提供了完整的前端代码和用node.js写的后端模拟数据,分别包括了get和post方式,因为EventSource只支持get方式,后用fetch支持了post方式,两种效果都是一样的。

前端用的vue2,node版本v16.20.2,介绍一篇nvm管理node版本的文章(https://blog.csdn.net/qq_41822157/article/details/141259132)

DeepSeekChatGet.vue

<template><div class="deepseek-chat"><div class="chat-container" ref="chatContainer"><div class="messages"><divv-for="(message1, index) in messages":key="index":class="['message', message1.role]"><div class="avatar"><span v-if="message1.role === 'user'"></span><span v-else>DS</span></div><div class="message-content"><divclass="message-body"v-for="(message, index1) in message1.arr":key="index1"><!-- 文本内容 --><div v-if="message1.role === 'user'" class="text-content"><p>{{ message.content }}</p></div><div v-else class="text-content"><p v-if="index === 0">{{ message.content }}</p><div v-else><div><pv-html="md.render(message.content)"class="chatDatas-box"></p></div></div></div><!-- 加载状态 --><divv-if="index1 === messages[messages.length - 1].arr.length - 1 &&isStreaming"class="typing-indicator"><span></span><span></span><span></span></div></div></div></div></div></div><div class="input-area"><div class="input-container"><textareav-model="userInput"placeholder="输入消息..."@keydown.enter.exact.prevent="sendMessage3"@keydown.shift.enter="newLine"rows="2"ref="textarea"></textarea><button @click="sendMessage3" :disabled="isStreaming"><span v-if="!isStreaming">发送</span><span v-else>生成中...</span></button></div></div></div>
</template><script>
class DeepSeekStream {constructor() {this.buffer = "";this.eventSource = null;}connect(url, onMessage, onComplete, onError, onStart) {this.eventSource = new EventSource(url);this.eventSource.addEventListener("message", (event) => {try {// 确保处理完整的消息if (event.data.trim()) {const message = JSON.parse(event.data);onMessage(message);}} catch (error) {onError(`消息解析错误: ${error.message}`);}});this.eventSource.addEventListener("end", () => {onComplete();this.close();});this.eventSource.addEventListener("error", (error) => {onError(`流错误: ${error.message}`);this.close();});this.eventSource.addEventListener("open", () => {//监听连接成功的时候onStart();});}close() {if (this.eventSource) {this.eventSource.close();this.eventSource = null;}}
}// 导入解析markdown语法的第三方库markdown-it
import MarkdownIt from "markdown-it";// 引入代码高亮
import hljs from "highlight.js";
// 你用到了什么语言就要引入什么语言,目前我还不知道怎么样导入所有语言
import javascript from "highlight.js/lib/languages/javascript";
//  这个是高亮的样式,有很多,我选了这个
import "highlight.js/styles/ir-black.css";hljs.registerLanguage("javascript", javascript);
import "highlight.js/styles/github-dark.css";
export default {name: "DeepSeekChat",data() {return {userInput: "js中 array.sort的用法",messages: [{role: "assistant",model: "deepseek-chat",arr: [{content: "您好!请输入您的问题",type: "text",},],},],isStreaming: false,streamHandler: null,selectedModel: "deepseek-chat",chatDatas: [],md: new MarkdownIt({html: true, // 允许HTML标签linkify: true, // 自动转换URL为链接typographer: true, // 优化排版breaks: true, // 将换行符转换为<br>highlight: function (str, lang) {// 代码高亮处理if (lang && hljs.getLanguage(lang)) {try {return ('<pre class="hljs"><code>' +hljs.highlight(lang, str, true).value +"</code></pre>");} catch (error) {console.error(error);}}return ('<pre class="hljs"><code>' +this.md.utils.escapeHtml(str) +"</code></pre>");},}),};},computed: {},methods: {sendMessage3() {if (!this.userInput.trim() || this.isStreaming) return;// 添加用户消息this.messages.push({role: "user",model: this.selectedModel,arr: [{content: this.userInput,},],});const prompt = this.userInput;// const prompt = "111";this.userInput = "";// 添加AI消息占位this.messages.push({role: "assistant",model: this.selectedModel,arr: [],});let arr1 = { content: "思考中,请稍候..." };this.messages[this.messages.length - 1].arr.push(arr1);// 创建流处理器this.streamHandler = new DeepSeekStream();const url = `http://localhost:3000/deepseek-stream?prompt=${encodeURIComponent(prompt)}&model=${this.selectedModel}`;console.log("this.messages", this.messages);this.streamHandler.connect(url,(data) => {// console.log("data--", data.content);arr1.content += data.content;// console.log("this.chatDatas---", this.chatDatas);// 滚动到底部this.scrollToBottom();},() => {console.log("结束了");this.isStreaming = false;this.scrollToBottom();},(error) => {console.error("流错误:", error);},() => {// console.log("开始---111");this.messages[this.messages.length - 1].arr[0].content = "";});this.scrollToBottom();},newLine() {this.userInput += "\n";this.$nextTick(() => {this.$refs.textarea.scrollTop = this.$refs.textarea.scrollHeight;});},copyCode(code) {navigator.clipboard.writeText(code).then(() => {// this.$toast.success("代码已复制到剪贴板");});},scrollToBottom() {this.$nextTick(() => {const container = this.$refs.chatContainer;container.scrollTop = container.scrollHeight;});},},mounted() {this.scrollToBottom();},beforeDestroy() {if (this.streamHandler) {this.streamHandler.close();}},
};
</script><style lang="less" scoped>
:
http://www.xdnf.cn/news/14895.html

相关文章:

  • 前端交互自定义封装类:“双回调自定义信息弹窗”
  • 香港维尔利健康科技集团AI健康云平台通过国际信息安全认证,打造全球健康数据合规新标杆
  • Transformer-BiGRU、Transformer、CNN-BiGRU、BiGRU、CNN五模型回归预测对比,Matlab代码实现
  • Ollama+OpenWebUI 0.42+0.3.35 最新版一键安装教程,解决手动更新失败问题
  • 传输层协议TCP、UDP
  • [NOIP][C++]洛谷P1376 [USACO05MAR] Yogurt factory 机器工厂
  • 实战Linux进程状态观察:R、S、D、T、Z状态详解与实验模拟
  • 智能推荐社交分享小程序(websocket即时通讯、协同过滤算法、时间衰减因子模型、热度得分算法)
  • 自动驾驶感知系统
  • 爬虫-request处理POST
  • 当DMA想“越狱”:IOMMU怎么硬核拦截?
  • c语言学习_函数递归
  • 深度学习-多分类
  • Linux网络:UDP socket创建流程与简单通信
  • AWS OpenSearch Dev Tools使用
  • FastAPI Docker环境管理脚本使用指南
  • 人体坐姿检测系统开发实战(YOLOv8+PyTorch+可视化)
  • 微服务集成snail-job分布式定时任务系统实践
  • 向量与向量组的线性相关性 线性代数
  • Spring Boot + Easy Excel 自定义复杂样式导入导出
  • [ESP32]VSCODE+ESP-IDF环境搭建及blink例程尝试(win10 win11均配置成功)
  • 香港站群服务器价格怎么样?
  • 容器技术入门之Docker环境部署
  • ffmpeg 中config 文件一些理解
  • Netstat高级分析工具:Windows与Linux双系统兼容的精准筛查利器
  • 一天一道Sql题(day03)
  • 如何用Python编程计算权重?
  • houdini云渲染和云解算新选择
  • 基于SpringBoot+Vue的非遗文化传承管理系统(websocket即时通讯、协同过滤算法、支付宝沙盒支付、可分享链接、功能量非常大)
  • 什么是2.5G交换机?