diff --git a/package.json b/package.json
index f5270c5..ad450c7 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,6 @@
},
"dependencies": {
"@kangc/v-md-editor": "^2.3.15",
- "axios": "^1.4.0",
"element-plus": "^2.3.4",
"sass": "^1.62.1",
"sass-loader": "^13.2.2",
diff --git a/src/App.vue b/src/App.vue
index d4d9d2b..7ca58a3 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -19,7 +19,8 @@ export default {
return {
showSettings: false,
setting: {
- model: new ChatGPT()
+ model: new ChatGPT(),
+ stream: true
},
}
},
diff --git a/src/components/chat.vue b/src/components/chat.vue
index fd0edcd..b2f98a1 100644
--- a/src/components/chat.vue
+++ b/src/components/chat.vue
@@ -17,7 +17,7 @@
-
+
发送
@@ -46,7 +46,7 @@ export default {
methods: {
handleSend() {
if (!!this.inputText) {
- const ai = this.settings.model
+ const ai = this.config.model
const myMsg = {
avatar: USER_AVATAR,
name: "我",
@@ -54,6 +54,7 @@ export default {
msg: this.inputText,
chatType: 0, //信息类型,0文字,1图片
uid: "me", //uid
+ role: "user"
}
this.chatHistory.push(myMsg)
this.loading = true
@@ -61,63 +62,58 @@ export default {
avatar: ai.avatar,
name: ai.name,
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
- msg: '',
+ msg: "",
chatType: 0, //信息类型,0文字,1图片
uid: "ai", //uid
+ role: "assistant"
}
this.chatHistory.push(aiMsg)
- ai.chat(this.chatHistory).finally(() => this.loading = false)
+ if (this.config.stream) {
+ ai.chatStream(this.chatHistory).then(reader => this.streamOutput(reader, this.chatHistory.at(-1))).finally(() => this.loading = false)
+ } else {
+ ai.chat(this.chatHistory).then(reply => {
+ const decodeArr = reply.split("")
+ decodeArr.forEach(e => this.chatHistory.at(-1).msg += e)
+ }).finally(() => this.loading = false)
+ }
} else {
this.$message.error("请不要发送空消息!")
}
},
- readStream(reader, _this, currentResLocation, type) {
+ streamOutput(reader, chat) {
return reader.read().then(({done, value}) => {
if (done) {
return;
}
- if (!_this.chatList[currentResLocation].reminder) {
- _this.chatList[currentResLocation].reminder = "";
+ if (!chat.reminder) {
+ chat.reminder = ""
}
- let decoded = new TextDecoder().decode(value);
- decoded = _this.chatList[currentResLocation].reminder + decoded;
- let decodedArray = decoded.split("data: ");
+ let decode = new TextDecoder().decode(value)
+ decode = chat.reminder + decode
+ let decodedArray = decode.split("data: ");
let longstr = "";
decodedArray.forEach(decoded => {
+ decoded = decoded.trim();
try {
- decoded = decoded.trim();
- if (longstr == "") {
- JSON.parse(decoded);
- } else {
+ if (longstr != "") {
decoded = longstr + decoded;
longstr = "";
- JSON.parse(decoded);
}
} catch (e) {
longstr = decoded;
decoded = "";
}
- if (decoded !== "") {
- if (decoded.trim() === "[DONE]") {
- return;
- } else {
- const choices = JSON.parse(decoded).choices
- if (choices && choices.length > 0) {
- if (type === "chat") {
- const response = choices[0].delta.content ? choices[0].delta.content : "";
- _this.chatList[currentResLocation].msg = _this.chatList[currentResLocation].msg + response
- _this.scrollBottom();
- } else {
- const response = choices[0].text;
- _this.chatList[currentResLocation].msg = _this.chatList[currentResLocation].msg + response
- }
- }
+ if (!!decoded && decoded !== "[DONE]") {
+ const choices = JSON.parse(decoded).choices
+ if (choices?.length > 0) {
+ const response = choices[0].delta.content || "";
+ chat.msg += response
}
}
})
- return this.readStream(reader, _this, currentResLocation, type);
- });
- },
+ return this.streamOutput(reader, chat)
+ })
+ }
}
}
diff --git a/src/components/chatContent.vue b/src/components/chatContent.vue
index b40848c..f1ec4e2 100644
--- a/src/components/chatContent.vue
+++ b/src/components/chatContent.vue
@@ -188,5 +188,9 @@ export default {
}
}
}
+
+ :deep(.vuepress-markdown-body) {
+ padding: 2px 0 !important;
+ }
}
diff --git a/src/components/chatInput.vue b/src/components/chatInput.vue
index 1b5f3ac..2b04c22 100644
--- a/src/components/chatInput.vue
+++ b/src/components/chatInput.vue
@@ -1,7 +1,8 @@
@@ -17,6 +18,15 @@ export default {
text: ""
}
},
+ methods: {
+ handleShortKey(e) {
+ if (e.ctrlKey && e.keyCode == 13) {
+ this.$emit('update:modelValue', this.text)
+ this.text = ""
+ this.$emit('enter')
+ }
+ }
+ }
}
diff --git a/src/utils/axios.js b/src/utils/axios.js
index a10c119..b4d07cc 100644
--- a/src/utils/axios.js
+++ b/src/utils/axios.js
@@ -1,11 +1,5 @@
-import axios from "axios";
-
-const ins = axios.create({
- headers: {
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Methods': 'GET, POST',
- 'Access-Control-Allow-Headers': 'Content-Type, Access-Control-Allow-Headers, Authorization'
- },
- responseType: 'json'
-})
+const ins = {
+ post: (url, body, config) => fetch(url, {...config, method: "POST", body}),
+ get: (url, config) => fetch(url, {...config, method: "GET"}),
+}
export default ins
diff --git a/src/utils/models.js b/src/utils/models.js
index 1193602..9ecd4dc 100644
--- a/src/utils/models.js
+++ b/src/utils/models.js
@@ -1,5 +1,5 @@
import axios from "./axios";
-import {AI_AVATAR} from "./env";
+import {AI_AVATAR, OPEN_AI_KEY} from "./env";
class BaseModel {
constructor(props) {
@@ -14,16 +14,33 @@ export class ChatGPT extends BaseModel {
constructor() {
super({
- avatar: AI_AVATAR,
- name: 'ChatGPT',
- id: "gpt-3.5-turbo",
- desc: "ChatGPT-3.5所基于的模型"
+ avatar: AI_AVATAR, name: 'ChatGPT', id: "gpt-3.5-turbo", desc: "ChatGPT-3.5所基于的模型",
});
+ this.apiKey = OPEN_AI_KEY
}
- async chat(history, callback) {
- return await axios.post(ChatGPT.base + "/v1/chat/completions")
+ setApiKey(key) {
+ this.apiKey = key
}
+
+ async chat(history) {
+ const messages = history.map(e => ({role: e.role, content: e.msg}))
+ return await axios.post(ChatGPT.base + "/v1/chat/completions", JSON.stringify({messages, model: this.id}), {
+ headers: {
+ Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
+ },
+ }).then(res => res.json()).then(data => data?.choices?.[0]?.message?.content || "key无效或网络波动,请重新尝试");
+ }
+
+ async chatStream(history) {
+ const messages = history.map(e => ({role: e.role, content: e.msg}))
+ return await axios.post(ChatGPT.base + "/v1/chat/completions", JSON.stringify({messages, model: this.id, stream: true}), {
+ headers: {
+ Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
+ },
+ }).then(res => res?.body?.getReader());
+ }
+
}
export class ChatGLM extends BaseModel {
@@ -31,10 +48,7 @@ export class ChatGLM extends BaseModel {
constructor() {
super({
- avatar: AI_AVATAR,
- name: 'ChatGLM',
- id: "chatglm-6b",
- desc: "ChatGLM-6B所基于的模型"
+ avatar: AI_AVATAR, name: 'ChatGLM', id: "chatglm-6b", desc: "ChatGLM-6B所基于的模型"
});
}