vue3+fetch请求+接收到流式的markdown数据+一边gpt打字机式输出内容,一边解析markdown语法+highlight.js实现代码高亮

news2024/9/17 8:47:23

这个问题终于解决了!好开心。

先看最终效果:

video_20240724_141543_edit

项目背景:vue3

场景:像gpt一样可以对话,当用户发送问题之后,ai回复,ai是一部分一部分回复,像打印机式输出。后端返回的是流式数据,且这个数据是如下格式:

data里的content存放的就是ai回复的一部分数据,但这个数据是Unicode格式的字符串,前端(我)需要做的就是实现视频中的效果:打印机式的输出+实时解析markdown文本并正确渲染到页面上。

如果你只是要实现打印机式的输出,直接看我之前的一篇文章就行:

像ChatGPT一样实现打印机式输出_vue 仿gpt打印显示-CSDN博客

如果你要实现:打印机式的输出+实时解析markdown文本并正确渲染到页面上,就请继续往下看。

特别提示:如果你接收到的数据格式和我的不一样,我也不确定能不能帮到你,因为之前我的后端给我返回的数据格式不长这样,之前是直接是data:'数据'的格式,我试过很多方法都不能边接收markdown语法的数据,边正确解析渲染到页面上,当时我没想过可能是后端数据格式的问题,我就一直认为是我这边的问题。所以如果你怎么试都不成功,可以试着让后端改改。

解析Unicode格式的字符串的方法

// 解码包含Unicode转义序列的字符串
function decodeUnicode(str) {
  return str.replace(/\\u[\dA-Fa-f]{4}/g, function(match) {
    return String.fromCharCode(parseInt(match.substr(2), 16));
  });
}

配置环境

//为了接收流式数据,需导入
npm install --save @microsoft/fetch-event-source
//这里我使用的是markdown-it这个库去解析markdown文本。
npm install markdown-it --save

 下面两块代码,其实就是整个效果的完整代码

//script标签中
 
// 导入EventSource,这里使用fetchEventSource去接收流式数据
import { fetchEventSource } from '@microsoft/fetch-event-source';
// 导入解析markdown语法的第三方库markdown-it
import MarkdownIt from 'markdown-it'
let md: MarkdownIt = new MarkdownIt()

// 聊天框内容列表
let chatDatas = ref([])

// 解码包含Unicode转义序列的字符串
function decodeUnicode(str) {
  return str.replace(/\\u[\dA-Fa-f]{4}/g, function(match) {
    return String.fromCharCode(parseInt(match.substr(2), 16));
  });
}
// 发送信息按钮
let sendMessage = async () => {
      let arr1=reactive({
        注意初始值要为空字符串,后面才能拼接
        content: ''
      });
      chatDatas.push(arr1)
      // 请求数据,流式输出
    await fetchEventSource(baseURL+'/require/stream_generate_requirements', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json;charset=utf-8'
        },
         body: JSON.stringify({
        要传递的参数
    }),
    
      async onmessage(ev) {
        // ev.data里面是实时传递过来的数据
        // 根据后端返回的数据,我这里需要将字符串转成对象
        let obj = JSON.parse(ev.data)
        // 拿到具体的内容
        let content = obj.content
        // Unicode转成中文
        let decodeContent = decodeUnicode(content)
        // 拼接:这里是数据打印机式输出的关键
        arr1.content+=decodeContent
      },
       //会话发送完毕时触发
  onclose() {
        这里可以写结束时,你需要做的事,如果没有,可以删除
      }
    })
}
    
 // template标签中
<div 
    v-for="i in chatDatas" 
    :key="i.content" 
>
  <p v-html="md.render(i.content)"></p>
</div>

拓展:代码高亮 

如果你收到的数据中包含代码,你想让代码高亮,则你需要添加这些东西:

配置:

 npm install highlight.js --save
// script标签中
// 引入代码高亮
import hljs from 'highlight.js';
// 你用到了什么语言就要引入什么语言,目前我还不知道怎么样导入所有语言
import javascript from 'highlight.js/lib/languages/javascript';
//  这个是高亮的样式,有很多,我选了这个
import 'highlight.js/styles/ir-black.css';

