extract code for saving chat history

This commit is contained in:
RockYang
2024-05-22 15:32:44 +08:00
parent 627396dbf7
commit 962de0183c
18 changed files with 261 additions and 717 deletions

View File

@@ -92,9 +92,9 @@ const items = [
},
{
icon: 'role',
index: '/admin/role',
title: '角色管理',
icon: 'menu',
index: '/admin/app',
title: '应用管理',
},
{
icon: 'api-key',

View File

@@ -46,7 +46,7 @@ const routes = [
component: () => import('@/views/Member.vue'),
},
{
name: 'chat-role',
name: 'chat-app',
path: '/apps',
meta: {title: '应用中心'},
component: () => import('@/views/ChatApps.vue'),
@@ -139,10 +139,10 @@ const routes = [
component: () => import('@/views/admin/Users.vue'),
},
{
path: '/admin/role',
name: 'admin-role',
meta: {title: '角色管理'},
component: () => import('@/views/admin/Roles.vue'),
path: '/admin/app',
name: 'admin-app',
meta: {title: '应用管理'},
component: () => import('@/views/admin/Apps.vue'),
},
{
path: '/admin/apikey',

View File

@@ -119,12 +119,12 @@ const mjModels = ref([
{name: "急速Turbo", value: "turbo"},
])
httpGet("/api/admin/config/get/draw").then(res => {
httpGet("/api/admin/config/get/app").then(res => {
sdConfigs.value = res.data.sd
mjPlusConfigs.value = res.data.mj_plus
mjProxyConfigs.value = res.data.mj_proxy
}).catch(e =>{
ElMessage.error("获取AI绘画配置失败:"+e.message)
ElMessage.error("获取配置失败:"+e.message)
})
const addConfig = (configs) => {

View File

@@ -87,7 +87,7 @@
<el-input v-model="item.name" autocomplete="off"/>
</el-form-item>
<el-form-item label="用途" prop="type">
<el-select v-model="item.type" placeholder="请选择用途" @change="changePlatform">
<el-select v-model="item.type" placeholder="请选择用途" @change="changeType">
<el-option v-for="item in types" :value="item.value" :label="item.name" :key="item.value">{{
item.name
}}
@@ -99,7 +99,8 @@
</el-form-item>
<el-form-item label="API URL" prop="api_url">
<el-input v-model="item.api_url" autocomplete="off"
placeholder="如果你用了第三方的 API 中转这里填写中转地址"/>
placeholder="必须填土完整的 Chat API URLhttps://api.openai.com/v1/chat/completions"/>
<div class="info">如果你使用了第三方中转这里就填写中转地址</div>
</el-form-item>
<el-form-item label="代理地址:" prop="proxy_url">
@@ -126,7 +127,7 @@ import {onMounted, onUnmounted, reactive, ref} from "vue";
import {httpGet, httpPost} from "@/utils/http";
import {ElMessage} from "element-plus";
import {dateFormat, removeArrayItem, substr} from "@/utils/libs";
import {DocumentCopy, Plus, ShoppingCart} from "@element-plus/icons-vue";
import {DocumentCopy, Plus, ShoppingCart, InfoFilled} from "@element-plus/icons-vue";
import ClipboardJS from "clipboard";
// 变量定义
@@ -142,39 +143,7 @@ const rules = reactive({
const loading = ref(true)
const formRef = ref(null)
const title = ref("")
const platforms = ref([
{
name: "OpenAI/中转ChatGPT",
value: "OpenAI",
api_url: "https://api.chat-plus.net/v1/chat/completions",
img_url: "https://api.chat-plus.net/v1/images/generations"
},
{
name: "【讯飞】星火大模型",
value: "XunFei",
api_url: "wss://spark-api.xf-yun.com/{version}/chat"
},
{
name: "【清华智普】ChatGLM",
value: "ChatGLM",
api_url: "https://open.bigmodel.cn/api/paas/v3/model-api/{model}/sse-invoke"
},
{
name: "【百度】文心一言",
value: "Baidu",
api_url: "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model}"
},
{
name: "【微软】Azure",
value: "Azure",
api_url: "https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15"
},
{
name: "【阿里】千义通问",
value: "QWen",
api_url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
},
])
const platforms = ref([])
const types = ref([
{name: "聊天", value: "chat"},
{name: "绘画", value: "img"},
@@ -191,6 +160,12 @@ onMounted(() => {
clipboard.value.on('error', () => {
ElMessage.error('复制失败!');
})
httpGet("/api/admin/config/get/app").then(res => {
platforms.value = res.data.platforms
}).catch(e =>{
ElMessage.error("获取配置失败:"+e.message)
})
})
onUnmounted(() => {
@@ -263,21 +238,24 @@ const set = (filed, row) => {
})
}
const changePlatform = () => {
let platform = null
const selectedPlatform = ref(null)
const changePlatform = (value) => {
console.log(value)
for (let v of platforms.value) {
if (v.value === item.value.platform) {
platform = v
break
if (v.value === value) {
selectedPlatform.value = v
item.value.api_url = v.chat_url
}
}
if (platform !== null) {
if (item.value.type === "img" && platform.img_url) {
item.value.api_url = platform.img_url
} else {
item.value.api_url = platform.api_url
}
}
const changeType = (value) => {
if (selectedPlatform.value) {
if(value === 'img') {
item.value.api_url = selectedPlatform.value.img_url
} else {
item.value.api_url = selectedPlatform.value.chat_url
}
}
}
</script>
@@ -306,7 +284,9 @@ const changePlatform = () => {
.el-form {
.el-form-item__content {
.info {
color #999999
}
.el-icon {
padding-left: 10px;
}

View File

@@ -9,25 +9,25 @@
<template #default="props">
<div>
<el-table :data="props.row.context" :border="childBorder">
<el-table-column label="对话角色" prop="role" width="120"/>
<el-table-column label="对话应用" prop="role" width="120"/>
<el-table-column label="对话内容" prop="content"/>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column label="角色名称" prop="name">
<el-table-column label="应用名称" prop="name">
<template #default="scope">
<span class="sort" :data-id="scope.row.id">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="角色标识" prop="key"/>
<el-table-column label="应用标识" prop="key"/>
<el-table-column label="绑定模型" prop="model_name"/>
<el-table-column label="启用状态">
<template #default="scope">
<el-switch v-model="scope.row['enable']" @change="roleSet('enable',scope.row)"/>
</template>
</el-table-column>
<el-table-column label="角色图标" prop="icon">
<el-table-column label="应用图标" prop="icon">
<template #default="scope">
<el-image :src="scope.row.icon" style="width: 45px; height: 45px; border-radius: 50%"/>
</template>
@@ -36,7 +36,7 @@
<el-table-column label="操作" width="150" align="right">
<template #default="scope">
<el-button size="small" type="primary" @click="rowEdit(scope.$index, scope.row)">编辑</el-button>
<el-popconfirm title="确定要删除当前角色吗?" @confirm="removeRole(scope.row)" :width="200">
<el-popconfirm title="确定要删除当前应用吗?" @confirm="removeRole(scope.row)" :width="200">
<template #reference>
<el-button size="small" type="danger">删除</el-button>
</template>
@@ -53,21 +53,21 @@
width="50%"
>
<el-form :model="role" label-width="120px" ref="formRef" label-position="left" :rules="rules">
<el-form-item label="角色名称:" prop="name">
<el-form-item label="应用名称:" prop="name">
<el-input
v-model="role.name"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="角色标志:" prop="key">
<el-form-item label="应用标志:" prop="key">
<el-input
v-model="role.key"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="角色图标:" prop="icon">
<el-form-item label="应用图标:" prop="icon">
<el-input v-model="role.icon">
<template #append>
<el-upload
@@ -107,7 +107,7 @@
<el-form-item label="上下文信息:" prop="context">
<template #default>
<el-table :data="role.context" :border="childBorder" size="small">
<el-table-column label="对话角色" width="120">
<el-table-column label="对话应用" width="120">
<template #default="scope">
<el-input
v-model="scope.row.role"
@@ -181,8 +181,8 @@ const loading = ref(true)
const rules = reactive({
name: [{required: true, message: '请输入用户名', trigger: 'blur',}],
key: [{required: true, message: '请输入角色标识', trigger: 'blur',}],
icon: [{required: true, message: '请输入角色图标', trigger: 'blur',}],
key: [{required: true, message: '请输入应用标识', trigger: 'blur',}],
icon: [{required: true, message: '请输入应用图标', trigger: 'blur',}],
sort: [
{required: true, message: '请输入排序数字', trigger: 'blur'},
{type: 'number', message: '请输入有效数字'},
@@ -204,13 +204,13 @@ onMounted(() => {
})
const fetchData = () => {
//
//
httpGet('/api/admin/role/list').then((res) => {
tableData.value = res.data
sortedTableData.value = copyObj(tableData.value)
loading.value = false
}).catch(() => {
ElMessage.error("获取聊天角色失败");
ElMessage.error("获取聊天应用失败");
})
const drawBodyWrapper = document.querySelector('.el-table__body tbody')
@@ -250,14 +250,14 @@ const roleSet = (filed, row) => {
//
const curIndex = ref(0)
const rowEdit = function (index, row) {
optTitle.value = "修改角色"
optTitle.value = "修改应用"
curIndex.value = index
role.value = copyObj(row)
showDialog.value = true
}
const addRole = function () {
optTitle.value = "添加新角色"
optTitle.value = "添加新应用"
role.value = {context: []}
showDialog.value = true
}

View File

@@ -214,15 +214,7 @@ const rules = reactive({
})
const loading = ref(true)
const formRef = ref(null)
const platforms = ref([
{name: "OpenAIChatGPT", value: "OpenAI"},
{name: "讯飞星火大模型", value: "XunFei"},
{name: "清华智普ChatGLM", value: "ChatGLM"},
{name: "百度文心一言", value: "Baidu"},
{name: "微软Azure", value: "Azure"},
{name: "阿里通义千问", value: "QWen"},
])
const platforms = ref([])
// 获取 API KEY
const apiKeys = ref([])
@@ -287,6 +279,12 @@ onMounted(() => {
clipboard.value.on('error', () => {
ElMessage.error('复制失败!');
})
httpGet("/api/admin/config/get/app").then(res => {
platforms.value = res.data.platforms
}).catch(e =>{
ElMessage.error("获取配置失败"+e.message)
})
})
onUnmounted(() => {