Преглед изворни кода

enhance: ChatGPT stream reception

0xJacky пре 2 година
родитељ
комит
94408cd21f

+ 0 - 1
frontend/components.d.ts

@@ -56,7 +56,6 @@ declare module '@vue/runtime-core' {
     ATabs: typeof import('ant-design-vue/es')['Tabs']
     ATag: typeof import('ant-design-vue/es')['Tag']
     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']
     ChartAreaChart: typeof import('./src/components/Chart/AreaChart.vue')['default']
     ChartRadialBarChart: typeof import('./src/components/Chart/RadialBarChart.vue')['default']

+ 1 - 1
frontend/package.json

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

+ 32 - 12
frontend/src/components/ChatGPT/ChatGPT.vue

@@ -46,13 +46,15 @@ async function request() {
 
     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'), {
         method: 'POST',
         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
     console.log('reading...')
     let reader = res.body!.getReader()
@@ -62,6 +64,8 @@ async function request() {
 
     let buffer = ''
 
+    let hasCodeBlockIndicator = false
+
     while (true) {
         let {done, value} = await reader.read()
         if (done) {
@@ -78,17 +82,32 @@ async function request() {
         const decoder = new TextDecoder('utf-8')
         const raw = decoder.decode(input)
 
-        const regex = /{"content":"(.+?)"}/g
-        const matches = raw.match(regex)
+        // console.log(input, raw)
+
+        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) {
                 buffer += c
-                if (isCodeBlockComplete(buffer)) {
-                    t.value.content = buffer
+                if (hasCodeBlockIndicator) {
+                    if (isCodeBlockComplete(buffer)) {
+                        t.value.content = buffer
+                        hasCodeBlockIndicator = false
+                    } else {
+                        t.value.content = buffer + '\n```'
+                    }
                 } else {
-                    t.value.content = buffer + '\n```'
+                    t.value.content = buffer
                 }
             }
         })
@@ -167,11 +186,12 @@ async function regenerate(index: number) {
 
 const editing_idx = ref(-1)
 
-const button_shape = computed(() => loading.value ? 'square' : 'circle')
+const show = computed(() => messages?.value?.length > 1)
+
 </script>
 
 <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">
             <a-list
                 class="chatgpt-log"

+ 1 - 1
frontend/src/version.json

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

+ 34 - 16
frontend/src/views/config/ConfigEdit.vue

@@ -8,6 +8,7 @@ import {message} from 'ant-design-vue'
 import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
 import ngx from '@/api/ngx'
 import InspectConfig from '@/views/config/InspectConfig.vue'
+import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
 
 const {$gettext, interpolate} = gettext
 const route = useRoute()
@@ -23,16 +24,22 @@ const name = computed(() => {
 })
 
 const configText = ref('')
+const history_chatgpt_record = ref([])
+const file_path = ref('')
 
 function init() {
     if (name.value) {
         config.get(name.value).then(r => {
             configText.value = r.config
+            history_chatgpt_record.value = r.chatgpt_messages
+            file_path.value = r.file_path
         }).catch(r => {
             message.error(r.message ?? $gettext('Server error'))
         })
     } else {
         configText.value = ''
+        history_chatgpt_record.value = []
+        file_path.value = ''
     }
 }
 
@@ -58,28 +65,39 @@ 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>
 
 
 <template>
     <inspect-config ref="inspect_config"/>
+    <a-row :gutter="16">
+        <a-col :xs="24" :sm="24" :md="editor_md">
+            <a-card :title="$gettext('Edit Configuration')">
+                <code-editor v-model:content="configText"/>
+                <footer-tool-bar>
+                    <a-space>
+                        <a-button @click="$router.go(-1)">
+                            <translate>Back</translate>
+                        </a-button>
+                        <a-button @click="format_code">
+                            <translate>Format Code</translate>
+                        </a-button>
+                        <a-button type="primary" @click="save">
+                            <translate>Save</translate>
+                        </a-button>
+                    </a-space>
+                </footer-tool-bar>
+            </a-card>
+        </a-col>
 
-    <a-card :title="$gettext('Edit Configuration')">
-        <code-editor v-model:content="configText"/>
-        <footer-tool-bar>
-            <a-space>
-                <a-button @click="$router.go(-1)">
-                    <translate>Back</translate>
-                </a-button>
-                <a-button @click="format_code">
-                    <translate>Format Code</translate>
-                </a-button>
-                <a-button type="primary" @click="save">
-                    <translate>Save</translate>
-                </a-button>
-            </a-space>
-        </footer-tool-bar>
-    </a-card>
+        <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>
 
 <style lang="less" scoped>

+ 1 - 1
frontend/version.json

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

BIN
resources/demo/demo.db


+ 1 - 0
server/api/config.go

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