hljs.registerLanguage('javascript', javascript);

let md: MarkdownIt = MarkdownIt({
  highlight: function (str: string, lang: string) {
    const language = hljs.getLanguage(lang);
    if (language) {
        try {
            return `<div>
                        <div>
                            <span>${lang}</span>
                        </div>
                        <div class="hljs">
                            <code>${hljs.highlight(lang, str, true).value}</code>
                        </div>
                    </div>`;
        } catch (error) {
            console.error(error);
        }
    }
    // 如果未指定语言或无法识别语言,则使用默认的逃逸 HTML 处理
    return `<div class="hl-code">
                <div>
                    <span>${lang}</span>
                </div>
                <div class="hljs">
                    <code>${md.utils.escapeHtml(str)}</code>
                </div>
            </div>`;
}
})

到这里,基本的功能和样式应该都实现了,希望能帮到你。

如果本文对你有帮助,希望能得到你的点赞或收藏或关注,这是对我最好的鼓励;

如你有问题或疑惑,欢迎在评论区写下,必将努力解答;

如本文有误区,希望你不吝赐教,让我们共勉!
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962323.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何将本地代码上传到github

将本地文件上传到GitHub仓库的过程通常包括以下几个步骤&#xff1a; 一 创建GitHub仓库&#xff1a; 如果你还没有一个GitHub仓库&#xff0c;首先需要在GitHub上创建一个新的仓库。登录到你的GitHub账户&#xff0c;然后点击“New repository”按钮&#xff0c;填写仓库的相关…

在linux运维中为什么第一道防线是云防火墙,而不是waf

在Linux运维和云计算环境中&#xff0c;第一道防线通常是云防火墙&#xff08;Cloud Firewall&#xff09;&#xff0c;而不是Web应用防火墙&#xff08;WAF&#xff09;&#xff0c;主要是因为云防火墙提供了更基础和广泛的网络层安全控制。以下是一些关键原因&#xff1a; 1…

AGI思考探究过程中的意义、价值与乐趣 Ⅱ

鉴于LLM与RL两者间在整体学习范式、学习目标、模型结构的差异化与统一的考量&#xff0c;业内不少的思路尝试将两种思想融合在一起以期待AGI的突破&#xff0c;但结合后要么看着不是很巧妙&#xff0c;要不就是看起来很僵硬&#xff0c;总感觉像是一个过渡性的方法&#xff0c;…

C语言指针·入门用法超详解

目录 1. 什么是指针 2. 指针变量的定义格式 3. 指针的作用 3.1 查询数据 3.2 存储数据&#xff08;修改数据&#xff09; 3.3 操作其他函数中的变量 3.4 函数返回多个值 3.5 函数的结果和计算状态分开 1. 什么是指针 通过内存地址&#xff0c;指向的空间&#…

装饰大师——装饰模式(Java实现)

引言 大家好&#xff0c;上期我们介绍了装饰模式在Python中的实现&#xff0c;今天&#xff0c;我们将继续探讨装饰模式&#xff0c;并展示如何在Java中实现它。 装饰模式概述 装饰模式的核心思想是将功能附加到对象上&#xff0c;而不是通过继承来实现&#xff0c;这种模式…

【JavaSE-线程安全问题-死锁详解】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 &#x1f308;…

HTML基础1-文本级元素

HTML 简介 什么是 HTML&#xff1f; HTML (HyperText Markup Language) 是一种用于创建网页的标准标记语言。它通过使用一系列预定义的元素来描述文档的结构和外观&#xff0c; 您可以使用 HTML 来建立自己的 WEB 站点。 HTML 的作用 HTML 用于定义网页的结构&#xff0c;…

快手文生图模型-Kolors快速上手

Kolors是什么 可图(Kolors)&#xff1a;用于真实感文本到图像合成的扩散模型的有效训练 可图&#xff0c;是快手开源的一个文生图模型&#xff0c;架构上使用了chatglm&#xff0c;比普通的sd模型在中文理解上要强大很多&#xff0c;以往sd模型的提示词理解能力往往只有两种 …

