Commit 0295590b authored by pengxin's avatar pengxin

Merge remote-tracking branch 'remotes/origin/ljgc-web'

# Conflicts:
#	src/api/GptController/KnowledgeManage.js
#	src/staticDict/gptStaticDict.js
#	src/views/gptTraining/knowledgeBase/card/index.vue
#	src/views/gptTraining/modelService/testOnline/components/contentView/filePreview/index.vue
#	src/views/gptTraining/modelService/testOnline/components/contentView/index.vue
#	src/views/gptTraining/modelService/testOnline/components/leftBox/index.vue
#	src/views/gptTraining/modelService/testOnline/components/rightBox/index.vue
#	src/views/gptTraining/promptProject/promptTemplate/components/dialog/createTemplate.vue
parents 49dc9a9c f56b2646
......@@ -19216,6 +19216,16 @@
"extsprintf": "^1.2.0"
}
},
"vis-data": {
"version": "7.1.9",
"resolved": "https://registry.npmmirror.com/vis-data/-/vis-data-7.1.9.tgz",
"integrity": "sha512-COQsxlVrmcRIbZMMTYwD+C2bxYCFDNQ2EHESklPiInbD/Pk3JZ6qNL84Bp9wWjYjAzXfSlsNaFtRk+hO9yBPWA=="
},
"vis-network": {
"version": "9.1.9",
"resolved": "https://registry.npmmirror.com/vis-network/-/vis-network-9.1.9.tgz",
"integrity": "sha512-Ft+hLBVyiLstVYSb69Q1OIQeh3FeUxHJn0WdFcq+BFPqs+Vq1ibMi2sb//cxgq1CP7PH4yOXnHxEH/B2VzpZYA=="
},
"vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz",
......
......@@ -36,6 +36,8 @@
"register-service-worker": "^1.6.2",
"sortablejs": "^1.7.0",
"v-charts": "^1.19.0",
"vis-data": "^7.1.9",
"vis-network": "^9.1.9",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.3",
"vue-demi": "^0.14.6",
......@@ -50,6 +52,7 @@
"xe-utils": "^3.5.4",
"xml-js": "^1.6.11"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-plugin-eslint": "~4.2.0",
......
<template>
<div>
<div style="height:100%;width:100%">
<router-view></router-view>
</div>
</template>
......
......@@ -8,7 +8,7 @@ export default class KnowledgeManage {
static recreate (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/recreate', 'post', params, axiosOption, httpOption);
}
static searchDocs (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/searchDocs', 'post', params, axiosOption, httpOption);
}
......@@ -18,34 +18,49 @@ export default class KnowledgeManage {
static uploadDocs (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/uploadDocs', 'post', params, axiosOption, httpOption);
}
static view (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/view', 'get', params, axiosOption, httpOption);
}
static export (sender, params, fileName) {
return sender.download('/admin/app/knowledgeManage/export', params, fileName);
}
static add (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/add', 'post', params, axiosOption, httpOption);
}
static update (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/update', 'post', params, axiosOption, httpOption);
}
static delete (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/delete', 'post', params, axiosOption, httpOption);
}
static deleteDocs (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/deleteDocs', 'post', params, axiosOption, httpOption);
}
static listForTree (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/listForTree', 'post', params, axiosOption, httpOption);
}
static load (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/load', 'post', params, axiosOption, httpOption);
}
static addKnowledgeUser (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/addKnowledgeUser', 'post', params, axiosOption, httpOption);
}
static listNotInKnowledgeUser (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/listNotInKnowledgeUser', 'post', params, axiosOption, httpOption);
}
static getSysUserListByKnowledgeId (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/listKnowledgeUser', 'post', params, axiosOption, httpOption);
}
static deleteKnowledgeUser (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/knowledgeManage/deleteKnowledgeUser', 'post', params, axiosOption, httpOption);
}
}
This diff is collapsed.
......@@ -7,6 +7,11 @@ html, body {
font-size: 14px;
font-family: Arial,"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",sans-serif;
background-color: rgb(228,240,255);
height: 100%;
width: 100%;
}
div{
word-break:break-all
}
.omit {
/* 一行省略 */
......
module.exports = {
baseUrl: 'http://192.168.0.36:8082/',
wsUrl: 'ws://192.168.0.36:7860/',
baseUrl: 'http://218.76.0.69:8082/',
wsUrl: 'ws://218.76.0.69:7860/',
projectName: '灵境大模型平台'
}
......@@ -11,7 +11,6 @@ import router from './router';
import store from './store';
import '@/staticDict/gptStaticDict.js';
import {SocketService} from '@/utils/websocket.js';
import TreeSelect from '@/components/TreeSelect';
import RichEditor from '@/components/RichEditor';
import InputNumberRange from '@/components/InputNumberRange';
......
......@@ -14,13 +14,14 @@ const routers = [
component: _import('login/index'),
name: 'root'
},
{path: '/aggregate', component: _import('welcome/index-2'), name: 'aggregate', meta: { title: '集群' }},
{
path: '/main',
component: _import('layout/index'),
name: 'main',
props: getProps,
redirect: {
name: 'welcome'
name: 'aggregate'
},
meta: {
title: '主页',
......@@ -89,6 +90,7 @@ const routers = [
// { path: 'batchOptimization', component: _import('gptTraining/promptProject/batchOptimization/index'), name: 'batchOptimization', props: getProps, meta: { title: '批量优化' } },
// 知识库
{ path: 'knowledgeBase', component: _import('gptTraining/knowledgeBase/index'), name: 'knowledgeBase', props: getProps, meta: { title: '知识库' } },
{ path: 'welcome', component: _import('welcome/index'), name: 'welcome', meta: { title: '欢迎' } }
]
}
......
......@@ -412,8 +412,13 @@ const ModeOfSpeaking = new DictionaryBase('对话模式', [
},
{
id: 3,
name: '文件对话',
name: '基于文件问答',
symbol: 'fileSession'
},
{
id: 4,
name: '知识图谱问答',
symbol: 'knowledgeGraph'
}
// {
// id: 2,
......
......@@ -36,8 +36,9 @@
</el-tooltip>
</div> -->
<div style="margin-bottom:10px">
<el-button :size="defaultFormItemSize" :plain="true" @click="handleCommand('auth',item)" >授权</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="handleCommand('edit',item)" >编辑</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="handleCommand('del',item)">删除</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="handleCommand('del',item)">删除</el-button>
</div>
</div>
</el-card>
......@@ -47,6 +48,7 @@
<script>
import { KnowledgeManage } from '@/api/gptController.js';
import editOrAdd from '../dialog/editOrAdd';
import authKnowledgeUser from '../dialog/authKnowledgeUser/index';
export default {
data () {
return {
......@@ -95,6 +97,13 @@ export default {
this.refresh();
}).catch(e => { this.refresh(); });
},
auth (item) {
this.$dialog.show('授权知识库', authKnowledgeUser, {
area: ['1100px', '600px']
}, { knowledgeId: item.knowledgeId }).then(res => {
this.refresh();
}).catch(e => { this.refresh(); });
},
del (item) {
this.$confirm('是否确认删除', '提示', {
confirmButtonText: '确定',
......@@ -123,6 +132,8 @@ export default {
this.del(item)
} else if (command === 'copy') {
this.copy(item)
} else if (command === 'auth') {
this.auth(item)
}
}
}
......
<template>
<div style="position: relative;">
<el-form ref="formKnowledgeUsers" :model="formData" label-width="75px" :size="defaultFormItemSize" label-position="right" @submit.native.prevent>
<filter-box :item-width="325" :hasSearch="false">
<el-form-item label="用户状态" prop="formFilter.sysUserStatus">
<el-select class="filter-item" v-model="formData.formFilter.sysUserStatus" :clearable="true"
placeholder="用户状态" :loading="formData.sysUserStatus.impl.loading"
@visible-change="onSysUserStatusVisibleChange">
<el-option v-for="item in formData.sysUserStatus.impl.dropdownList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item label="用户名" prop="formFilter.sysUserLoginName">
<el-input class="filter-item" v-model="formData.formFilter.sysUserLoginName" maxlength="12"
:clearable="true" placeholder="用户名" />
</el-form-item>
<div class="search-box" style="padding-left: 8px;margin-bottom: 16px;">
<el-button slot="operator" type="default" :plain="true" :size="defaultFormItemSize" @click="onReset">重置</el-button>
<el-button slot="operator" type="primary" :plain="true" :size="defaultFormItemSize" @click="refreshFormKnowledgeUserList(true)" icon="el-icon-search">查询</el-button>
<el-button :size="defaultFormItemSize" type="primary" :plain="false" @click="onSetUser"
:disabled="selectUsers == null || selectUsers.length <= 0">授权人员</el-button>
</div>
</filter-box>
</el-form>
<el-row>
<el-col :span="24">
<el-table :data="formData.SysUser.impl.dataList" :size="defaultFormItemSize" row-key="userId" ref="userTable"
header-cell-class-name="table-header-gray" @selection-change="onTableSelectionChange">
<el-table-column label="序号" header-align="center" align="center" type="index" width="50px" :index="formData.SysUser.impl.getTableIndex" />
<el-table-column header-align="center" align="center" type="selection" width="50px" :reserve-selection="true" />
<el-table-column label="用户名" prop="loginName">
</el-table-column>
<el-table-column label="昵称" prop="showName">
</el-table-column>
<el-table-column label="账号类型">
<template slot-scope="scope">
<span>{{SysUserType.getValue(scope.row.userType)}}</span>
</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
<el-tag :type="getUserStatusType(scope.row.userStatus)" :size="defaultFormItemSize">{{SysUserStatus.getValue(scope.row.userStatus)}}</el-tag>
</template>
</el-table-column>
</el-table>
<el-col :span="24">
<el-row type="flex" justify="end" style="margin-top: 10px;">
<el-pagination
:total="formData.SysUser.impl.totalCount"
:current-page="formData.SysUser.impl.currentPage"
:page-size="formData.SysUser.impl.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
@current-change="formData.SysUser.impl.onCurrentPageChange"
@size-change="formData.SysUser.impl.onPageSizeChange">
</el-pagination>
</el-row>
</el-col>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
/* eslint-disable-next-line */
import { DropdownWidget, TableWidget } from '@/utils/widget.js';
/* eslint-disable-next-line */
import { uploadMixin, statsDateRangeMixin, cachePageMixin } from '@/core/mixins';
/* eslint-disable-next-line */
import { DictionaryController } from '@/api';
import { KnowledgeManage } from '@/api/gptController.js';
export default {
name: 'formKnowledgeUsers',
props: {
knowledgeId: {
type: [String, Number],
required: true
}
},
mixins: [uploadMixin, statsDateRangeMixin, cachePageMixin],
data () {
return {
formData: {
formFilter: {
sysUserStatus: undefined,
sysUserLoginName: undefined
},
formFilterCopy: {
sysUserStatus: undefined,
sysUserLoginName: undefined
},
sysUserStatus: {
impl: new DropdownWidget(this.loadSysUserStatusDropdownList)
},
SysUser: {
impl: new TableWidget(this.loadSysUserData, this.loadSysUserVerify, true, false)
},
isInit: false
},
selectUsers: []
}
},
methods: {
/**
* 用户状态下拉数据获取函数
*/
loadSysUserStatusDropdownList () {
return new Promise((resolve, reject) => {
let params = {};
DictionaryController.dictSysUserStatus(this, params).then(res => {
resolve(res.getList());
}).catch(e => {
reject(e);
});
});
},
/**
* 用户状态下拉框显隐
*/
onSysUserStatusVisibleChange (show) {
this.formData.sysUserStatus.impl.onVisibleChange(show).catch(e => {});
},
getUserStatusType (status) {
if (status === this.SysUserStatus.NORMAL) {
return 'success';
} else if (status === this.SysUserStatus.LOCKED) {
return 'danger';
} else {
return 'info';
}
},
onTableSelectionChange (values) {
this.selectUsers = values;
},
onSetUser () {
let params = {
knowledgeId: this.knowledgeId,
userIdListString: this.selectUsers.map((item) => {
return item.userId
}).join(',')
}
KnowledgeManage.addKnowledgeUser(this, params).then(res => {
this.$message.success('授权成功');
this.refreshFormKnowledgeUserList(true);
this.$refs.userTable.clearSelection();
this.selectUsers = [];
}).catch(e => {});
},
onCancel () {
this.$router.go(-1);
},
onReset () {
this.$refs.formKnowledgeUsers.resetFields();
this.refreshFormKnowledgeUserList(true);
},
loadSysUserData (params) {
params.knowledgeId = this.knowledgeId;
params.sysUserDtoFilter = {
loginName: this.formData.formFilterCopy.sysUserLoginName,
userStatus: this.formData.formFilterCopy.sysUserStatus
}
return new Promise((resolve, reject) => {
KnowledgeManage.listNotInKnowledgeUser(this, params).then(res => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount
});
}).catch(e => {
reject(e);
});
});
},
/**
* 获取检测函数,返回true正常获取数据,返回false停止获取数据
*/
loadSysUserVerify () {
this.formData.formFilterCopy.sysUserLoginName = this.formData.formFilter.sysUserLoginName;
this.formData.formFilterCopy.sysUserStatus = this.formData.formFilter.sysUserStatus;
return true;
},
refreshFormKnowledgeUserList (reloadData = false) {
// 重新获取数据组件的数据
if (reloadData) {
this.formData.SysUser.impl.refreshTable(true, 1);
} else {
this.formData.SysUser.impl.refreshTable();
}
this.formData.sysUserStatus.impl.onVisibleChange(true).catch(e => {});
this.formData.isInit = true;
},
initFormData () {
},
formInit () {
this.initFormData();
this.refreshFormKnowledgeUserList();
}
},
computed: {
getContextHeightStyle () {
return [
{'height': (this.getClientHeight - 142) + 'px'}
]
},
...mapGetters(['getClientHeight'])
},
created () {
this.formInit();
}
}
</script>
<style>
</style>
<template>
<div style="position: relative;">
<el-form ref="formKnowledgeUser" :model="formData" label-width="75px" :size="defaultFormItemSize" label-position="right" @submit.native.prevent>
<filter-box :item-width="350" :hasSearch="false">
<el-form-item label="用户名" prop="formFilter.sysUserLoginName">
<el-input class="filter-item" v-model="formData.formFilter.sysUserLoginName" maxlength="12" :clearable="true" placeholder="输入用户名 / 昵称查询"/>
</el-form-item>
<div class="search-box" style="padding-left: 8px;margin-bottom: 16px;">
<el-button slot="operator" type="default" :size="defaultFormItemSize" :plain="true" @click="onReset">重置</el-button>
<el-button slot="operator" type="primary" :size="defaultFormItemSize" :plain="true" @click="refreshFormKnowledgeUser(true)" icon="el-icon-search">查询</el-button>
<el-button type="primary" :size="defaultFormItemSize" :plain="false" @click="onAddRow()" icon="el-icon-plus">添加用户</el-button>
</div>
</filter-box>
</el-form>
<el-row>
<el-col :span="24">
<el-table :data="formData.SysUser.impl.dataList" :size="defaultFormItemSize" @sort-change="formData.SysUser.impl.onSortChange"
header-cell-class-name="table-header-gray">
<el-table-column label="序号" header-align="center" align="center" type="index" width="50px" :index="formData.SysUser.impl.getTableIndex" />
<el-table-column label="用户名" prop="loginName">
</el-table-column>
<el-table-column label="昵称" prop="showName">
</el-table-column>
<el-table-column label="账号类型">
<template slot-scope="scope">
<span>{{SysUserType.getValue(scope.row.userType)}}</span>
</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
<el-tag :type="getUserStatusType(scope.row.userStatus)" :size="defaultFormItemSize">{{SysUserStatus.getValue(scope.row.userStatus)}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="80px">
<template slot-scope="scope">
<el-button class="btn-table-delete" type="text" :size="defaultFormItemSize" @click="onDeleteRow(scope.row)">
移除
</el-button>
</template>
</el-table-column>
</el-table>
<el-col :span="24">
<el-row type="flex" justify="end" style="margin-top: 10px;">
<el-pagination
:total="formData.SysUser.impl.totalCount"
:current-page="formData.SysUser.impl.currentPage"
:page-size="formData.SysUser.impl.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
@current-change="formData.SysUser.impl.onCurrentPageChange"
@size-change="formData.SysUser.impl.onPageSizeChange">
</el-pagination>
</el-row>
</el-col>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
/* eslint-disable-next-line */
import {TableWidget } from '@/utils/widget.js';
/* eslint-disable-next-line */
import { uploadMixin, statsDateRangeMixin, cachePageMixin } from '@/core/mixins';
/* eslint-disable-next-line */
import { KnowledgeManage } from '@/api/gptController.js';
import formKnowLedgeUserEdit from './edit.vue';
export default {
name: 'formKnowledgeUser',
props: {
knowledgeId: {
type: [String, Number],
required: true
}
},
mixins: [uploadMixin, statsDateRangeMixin, cachePageMixin],
data () {
return {
formData: {
formFilter: {
sysUserLoginName: undefined
},
SysUser: {
impl: new TableWidget(this.loadSysUserData, this.loadSysUserVerify, true, false)
},
isInit: false
}
}
},
methods: {
onReset () {
this.$refs.formKnowledgeUser.resetFields();
this.refreshFormKnowledgeUser(true);
},
getUserStatusType (status) {
if (status === this.SysUserStatus.NORMAL) {
return 'success';
} else if (status === this.SysUserStatus.LOCKED) {
return 'danger';
} else {
return 'info';
}
},
onAddRow () {
this.$dialog.show('添加授权用户', formKnowLedgeUserEdit, {
area: ['1100px', '600px']
}, {
knowledgeId: this.knowledgeId
}).catch(e => {
this.refreshFormKnowledgeUser(true);
});
},
onDeleteRow (row) {
this.$confirm('是否移除此用户?').then(res => {
let params = {
knowledgeId: this.knowledgeId,
userId: row.userId
}
return KnowledgeManage.deleteKnowledgeUser(this, params);
}).then(res => {
this.$message.success('移除授权用户成功');
this.refreshFormKnowledgeUser(true);
}).catch(e => {});
},
/**
* 用户管理数据获取函数,返回Primise
*/
loadSysUserData (params) {
return new Promise((resolve, reject) => {
params.knowledgeId = this.knowledgeId;
params.sysUserDtoFilter = {
loginName: this.formData.formFilter.sysUserLoginName
}
KnowledgeManage.getSysUserListByKnowledgeId(this, params).then(res => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount
});
}).catch(e => {
reject(e);
});
});
},
/**
* 用户管理数据获取检测函数,返回true正常获取数据,返回false停止获取数据
*/
loadSysUserVerify () {
return true;
},
/**
* 更新用户管理
*/
refreshFormKnowledgeUser (reloadData = false) {
// 重新获取数据组件的数据
if (reloadData) {
this.formData.SysUser.impl.refreshTable(true, 1);
} else {
this.formData.SysUser.impl.refreshTable();
}
this.formData.isInit = true;
},
onResume () {
this.refreshFormKnowledgeUser();
},
initFormData () {
},
formInit () {
this.initFormData();
this.refreshFormKnowledgeUser();
}
},
computed: {
getTableHeight () {
return (this.getMainContextHeight - 92);
},
...mapGetters(['getMainContextHeight'])
},
created () {
this.formInit();
}
}
</script>
......@@ -31,6 +31,7 @@ import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/
import { MyModel } from '@/api/gptController.js';
import card from './card/index';
/* eslint-disable-next-line */
import particulars from './particulars/index';
export default {
data () {
......@@ -100,11 +101,12 @@ export default {
},
particulars (item) {
this.$dialog.show('详情', particulars, {
area: ['100%', '100%']
}, { tableItem: item }).then(res => {
this.refresh();
}).catch(e => { });
console.log('详情');
// this.$dialog.show('详情', particulars, {
// area: ['100%', '100%']
// }, { tableItem: item }).then(res => {
// this.refresh();
// }).catch(e => { });
},
refresh (reloadData = false) {
if (reloadData) {
......
......@@ -18,9 +18,9 @@
</div>
<div class="video" v-if="['mp4', 'webm', 'ogg', 'ogv'].indexOf(fileType)>-1&&url">
<video controls style="width: 100%">
<source :src="item" type="video/mp4" />
<source :src="item" type="video/ogg" />
<source :src="item" type="video/webm" />
<source :src="url" type="video/mp4" />
<source :src="url" type="video/ogg" />
<source :src="url" type="video/webm" />
您的浏览器不支持 video 标签。
</video>
</div>
......@@ -127,7 +127,6 @@ export default {
},
rendered () {
this.fullscreenLoading = false
console.log('渲染完成')
}
}
}
......
......@@ -19,7 +19,7 @@
<el-form-item label="提示词:" style="">
<div style="display: flex;flex-direction: row;align-items: center;">
<el-select v-model="promptTemplate" filterable placeholder="提示词" value-key="templateId" @change="templateControllerChange" clearable>
<el-option v-for="item in templateControllerList" :key="item.value" :label="item.label" :value="item">
<el-option v-for="item in templateControllerList" :key="item.templateId" :label="item.label" :value="item">
</el-option>
</el-select>
<el-switch @change="changePromptTemplate" style="margin-left: 10px;" v-model="isPromptTemplate" active-color="#13ce66" inactive-color="#ff4949">
......@@ -92,6 +92,26 @@
</el-collapse-item>
</el-collapse>
</el-form-item>
<!-- <el-form-item label-width="0px" v-if="form.pattern == '知识图谱问答'">
<el-collapse value="1">
<el-collapse-item name="1">
<template slot="title">知识图谱配置</template>
<el-form-item label="请选择知识图谱:" style="margin-bottom:30px">
<el-select ref="knowledgeSelect" v-model="form.knowledgeGraphConfige. knowledge_graph_name" placeholder="请选择" >
<el-option v-for="item in []" :key="item.knowledgeId" :label="item.knowledgeGraphName" :value="item.knowledgeGraphName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="匹配知识条数:" style="margin-bottom:30px">
<el-input-number v-model="form.knowledgeGraphConfige.top_k" :min="1" :max="20"></el-input-number>
</el-form-item>
<el-form-item label="匹配精度:">
<el-slider v-model="knowledgeScoreThreshold" :format-tooltip="formatTooltip" @change="form.knowledgeGraphConfige.score_threshold = knowledgeGraphThreshold / 100"></el-slider>
</el-form-item>
</el-collapse-item>
</el-collapse>
</el-form-item> -->
</el-form>
</template>
......@@ -114,6 +134,7 @@ export default {
knowledgeList: [],
knowledgeScoreThreshold: 50,
fileThreshold: 50,
knowledgeGraphThreshold: 50,
form: {
pattern: '通用智能问答', // 对话模式
model_name: undefined, // 模型名称
......@@ -129,13 +150,19 @@ export default {
search_engine_name: 'bing',
top_k: 1
},
fileConfige: {
fileConfige: {// 文件对哈配置
top_k: 1,
score_threshold: 0.5,
knowledge_id: undefined,
// max_tokens: 0,
prompt_name: 'default'
},
knowledgeGraphConfige: {// 知识图谱对话
knowledge_graph_name: '',
top_k: 1,
score_threshold: 0.5
}
},
filesForm: {
......@@ -188,6 +215,7 @@ export default {
this.modelList = res.data.map((item) => {
return { id: item.modelId, name: item.modelName, children: item.modelVersionList === [] ? [] : item.modelVersionList.map((item2) => { return { id: item2.versionId, name: item2.versionName } }) }
})
this.getActiveModelList()
}).catch(e => {
console.log(e);
......@@ -232,7 +260,6 @@ export default {
switchModel (versionId) { // 切换模型
this.openLoading('LLM模型加载中')
ModelVersion.change(this, { versionId: versionId }).then(res => {
console.log(res);
this.loading.close();
}).catch(e => {
this.loading.close();
......
<!-- 右侧聊天界面 -->
<template>
<div class="box">
<div class="box" ref="box">
<div class="contentBox" ref="contentBox" v-if="myHistory.length > 0">
<div v-for="(item, index) in myHistory" :key="index">
<div v-for=" item in myHistory" :key="item.id">
<div class="userBox">
<div class="content">
......@@ -18,13 +18,13 @@
GPT
</div>
<div class="content">
<contentView :content="item.answer" ref="contentView" :index="index" :isSuccess="isSuccess" />
<contentView :content="item.answer" :ref="'contentView' + item.id" />
</div>
</div>
</div>
</div>
<div class="initBox" v-else>
<div class="initBox" ref="initBox" v-else>
<div class="text">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你好,<br>
我是人工智能语言模型<br>
......@@ -38,10 +38,12 @@
<el-button icon="el-icon-delete" style="margin-left:10px" @click="clear" type="danger" plain></el-button>
</div>
<div id="network"></div>
</div>
</template>
<script>
import { GetStreaming } from '@/utils/getStreaming.js';
// import codePreview from '../codePreview';
import contentView from '../contentView';
......@@ -49,7 +51,6 @@ import contentView from '../contentView';
export default {
data () {
return {
isSuccess: false,
templateController: undefined,
isPromptTemplate: true,
inputContent: null,
......@@ -81,6 +82,7 @@ export default {
// 移除监听事件 "share"
this.$bus.$off('isPromptTemplate')
},
methods: {
clear () {
......@@ -90,7 +92,6 @@ export default {
this.myHistory = []
},
submit () {
this.isSuccess = false
this.param.model_name = this.chatForm.model_name
this.param.temperature = this.chatForm.temperature
this.heistoryRotate = this.chatForm.heistoryRotate
......@@ -104,13 +105,16 @@ export default {
} else if (this.chatForm.pattern === '搜索引擎问答') {
apiUrl = '/2api/chat/search_engine_chat'
this.param = { ...this.param, ...this.chatForm.searchConfige }
} else if (this.chatForm.pattern === '文件对话') {
} else if (this.chatForm.pattern === '基于文件问答') {
apiUrl = '/2api/chat/file_chat'
this.param = { ...this.param, ...this.chatForm.fileConfige }
if (!this.chatForm.fileConfige.knowledge_id) {
this.$message.error('请先上传文件');
return
}
} else if (this.chatForm.pattern === '知识图谱问答') {
apiUrl = '/2api/chat/mapping_knowledge'
this.param = { ...this.param, ...this.chatForm.knowledgeGraphConfige }
}
if (!this.inputContent) return
this.param.query = this.inputContent;
......@@ -118,49 +122,58 @@ export default {
'role': 'user',
'content': this.inputContent,
'answer': '',
'excludeReferenceAnswer': ''
'excludeReferenceAnswer': '',
'id': this.generateRandomString(8)
})
this.inputContent = null;
this.inputContent = null;
this.param.history = []
this.myHistory.slice(0, -1).slice(-this.heistoryRotate).forEach((item) => {
this.param.history.push(...[{ role: item.role, content: item.content }, { role: 'assistant', content: item.excludeReferenceAnswer}])
this.param.history.push(...[{ role: item.role, content: item.content }, { role: 'assistant', content: item.excludeReferenceAnswer }])
})
this.$emit('submit')
let getData = new GetStreaming(apiUrl, this.param, this.onmessage, this.success)
let getData = new GetStreaming(apiUrl, this.param, this.onmessage, this.setSuccess)
getData.initeventSource()
},
success () {
this.isSuccess = true
setSuccess () {
this.$nextTick(() => {
let nowChat = this.myHistory[this.myHistory.length - 1]
this.$refs['contentView' + nowChat.id][0].isSuccess()
})
},
onmessage (data) {
let nowChat = this.myHistory[this.myHistory.length - 1]
if (this.chatForm.pattern === '通用智能问答') {
nowChat.answer += data
nowChat.excludeReferenceAnswer += data
nowChat.answer += data;
} else if (this.chatForm.pattern === '专业知识库问答') {
console.log(data);
let temporary = JSON.parse(`[${data}]`.replace(/}{/g, '},{'))
temporary.forEach((item) => {
if (item.docs) {
item.docs = item.docs.map((item2) => {
return item2.replace('出处', '知识溯源')
})
}
this.modifyContent(item)// 修改返回内容
nowChat.excludeReferenceAnswer += item.answer || '' // 排除回答中的引用内容
nowChat.answer += item.answer || '\n' + item.docs
})
} else if (this.chatForm.pattern === '搜索引擎问答') {
} else if (this.chatForm.pattern === '文件对话') {
} else if (this.chatForm.pattern === '基于文件问答') {
let temporary = JSON.parse(`[${data}]`.replace(/}{/g, '},{'))
temporary.forEach((item) => {
if (item.docs) {
item.docs = item.docs.map((item2) => {
return item2.replace('出处', '知识溯源')
})
}
this.modifyContent(item)// 修改返回内容
nowChat.excludeReferenceAnswer += item.answer || '' // 排除回答中的引用内容
nowChat.answer += item.answer || '\n' + item.docs
})
} else if (this.chatForm.pattern === '知识图谱问答') {
console.log(data);
let temporary = JSON.parse(`[${data}]`.replace(/}{/g, '},{'))
temporary.forEach((item) => {
this.modifyContent(item)// 修改返回内容
nowChat.excludeReferenceAnswer += item.answer || '' // 排除回答中的引用内容
nowChat.answer += item.answer || '\n' + item.docs
})
......@@ -169,6 +182,60 @@ export default {
this.$nextTick(() => {
this.$refs.contentBox.scrollTo(0, this.$refs.contentBox.scrollHeight)
})
},
modifyContent (item) { // 修改返回内容
if (item.docs) {
item.docs = item.docs.map((item2) => {
let tagUrl = ((item2?.match(/\]\((.*?)\)/g) || [])[0] || '').slice(2, -1)
let url = ''
// item2 = item2.replace(/\n/g, '<br>')
if (tagUrl.indexOf('https') !== -1) {
url = tagUrl.replace(/^https:\/\/[^/]+\//, `https://${window.location.hostname}:${window.location.port}/`);
item2 = item2.replace(/\]\((.*?)\)/g, `](${url})`)
} else {
url = tagUrl.replace(/^http:\/\/[^/]+\//, `http://${window.location.hostname}:${window.location.port}/`);
item2 = item2.replace(/\]\((.*?)\)/g, `](${url})`)
}
/// ////////出处内容包装div
var match = (item2.match(/出处(.*)\)/) || [])[0]
// 查找指定字符串的位置
var indexOfSpecifiedString = item2.indexOf(match);
if (indexOfSpecifiedString !== -1) {
// 使用 slice 获取指定字符串后面的所有内容
var contentAfterSpecifiedString = item2.slice(indexOfSpecifiedString + match.length);
item2 = item2.replace(contentAfterSpecifiedString, `<div class="describe-view">${contentAfterSpecifiedString}</div>`)
} else {
console.log('未找到匹配的指定字符串');
}
/// ////////特殊标签后包装div
// var specifiedString = '<a class="show_detail"></a>';
// var match2 = item2.match(new RegExp(specifiedString + '(.*)')) || [];
const match2 = item2.match(/<a\s+class="show_detail"\s+data="([^"]*)"><\/a>([\s\S]*)/);
if (match2 && match2.length === 3) {
var textAfterSpecifiedString = match2[2];
var data = match2[1]
// 修改文本内容
textAfterSpecifiedString = `<div class="describe-view" data="${data}" >${textAfterSpecifiedString}</div>`
item2 = item2.replace(match2[2], textAfterSpecifiedString)
}
return item2.replace('出处', '知识溯源')
})
}
},
generateRandomString (length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
const randomValues = new Uint32Array(length);
crypto.getRandomValues(randomValues);
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(randomValues[i] % charactersLength);
}
return result;
}
}
......@@ -253,4 +320,5 @@ export default {
.inputBox {
display: flex;
}</style>
}
</style>
......@@ -11,7 +11,7 @@
</el-select>
</el-form-item>
<el-form-item label="场景类型:" >
<el-radio v-model="form.scenarioType" v-for="item in ScenarioTypeDict.getList()" :label="item.id" :size="defaultFormItemSize" :key="item.id">{{ item.name }}</el-radio>
<el-radio v-model="form.scenarioType" v-for="item in ScenarioTypeDict.getList()" :label="item.id" :size="defaultFormItemSize" :key="item.id" @input="changeScenarioType">{{ item.name }}</el-radio>
</el-form-item>
<el-form-item label="变量识别符:">
<el-select v-model="form.parameterFormat" placeholder="请选择" :size="defaultFormItemSize" class="inputWidth">
......@@ -21,21 +21,23 @@
</el-form-item>
<template v-if="form.scenarioType === 0 ">
<el-form-item label="模板框架:" class="templateFramework" v-if=" !isEdit">
<el-tooltip class="item" effect="dark" :content="item.name" placement="top" v-for="item in TemplateFrameworkDict.getList()" :label="item.id" :size="defaultFormItemSize" :key="item.id">
<el-radio v-model="form.templateFramework" @input="$refs.promptInput.init()" :label="item.id">{{ item.symbol }}</el-radio>
</el-tooltip>
</el-form-item>
<el-form-item label="Prompt:" prop="templateContent">
<el-form-item label="Prompt:" prop="templateContent" key="templateContent1">
<promptInput ref="promptInput" v-model="form.templateContent" :templateFramework="form.templateFramework" :isEdit="isEdit" />
</el-form-item>
</template>
<template v-else>
<el-form-item label="正向Prompt:">
<el-form-item label="正向Prompt:" prop="templateContent" key="templateContent2">
<el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="form.templateContent" class="inputWidth">
</el-input>
</el-form-item>
<el-form-item label="负向Prompt:">
<el-form-item label="负向Prompt:" prop="negativeTemplateContent" key="negativeTemplateContent1">
<el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="form.negativeTemplateContent" class="inputWidth">
</el-input>
......@@ -58,7 +60,7 @@ export default {
interfaceAddress: '',
negativeTemplateContent: '',
negativeTemplateVariables: '',
parameterFormat: '',
parameterFormat: '{}',
scenarioType: 0,
templateContent: '',
templateFramework: 0,
......@@ -70,7 +72,8 @@ export default {
},
rules: {
'templateName': [{ required: true, message: '请选输入名称', trigger: 'blur' }],
'templateContent': [{ required: true, message: '请选输入Prompt', trigger: 'blur' }]
'templateContent': [{ required: true, message: '请选输入Prompt', trigger: 'blur' }],
'negativeTemplateContent': [{ required: true, message: '请选输入负向Prompt', trigger: 'blur' }]
}
};
......@@ -129,6 +132,13 @@ export default {
}
});
});
},
changeScenarioType (data) {
if (this.$refs.promptInput) {
this.$refs.promptInput.init()
}
this.form.templateContent = ''
this.form.negativeTemplateContent = ''
}
}
};
......
<!--prompt输入 -->
<template>
<div >
<el-input v-if="[1,2,3].indexOf(templateFramework)===-1||isEdit" type="textarea" :rows="5" placeholder="请输入内容" :value="prompt" class="inputWidth" @input="changeInput"></el-input>
<el-input v-if="[1,2,3].indexOf(templateFramework)===-1||isEdit" type="textarea" :rows="5" placeholder="请输入内容" :value="prompt" class="inputWidth" @input="changeInput2"></el-input>
<el-card class="box-card" style="width:600px" v-else>
<div class="inputBox" v-for="(item,index) in myPrompts" :key="index">
......@@ -128,9 +128,13 @@ export default {
return item.label + ':' + item.value + '\n'
}
}).join('')
console.log(promptsString);
console.log(this.templateFramework);
this.$emit('input', [1, 2, 3].indexOf(this.templateFramework) === -1 ? this.prompt : promptsString)
},
changeInput2 (data) {
this.prompt = data
this.$emit('input', this.prompt)
},
add (item) {
if (item.tableData.length === 20) return
item.tableData.push({
......
......@@ -4,7 +4,7 @@
<div class="topBox">
<div class="title">Prompt 模板</div>
<div class="instructions">
集中管理平台训练、压缩及预置的生成式大模型,支持对模型进行评估、压缩及部署
管理和查看prompt模板,支持在服务调用时组合prompt输入推理
</div>
</div>
<div class="topButtonBox">
......
......@@ -7,9 +7,9 @@
<el-form-item label="模板名称" prop="formFilter.templateName">
<el-input class="filter-item" v-model="myDataSetPage.formFilter.templateName" :clearable="true" placeholder="模板名称" />
</el-form-item>
<el-form-item label-width="0px">
<!-- <el-form-item label-width="0px">
<el-button class="add" type="primary" icon="el-icon-plus" :size="defaultFormItemSize" @click="add">创建模板</el-button>
</el-form-item>
</el-form-item> -->
</filter-box>
</el-form>
<div class="listBox">
......
<!--预置模板-->
<template>
<div class="presetTemplate">
<el-form ref="myDataSetPage" :model="myDataSetPage" label-width="75px" :size="defaultFormItemSize" label-position="right" @submit.native.prevent>
<el-form
ref="myDataSetPage"
:model="myDataSetPage"
label-width="75px"
:size="defaultFormItemSize"
label-position="right"
@submit.native.prevent
>
<filter-box :item-width="350" @search="refresh()" @reset="onReset">
<el-form-item label="模板名称" prop="formFilter.templateName">
<el-input class="filter-item" v-model="myDataSetPage.formFilter.templateName" :clearable="true" placeholder="模板名称" />
<el-input
class="filter-item"
v-model="myDataSetPage.formFilter.templateName"
:clearable="true"
placeholder="模板名称"
/>
</el-form-item>
<el-form-item label-width="0px">
<!-- <el-form-item label-width="0px">
<el-button class="add" type="primary" icon="el-icon-plus" :size="defaultFormItemSize" @click="add">创建模板</el-button>
</el-form-item>
</el-form-item> -->
</filter-box>
</el-form>
<div class="listBox">
<card :dataList='myDataSetPage.operationLog.impl.dataList' :isPreset="true" :refresh="refresh"></card>
<card
:dataList="myDataSetPage.operationLog.impl.dataList"
:isPreset="true"
:refresh="refresh"
></card>
<el-row slot="pagination" type="flex" justify="end" style="margin-top: 16px;width: 100%;">
<el-pagination :total="myDataSetPage.operationLog.impl.totalCount" :current-page="myDataSetPage.operationLog.impl.currentPage" :page-size="myDataSetPage.operationLog.impl.pageSize" :page-sizes="[10, 20, 50, 100]" layout="total, prev, pager, next, sizes" @current-change="myDataSetPage.operationLog.impl.onCurrentPageChange" @size-change="myDataSetPage.operationLog.impl.onPageSizeChange">
<el-row
slot="pagination"
type="flex"
justify="end"
style="margin-top: 16px; width: 100%"
>
<el-pagination
:total="myDataSetPage.operationLog.impl.totalCount"
:current-page="myDataSetPage.operationLog.impl.currentPage"
:page-size="myDataSetPage.operationLog.impl.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
@current-change="myDataSetPage.operationLog.impl.onCurrentPageChange"
@size-change="myDataSetPage.operationLog.impl.onPageSizeChange"
>
</el-pagination>
</el-row>
</div>
......@@ -25,7 +54,12 @@
<script>
import { mapGetters } from 'vuex';
/* eslint-disable-next-line */
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
import {
// DropdownWidget,
TableWidget
// UploadWidget,
// ChartWidget
} from '@/utils/widget.js';
import { TemplateController } from '@/api/gptController.js';
import createTemplate from '../components/dialog/createTemplate';
import card from '../components/card/index';
......@@ -49,20 +83,26 @@ export default {
},
operationLog: {
impl: new TableWidget(this.getwidgetData, true, true, false, undefined, false)
impl: new TableWidget(
this.getwidgetData,
true,
true,
false,
undefined,
false
)
}
}
};
},
components: {card},
components: { card },
computed: {
...mapGetters(['getMainContextHeight']),
tableHeight () {
return this.getMainContextHeight - 149 - 94 - 40 + 'px';
}
},
methods: {
......@@ -95,31 +135,49 @@ export default {
templateSource: this.myDataSetPage.formFilter.templateSource,
variable: this.myDataSetPage.formFilter.variable
}
}
};
return new Promise((resolve, reject) => {
TemplateController.listForPreset(this, params).then(res => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount
TemplateController.listForPreset(this, params)
.then((res) => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount
});
})
.catch((e) => {
reject(e);
});
}).catch(e => {
reject(e);
});
});
},
add () {
this.$dialog.show('创建模版', createTemplate, {
area: ['100%', '100%']
}, { isEdit: false }).then(res => {
this.refresh();
}).catch(e => { });
this.$dialog
.show(
'创建模版',
createTemplate,
{
area: ['100%', '100%']
},
{ isEdit: false }
)
.then((res) => {
this.refresh();
})
.catch((e) => { });
},
edit () {
this.$dialog.show('修改模版', createTemplate, {
area: ['100%', '100%']
}, { isEdit: true }).then(res => {
this.refresh();
}).catch(e => { });
this.$dialog
.show(
'修改模版',
createTemplate,
{
area: ['100%', '100%']
},
{ isEdit: true }
)
.then((res) => {
this.refresh();
})
.catch((e) => { });
},
refresh (reloadData = false) {
if (reloadData) {
......@@ -137,11 +195,10 @@ export default {
},
handleChange () { }
},
mounted () {
this.formInit()
this.formInit();
}
};
</script>
......@@ -224,5 +281,4 @@ export default {
align-content: flex-start;
justify-content: space-between;
}
</style>
......@@ -4,7 +4,6 @@
<slot name="title"> </slot>
<slot name="content"> </slot>
</div>
</template>
<script>
......
<template>
<div class="aggregate">
<div class="logo">
<img src="@/assets/img/logo2.png" alt="">
<span class="title">陆军装备知识图谱系统</span>
</div>
<div class="aggregateBox">
<div class="itemBox" v-for="(item,index) in itemList" :key="index" @click="goPage(item.url)">
<span class="text">
{{ item.name }}
</span>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
itemList: [
{
name: '基于NEO4J的知识图谱构建',
url: `http://${window.location.hostname}:${window.location.port}/#/main/welcome`
},
{
name: '基于大语言模型与知识图谱双轮驱动的机械维修保障智能问答系统',
url: `http://${window.location.hostname}:${window.location.port}/#/main/welcome`
},
{
name: '基于gstore的知识图谱系统',
url: `http://${window.location.hostname}:${window.location.port}/#/main/welcome`
}
]
}
},
components: {},
mounted () {
},
methods: {
goPage (url) {
location.href = url
}
}
}
</script>
<style lang="scss" scoped>
.logo {
position: absolute;
top: 20px;
left: 20px;
display: flex;
img {
height: 40px;
}
.title {
color: #fff;
font-size: 18px;
height: 40px;
line-height: 40px;
display: inline-block;
margin-left: 20px;
}
}
.aggregate {
height: 100%;
width: 100%;
background: url(~@/assets/img/login_bg_2.jpg) center center;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
}
.aggregateBox {
width: 80%;
height: 50%;
min-width: 1000px;
min-height: 400px;
border-radius: 20px;
background-color: rgba(255, 255, 255, 0.1); /* 背景色透明度,根据需要调整 */
backdrop-filter: blur(10px); /* 模糊程度,根据需要调整 */
display: flex;
padding: 20px; /* 内边距,根据需要调整 */
justify-content: space-around;
flex-direction: row;
align-items: center;
.itemBox {
width: 400px;
cursor: pointer;
height: 200px;
background: url(~@/assets/img/cardBg.png) center center;
background-size: cover;
border-radius: 10px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 20px;
border: 1px solid #b1b1b1;
font-size: 20px;
line-height: 30px;
// color: #5b6fab;
color: #273379;
font-weight: 900;
.text {
background-color: #fff;
padding: 10px;
border-radius: 5px;
}
}
}
.aggregateBox :hover {
box-shadow: 1px 1px 8px 1px #fff;
transition: all 0.5s;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment