kefu/static/templates/default/setting_training.html

506 lines
21 KiB
HTML
Raw Permalink Normal View History

2024-12-10 02:50:12 +00:00
{{template "header" }}
<div id="app" style="width:100%">
<template>
<el-tabs type="border-card" v-model="activeTab">
<el-tab-pane label="训练素材" name="fileList">
<el-input placeholder="搜索知识库 (基于向量相似性语义搜索)" v-model="article.search" style="width:300px;margin:0px 0px 10px 10px;"></el-input>
<el-button type="primary" @click="searchKnowledge()">搜索</el-button>
<el-table
:data="fileList"
border
style="width: 100%;margin-top: 10px">
<el-table-column
prop="id"
label="ID">
</el-table-column>
<el-table-column
prop="file_name"
label="文件名">
<template slot-scope="scope">
<a @click="activeTab='knowledgeList';fileId=scope.row.id;getAllKnowledge()"><{scope.row.file_name}></a>
</template>
</el-table-column>
<el-table-column
prop="file_name"
label="文件路径">
<template slot-scope="scope">
<{getFilePath(scope.row.collect_name,scope.row.file_name)}>
</template>
</el-table-column>
<el-table-column
prop="file_size"
label="字符数">
</el-table-column>
<el-table-column
prop="created_at"
label="上传时间">
<template slot-scope="scope">
<{dateFormat(scope.row.created_at)}>
</template>
</el-table-column>
<el-table-column
prop="id"
label="操作">
<template slot-scope="scope">
<el-button style="margin-right: 10px" @click="activeTab='knowledgeList';fileId=scope.row.id;getAllKnowledge()" type="text">知识列表</el-button>
<el-button style="margin-right: 15px" @click="addSigleTxt.content='',addSigleTxt.title=scope.row.file_name;addSigleTxt.fileId=scope.row.id;addSigleTxt.dialog=true" type="text">添加</el-button>
<el-button style="margin-right: 10px" @click="exportToExcel(scope.row.id,scope.row.file_name)" type="text">导出</el-button>
<el-button style="margin-right: 10px" @click="delFile(scope.row.id)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="手动录入">
<el-descriptions style="font-size: 14px;" direction="vertical" :column="1" border>
<el-descriptions-item label="输入文本">
<el-form style="font-size: 14px;width: 800px">
<el-form-item label="文本标题">
<el-input v-model="singleTxt.title"></el-input>
</el-form-item>
<el-form-item label="文本内容">
<el-input type="textarea" show-word-limit rows="10" v-model="singleTxt.content"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="addPoints" type="primary" size="small">提交</el-button>
</el-form-item>
</el-form>
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="上传素材">
<el-alert
title="注意: 支持上传.txt .docx .pdf .xlsx文档! pdf文档不能是图片扫描生成的,读取不到数据! excel文档会按行进行分割入库"
type="info"
show-icon>
</el-alert>
<el-form style="margin:10px 0px;">
<el-upload
multiple
drag
style="margin:10px 0px;"
:action="uploadUrl"
:on-success="uploadDocSuccess"
:on-error="uploadError"
:before-upload="beforeUpload"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<el-form-item style="display: none">
<el-input style="width: 800px;" v-model="learnUrl" placeholder="网页地址"></el-input>
</el-form-item>
<el-form-item style="display: none">
<el-button @click="uploadUrlPage" icon="el-icon-upload" type="primary">上传网址</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="知识列表" name="knowledgeList">
<el-input placeholder="搜索知识库 (基于向量相似性语义搜索)" v-model="article.search" style="width:300px;margin:0px 0px 10px 10px;"></el-input>
<el-button type="primary" @click="searchKnowledge()">搜索</el-button>
<el-table
:data="filePoints"
border
style="width: 100%;margin-top: 10px">
<el-table-column
prop="content"
label="内容">
<template slot-scope="scope">
<{scope.row.payload.text}>
</template>
</el-table-column>
<el-table-column
width="380px"
prop="content"
label="文件ID">
<template slot-scope="scope">
<{scope.row.payload.fileid}>
</template>
</el-table-column>
<el-table-column
width="180px"
prop="id"
label="操作">
<template slot-scope="scope">
<el-button style="float: right;margin-right: 10px" @click="delPoints(scope.row.id)" type="text">删除</el-button>
<el-button style="float: right;margin-right: 15px" @click="article.fileId=fileId;article.title=scope.row.payload.url;article.id=scope.row.id;article.content=scope.row.payload.text;article.dialog=true" type="text">编辑</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="提问日志" name="questionList">
<el-button type="primary" @click="getLogs()">刷新</el-button>
<el-table
:data="logList.list"
border
style="width: 100%;margin-top: 10px">
<el-table-column
prop="question"
width="800"
label="提问日志">
<template slot-scope="scope">
<div v-html='replace(scope.row.question,"\n","<br>")'></div>
</template>
</el-table-column>
<el-table-column
prop="answer"
label="回答日志">
</el-table-column>
<el-table-column
prop="created_at"
label="时间">
</el-table-column>
</el-table>
<el-pagination
background
@current-change="getLogs"
:current-page="logList.page"
layout="prev,pager, next"
:page-size="logList.pagesize"
:total="logList.count">
</el-pagination>
</el-tab-pane>
</el-tabs>
<el-dialog
title="添加知识"
:visible.sync="addSigleTxt.dialog"
width="50%"
:close-on-click-modal="false"
top="3%"
>
<el-form size="medium">
<el-form-item label="内容">
<el-input type="textarea" show-word-limit :rows="10" v-model="addSigleTxt.content"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addSigleTxt.dialog = false">取消</el-button>
<el-button type="primary" @click="saveFilePoints()">确认</el-button>
</span>
</el-dialog>
<el-dialog
title="优化修改"
:visible.sync="article.dialog"
width="50%"
:close-on-click-modal="false"
top="3%"
>
<el-form size="medium">
<el-form-item label="内容" prop="remark">
<el-input type="textarea" :rows="10" v-model="article.content"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="article.dialog = false">取消</el-button>
<el-button type="primary" @click="savePoints()">确认</el-button>
</span>
</el-dialog>
</template>
</div>
<script src="/static/js/xlsx.full.min.js" type="text/javascript"></script>
<script>
new Vue({
el: '#app',
delimiters: ["<{", "}>"],
data: {
activeTab:"fileList",
fileList:[],
filePoints:[],
fileId:"",
addSigleTxt:{
dialog:false,
fileId:"",
content:"",
title:"",
},
singleTxt:{
title:"",
content:""
},
article:{
title:"",
dialog:false,
id:"",
content:"",
search:"",
},
uploadUrl:"",
learnUrl:"",
logList:{
page:1,
count:0,
pagesize:0,
list:[],
},
},
methods: {
//文件列表
getFileList(){
let _this=this;
sendAjax('/kefu/ai/fileList',"GET",{},function(data){
if(data.result){
_this.fileList=data.result;
}else{
_this.$message({
message:"请联系管理员创建集合,然后补充完整(大模型接口大模型key知识库集合)",
type: 'error'
});
}
})
},
//时间格式化
dateFormat(oldTime){
return dateFormat("YYYY-mm-dd HH:MM:SS",new Date(oldTime))
},
//上传文本数据
addPoints(){
let _this=this;
this.listLoading = this.$loading({
lock: true,
text: "上传中",
});
sendAjax('/kefu/ai/training',"POST",this.singleTxt,function(data){
_this.activeTab="fileList";
_this.listLoading.close();
let ret=JSON.parse(data);
if(ret.status!="ok"){
_this.$message({
message:data,
type: 'error'
});
return;
}
_this.singleTxt={
title:"",
content:""
};
_this.getFileList();
_this.$message({
message: "success",
type: 'success'
});
})
},
//编辑知识
savePoints(){
let _this=this;
this.listLoading = this.$loading({
lock: true,
text: "修改中",
});
sendAjax('/kefu/ai/training',"POST",this.article,function(data){
_this.listLoading.close();
let ret=JSON.parse(data);
if(ret.status!="ok"){
_this.$message({
message:data,
type: 'error'
});
return;
}
_this.article.dialog = false;
_this.getAllKnowledge();
_this.searchKnowledge();
_this.$message({
message: "success",
type: 'success'
});
})
},
//搜索知识
searchKnowledge(){
let _this=this;
if(!this.article.search) return;
this.listLoading = this.$loading({
lock: true,
text: "搜索中",
});
sendAjax('/kefu/ai/searchPoints',"POST",{search:this.article.search},function(data){
_this.listLoading.close();
let ret=JSON.parse(data)
if(ret.result){
_this.filePoints=ret.result;
_this.activeTab='knowledgeList'
}
})
},
//新增知识
saveFilePoints(){
let _this=this;
this.listLoading = this.$loading({
lock: true,
text: "添加中",
});
sendAjax('/kefu/ai/training',"POST",this.addSigleTxt,function(data){
_this.listLoading.close();
let ret=JSON.parse(data);
if(ret.status!="ok"){
_this.$message({
message:data,
type: 'error'
});
return;
}
_this.addSigleTxt.dialog=false;
_this.getFileList();
_this.$message({
message: "success",
type: 'success'
});
})
},
delFile(id){
let _this=this;
this.$confirm("是否删除", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function(){
sendAjax('/kefu/ai/delFile',"GET",{id:id},function(data){
_this.getFileList();
_this.$message({
message: "success",
type: 'success'
});
})
}).catch(function(){
});
},
//知识列表
getAllKnowledge(){
let _this=this;
let id=this.fileId;
if(id){
sendAjax('/kefu/ai/filePoints',"GET",{id:id},function(data){
let ret=JSON.parse(data)
if(ret.result){
_this.filePoints=ret.result;
}
})
}
},
//删除知识
delPoints(id){
let _this=this;
this.$confirm("是否删除", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function(){
sendAjax('/kefu/ai/delPoints',"GET",{id:id},function(data){
_this.getAllKnowledge();
})
}).catch(function(){
});
},
//上传文件失败
uploadDocSuccess(response, file, fileList){
this.listLoading.close();
this.activeTab="fileList";
if(response.code==200){
this.$message({
message: "上传成功",
type: 'success'
});
this.getFileList();
}else{
this.$message({
message: response.msg,
type: 'error'
});
}
},
//上传文件失败
uploadError(){
this.listLoading.close();
},
//上传之前
beforeUpload(file){
this.listLoading = this.$loading({
lock: true,
text: "上传中",
});
let ext=file.name.substring(file.name.lastIndexOf(".")+1);
if (ext != 'txt' && ext != 'docx' && ext != 'xlsx' && ext != 'pdf') {
this.$message.error('上传文件只能是 .txt .docx .xlsx .pdf 格式!');
this.listLoading.close();
return false;
}
},
//上传URL
uploadUrlPage(){
let _this=this;
this.listLoading = this.$loading({
lock: true,
text: "上传中",
});
sendAjax('/kefu/ai/uploadUrl',"POST",{url:this.learnUrl},function(data){
_this.listLoading.close();
_this.learnUrl="";
_this.getFileList();
_this.activeTab="fileList";
_this.$message({
message: "success",
type: 'success'
});
})
},
//获取文件路径
getFilePath(collectName,fileName){
if(fileName.includes(".")){
return "/static/upload/ai/"+collectName+"/"+fileName;
}else{
return "文案知识";
}
},
//导出excel
exportToExcel(id,filename) {
let _this=this;
this.listLoading = this.$loading({
lock: true,
text: "正在导出excel",
});
sendAjax('/kefu/ai/filePoints',"GET",{id:id},function(data){
let ret=JSON.parse(data)
if(ret.result){
let data=[[filename+'的主要内容']];
for(let i in ret.result){
data.push([ret.result[i].payload.text]);
}
const worksheet = XLSX.utils.aoa_to_sheet(data);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
XLSX.writeFile(workbook, filename+'.xlsx');
_this.listLoading.close();
}
})
},
//获取日志列表
getLogs(page){
var _this=this;
sendAjax("/kefu/llmLogs","get",{page:page,pagesize:20},function(result){
_this.logList=result.result;
});
},
replace(str,source,dest){
return str.replaceAll(source,dest);
},
},
mounted:function(){
},
created: function () {
this.singleTxt.title="文本-"+this.dateFormat(new Date());
this.uploadUrl=`/kefu/ai/uploadDoc?token=`+localStorage.getItem("token");
this.getFileList();
this.getLogs();
}
});
</script>