《BeanShell 在 JMeter 中的应用》总结

通过案例进行讲解 一、BeanShell 介绍 官网: http://www.BeanShell.org BeanShell 是一种完全符合 Java 语法规范的脚本语言&#xff0c;具有以下特点&#xff1a; 是一种松散类型的脚本语言&#xff0c;类似 JS。是用 Java 写成的小型、免费、可下载的嵌入式 Java 源代码解…

计算机毕业设计选题推荐-零食批发商仓库管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

LocalDateTime的序列化和反序列化

背景 最近定位出一个LocalDateTime序列化相关的问题&#xff0c;简单记录一下。本文重点介绍Jackson对LocalDateTime的序列化和反序列化&#xff0c;并结合Spring应用场景进行介绍。 1.LocalDateTime与字符串转换 可以通过DateTimeFormatter实现LocalDateTime与字符串的相互…

Windows远程桌面无法拷贝文件问题

场景说明 Winwdows远程桌面&#xff0c;相比Linux方便一点就是&#xff0c;同是windows连接&#xff0c;其中复制粘贴功能&#xff0c;可以在两个windows无缝切换。 但最近笔者远程一台测试windows服务器时&#xff0c;发现无法在服务器上复制内容到本地&#xff0c;也无法从…

西门子s7第三方(S7netplus)读写操作

和西门子PLC通讯需要使用S7netplus​​这个包&#xff0c;可以在NuGet​​上搜索下载&#xff0c;下载后引入命令空间using S7.Net;​​ 创建PLC对象进行连接使用Write Read进行读写操作即可不需要在发请求帧 //创建Plc对象Plc plc; //西门子设备是s7-1200//参数1 CPu类型//参…

微信小程序+JAVA实现微信支付

时隔两年再次回归 本文主要讲的是小程序实现微信支付功能&#xff0c;后台采用JAVA。 一.准备工作 1.小程序 2.微信商户号 1.商户号申请 这里对小程序的申请不做赘述。 如果没有微信商户号的同学&#xff0c;点击该链接https://pay.weixin.qq.com/&#xff0c;按照下属步骤…

低代码与人工智能的融合:加速应用开发的未来趋势

什么是低代码&#xff0c;它是如何工作的&#xff1f; 低代码是一种软件开发概念&#xff0c;它通过最小化手工编码的方式&#xff0c;为开发和部署定制化应用提速。低代码平台具备模型驱动、沙盒多环境、可编程的可视化开发方式等&#xff0c;能用于开发包含有用户界面、业务逻…

二叉树——链式结构的实现

首先是分为三个文件进行实现&#xff1a;tree.h、tree.c、test.c tree.h 用链表来表示⼀棵⼆叉树&#xff0c;即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成&#xff0c;数据域和左右指针域&#xff0c;左右指针分别用来给出该结点左孩⼦和右孩⼦所在…

基于Springboot + vue + mysql 校友社交管理系统 设计实现

目录 &#x1f4da; 前言 &#x1f4d1;摘要 1.1 研究背景 &#x1f4d1;操作流程 &#x1f4da; 系统架构设计 &#x1f4da; 数据库设计 &#x1f4ac; E-R表 4.2.2数据库逻辑结构设计 &#x1f4da; 系统功能的具体实现 系统功能模块 系统首页 校友会信息 校友活动 …

仿RabbitMQ实现消息队列———整体框架

目录 一、项目简介 需求分析 AMQP 特点&#xff1a; AMQP 模型&#xff1a; 交换机类型 持久化 网络通信 二、服务端模块 1、交换机数据管理 2、队列数据管理 3、绑定数据管理 4、消息数据管理 5、虚拟机数据管理 6、路由匹配管理 7、消费者管理 8、信道管理 …

智源发布三款BGE新模型,再次刷新向量检索最佳水平

近期&#xff0c;以大语言模型&#xff08;LLM&#xff09;为基础的向量模型&#xff08;embedding model&#xff09;变得愈发流行。得益于大语言模型强大的语义理解能力&#xff0c;相关模型在下游任务中的检索精度得到了显著的提升。然而&#xff0c;当前基于大模型的向量模…