This commit is contained in:
Twilight 2024-08-04 23:09:39 +08:00
parent 2f9744d5a8
commit de00770bff
2 changed files with 145 additions and 128 deletions

View File

@ -2,13 +2,18 @@
<div> <div>
<h3 class="mb-3">聊天记录</h3> <h3 class="mb-3">聊天记录</h3>
<v-card v-for="message in messages.data" :key="message.id" class="mx-auto mt-3" width="100%"> <v-card
v-for="message in messages.data"
:key="message.id"
class="mx-auto mt-3"
width="100%"
>
<template #title> <template #title>
<div class="font-weight-black"> <div class="font-weight-black">
<div v-if="message.role == 'assistant'"> AI </div> <div v-if="message.role == 'assistant'">AI</div>
<div v-else-if="message.role == 'system'"> 系统 </div> <div v-else-if="message.role == 'system'">系统</div>
<div v-else-if="message.role == 'user'" class="text-right"> 用户 </div> <div v-else-if="message.role == 'user'" class="text-right">用户</div>
<div v-else> <div v-else>
{{ message.role }} {{ message.role }}
@ -24,40 +29,52 @@
<div class="mt-3"> <div class="mt-3">
<div v-if="toolError" class="mb-3"> <div v-if="toolError" class="mb-3">
<v-alert density="compact" text="这个工具出现了异常,这应该不是我们的问题,如果你是此工具的开发者,请打开开发者控制台查看具体错误。" <v-alert
:title="'工具 ' + toolName + ' 出现异常'" type="warning"></v-alert> density="compact"
text="这个工具出现了异常,这应该不是我们的问题,如果你是此工具的开发者,请打开开发者控制台查看具体错误。"
:title="'工具 ' + toolName + ' 出现异常'"
type="warning"
></v-alert>
</div> </div>
<div v-show="toolCalling"> <div v-show="toolCalling">
<v-progress-circular color="primary" indeterminate :size="16"></v-progress-circular> <v-progress-circular
color="primary"
indeterminate
:size="16"
></v-progress-circular>
正在执行 {{ toolName }} 正在执行 {{ toolName }}
</div> </div>
<v-text-field v-model="input" label="输入消息" @keyup.enter="sendMessage"></v-text-field> <v-text-field
v-model="input"
label="输入消息"
@keyup.enter="sendMessage"
></v-text-field>
<v-btn color="primary" @click="sendMessage">发送</v-btn> <v-btn color="primary" @click="sendMessage">发送</v-btn>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ApiV1ChatsIdMessagesGet200Response } from "@/api" import { ApiV1ChatsIdMessagesGet200Response } from "@/api";
import { ref } from "vue" import { ref } from "vue";
import { api, conf } from "@/plugins/api" import { api, conf } from "@/plugins/api";
import VueMarkdown from "vue-markdown-render" import VueMarkdown from "vue-markdown-render";
// @ts-ignore // @ts-ignore
const chatId = parseInt(useRoute().params.id as string) const chatId = parseInt(useRoute().params.id as string);
const messages: Ref<ApiV1ChatsIdMessagesGet200Response> = ref({ const messages: Ref<ApiV1ChatsIdMessagesGet200Response> = ref({
data: [], data: [],
}) });
const input = ref("") const input = ref("");
const toolName = ref("") const toolName = ref("");
const toolError = ref(false) const toolError = ref(false);
const toolCalling = ref(false) const toolCalling = ref(false);
function sendMessage() { function sendMessage() {
if (input.value !== "") { if (input.value !== "") {
toolError.value = false toolError.value = false;
api.ChatMessage.apiV1ChatsIdMessagesPost(chatId, { api.ChatMessage.apiV1ChatsIdMessagesPost(chatId, {
message: input.value, message: input.value,
}) })
@ -65,109 +82,113 @@ function sendMessage() {
const newMessage = { const newMessage = {
content: input.value, content: input.value,
role: "user", role: "user",
} };
if (messages.value.data == null) { if (messages.value.data == null) {
messages.value.data = [newMessage] messages.value.data = [newMessage];
} else { } else {
messages.value.data?.push(newMessage) messages.value.data?.push(newMessage);
} }
const streamId = res.data.data?.stream_id const streamId = res.data.data?.stream_id;
if (streamId) { if (streamId) {
streamChat(streamId) streamChat(streamId);
} }
}) })
.catch((err) => { .catch((err) => {
// if 409 // if 409
if (err.response.status === 409) { if (err.response.status === 409) {
const streamId = err.response.data.data?.stream_id const streamId = err.response.data.data?.stream_id;
if (streamId) { if (streamId) {
streamChat(streamId) streamChat(streamId);
} }
} }
}) });
} }
} }
function streamChat(streamId: String) { function streamChat(streamId: String) {
const url = conf.basePath + "/api/v1/stream/" + streamId const url = conf.basePath + "/api/v1/stream/" + streamId;
const evtSource = new EventSource(url) const evtSource = new EventSource(url);
let messageAdded = false
let messageAdded = false;
// //
window.scrollTo(0, document.body.scrollHeight) window.scrollTo(0, document.body.scrollHeight);
// set index // set index
const i = (messages.value.data?.length ?? 1) - 1 const i = (messages.value.data?.length ?? 1) - 1;
evtSource.addEventListener("data", (e) => { evtSource.addEventListener("data", (e) => {
const data = JSON.parse(e.data) const data = JSON.parse(e.data);
console.log(data.state) console.log(data.state);
let append = true
let append = true;
switch (data.state) { switch (data.state) {
case "tool_calling": case "tool_calling":
toolCalling.value = true toolCalling.value = true;
toolName.value = data.tool_call_message.tool_name + " 中的 " + data.tool_call_message.function_name toolName.value =
break data.tool_call_message.tool_name +
" 中的 " +
data.tool_call_message.function_name;
break;
case "tool_response": case "tool_response":
setTimeout(() => { setTimeout(() => {
toolName.value = "" toolName.value = "";
toolCalling.value = false toolCalling.value = false;
}, 300) }, 300);
break break;
case "tool_failed": case "tool_failed":
toolName.value = data.tool_response_message.tool_name + " 中的 " + data.tool_response_message.function_name toolName.value =
toolError.value = true data.tool_response_message.tool_name +
append = false " 中的 " +
data.tool_response_message.function_name;
toolError.value = true;
append = false;
setTimeout(() => { setTimeout(() => {
toolCalling.value = false toolCalling.value = false;
}, 300) }, 300);
break break;
case "chunk": case "chunk":
if (!messageAdded) { if (!messageAdded) {
const newMessage = { const newMessage = {
content: "", content: "",
role: "assistant", role: "assistant",
} };
if (messages.value.data == null) { if (messages.value.data == null) {
messages.value.data = [newMessage] messages.value.data = [newMessage];
} else { } else {
// add to messages // add to messages
messages.value.data?.push(newMessage) messages.value.data?.push(newMessage);
} }
messageAdded = true messageAdded = true;
append = true append = true;
} }
} }
if (append && messageAdded) { if (append && messageAdded) {
// @ts-ignore // @ts-ignore
messages.value.data[i].content += data.content messages.value.data[i].content += data.content;
} }
}) });
// close // close
evtSource.addEventListener("close", () => { evtSource.addEventListener("close", () => {
evtSource.close() evtSource.close();
}) });
} }
const getMessages = () => { const getMessages = () => {
api.ChatMessage.apiV1ChatsIdMessagesGet(chatId).then((res) => { api.ChatMessage.apiV1ChatsIdMessagesGet(chatId).then((res) => {
messages.value = res.data messages.value = res.data;
}) });
} };
getMessages() getMessages();
</script> </script>

