Sfoglia il codice sorgente

【功能】使用sse发请求

xcbosa mbp16 1 anno fa
parent
commit
e6adde65c6
5 ha cambiato i file con 393 aggiunte e 451 eliminazioni
  1. BIN
      build/logo.png
  2. 276 436
      package-lock.json
  3. 5 0
      package.json
  4. 10 10
      src/components/CCDChatCell.vue
  5. 102 5
      src/components/CCDChatSystem.vue

BIN
build/logo.png


File diff suppressed because it is too large
+ 276 - 436
package-lock.json


+ 5 - 0
package.json

@@ -10,7 +10,12 @@
     "build": "node build/build.js"
     "build": "node build/build.js"
   },
   },
   "dependencies": {
   "dependencies": {
+    "@microsoft/fetch-event-source": "^2.0.1",
+    "@rangermauve/fetch-event-source": "^1.0.3",
+    "highlight.js": "^11.9.0",
     "jquery": "^3.6.4",
     "jquery": "^3.6.4",
+    "marked": "4.0.0",
+    "marked-highlight": "^2.1.1",
     "view-full-screen": "^0.1.5",
     "view-full-screen": "^0.1.5",
     "vue": "^2.5.2",
     "vue": "^2.5.2",
     "vue-router": "^3.0.1"
     "vue-router": "^3.0.1"

+ 10 - 10
src/components/CCDChatCell.vue

@@ -6,18 +6,13 @@
       <div style="text-align: center">
       <div style="text-align: center">
         <img src="../assets/roundicon.png" style="width: 36px; height: 36px; display: inline; vertical-align: middle">
         <img src="../assets/roundicon.png" style="width: 36px; height: 36px; display: inline; vertical-align: middle">
         <p style="font-size: x-large; font-weight: bold; display: inline; vertical-align: middle; margin-left: 5px; color: #fff5be">C Code Develop</p>
         <p style="font-size: x-large; font-weight: bold; display: inline; vertical-align: middle; margin-left: 5px; color: #fff5be">C Code Develop</p>
-        <p style="font-size: x-large; display: inline; vertical-align: middle; color: #beffc1">ChatBot</p>
-      </div>
-      <div style="text-align: center">
-        <p>基于 ChatGLM & lang-chain 开源项目</p>
-        <p style="display: inline">您可以问我任意问题,例如 </p>
-        <p style="display: inline; color: yellow; font-style: italic">C Code Develop可以做简单的UI吗?</p>
+        <p style="font-size: x-large; display: inline; vertical-align: middle; color: #beffc1">ChatBot 2</p>
       </div>
       </div>
     </div>
     </div>
   </template>
   </template>
   <template v-if="cellType == 'ask'">
   <template v-if="cellType == 'ask'">
-    <p style="font-size: small; text-align: right; margin-bottom: -10px; margin-right: 20px; color: #00c4c4; font-weight: bold">我 (没有登陆)</p>
-    <div class="shineRight" style="border-radius: 15px; background-color: #006e6e; width: calc(100% - 60px); margin: 10px 10px 10px 50px;">
+    <p style="font-size: small; text-align: right; margin-bottom: -10px; margin-right: 20px; color: #00c4c4; font-weight: bold">我</p>
+    <div class="shineRight" style="border-radius: 15px; background-color: #313131; width: calc(100% - 60px); margin: 10px 10px 10px 50px;">
       <div style="margin: 10px;">
       <div style="margin: 10px;">
         <p style="word-wrap: break-word; padding-top: 8px; padding-bottom: 8px; text-align: right">{{ message }}</p>
         <p style="word-wrap: break-word; padding-top: 8px; padding-bottom: 8px; text-align: right">{{ message }}</p>
       </div>
       </div>
@@ -25,9 +20,9 @@
   </template>
   </template>
   <template v-if="cellType == 'answer'">
   <template v-if="cellType == 'answer'">
     <p style="font-size: small; margin-bottom: -10px; margin-left: 20px; color: #ffc745; font-weight: bold">C Code Develop</p>
     <p style="font-size: small; margin-bottom: -10px; margin-left: 20px; color: #ffc745; font-weight: bold">C Code Develop</p>
-    <div class="shineLeft" style="border-radius: 15px; background-color: #a85a00; width: calc(100% - 60px); margin: 10px 50px 10px 10px;">
+    <div class="shineLeft" style="border-radius: 15px; background-color: #313131; width: calc(100% - 60px); margin: 10px 50px 10px 10px;">
       <div style="margin: 10px;">
       <div style="margin: 10px;">
-        <p style="word-wrap: break-word; padding-top: 8px; padding-bottom: 8px">{{ message }}</p>
+        <p style="word-wrap: break-word; padding-top: 8px; padding-bottom: 8px" v-html="parseMarkdown(message)"></p>
       </div>
       </div>
     </div>
     </div>
   </template>
   </template>
@@ -49,6 +44,8 @@
 </template>
 </template>
 
 
 <script>
 <script>
+import { marked } from 'marked';
+
 export default {
 export default {
   name: "CCDChatCell",
   name: "CCDChatCell",
   props: {
   props: {
@@ -59,6 +56,9 @@ export default {
   methods: {
   methods: {
     onShutdown() {
     onShutdown() {
       this.$emit("shutdown", this)
       this.$emit("shutdown", this)
+    },
+    parseMarkdown(str) {
+      return marked(str)
     }
     }
   }
   }
 }
 }

+ 102 - 5
src/components/CCDChatSystem.vue

@@ -43,7 +43,9 @@ input {
 
 
 <script>
 <script>
 import CCDChatCell from "@/components/CCDChatCell";
 import CCDChatCell from "@/components/CCDChatCell";
+import { fetchEventSource } from '@microsoft/fetch-event-source';
 let websocketAPIURL = "wss://chat.forgetive.net/free_chat"
 let websocketAPIURL = "wss://chat.forgetive.net/free_chat"
+let sseAPIURL = "https://notebook.forgetive.net/freeai/llm"
 
 
 export default {
 export default {
   name: 'CCDChatSystem',
   name: 'CCDChatSystem',
@@ -57,12 +59,14 @@ export default {
         },
         },
         {
         {
           "type" : "tip",
           "type" : "tip",
-          "content" : "您好,我是 C Code Develop & C Notebook 智能代码工具,可以为您生成代码"
+          "content" : "您好,我是 C Code Develop & C Notebook AI助手,可以帮您解决代码问题。从编程技巧到历史人文,我无所不知。快来跟我聊天吧~"
         }
         }
       ],
       ],
       history: [],
       history: [],
       socketObject: null,
       socketObject: null,
-      wannaKill: false
+      wannaKill: false,
+      sseInstance: null,
+      abortController: null
     }
     }
   },
   },
   mounted() {
   mounted() {
@@ -83,6 +87,9 @@ export default {
       this.scrollViewScrollToBottom()
       this.scrollViewScrollToBottom()
     },
     },
     doPostMessage() {
     doPostMessage() {
+      if (this.sseInstance) {
+        return;
+      }
       let question = this.$refs.inputAsk.value
       let question = this.$refs.inputAsk.value
       if (question.length == 0) {
       if (question.length == 0) {
         this.insertMessageBlock({
         this.insertMessageBlock({
@@ -91,8 +98,85 @@ export default {
         })
         })
         return
         return
       }
       }
+      this.insertMessageBlock({
+        "type" : "ask",
+        "content" : question
+      })
       this.$refs.inputAsk.value = ""
       this.$refs.inputAsk.value = ""
-      this.doAsyncChat(question)
+      this.doAsyncSSE(question)
+    },
+    doAsyncSSE(message) {
+      let self = this
+      self.allowInput = false
+      let messageCard = {
+        "type" : "answer",
+        "content" : ""
+      }
+
+      let messageModel = []
+      for (let index in self.model) {
+        let model = self.model[index]
+        if (model.type == "ask") {
+          messageModel.push({
+            "role" : "user",
+            "content" : model.content
+          })
+        }
+        else if (model.type == "answer") {
+          messageModel.push({
+            "role" : "assistant",
+            "content" : model.content
+          })
+        }
+      }
+
+      self.insertMessageBlock(messageCard)
+      self.insertMessageBlock({
+        "type" : "answerTyping",
+        "content" : ""
+      })
+
+      self.abortController = new AbortController()
+      let eventSource = fetchEventSource(sseAPIURL, {
+        method: 'POST',
+        signal: self.abortController.signal,
+        headers: {
+          "Content-Type": 'application/json',
+          "Access-Control-Allow-Origin": true
+        },
+        body: JSON.stringify({
+          "stream" : true,
+          "messages" : messageModel
+        }),
+        onmessage(event) {
+          let partModel = JSON.parse(event.data)
+          if (partModel["v"] != null) {
+            messageCard.content += partModel["v"]
+            self.scrollViewScrollToBottom()
+          }
+        },
+        onerror(err) {
+          if (messageCard.content.length < 5) {
+            messageCard.content = "回答出了一点问题"
+          }
+          self.sseInstance = null
+          self.allowInput = true
+          self.doShutdown()
+          throw err
+        },
+        onclose() {
+          self.sseInstance = null
+          self.allowInput = true
+          self.abortController = null
+          for (let id = 0; id < self.model.length; id++) {
+            if (self.model[id].type == "answerTyping") {
+              self.model.splice(id, 1)
+              id--;
+            }
+          }
+        }
+      })
+      self.sseInstance = eventSource
     },
     },
     doAsyncChat(message) {
     doAsyncChat(message) {
       this.allowInput = false
       this.allowInput = false
@@ -157,8 +241,21 @@ export default {
       }
       }
     },
     },
     doShutdown() {
     doShutdown() {
-      if (this.socketObject != null) {
-        this.socketObject.close(1000)
+      let self = this
+      if (self.socketObject != null) {
+        self.socketObject.close(1000)
+      }
+      if (self.abortController != null) {
+        self.abortController.abort()
+        self.sseInstance = null
+        self.allowInput = true
+        self.abortController = null
+        for (let id = 0; id < self.model.length; id++) {
+          if (self.model[id].type == "answerTyping") {
+            self.model.splice(id, 1)
+            id--;
+          }
+        }
       }
       }
     }
     }
   }
   }

Some files were not shown because too many files changed in this diff