kefu/static/templates/default/setting_training.html

506 lines
21 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{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>