v-md-editor和SSE實現ChatGPT的打字機式輸出

概述

不論是GPT還是文心一言,在回答的時候類似于打字機式的將答案呈現給我們,這樣的交互一方面比較友好,另一方面,當答案比較多、生成比較慢的時候也能爭取一些答案的生成時間。本文后端使用expressstream,使用SSE將結果逐漸輸出,前端使用v-md-editor對返回的結果進行呈現。

實現效果

動畫.gif

實現

1. 后端

const stream = require("stream");
const R = require('../utils/result')let sse = null,contentId = 0,flag = 0;function toDataString(data) {if (typeof data === "object") return toDataString(JSON.stringify(data));return data.split(/\r\n|\r|\n/).map((line) => `data: ${line}\n`).join("");
}const messageStr = `JavaScript中常用的排序算法有以下幾種:1. 冒泡排序冒泡排序是一種簡單的排序算法,它重復地遍歷要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。遍歷數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。\`\`\`javascript
function bubbleSort(arr) {var len = arr.length;for (var i = 0; i < len - 1; i++) {for (var j = 0; j < len - 1 - i; j++) {if (arr[j] > arr[j + 1]) {[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];}}}return arr;
}
\`\`\`2. 選擇排序選擇排序是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。\`\`\`javascript
function selectionSort(arr) {var len = arr.length;for (var i = 0; i < len - 1; i++) {var minIndex = i;for (var j = i + 1; j < len; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];}return arr;
}
\`\`\`3. 插入排序插入排序的工作原理是通過構造一個有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。\`\`\`javascript
function insertionSort(arr) {var len = arr.length;for (var i = 1; i < len; i++) {var key = arr[i];var j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}return arr;
}
\`\`\`4. 快速排序快速排序是一種高效的排序算法,它的基本思想是使用分治法。\`\`\`javascript
function quickSort(arr, left = 0, right = arr.length - 1) {if (left < right) {let pivotIndex = partition(arr, left, right);quickSort(arr, left, pivotIndex - 1);quickSort(arr, pivotIndex + 1, right);}return arr;
}function partition(arr, left, right) {let pivotValue = arr[right];let pivotIndex = left;for (let i = left; i < right; i++) {if (arr[i] <= pivotValue) {[arr[i], arr[pivotIndex]] = [arr[pivotIndex], arr[i]];pivotIndex++;}}[arr[pivotIndex], arr[right]] = [arr[right], arr[pivotIndex]];return pivotIndex;
}
\`\`\`5. 歸并排序歸并排序是建立在歸并操作上的一種有效的排序算法,效率為O(nlogn)。\`\`\`javascript
function mergeSort(arr) {if (arr.length < 2) {return arr;}var mid = Math.floor(arr.length / 2);var left = arr.slice(0, mid);var right = arr.slice(mid);return merge(mergeSort(left), mergeSort(right));
}function merge(left, right) {var result = [];while (left.length && right.length) {if (left[0] <= right[0]) {result.push(left.shift());} else {result.push(right.shift());}}while (left.length) {result.push(left.shift());}while (right.length) {result.push(right.shift());}return result;
}
\`\`\`以上就是JavaScript中常見的幾種排序算法,每種算法都有其適用的場景和優缺點,根據實際需求選擇合適的排序算法可以提高程序的運行效率。`const gptController = {getAnswer: async function (req, res, next) {// 觸動定時觸發let index = 0clearInterval(flag)flag = setInterval(() => {const r = new R();if(index < messageStr.length) {const message = {data: r.ok({msg: messageStr.slice(0, index + 1)}),event: "dynamicUpdate", // 事件類型,需要客戶端添加對應的事件監聽id: ++contentId,retry: 2000,};sse?.write(message);index += 1} else {const message = {data: r.ok({msg: 'end'}),event: "dynamicUpdate", // 事件類型,需要客戶端添加對應的事件監聽id: ++contentId,retry: 2000,};sse?.write(message);clearInterval(flag)}}, 60);res.writeHead(200, {"Content-Type": "text/event-stream; charset=utf-8",});sse = new stream.Transform({ objectMode: true });sse._transform = (message, encoding, callback) => {if (message.comment) sse.push(`: ${message.comment}\n`);if (message.event) sse.push(`event: ${message.event}\n`);if (message.id) sse.push(`id: ${message.id}\n`);if (message.retry) sse.push(`retry: ${message.retry}\n`);if (message.data) sse.push(toDataString(message.data));sse.push("\n");callback();};sse.write(":ok\n\n");sse.pipe(res);},
};module.exports = gptController;

2. 前端實現

在主入口引入v-md-editor

// main.js
import VMdPreview from '@kangc/v-md-editor/lib/preview';
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js';
import createCopyCodePlugin from '@kangc/v-md-editor/lib/plugins/copy-code/index';
import '@kangc/v-md-editor/lib/style/base-editor.css';
import '@kangc/v-md-editor/lib/style/preview.css';
import '@kangc/v-md-editor/lib/plugins/copy-code/copy-code.css';
import '@kangc/v-md-editor/lib/theme/style/vuepress.css';
import '@kangc/v-md-editor/lib/style/codemirror-editor.css';
import '@kangc/v-md-editor/lib/theme/style/github.css';
import createLineNumbertPlugin from '@kangc/v-md-editor/lib/plugins/line-number/index';
import '@kangc/v-md-editor/lib/plugins/tip/tip.css';
import Prism from 'prismjs';VMdPreview.use(vuepressTheme, { Prism });
VMdPreview.use(createCopyCodePlugin());
VMdPreview.use(createLineNumbertPlugin());const app = createApp(App)
app.use(VMdPreview).mount('#app')

頁面引用v-md-preview

<template><div class="app"><v-md-preview :text="mdText"></v-md-preview></div>
</template><script>
export default {data() {return {mdText: "",};},mounted() {const that = thisconst es = new EventSource("http://localhost:8080/gpt/sse");es.addEventListener("dynamicUpdate", (e) => {const data = JSON.parse(e.data);const msg = data.data.msg;if (msg === "end") {es.close();} else {that.mdText = msg}});es.onopen = () => {console.log("已開啟。。。");};es.onmessage = (e, me) => {console.log("默認推送:" + e.data);};es.onerror = (err) => {console.log(err);};},
};
</script><style scoped>
.app {width: 100%;height: 100%;
}
</style>

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

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

相關文章

Boosting Cache Performance by Access Time Measurements——論文泛讀

TOC 2023 Paper 論文閱讀筆記整理 問題 大多數現代系統利用緩存來減少平均數據訪問時間并優化其性能。當緩存未命中的訪問時間不同時&#xff0c;最大化緩存命中率與最小化平均訪問時間不同。例如&#xff1a;系統使用多種不同存儲介質時&#xff0c;不同存儲介質訪問時間不同…

【C++初階】—— 類和對象 (上)

&#x1f4dd;個人主頁&#x1f339;&#xff1a;EterNity_TiMe_ ?收錄專欄?&#xff1a;C “ 登神長階 ” &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; 類和對象 1. 初步認識C2. 類的引入3. 類的定義聲明和定義全部放在類體中聲明和定義分開存放 4.…

8個實用網站和軟件,收藏起來一定不后悔~

整理了8個日常生活中經常能用得到的網站和軟件&#xff0c;收藏起來一定不會后悔~ 1.ZLibrary zh.zlibrary-be.se/這個網站收錄了超千萬的書籍和文章資源&#xff0c;國內外的各種電子書資源都可以在這里搜索&#xff0c;98%以上都可以在網站內找到&#xff0c;并且支持免費下…

Android系統的/etc/mkshrc文件

/etc/mkshrc 文件是用于配置 mksh&#xff08;MirBSD Korn Shell&#xff09;環境的啟動腳本。mksh 是 Android 默認使用的 shell&#xff0c;在 shell 啟動時會讀取并執行這個文件中的配置。以下是關于 /etc/mkshrc 文件的詳細信息及其用途。 /etc/mkshrc 文件的作用 環境配…

sql server專題實驗4 復雜查詢

SQL Server 是微軟開發的數據庫管理系統&#xff0c;它支持復雜的查詢操作&#xff0c;允許用戶從數據庫中檢索、分析和處理數據。在進行復雜查詢時&#xff0c;通常會用到以下幾種SQL語句和概念&#xff1a; 連接&#xff08;Join&#xff09;: INNER JOIN&#xff1a;只返回兩…

設計模式--備忘錄模式

備忘錄模式是一種行為設計模式&#xff0c;它用于在不破壞封裝的前提下&#xff0c;保存一個對象的內部狀態&#xff0c;以便以后可以恢復到這個狀態。這種模式在許多應用場景中非常有用&#xff0c;例如在實現撤銷操作、保存游戲進度、恢復文件備份以及保持工作狀態等。 備忘…

linux中ansible整理筆記

一、工作模式 1. adhoc臨時命令 語法&#xff1a; ansible 主機或者組列表 -m 模塊 -a “參數” 2. playbook 語法&#xff1a; ansible-playbook xxx.yml 二、模塊 1. ping 2.command:默認模塊&#xff08;不支持重定向&#xff0c;管道&#xff09; 3.shell:類似com…

IP地址顯示“不安全”怎么辦|已解決

解決IP地址顯示“不安全”的問題&#xff0c;通常需要確保網站或服務使用HTTPS協議進行加密通信&#xff0c;可以通過部署SSL證書來解決&#xff0c;以下是具體的解決步驟&#xff1a; 1 申請IP地址SSL證書&#xff1a;網站管理員應向證書頒發機構&#xff08;CA&#xff09;申…

網絡拓撲—WEB-IIS服務搭建

文章目錄 WEB-IIS服務搭建網絡拓撲配置網絡IISPC 安裝IIS服務配置IIS服務&#xff08;默認站點&#xff09;PC機訪問網頁 配置IIS服務&#xff08;新建站點&#xff09;PC機訪問網頁 WEB-IIS服務搭建 網絡拓撲 //交換機忽略不計 IIS服務IP&#xff1a;192.168.1.1 PC機IP&…

人類交互2 聽覺處理和語言中樞

人類聽覺概述 人類聽覺是指通過耳朵接收聲音并將其轉化為神經信號&#xff0c;從而使我們能夠感知和理解聲音信息的能力。聽覺是人類五種感覺之一&#xff0c;對我們的日常生活和交流至關重要。 聽覺是人類交流和溝通的重要工具。通過聽覺&#xff0c;我們能夠聽到他人的語言…

安裝錯誤提示Please run MaterialLibrary2018.msi first或者其他MaterialLibrary版本

打開autoremove&#xff0c;系統檢查&#xff0c;點擊開始檢查。檢查完成修復。 可以解決部分該問題&#xff0c;如果沒解決的請咨詢

Linux中的文件描述符

1.系統調用接口和庫函數的關系 函數&#xff1a;fopen fclose fread fwrite 都是c標準庫當中的函數&#xff0c;也就是用戶操作接口中ibc系統調用&#xff1a;open close read write 都是系統調用提供的接口 c語言中接口底層封裝的都是系統調用接口 FILE* stdin stdout stderr…

[POI2008] STA-Station/洛谷P3478(樹形dp)

[ P O I 2008 ] S T A ? S t a t i o n ( 樹形 d p ) \Huge{[POI2008] STA-Station(樹形dp)} [POI2008]STA?Station(樹形dp) 題目鏈接&#xff1a;[P3478 POI2008] STA-Station - 洛谷 文章目錄 題意思路標程 題意 給定一個 n n n個點的樹&#xff0c;請求出一個結點&#…

js無感刪除url搜索部分,不刷新頁面

如&#xff1a;把下面的網址 http://127.0.0.1:5173/?code3b9cc36e&state 改成 http://127.0.0.1:5173 history.pushState(null, 網站標題, location.origin)

TikTok越獄檢測之二 <調試器檢測>

來了&#xff0c;調試器檢測。總結如下,多多指教: 檢測app 是否被附加調試: 原理就是檢測父進程是否 launchd啟動&#xff0c;在OS X和iOS 系統中&#xff0c;用戶環境始于launchd&#xff0c;為用戶態出現的第一個進程&#xff0c;為所有的進程的祖先&#xff0c;launchd 的進…

Python模塊、包和異常處理

大家好&#xff0c;在當今軟件開發領域&#xff0c;Python作為一種簡潔、易讀且功能強大的編程語言&#xff0c;被廣泛應用于各種領域。作為一名測試開發工程師&#xff0c;熟練掌握Python的模塊、包和異常處理是提高代碼可維護性和錯誤處理能力的關鍵。本文將和大家一起探討Py…

SAP-MRP和采購申請

1、如果采購申請是手工創建的,跑MRP會不會被覆蓋? 創建一個采購申請18089476,然后運行MRP-MD03,再用MD04查看下 從上圖看,手工創建的采購申請被打上*號,沒有被覆蓋掉。 2、如果采購申請被審批了,會不會被覆蓋掉? 首先創建一個獨立需求MD61 然后庫存消耗掉為0,運行M…

shell實現ssh服務防止暴力破解 —— 筑夢之路

實現原理 對系統登陸日志文件/var/log/secure&#xff0c;進行數據篩選&#xff0c;查找登陸失敗的ip地址&#xff0c;然后將ip加入到黑名單中。 腳本內容 #!/bin/bash# 獲取登陸失敗的ip地址failedcat /var/log/secure|grep "Failed"|awk {print $11}|sort|uniq …

普源精電收購耐數電子——用“鈔能力”拿下“量子”?

「量子市界」聚焦量子前沿&#xff0c;揭秘市場動態┃2024年4月30日&#xff0c;普源精電新增“量子科技”概念。 似乎一夜之間&#xff0c;新增“量子科技”概念的上市企業如雨后春筍般登場——普源精電就是其一。普源精電本就持有耐數電子32.26%股權&#xff0c;于4月2日發布…

c4d云渲染是工程文件會暴露嗎?

在數字創意產業飛速發展的今天&#xff0c;C4D云渲染因其高效便捷而備受歡迎。然而&#xff0c;隨著技術應用的深入&#xff0c;人們開始關注一個核心問題&#xff1a;在享受云渲染帶來的便利的同時&#xff0c;C4D工程文件安全嗎&#xff1f;是否會有暴露的風險&#xff1f;下…