Commit 49dc9a9c authored by mhw's avatar mhw

同步更改

parent d4147d35
......@@ -45,4 +45,7 @@ export default class KnowledgeManage {
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);
}
}
......@@ -14,7 +14,9 @@ html, body {
white-space: nowrap;
text-overflow: ellipsis;
}
.el-message {
white-space: pre-line;
}
.omit_2 {
/*2行省略 */
text-overflow: -o-ellipsis-lastline;
......
......@@ -269,6 +269,7 @@
/* Break-point
--------------------------*/
.el-message {
white-space: pre-line;
min-width: 380px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
......
......@@ -189,13 +189,24 @@ const fetchUpload = function (url, params, isDefUrl = true) {
}
]
}).then(res => {
console.log(res);
console.log(res, res.data.msg);
if ((res.data && res.data.success) || res.data.code === 200) {
resolve(res.data);
} else {
reject(res)
let failedFiles = res.data?.data?.failed_files
let msg = ''
if (failedFiles) {
for (const key in failedFiles) {
if (Object.hasOwnProperty.call(failedFiles, key)) {
const element = failedFiles[key];
msg += key + ':' + element + '\n'
}
}
}
showErrorMessage({
showClose: true,
message: res.data.errorMessage ? res.data.errorMessage : '数据请求失败'
message: res.data.errorMessage || res.data.msg ? res.data.errorMessage || msg : '数据请求失败'
});
}
}).catch(e => {
......@@ -279,8 +290,6 @@ const doUrl = function (url, type, params, axiosOption, options) {
};
const streamRequest = (url, params) => {
return new Promise((resolve, reject) => {
// requestUrl(url)
console.log(url);
axios({
method: 'post',
url: url,
......
......@@ -65,17 +65,17 @@ const TemplateFrameworkDict = new DictionaryBase('模板框架', [
},
{
id: 1,
name: 'Basic Prompt Framework',
name: '基本提示框架',
symbol: 'Basic Prompt Framework'
},
{
id: 2,
name: 'CRISPE Prompt Framework',
name: 'CRISPE提示框架',
symbol: 'CRISPE Prompt Framework'
},
{
id: 3,
name: 'Few-shot Prompt',
name: '少样本提示',
symbol: 'Few-shot Prompt'
}
]);
......@@ -320,7 +320,7 @@ const TaskType = new DictionaryBase('任务类型', [
name: '模型压缩',
symbol: 'ModelCompression'
}
]);
Vue.prototype.TaskType = TaskType;
// const SftTaskType = new DictionaryBase('sft任务类型', [
......@@ -334,7 +334,7 @@ Vue.prototype.TaskType = TaskType;
// name: '文生图模型',
// symbol: ''
// }
// ]);
// Vue.prototype.SftTaskType = SftTaskType;
const TaskStatus = new DictionaryBase('任务状态', [
......@@ -402,13 +402,18 @@ Vue.prototype.PublishWay = PublishWay;
const ModeOfSpeaking = new DictionaryBase('对话模式', [
{
id: 0,
name: 'LLM 对话',
name: '通用智能问答',
symbol: 'llm'
},
{
id: 1,
name: '知识库问答',
name: '专业知识库问答',
symbol: 'repository'
},
{
id: 3,
name: '文件对话',
symbol: 'fileSession'
}
// {
// id: 2,
......@@ -418,7 +423,7 @@ const ModeOfSpeaking = new DictionaryBase('对话模式', [
]);
Vue.prototype.ModeOfSpeaking = ModeOfSpeaking;
const RunningStatus = new DictionaryBase('运行状态', [
{
id: -1,
name: '训练失败',
......
<!-- 创建知识库 -->
<template>
<div>
<el-steps :active="active">
<el-step title="基本信息"></el-step>
<el-step title="导入配置"></el-step>
<!-- <el-step title="索引配置"></el-step> -->
</el-steps>
<essentialInformation v-if="active==1" :item="item" :isEdit="isEdit" />
<importConfiguration v-if="active==2" :item="item" :knowledgeName="knowledgeName" />
</div>
</template>
<div>
<el-steps :active="active" style="width:100%;margin:0 auto 20px auto">
<el-step title="基本信息" icon="el-icon-s-order"></el-step>
<el-step title="导入配置" icon="el-icon-upload"></el-step>
<!-- <el-step title="索引配置"></el-step> -->
</el-steps>
<essentialInformation v-if="active==1" :item="item" :isEdit="isEdit" />
<importConfiguration v-if="active==2" :item="item" :knowledgeName="knowledgeName" />
</div>
</template>
<script>
// import indexConfiguration from './indexConfiguration/index';
import importConfiguration from './importConfiguration/index';
import essentialInformation from './essentialInformation/index';
export default {
data () {
return {
active: 1,
knowledgeName: '',
knowledgeCode: ''
};
},
props: ['isEdit', 'item'],
components: { importConfiguration, essentialInformation},
computed: {
},
mounted () {
},
methods: {
onCancel (isSuccess) {
if (this.observer != null) {
this.observer.cancel(isSuccess);
}
}
}
};
</script>
<style scoped>
.inputWidth {
width: 600px;
}
form /deep/ .dialog-btn-layer {
position: absolute;
bottom: 20px;
right: 20px;
background: #fff;
}</style>
<style scoped>
.inputWidth {
width: 600px;
}
form /deep/ .dialog-btn-layer {
position: absolute;
bottom: 20px;
right: 20px;
background: #fff;
}</style>
<!-- 基本信息 -->
<template>
<el-form label-position="left" ref="form" label-width="120px" :model="form" :size="defaultFormItemSize" :rules="rules">
<el-row class="title">基本信息</el-row>
<el-form-item label="知识库名称:" prop="knowledgeName">
<el-input :disabled="this.isEdit" v-model="form.knowledgeName" class="inputWidth" :size="defaultFormItemSize" ></el-input>
</el-form-item>
<el-form-item label="知识库描述:" prop="knowledgeDescribe">
<el-input v-model="form.knowledgeDescribe" type="textarea" :rows="4" class="inputWidth" :size="defaultFormItemSize" placeholder="描述这个知识库的内容,详细的描述可以让AI及时访问知识库的内容。如果为空,将影响该知识库在知识问答中被检索到的概率,因此建议尽可能对知识库详细地总结描述。"></el-input>
</el-form-item>
<el-row type="flex" justify="end" class="dialog-btn-layer mt20">
<template>
<el-button :size="defaultFormItemSize" :plain="true" @click="onCancel()" >取消</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="onSubmit()">下一步</el-button>
</template>
</el-row>
</el-form >
</template>
<el-form label-position="left" ref="form" label-width="120px" :model="form" :size="defaultFormItemSize" :rules="rules">
<el-row class="title">基本信息</el-row>
<el-form-item label="知识库名称:" prop="knowledgeName">
<el-input :disabled="this.isEdit" v-model="form.knowledgeName" class="inputWidth" :size="defaultFormItemSize" ></el-input>
</el-form-item>
<el-form-item label="知识库描述:" prop="knowledgeDescribe">
<el-input v-model="form.knowledgeDescribe" type="textarea" :rows="4" class="inputWidth" :size="defaultFormItemSize" placeholder="描述这个知识库的内容,详细的描述可以让AI及时访问知识库的内容。如果为空,将影响该知识库在知识问答中被检索到的概率,因此建议尽可能对知识库详细地总结描述。"></el-input>
</el-form-item>
<el-row type="flex" justify="end" class="dialog-btn-layer mt20">
<template>
<el-button :size="defaultFormItemSize" :plain="true" @click="onCancel()" >取消</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="onSubmit()">下一步</el-button>
</template>
</el-row>
</el-form >
</template>
<script>
import { KnowledgeManage } from '@/api/gptController.js';
export default {
......@@ -37,13 +37,13 @@ export default {
},
props: ['isEdit', 'item'],
components: {},
computed: {},
mounted () {
this.init()
},
methods: {
init () {
if (this.isEdit) {
......@@ -59,7 +59,7 @@ export default {
if (valid) {
let params = {};
params.knowledgeManageDto = { ...this.form };
if (this.isEdit) {
KnowledgeManage.update(this, params).then(res => {
resolve(res);
......@@ -94,15 +94,15 @@ export default {
}
}
}
</script>
<style scoped>
.introduce{
font-size: 12px;
color: #909399;
}
.title {
font-size: 20px;
margin-bottom: 16px;
}
</style>
<style scoped>
.introduce{
font-size: 12px;
color: #909399;
}
.title {
font-size: 20px;
margin-bottom: 16px;
}
</style>
<!--导入配置 -->
<template>
<el-form label-position="left" ref="form" label-width="120px" :model="form" :size="defaultFormItemSize" :rules="rules" v-loading.fullscreen.lock="fullscreenLoading">
<el-form label-position="left" ref="form" label-width="130px" :model="form" :size="defaultFormItemSize" :rules="rules" v-loading.fullscreen.lock="fullscreenLoading">
<el-form-item label="上传知识库文件:" prop="filesArr">
<el-button @click="clickUp" :size="defaultFormItemSize" type="primary">上传</el-button>
<input style="display:none" ref="upFile" type="file" @change="fileinfo($event.target.files)" >
<div class="itemFile" v-for="(item,index) in files" :key="item.name">{{ item.name }}
<input style="display:none" ref="upFile" type="file" @change="fileinfo($event.target.files)" multiple accept=".html, .md, .json, .jsonl, .csv, .pdf, .png, .jpg, .jpeg, .bmp, .eml, .msg, .epub, .xlsx, .xls, .ipynb, .odt, .py, .rst, .rtf, .srt, .toml, .tsv, .docx, .doc, .xml, .ppt, .pptx, .txt, .htm">
<div class="el-upload__tip"> 可上传HTML, MD, JSON, JSONL, CSV, PDF, PNG, JPG, JPEG, BMP, EML, MSG, EPUB, XLSX, XLSD, IPYNB, ODT, PY, RST, RTF, SRT, TOML, TSV, DOCX, DOC, XML, PPT, PPTX, TXT, HTM文件</div>
<div class="itemFile" v-for="(item,index) in files" :key="item.name"><i class="el-icon-document" style="color:#909399;margin-right:5px"></i>{{ item.name }}
<i class="el-icon-circle-close" style="color:#0092FF;cursor: pointer;" @click="clearFile(index)"></i>
</div>
</el-form-item>
......@@ -13,7 +14,7 @@
</el-slider>
</el-form-item>
<el-form-item label="相邻文本重合长度:">
<el-slider :min="0" :max="12" v-model="form.chunk_overlap" show-input>
<el-slider :min="0" :max="250" v-model="form.chunk_overlap" show-input>
</el-slider>
</el-form-item>
<el-form-item label="开启中文标题加强:">
......@@ -38,12 +39,13 @@
<el-button type="text" @click="down(scope.row)" :size="defaultFormItemSize" >下载</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-row type="flex" justify="end" class="dialog-btn-layer mt20">
<template>
<el-button :size="defaultFormItemSize" :plain="true" @click="back" >上一步</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="$parent.onCancel(false)" >取消</el-button>
<el-button :size="defaultFormItemSize" :plain="true" @click="onSubmit">确认上传</el-button>
</template>
</el-row>
......@@ -88,14 +90,19 @@ export default {
},
methods: {
fileinfo (files) {
if (this.files.map((item) => item.name).indexOf(files[0].name) === -1) {
this.files.push(files[0])
} else {
console.log('重复上传');
for (const key in files) {
if (Object.hasOwnProperty.call(files, key)) {
const element = files[key];
if (this.files.map((item) => item.name).indexOf(element.name) === -1) {
this.files.push(element)
this.form.filesArr = this.files
} else {
console.log('重复上传');
}
}
}
this.form.filesArr = this.files
},
clickUp () {
this.$refs.upFile.click()
......@@ -104,7 +111,7 @@ export default {
return new Promise((resolve, reject) => {
this.$refs['form'].validate((valid) => {
if (valid) {
this.form.knowledge_base_name = this.$parent.knowledgeName
this.form.knowledge_base_name = this.$parent.knowledgeCode
let params = {};
params = { ...this.form };
this.fullscreenLoading = true
......@@ -114,6 +121,8 @@ export default {
this.fullscreenLoading = false
this.$parent.onCancel(false)
}).catch(e => {
this.fullscreenLoading = false
this.getFiles()
reject(e);
});
}
......@@ -121,7 +130,7 @@ export default {
});
},
getFiles () {
let params = {knowledgeName: this.$parent.knowledgeName};
let params = {knowledgeName: this.$parent.knowledgeCode};
KnowledgeManage.listFiles(this, params).then(res => {
this.listFiles = res.data.map((item) => {
return {
......@@ -134,13 +143,13 @@ export default {
},
delFile (row) {
let params = {
'knowledge_base_name': this.$parent.knowledgeName,
'knowledge_base_name': this.$parent.knowledgeCode,
'file_names': [
row.name
],
'delete_content': false,
'not_refresh_vs_cache': false
};
this.$confirm('是否确认删除', '提示', {
confirmButtonText: '确定',
......@@ -163,10 +172,10 @@ export default {
this.files.splice(index, 1)
},
down (row) { // 下载文件
let params = {knowledge_base_name: this.item.knowledgeName, file_name: row.name, boolean: false}
let params = {knowledge_base_name: this.item.knowledgeCode, file_name: row.name, boolean: false}
this.download('/2api/knowledge_base/download_doc', params, row.name, 'get', false).then((res) => {
this.download('/2api/knowledge_base/download_docs', params, row, 'get', false).then((res) => {
console.log(res);
})
}
}
......@@ -185,4 +194,9 @@ export default {
.itemFile{
}
.el-upload__tip{
font-size: 12px !important;
}
</style>
......@@ -4,7 +4,7 @@
<div style="position: relative">
<div class="topBox">
<div class="title">知识库</div>
<div class="instructions">面向客户构建私域文档或知识管理的能力,实现本地或BOS等多种数据源文档的上传、分段和清洗并储存至向量数据库中。</div>
<div class="instructions">面向客户构建私域文档或知识管理的能力,实现本地数据源文档的上传、分段和清洗并储存至向量数据库中。</div>
</div>
<div class="tableBox" :style="{ height: tableHeight }">
<el-form ref="myDataSetPage" :model="myDataSetPage" label-width="75px" :size="defaultFormItemSize" label-position="right" @submit.native.prevent>
......@@ -21,7 +21,6 @@
<card v-for="item in myDataSetPage.tableData.impl.dataList" :item="item" :key="item.knowledgeId" :refresh="refresh"></card>
<div class="box-card-2" v-for="item in 3" :key="item"></div>
</div>
<el-row slot="pagination" type="flex" justify="end" style="margin-top: 16px;">
<el-pagination :total="myDataSetPage.tableData.impl.totalCount" :current-page="myDataSetPage.tableData.impl.currentPage" :page-size="myDataSetPage.tableData.impl.pageSize" :page-sizes="[10, 20, 50, 100]" layout="total, prev, pager, next, sizes" @current-change="myDataSetPage.tableData.impl.onCurrentPageChange" @size-change="myDataSetPage.tableData.impl.onPageSizeChange">
</el-pagination>
......
......@@ -13,7 +13,8 @@
</div>
<pdf :page="currentPage" :src="url" class="pdf"></pdf>
</template>
<div class="txt" v-else-if="['txt'].indexOf(fileType)>-1" v-html="txtContent">
<div class="txt" v-else-if="['txt'].indexOf(fileType)>-1">
{{ txtContent }}
</div>
<div class="video" v-if="['mp4', 'webm', 'ogg', 'ogv'].indexOf(fileType)>-1&&url">
<video controls style="width: 100%">
......@@ -68,7 +69,7 @@ export default {
fileReader.addEventListener('load', () => {
const fileContent = fileReader.result;
// 处理文件内容
this.txtContent = fileContent.replace(/\n/g, '<br/>')
this.txtContent = fileContent
});
fileReader.readAsText(res, 'utf-8');
......@@ -136,6 +137,7 @@ export default {
.txt {
height: 100%;
overflow: auto;
white-space: pre-line;
}
.pagination {
......
......@@ -42,38 +42,63 @@ export default {
watch: {
'isSuccess' () {
if (this.isSuccess) {
let that = this
const anchorTags = document.querySelectorAll(`#myContainer${this.index} a`);
// 遍历并输出链接的 href 属性
anchorTags.forEach((aTag) => {
aTag.addEventListener('click', function (event) {
let tagUrl = aTag.getAttribute('href')
let url;
// alert(aTag.getAttribute('href'))
if (['pdf', 'jpg', 'gif', 'jpeg', 'png', 'docx', 'doc', 'xlsx', 'xls', 'mp4', 'webm', 'ogg', 'ogv', 'txt'].indexOf(tagUrl.split('.').pop().toLowerCase()) !== -1) {
// 阻止默认点击事件
event.preventDefault();
if (tagUrl.indexOf('https') !== -1) {
url = tagUrl.replace(/^https:\/\/[^/]+\//, `https://${window.location.hostname}:${window.location.port}/`);
} else {
url = tagUrl.replace(/^http:\/\/[^/]+\//, `http://${window.location.hostname}:${window.location.port}/`);
}
console.log(url);
that.$dialog.show('文件预览', filePreview, {
area: ['100%', '100%']
}, {url}).then(res => {
}).catch(e => { });
}
});
});
this.preview(anchorTags)
}
}
},
methods: {
preview (anchorTags) {
let that = this
// 遍历并输出链接的 href 属性
anchorTags.forEach((aTag) => {
let tagUrl = aTag.getAttribute('href')
let isFile = ['pdf', 'jpg', 'gif', 'jpeg', 'png', 'docx', 'doc', 'xlsx', 'xls', 'mp4', 'webm', 'ogg', 'ogv', 'txt'].indexOf(tagUrl.split('.').pop().toLowerCase()) !== -1
if (isFile) {
this.setDescribeStyle(aTag)
}
aTag.addEventListener('click', function (event) {
let url;
if (isFile) {
// 阻止默认点击事件
event.preventDefault();
if (tagUrl.indexOf('https') !== -1) {
url = tagUrl.replace(/^https:\/\/[^/]+\//, `https://${window.location.hostname}:${window.location.port}/`);
} else {
url = tagUrl.replace(/^http:\/\/[^/]+\//, `http://${window.location.hostname}:${window.location.port}/`);
}
that.$dialog.show('文件预览', filePreview, {
area: ['100%', '100%']
}, {url}).then(res => {
}).catch(e => { });
}
});
});
},
setDescribeStyle (aTag) {
let describeDom = aTag.parentNode.nextElementSibling
// 在当前元素前插入新的 HTML 内容
describeDom.insertAdjacentHTML('beforebegin', `
<button style="margin-bottom:10px" type="button" class="el-button el-button--primary el-button--mini is-round"><span style="margin-right:5px">详情</span><i class="el-icon-arrow-down"></i></button>
`);
describeDom.classList.add('describe')
let height = describeDom.scrollHeight
describeDom.setAttribute('style', `height:${height}px;`)
describeDom.previousElementSibling.addEventListener('click', function (event) {
if (height > 0 && (describeDom.style.height !== '0px' && describeDom.style.height !== '')) {
describeDom.setAttribute('style', 'height:0px;')
} else {
describeDom.setAttribute('style', `height:${height}px;`)
}
})
}
}
}
......@@ -86,4 +111,16 @@ export default {
.markdown-body pre{
background-color: #3b3d3f;
}
</style>
<style>
.describe{
overflow: hidden;
transition: 0.5s all;
color: #007fff;
font-size: 14px;
background-color: #Fff;
border-radius: 10px;
padding: 0 20px 0 20px;
}
</style>
<!--左侧操作界面 -->
<template>
<el-form label-position="left" ref="form" label-width="120px" :model="form" :size="defaultFormItemSize" style="padding:20px;width:400px">
<el-form-item label="对话模式:">
<el-select v-model="form.pattern" placeholder="请选择" >
<el-form label-position="left" ref="form" label-width="120px" :model="form" :size="defaultFormItemSize" style="padding:20px;width:400px" v-loading.fullscreen.lock="fullscreenLoading">
<el-form-item label="问答模式:">
<el-select v-model="form.pattern" placeholder="请选择" @change="patternChange">
<el-option v-for="item in ModeOfSpeaking.getList()" :key="item.id" :label="item.name" :value="item.name">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="LLM模型:">
<el-form-item label="模型选择:">
<el-cascader v-model="form.model_name" ref="modelCascader" :options="modelList" :props='{ label: "name", value: "name", emitPath: false }' @change="changeModel"></el-cascader>
</el-form-item>
<el-form-item label="Temperature:">
......@@ -31,7 +31,7 @@
{{ form.prompt_template }}
</div>
</el-form-item>
<el-form-item label-width="0px" v-if="form.pattern == '知识库问答'">
<el-form-item label-width="0px" v-if="form.pattern == '专业知识库问答'">
<el-collapse value="1">
<el-collapse-item name="1">
<template slot="title">知识库配置</template>
......@@ -40,11 +40,14 @@
<el-option v-for="item in knowledgeList" :key="item.knowledgeId" :label="item.knowledgeName" :value="item.knowledgeCode">
</el-option>
</el-select>
<div class="el-upload__tip" >{{knowledgeDescribe}}</div>
</el-form-item>
<el-form-item label="匹配知识条数:" style="margin-bottom:30px">
<el-input-number v-model="form.knowledgeConfige.top_k" :min="1" :max="20"></el-input-number>
</el-form-item>
<el-form-item label="知识匹配分数阈值:">
<el-form-item label="匹配精度:">
<el-slider v-model="knowledgeScoreThreshold" :format-tooltip="formatTooltip" @change="form.knowledgeConfige.score_threshold = knowledgeScoreThreshold / 100"></el-slider>
</el-form-item>
</el-collapse-item>
......@@ -66,7 +69,29 @@
</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-button @click="clickUp" :size="defaultFormItemSize" type="primary">选择文件</el-button>
<input style="display:none" ref="upFile" type="file" @change="fileinfo($event.target.files)" multiple accept=".html, .md, .json, .jsonl, .csv, .pdf, .png, .jpg, .jpeg, .bmp, .eml, .msg, .epub, .xlsx, .xls, .ipynb, .odt, .py, .rst, .rtf, .srt, .toml, .tsv, .docx, .doc, .xml, .ppt, .pptx, .txt, .htm">
<div class="el-upload__tip" >可上传HTML, MD, JSON, JSONL, CSV, PDF, PNG, JPG, JPEG, BMP, EML, MSG, EPUB, XLSX, XLSD, IPYNB, ODT, PY, RST, RTF, SRT, TOML, TSV, DOCX, DOC, XML, PPT, PPTX, TXT, HTM文件</div>
<div class="itemFile" v-for="(item,index) in files" :key="item.name"><i class="el-icon-document" style="color:#909399;margin-right:5px"></i>{{ item.name }}
<i class="el-icon-circle-close" style="color:#0092FF;cursor: pointer;" @click="clearFile(index)"></i>
</div>
<el-button style="display:block;margin-top:10px" :size="defaultFormItemSize" type="primary" @click="uploadFiles" :disabled="files.length===0" >上传</el-button>
</el-form-item>
<el-form-item label="匹配知识条数:" style="margin-bottom:30px">
<el-input-number v-model="form.fileConfige.top_k" :min="1" :max="20"></el-input-number>
</el-form-item>
<el-form-item label="知识匹配分数阈值:">
<el-slider v-model="fileThreshold" :format-tooltip="formatTooltip" @change="form.fileConfige.score_threshold = fileThreshold / 100"></el-slider>
</el-form-item>
</el-collapse-item>
</el-collapse>
</el-form-item>
</el-form>
</template>
......@@ -76,6 +101,9 @@ import promptWordTemplate from '../promptWordTemplate';
export default {
data () {
return {
knowledgeDescribe: '',
files: [],
fullscreenLoading: false,
isPromptTemplate: true,
promptTemplate: '',
templateControllerList: [],
......@@ -85,9 +113,9 @@ export default {
temperature: 70,
knowledgeList: [],
knowledgeScoreThreshold: 50,
fileThreshold: 50,
form: {
pattern: 'LLM 对话', // 对话模式
pattern: '通用智能问答', // 对话模式
model_name: undefined, // 模型名称
temperature: 0.7,
prompt_template: '',
......@@ -100,7 +128,21 @@ export default {
searchConfige: {// 搜索引擎配置
search_engine_name: 'bing',
top_k: 1
},
fileConfige: {
top_k: 1,
score_threshold: 0.5,
knowledge_id: undefined,
// max_tokens: 0,
prompt_name: 'default'
}
},
filesForm: {
filesArr: undefined,
chunk_size: 250,
chunk_overlap: 50,
zh_title_enhance: false
}
};
},
......@@ -153,9 +195,8 @@ export default {
},
getKnowledgeList () {
let params = {}
KnowledgeManage.listForTree(this, params).then(res => {
KnowledgeManage.load(this, params).then(res => {
this.knowledgeList = res.data
console.log(res.data);
}).catch(e => {
console.log(e);
});
......@@ -203,11 +244,13 @@ export default {
let id = this.$refs.modelCascader.getCheckedNodes()[0].data.id
this.switchModel(id)
},
changeKnowledge (dtat) { // 修改知识库
changeKnowledge (data) { // 修改知识库
// this.openLoading('知识库加载中')
// console.log(this.$refs.knowledgeSelect);
this.knowledgeDescribe = this.knowledgeList.filter((item) => {
return item.knowledgeCode === data
})[0].knowledgeDescribe
},
changeSe (dtat) { // 修改模型引擎
changeSe (data) { // 修改模型引擎
// this.openLoading('模型引擎加载中')
// console.log(this.$refs.searchSelect);
},
......@@ -226,7 +269,43 @@ export default {
},
changePromptTemplate () {
this.$bus.$emit('isPromptTemplate', this.isPromptTemplate);
},
fileinfo (files) {
for (const key in files) {
if (Object.hasOwnProperty.call(files, key)) {
const element = files[key];
if (this.files.map((item) => item.name).indexOf(element.name) === -1) {
this.files.push(element)
this.filesForm.filesArr = this.files
} else {
console.log('重复上传');
}
}
}
},
clickUp () {
this.$refs.upFile.click()
},
clearFile (index) {
this.files.splice(index, 1)
},
uploadFiles () {
this.fullscreenLoading = true
let params = this.filesForm
this.upload('/2api/knowledge_base/upload_temp_docs', params, false).then(res => {
this.$message.success('上传成功');
this.fullscreenLoading = false;
this.form.fileConfige.knowledge_id = res.data.id
}).catch(e => {
console.log(e);
});
},
patternChange () {
// console.log(111);
// Object.assign(this.$data.form, this.$options.data().form);
}
}
}
......@@ -235,4 +314,8 @@ export default {
.myLoading .el-loading-spinner i {
font-size: 24px !important;
}
.el-upload__tip{
line-height: normal;
font-size: 12px !important;
}
</style>
......@@ -6,7 +6,7 @@
<div v-for="(item, index) in myHistory" :key="index">
<div class="userBox">
<div class="content">
<contentView :content="item.content" />
</div>
<div class="icon">
......@@ -96,27 +96,35 @@ export default {
this.heistoryRotate = this.chatForm.heistoryRotate
this.param.prompt_template = this.isPromptTemplate ? this.chatForm.prompt_template : undefined
let apiUrl
if (this.chatForm.pattern === 'LLM 对话') {
if (this.chatForm.pattern === '通用智能问答') {
apiUrl = '/2api/chat/chat'
} else if (this.chatForm.pattern === '知识库问答') {
} else if (this.chatForm.pattern === '专业知识库问答') {
apiUrl = '/2api/chat/knowledge_base_chat'
this.param = { ...this.param, ...this.chatForm.knowledgeConfige }
} else if (this.chatForm.pattern === '搜索引擎问答') {
apiUrl = '/2api/chat/search_engine_chat'
this.param = { ...this.param, ...this.chatForm.searchConfige }
} 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
}
}
if (!this.inputContent) return
this.param.query = this.inputContent;
this.myHistory.push({
'role': 'user',
'content': this.inputContent,
'answer': ''
'answer': '',
'excludeReferenceAnswer': ''
})
this.inputContent = null;
this.myHistory.slice(0, -1).slice(-this.heistoryRotate).forEach((item) => {
this.param.history.push(...[{ role: item.role, content: item.content }, { role: 'assistant', content: item.answer}])
this.param.history.push(...[{ role: item.role, content: item.content }, { role: 'assistant', content: item.excludeReferenceAnswer}])
})
this.$emit('submit')
......@@ -124,22 +132,38 @@ export default {
getData.initeventSource()
},
success () {
console.log(1111);
this.isSuccess = true
},
onmessage (data) {
let nowChat = this.myHistory[this.myHistory.length - 1]
if (this.chatForm.pattern === 'LLM 对话') {
if (this.chatForm.pattern === '通用智能问答') {
nowChat.answer += data
} else if (this.chatForm.pattern === '知识库问答') {
console.log(data);
} else if (this.chatForm.pattern === '专业知识库问答') {
let temporary = JSON.parse(`[${data}]`.replace(/}{/g, '},{'))
console.log(temporary);
temporary.forEach((item) => {
if (item.docs) {
item.docs = item.docs.map((item2) => {
return item2.replace('出处', '知识溯源')
})
}
nowChat.excludeReferenceAnswer += item.answer || '' // 排除回答中的引用内容
nowChat.answer += item.answer || '\n' + item.docs
})
} 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('出处', '知识溯源')
})
}
nowChat.excludeReferenceAnswer += item.answer || '' // 排除回答中的引用内容
nowChat.answer += item.answer || '\n' + item.docs
})
}
this.$nextTick(() => {
......
......@@ -21,7 +21,9 @@
</el-form-item>
<template v-if="form.scenarioType === 0 ">
<el-form-item label="模板框架:" class="templateFramework" v-if=" !isEdit">
<el-radio v-model="form.templateFramework" v-for="item in TemplateFrameworkDict.getList()" :label="item.id" :size="defaultFormItemSize" :key="item.id" @input="$refs.promptInput.init()">{{ item.name }}</el-radio>
<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">
<promptInput ref="promptInput" v-model="form.templateContent" :templateFramework="form.templateFramework" :isEdit="isEdit" />
......
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