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

前端对接fastGPT流式数据+打字机效果

首先在对接api时 参数要设置stream: true,

      const data = {chatId: 'abc',stream: true,//这里true返回流式数据detail: false,variables: {uid: 'sfdsdf',name: 'zhaoyunyao,'},messages: [{ content: text, role: 'user' }]};

不要用axios发请求 不然处理不了流式数据 我这里使用fetch

        const response = await fetch(`${url}`, {method: 'post',headers: headers,body: JSON.stringify(data)});const reader = response.body.getReader();//创建了一个读取器对象,用于从响应主体中读取数据。response.body 是一个 ReadableStream 对象,通过调用 getReader() 方法可以获取一个读取器对象,以便逐步读取响应的内容。// 循环读取响应流while (true) {const { done, value } = await reader.read();if (done) break;// 将ArrayBuffer转为文本const chunk = new TextDecoder('utf-8').decode(value);// 处理文本为json格式const jsonArr = chunk.trim().replace(/\n/g, '').split('data: ').splice(1)for (let index = 0; index < jsonArr.length; index++) {const json = jsonArr[index];try {if (JSON.parse(json).choices) {const text = JSON.parse(json).choices[0].delta.content ?? ''content += text.replace(/^\n/g, '')} else {content = "内部出了问题o(╥﹏╥)o"}} catch {// 处理转json不报错}}obj.content = content //这里的content就是最终输出的文本}

然后我们再加一个打字机的光标 用html+css实现

              <div class="chat-item-details">{{ item.content }}/** 这里的span就是光标 **/<span class="cursor-blink" v-show="item.awaitReply">  </span></div>

再写上对应的css 

              .cursor-blink {display: inline-block;height: 16px;margin-bottom: -3px;width: 2px;animation: blink 1s infinite steps(1, start);}/*这里设置动画blink*/@keyframes blink {0%,100% {background-color: #000;color: #aaa;}50% {background-color: #bbb;/* not #aaa because it's seem there is Google Chrome bug */color: #000;}}

最后呈现的效果

上图呈现的差不多是打字机的效果了 不过呢 但在传输过程中每次停顿后会跳出一串内容然后又停顿一会,阅读体验有些不流畅, 就像玩游戏时帧数低卡顿的感觉, 我们用一个队列让它逐字地展示出来,并且根据传输速度控制输出的速度

  1. 需要一个打字机队列
  2. 队列提供入队和消费功能
  3. 需要一个动态时间来控制文字输出

 

    // 打字机队列// 添加队列addQueue(str,obj) {obj.queue.push(...str.split(''))},// 消费队列consume(obj) {if (obj.queue.length > 0) {let str = obj.queue.shift()str && this.onConsume(str,obj)} else if (obj.isDone) {obj.consuming = falseclearTimeout(obj.timmer)obj.awaitReply = falsethis.scrollBottom()}},// 消费间隔time(obj) {let time = 1000 / obj.queue.lengthreturn time > 100 ? 100 : time},// 消费下一个next(obj) {this.consume(obj)obj.timmer = setTimeout(() => {if (obj.consuming) {this.next(obj)}}, this.time(obj))},start(obj) {obj.consuming = trueobj.isDone=falsethis.next(obj)},done(obj) {obj.isDone=true},onConsume(str,obj) {obj.content += str},

 加了过后的效果

最后附上完整代码

export default {data() {return {key: "xxx",AppId: "xx",text: "",readonly: false,messages: [{ content: "您好,我是小环!请问需要什么帮助呢?", role: 'assistant', awaitReply: false },],userImg: this.$store.getters.avatar,username: this.$store.getters.nickname,awaitReply: false,timmer: null,obj: null,queue: [],consuming: false,isDone: false}},mounted() {const messageTextarea = document.getElementById('messageTextarea');messageTextarea.addEventListener('keydown', (event) => {// 如果按下的是回车键(Enter)if (event.key === 'Enter' && !event.ctrlKey) {event.preventDefault(); // 阻止默认的换行行为// 在这里可以添加发送消息的逻辑this.send();} else if (event.key === 'Enter' && event.ctrlKey) {const cursorPosition = messageTextarea.selectionStart; // 获取光标位置const textBeforeCursor = messageTextarea.value.substring(0, cursorPosition); // 获取光标前的文本const textAfterCursor = messageTextarea.value.substring(cursorPosition); // 获取光标后的文本messageTextarea.value = textBeforeCursor + '\n' + textAfterCursor; // 在光标位置插入换行符messageTextarea.selectionStart = cursorPosition + 1; // 设置光标位置为插入换行符后的位置messageTextarea.selectionEnd = cursorPosition + 1;}});},methods: {// 打字机队列// 添加队列addQueue(str, obj) {obj.queue.push(...str.split(''))},// 消费队列consume(obj) {if (obj.queue.length > 0) {let str = obj.queue.shift()str && this.onConsume(str, obj)} else if (obj.isDone) {obj.consuming = falseclearTimeout(obj.timmer)obj.awaitReply = falsethis.scrollBottom()}},// 消费间隔time(obj) {let time = 500 / obj.queue.lengthreturn time > 50 ? 50 : time},// 消费下一个next(obj) {this.consume(obj)obj.timmer = setTimeout(() => {if (obj.consuming) {this.next(obj)}}, this.time(obj))},start(obj) {obj.consuming = trueobj.isDone = falsethis.next(obj)},done(obj) {obj.isDone = true},onConsume(str, obj) {obj.content += str},async send() {if (this.text === "" || /^\s+$/.test(this.text)) {this.$message.warning('请输入内容')return}const text = this.textthis.text = ""const url = 'https://api.fastgpt.in/api/v1/chat/completions';this.messages.push({ role: 'user', content: text });let obj = { content: "", role: 'assistant', awaitReply: true, queue: [], consuming: false, isDone: false, timmer: null }this.messages.push(obj);this.scrollBottom()const data = {// 这里可以设置请求参数chatId: 'abc',stream: true,detail: false,variables: {uid: 'sfdsdf',name: 'zhaoyunyao,'},messages: [{ content: text, role: 'user' }]};const headers = {// 这里可以设置请求头Authorization: `Bearer ${this.key}`,"Content-Type": "application/json"};try {const response = await fetch(`${url}`, {method: 'post',headers: headers,body: JSON.stringify(data)});const reader = response.body.getReader();//let content = ""// 开始打字机队列this.start(obj)// 循环读取响应流while (true) {const { done, value } = await reader.read();if (done) break;// 将ArrayBuffer转为文本const chunk = new TextDecoder('utf-8').decode(value);// 处理文本为json格式const jsonArr = chunk.trim().replace(/\n/g, '').split('data: ').splice(1)for (let index = 0; index < jsonArr.length; index++) {const json = jsonArr[index];try {if (JSON.parse(json).choices) {const text = JSON.parse(json).choices[0].delta.content ?? ''this.addQueue(text.replace(/^\n/g, ''), obj)} else {this.addQueue('内部出了问题o(╥﹏╥)o', obj)}} catch {// 处理转json不报错}}this.scrollBottom()}} catch (error) {console.error('请求错误:', error);}this.done(obj)},// 滚到最底部scrollBottom() {setTimeout(() => {const mainChat = this.$refs.mainChatmainChat.scrollTop = mainChat.scrollHeight}, 0)},}
}

相关文章:

前端对接fastGPT流式数据+打字机效果

首先在对接api时 参数要设置stream: true, const data {chatId: abc,stream: true,//这里true返回流式数据detail: false,variables: {uid: sfdsdf,name: zhaoyunyao,},messages: [{ content: text, role: user }]}; 不要用axios发请求 不然处理不了流式数据 我这里使用fetch …...

避免使用第三方工具完成电脑环境检测

0. 简介 在之前配置各种深度学习环境的时候经常需要先检测一下电脑的软硬件环境&#xff0c;其实整个过程比较重复和固定&#xff0c;所以我们是否有可能一键检测Python版本、PIP版本、Conda版本、CUDA版本、电脑系统、CPU核数、CPU频率、内存、硬盘等内容这是很多Deepper苦恼…...

vue 中 mixin 的应用场景,原理和合并规则

应用场景 多个组件的相同逻辑可以提出去来一个公共的 mixin 原理 Mixin 的工作原理是将 Mixin 中的选项合并到组件的选项中 合并规则 优先处理 mixinsprops 、method、inject、computed 同名的使用组件内的&#xff0c;不使用mixin 的data 进行合并生命周期和watch 先执行…...

点击按钮(文字)调起elementUI大图预览

时隔一年&#xff0c;我又回来了 ~ 最近在做后台&#xff0c;遇到一个需求&#xff0c;就是点击“查看详情”按钮&#xff0c;调起elementUI的大图预览功能&#xff0c;预览多张图片&#xff0c;如下图&#xff1a; 首先想到的是使用element-ui的el-image组件&#xff0c;但它是…...

全面学习SpringCloud框架指南

要深入学习Spring Cloud框架,你需要系统地掌握其核心组件和概念,并了解如何在实际项目中应用这些知识。以下是一些关键的学习点和相应的学习内容: 一共分为10个模块包括: 1、微服务架构基础: 理解微服务架构的概念和优势。 学习单体架构向微服务架构演进的过程。 掌握…...

5G智慧水利数字孪生可视化平台,推进水利行业数字化转型

5G智慧水利数字孪生可视化平台&#xff0c;推进水利行业数字化转型。随着5G技术的快速发展&#xff0c;越来越多的行业开始探索数字化转型的道路。水利行业作为国民经济的重要支柱&#xff0c;也面临着数字化转型的迫切需求。5G智慧水利数字孪生可视化平台作为水利行业数字化转…...

新手入门:大语言模型训练指南

在这个信息爆炸的时代&#xff0c;人工智能技术正以前所未有的速度渗透到我们生活的方方面面。从智能手机上的语音助手到自动驾驶汽车&#xff0c;AI的应用无处不在。而在这些令人惊叹的技术背后&#xff0c;大语言模型&#xff08;LLM&#xff09;扮演着至关重要的角色。它们不…...

Win11 WSL2 install Ubuntu20.04 and Seismic Unix

Win11系统&#xff0c;先启用或关闭Windows功能&#xff0c;勾选“适用于Linux的Windows子系统”和“虚拟机平台”两项 设置wsl默认版本为wsl2&#xff0c;并更新 wsl --list --verbose # 查看安装版本及内容 wsl --set-default-version 2 # 设置wsl默认版本为wsl2 # 已安装…...

rust使用print控制台打印输出五颜六色的彩色红色字体

想要在控制台打印输出彩色的字体&#xff0c;可以使用一些已经封装好的依赖库&#xff0c;比如ansi_term这个依赖库&#xff0c;官方依赖库地址&#xff1a;https://crates.io/crates/ansi_term 安装依赖&#xff1a; cargo add ansi_term 或者在Cargo.toml文件中加入&#…...

贪心算法|435.无重叠区间

力扣题目链接 class Solution { public:// 按照区间右边界排序static bool cmp (const vector<int>& a, const vector<int>& b) {return a[1] < b[1];}int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.siz…...

C++的并发世界(七)——互斥锁

0.死锁的由来 假设有两个线程T1和T2&#xff0c;它们需要对两个互斥量mtx1和mtx2进行访问。而且需要按照以下顺序获取互斥量的所有权&#xff1a; -T1先获取mte1的所有权,再获取mt2的所有权。 -T2先获取 mtx2的所有权。再铁取 mtx1的所有权。 如果两个线程同时执行&#xff0c…...

NI-LabView的DAQ缺少或丢失的解决办法(亲测有效)

DAQmx在Labview中不显示或缺失 问题&#xff1a;在NI Packasge Manager安装完DAQ后在labview中不显示控件解决办法 问题&#xff1a;在NI Packasge Manager安装完DAQ后在labview中不显示控件 在打开测量I/O时&#xff0c;见不到 DAQmx&#xff0c;或者在Express中见不到DAQ助手…...

cesium 调整3dtiles的位置 世界坐标下 相对坐标下 平移矩阵

cesium调整3dtiles的位置用到的是平移矩阵&#xff0c;原理是在世界坐标系中用偏移点减去原始点得到一个平移向量&#xff0c;再根据这个向量得到平移矩阵。 原始点&#xff1a;一般是模型的中心点位置&#xff0c;可通过模型的包围盒得到偏移点&#xff1a;可分为两种情况&…...

flutter跑通腾讯云直播Demo

运行示例 前提条件 要求java jdk 11版本 并且配置到了环境变量 重要 要求flutter 版本 2.8.0 并且配置到了环境变量 重要 要求dart-sdk版本2.15 并且配置到了环境变量 重要 您已 注册腾讯云 账号&#xff0c;并完成 实名认证。 申请 SDKAPPID 和 SECRETKEY 登录实时音视频控…...

飞机降落蓝桥杯[2023蓝桥省赛B组]

2023蓝桥省赛B组 B题 飞机降落 题解 标准深搜板子题&#xff0c;难度不大 #include<bits/stdc.h> using namespace std; #define MAX 10 struct node{int t,d,l;//t:飞机到达时间 d:飞机最大盘旋时间 l:飞机降落所需时间bool v;//标记此架飞机是否被搜索过 用于剪枝 };…...

如何动态渲染HTML内容?用v-html!

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

EFcore 6 连接oracle19 WinForm vs2022

用EFcore访问Oracle&#xff0c;终于不需要Oracle的什么安装包了&#xff0c;直接在VS2022中就可以轻松搞定。在csdn上看到一哥们的帖子&#xff0c;测试了一下&#xff0c;发现很方便。使用的场景是&#xff1a;VS2022中EFcore6。经过测试&#xff0c;同 Navicat Premium 16比…...

(delphi11最新学习资料) Object Pascal 学习笔记---第9章第2节(finally代码块)

9.2 finally 代码块 ​ 还有第四个用于异常处理的关键字&#xff0c;我已经提到过&#xff0c;但到目前为止还没有使用过&#xff0c;那就是 finally。finally块用于执行一些应始终执行的操作&#xff08;通常是清理操作&#xff09;。事实上&#xff0c;无论是否发生异常&…...

220 基于matlab的考虑直齿轮热弹耦合的动力学分析

基于matlab的考虑直齿轮热弹耦合的动力学分析&#xff0c;输入主动轮、从动轮各类参数&#xff0c;考虑润滑油温度、润滑油粘度系数等参数&#xff0c;输出接触压力、接触点速度、摩擦系数、对流传热系数等结果。程序已调通&#xff0c;可直接运行。 220直齿轮热弹耦合 接触压力…...

Intrigue Core:一款功能强大的攻击面枚举引擎

关于Intrigue Core Intrigue Core是一款功能强大的开源攻击面枚举引擎&#xff0c;该工具可以帮助广大研究人员更好地管理应用程序的攻击面。 Intrigue Core集成了各种各样的安全数据源&#xff0c;可以将这些数据提取到标准化的对象模型中&#xff0c;并通过图形数据库跟踪关…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...