View File

@ -1,83 +1,79 @@
<template> <template>
<h3>验证语法</h3> <h3>验证语法</h3>
<p>目前处于测试阶段不一定准确但是能保证你添加成功</p> <p>目前处于测试阶段不一定准确但是能保证你添加成功</p>
<!-- input -->
<v-textarea v-model="input" label="你的 JSON 数据"></v-textarea>
<v-btn class="mt-3 mb-3" color="primary" @click="validate()">验证</v-btn>
<!-- input --> <div v-show="checked">
<v-textarea v-model="input" label="你的 JSON 数据"></v-textarea> <p v-show="error" class="text-danger">错误{{ errorReason }}</p>
<p v-show="!error" class="text-success">正确</p>
<v-btn color="primary" class="mt-3 mb-3" @click="validate()">验证</v-btn> </div>
<div v-show="checked">
<p v-show="error" class="text-danger">错误{{ errorReason }}</p>
<p v-show="!error" class="text-success">正确</p>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { RagNewInternalSchemaToolDiscoveryInput } from '@/api' import { RagNewInternalSchemaToolDiscoveryInput } from "@/api";
import { api } from '@/plugins/api' import { api } from "@/plugins/api";
const exampleJSON = { const exampleJSON = {
"name": "My Functions", name: "My Functions",
"description": "My Functions", description: "My Functions",
"homepage_url": "https://ivampiresp.com/test", homepage_url: "https://ivampiresp.com/test",
"callback_url": "https://ivampiresp.com/files/tool_test/index.php", callback_url: "https://ivampiresp.com/files/tool_test/index.php",
"functions": [ functions: [
{ {
"name": "get_current_time", name: "get_current_time",
"description": "当你想知道现在的时间时非常有用。", description: "当你想知道现在的时间时非常有用。",
"parameters": {} parameters: {},
},
{
name: "get_current_weather",
description: "当你想查询指定城市的天气时非常有用。",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "城市或县区,比如北京市、杭州市、余杭区等。",
},
}, },
{ },
"name": "get_current_weather", required: ["location"],
"description": "当你想查询指定城市的天气时非常有用。", },
"parameters": { ],
"type": "object", };
"properties": {
"location": {
"type": "string",
"description": "城市或县区,比如北京市、杭州市、余杭区等。"
}
}
},
"required": [
"location"
]
}
]
}
const input = ref("") const input = ref("");
const checked = ref(false) const checked = ref(false);
const error = ref(false) const error = ref(false);
const errorReason = ref("") const errorReason = ref("");
// unmashal // unmashal
input.value = JSON.stringify(exampleJSON, null, 4) input.value = JSON.stringify(exampleJSON, null, 4);
function validate() { function validate() {
checked.value = true checked.value = true;
// json // json
try { try {
JSON.parse(input.value) JSON.parse(input.value);
} catch (e) { } catch (e) {
error.value = true error.value = true;
errorReason.value = "JSON 格式错误" errorReason.value = "JSON 格式错误";
return return;
} }
// //
const data: RagNewInternalSchemaToolDiscoveryInput = JSON.parse(input.value) const data: RagNewInternalSchemaToolDiscoveryInput = JSON.parse(input.value);
api.Tool.apiV1ToolsSyntaxPost(data)
api.Tool.apiV1ToolsSyntaxPost(data).then((res) => { .then(() => {
error.value = false error.value = false;
errorReason.value = "" errorReason.value = "";
}).catch((e) => {
error.value = true
errorReason.value = e.response.data.error
}) })
.catch((e) => {
error.value = true;
errorReason.value = e.response.data.error;
});
} }
</script> </script>