最近高了一个简单chatgpt
对话功功能,回复时希望流式回复,而不是直接显示结果,其实很简单,前端流式读取即可,后端SSE
实现流式传输
前端用到fetch
获取数据,然后利用reader
读取
let requestId = parseInt(Math.random() * 1000000000) // 创建提问ID,用于停止生成
let keyWord = 'xxx' // 问题
let resp = await fetch(`http://10.0.192.84:11015/SYSmartGPTActor/V1.0/sse?keyWord=${keyWord}&requestId=${requestId}`, {method: 'get',headers: {'Content-Type': 'application/json','Authorization': 'Bearer Token'}})
// 读取器
let reader = resp.body.getReader()
// 文字解析器
let decoder = new TextDecoder()
while (true) {// 读取的结果,done为true完成,反之未完成,返回unitArraylet { done, value } = await reader.read()if (done) {// 停止生成this.generationEnded()break}// 对读取到的结果处理下let result = decoder.decode(value)if (result) {this.text += result// 滚动到底部this.scrollToBottom()}
}
这里可以用EventSource
来读取,但是EventSource
不支持自定义请求头,如果没有鉴权,直接实现如下:
let eventSource = new EventSource('http://10.0.192.84:11015/SYSmartGPTActor/V1.0/sse')eventSource.addEventListener("message", event => {this.text += decodeURIComponent(event.data)})
如果接口回加粗等Markdown
语法,则需要利用marked.js
处理下,然后代码片段着色利用highlight.js
处理:
npm install marked.js highlight.js -S
import { marked } from 'marked'
import hljs from "highlight.js"; // 引入 highlight.js
import "highlight.js/styles/default.css"let rendererMD = new marked.Renderer();
marked.setOptions({renderer: rendererMD,gfm: true, //默认为true。 允许 Git Hub标准的markdown.tables: true, //默认为true。 允许支持表格语法。该选项要求 gfm 为true。breaks: true, //默认为false。 允许回车换行。该选项要求 gfm 为true。pedantic: false, //默认为false。 尽可能地兼容 markdown.pl的晦涩部分。不纠正原始模型任何的不良行为和错误。sanitize: true, //对输出进行过滤(清理)smartLists: true,smartypants: true, //使用更为时髦的标点,比如在引用语法中加入破折号。
});// 最终将result渲染
let result = marked.parse(this.text)
最终效果如下: