最近高了一个简单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完成,反之未完成,返回unitArray
let { 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)
最终效果如下: