enhance: ChatGPT stream reception

This commit is contained in:
0xJacky 2023-03-22 09:10:00 +08:00
parent 11d1d59725
commit 94408cd21f
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
8 changed files with 70 additions and 32 deletions

View file

@ -56,7 +56,6 @@ declare module '@vue/runtime-core' {
ATabs: typeof import('ant-design-vue/es')['Tabs'] ATabs: typeof import('ant-design-vue/es')['Tabs']
ATag: typeof import('ant-design-vue/es')['Tag'] ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
BreadcrumbBreadcrumb: typeof import('./src/components/Breadcrumb/Breadcrumb.vue')['default'] BreadcrumbBreadcrumb: typeof import('./src/components/Breadcrumb/Breadcrumb.vue')['default']
ChartAreaChart: typeof import('./src/components/Chart/AreaChart.vue')['default'] ChartAreaChart: typeof import('./src/components/Chart/AreaChart.vue')['default']
ChartRadialBarChart: typeof import('./src/components/Chart/RadialBarChart.vue')['default'] ChartRadialBarChart: typeof import('./src/components/Chart/RadialBarChart.vue')['default']

View file

@ -1,7 +1,7 @@
{ {
"name": "nginx-ui-frontend-next", "name": "nginx-ui-frontend-next",
"private": true, "private": true,
"version": "1.7.7", "version": "1.7.8",
"type": "commonjs", "type": "commonjs",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View file

@ -46,13 +46,15 @@ async function request() {
console.log('fetching...') console.log('fetching...')
messages.value.push(t.value)
emit('update:history_messages', messages.value)
let res = await fetch(urlJoin(window.location.pathname, '/api/chat_gpt'), { let res = await fetch(urlJoin(window.location.pathname, '/api/chat_gpt'), {
method: 'POST', method: 'POST',
headers: {'Accept': 'text/event-stream', Authorization: token.value}, headers: {'Accept': 'text/event-stream', Authorization: token.value},
body: JSON.stringify({messages: messages.value}) body: JSON.stringify({messages: messages.value.slice(0, messages.value?.length - 1)})
}) })
messages.value.push(t.value)
// read body as stream // read body as stream
console.log('reading...') console.log('reading...')
let reader = res.body!.getReader() let reader = res.body!.getReader()
@ -62,6 +64,8 @@ async function request() {
let buffer = '' let buffer = ''
let hasCodeBlockIndicator = false
while (true) { while (true) {
let {done, value} = await reader.read() let {done, value} = await reader.read()
if (done) { if (done) {
@ -78,18 +82,33 @@ async function request() {
const decoder = new TextDecoder('utf-8') const decoder = new TextDecoder('utf-8')
const raw = decoder.decode(input) const raw = decoder.decode(input)
const regex = /{"content":"(.+?)"}/g // console.log(input, raw)
const matches = raw.match(regex)
const line = raw.split('\n\n')
line?.forEach(v => {
const data = v.slice('event:message\ndata:'.length)
if (!data) {
return
}
const content = JSON.parse(data).content
if (!hasCodeBlockIndicator) {
hasCodeBlockIndicator = content.indexOf('`') > -1
}
matches?.forEach(v => {
const content = JSON.parse(v).content
for (let c of content) { for (let c of content) {
buffer += c buffer += c
if (hasCodeBlockIndicator) {
if (isCodeBlockComplete(buffer)) { if (isCodeBlockComplete(buffer)) {
t.value.content = buffer t.value.content = buffer
hasCodeBlockIndicator = false
} else { } else {
t.value.content = buffer + '\n```' t.value.content = buffer + '\n```'
} }
} else {
t.value.content = buffer
}
} }
}) })
} }
@ -167,11 +186,12 @@ async function regenerate(index: number) {
const editing_idx = ref(-1) const editing_idx = ref(-1)
const button_shape = computed(() => loading.value ? 'square' : 'circle') const show = computed(() => messages?.value?.length > 1)
</script> </script>
<template> <template>
<a-card class="chatgpt" title="ChatGPT" v-if="messages?.length>1"> <a-card class="chatgpt" title="ChatGPT" v-if="show">
<div class="chatgpt-container"> <div class="chatgpt-container">
<a-list <a-list
class="chatgpt-log" class="chatgpt-log"

View file

@ -1 +1 @@
{"version":"1.7.7","build_id":85,"total_build":155} {"version":"1.7.8","build_id":86,"total_build":156}

View file

@ -8,6 +8,7 @@ import {message} from 'ant-design-vue'
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue' import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
import ngx from '@/api/ngx' import ngx from '@/api/ngx'
import InspectConfig from '@/views/config/InspectConfig.vue' import InspectConfig from '@/views/config/InspectConfig.vue'
import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
const {$gettext, interpolate} = gettext const {$gettext, interpolate} = gettext
const route = useRoute() const route = useRoute()
@ -23,16 +24,22 @@ const name = computed(() => {
}) })
const configText = ref('') const configText = ref('')
const history_chatgpt_record = ref([])
const file_path = ref('')
function init() { function init() {
if (name.value) { if (name.value) {
config.get(name.value).then(r => { config.get(name.value).then(r => {
configText.value = r.config configText.value = r.config
history_chatgpt_record.value = r.chatgpt_messages
file_path.value = r.file_path
}).catch(r => { }).catch(r => {
message.error(r.message ?? $gettext('Server error')) message.error(r.message ?? $gettext('Server error'))
}) })
} else { } else {
configText.value = '' configText.value = ''
history_chatgpt_record.value = []
file_path.value = ''
} }
} }
@ -58,12 +65,16 @@ function format_code() {
}) })
} }
const editor_md = computed(() => history_chatgpt_record?.value?.length > 1 ? 16 : 24)
const chat_md = computed(() => history_chatgpt_record?.value?.length > 1 ? 8 : 24)
</script> </script>
<template> <template>
<inspect-config ref="inspect_config"/> <inspect-config ref="inspect_config"/>
<a-row :gutter="16">
<a-col :xs="24" :sm="24" :md="editor_md">
<a-card :title="$gettext('Edit Configuration')"> <a-card :title="$gettext('Edit Configuration')">
<code-editor v-model:content="configText"/> <code-editor v-model:content="configText"/>
<footer-tool-bar> <footer-tool-bar>
@ -80,6 +91,13 @@ function format_code() {
</a-space> </a-space>
</footer-tool-bar> </footer-tool-bar>
</a-card> </a-card>
</a-col>
<a-col class="col-right" :xs="24" :sm="24" :md="chat_md">
<chat-g-p-t :content="configText" :path="file_path"
v-model:history_messages="history_chatgpt_record"/>
</a-col>
</a-row>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>

View file

@ -1 +1 @@
{"version":"1.7.7","build_id":85,"total_build":155} {"version":"1.7.8","build_id":86,"total_build":156}

Binary file not shown.

View file

@ -96,6 +96,7 @@ func GetConfig(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"config": string(content), "config": string(content),
"chatgpt_messages": chatgpt.Content, "chatgpt_messages": chatgpt.Content,
"file_path": path,
}) })
} }