config/vite.config.prod.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/authority.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/authority/users/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/IntelligentAgent/components/agentConfig.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/IntelligentAgent/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/knowledgeLib/config.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/knowledgeLib/config1.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/knowledgeLib/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/dmx/knowledgeLib/test.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/session/sessionRecordsManager/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
yarn.lock | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
config/vite.config.prod.ts
@@ -14,29 +14,6 @@ configArcoResolverPlugin(), configImageminPlugin(), ], server: { open: true, // 项目启动后,自动打开 fs: { strict: true, }, proxy: { '/base': { target: 'http://192.168.20.116:8089', changeOrigin: true, ws: true, }, '/api': { target: 'http://192.168.20.116:8089', changeOrigin: true, ws: true, }, '/api/v1': { target: 'http://192.168.20.116:8089', changeOrigin: true, ws: true, }, }, }, build: { rollupOptions: { output: { package.json
@@ -34,6 +34,7 @@ "axios": "^0.24.0", "dayjs": "^1.11.5", "echarts": "^5.4.0", "eventsource-parser": "^2.0.1", "js-base64": "^3.7.5", "jsencrypt": "^3.3.2", "lodash": "^4.17.21", src/api/authority.ts
@@ -8,6 +8,7 @@ email: string; phoneNumber: string; dept: any; deptName:string; resources: any; knowledges: any; dialogs: any; src/views/authority/users/index.vue
@@ -369,6 +369,7 @@ let editform = ref<User>({ createTime: '', dept: undefined, deptName:"", email: '', nickName: '', phoneNumber: '', @@ -499,8 +500,8 @@ slotName: 'index', }, { title: t('用户名'), dataIndex: 'userName', title: t('登录名'), dataIndex: 'email', }, { title: t('创建时间'), @@ -508,8 +509,8 @@ }, { title: t('所属部门'), dataIndex: 'dept', slotName: 'dept', dataIndex: 'deptName', slotName: 'deptName', }, { title: t('状态'), @@ -630,7 +631,7 @@ //删除 if (t == 3) { await UserDelete(record.userId).then((res) => { if (res.code == 20000) { if (res.code == 200) { fetchData(); } }); @@ -646,28 +647,35 @@ checkStrictlyDialog.value = []; checkedKeysDialog.value = []; selectUser.value = record; record.resources.forEach((val) => { checkStrictlyMenu.value.push({ menuId: val.menuId, menuName: val.menuName, if (record.resources) { record.resources.forEach((val) => { checkStrictlyMenu.value.push({ menuId: val.menuId, menuName: val.menuName }); checkedKeysMenu.value.push(val.menuId); expandKdysMenu.value.push(val.menuId); }); checkedKeysMenu.value.push(val.menuId); expandKdysMenu.value.push(val.menuId); }); record.knowledges.forEach((val) => { checkStrictlyKnowledge.value.push({ knowledgeId: val.id, knowledgeName: val.name, } if (record.knowledges) { record.knowledges.forEach((val) => { checkStrictlyKnowledge.value.push({ knowledgeId: val.id, knowledgeName: val.name }); checkedKeysKnowledge.value.push(val.id); }); checkedKeysKnowledge.value.push(val.id); }); record.dialogs.forEach((val) => { checkStrictlyDialog.value.push({ dialogId: val.id, dialogName: val.name, } if (record.dialogs) { record.dialogs.forEach((val) => { checkStrictlyDialog.value.push({ dialogId: val.id, dialogName: val.name }); checkedKeysDialog.value.push(val.id); }); checkedKeysDialog.value.push(val.id); }); } } //机构 if (t == 5) { @@ -677,14 +685,16 @@ checkStrictly.value = []; selectUser.value = record; expandKdys.value.push('0'); record.dept.forEach((val) => { checkStrictly.value.push({ deptId: val.deptId, deptName: val.deptName, if (record.dept) { record.dept.forEach((val) => { checkStrictly.value.push({ deptId: val.deptId, deptName: val.deptName }); checkedKeys.value.push(val.deptId); expandKdys.value.push(val.deptId); }); checkedKeys.value.push(val.deptId); expandKdys.value.push(val.deptId); }); } } }; @@ -694,6 +704,17 @@ setLoading(true); try { await UserList(params).then((res) => { for (const user of res.rows) { if (user.dept) { for (const d of user.dept) { if (user.deptName) { user.deptName += d.deptName + ","; } else { user.deptName = d.deptName + ","; } } } } renderData.value = res.rows; console.log(renderData); pagination.current = params.current; src/views/dmx/IntelligentAgent/components/agentConfig.vue
@@ -48,49 +48,13 @@ </a-form-item> <a-form-item label="智能体图标"> <a-space direction="vertical" :style="{ width: '100%' }"> <a-upload :auto-upload="false" :fileList="file ? [file] : []" :show-file-list="false" @change="onChange" @progress="onProgress" > <template #upload-button> <div :class="`arco-upload-list-item${ file && file.status === 'error' ? ' arco-upload-list-item-error' : '' }`" > <div class="arco-upload-list-picture custom-upload-avatar" v-if="file && file.url" > <img :src="file.url" /> <div class="arco-upload-list-picture-mask"> <IconEdit /> </div> <a-progress v-if="file.status === 'uploading' && file.percent < 100" :percent="file.percent" type="circle" size="mini" :style="{ position: 'absolute', left: '50%', top: '50%', transform: 'translateX(-50%) translateY(-50%)', }" /> </div> <div class="arco-upload-picture-card" v-else> <div class="arco-upload-picture-card-text"> <IconPlus /> <div style="margin-top: 10px; font-weight: 600">上传</div> </div> </div> </div> </template> </a-upload> <Upload :action="uploadAction" :limit="1" :url="form.icon" @update:fileList="updateFileList" @success="handleSuccess" ></Upload> </a-space> </a-form-item> <a-form-item label="空回复"> @@ -370,26 +334,18 @@ return `${(value / 100).toFixed(2)}` }; const onChange = (_, currentFile) => { file.value = currentFile; convertImageToBase64(file.value.file).then((result) => { form.icon = result; }); const uploadAction = '/api/v1/llm/upload'; // 替换为你的上传API const fileList = ref([]); const imageUrls = ref([]); const updateFileList = (newFileList) => { fileList.value = newFileList; console.log(newFileList, 88); }; function convertImageToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsDataURL(file); }); } const onProgress = (currentFile) => { file.value = currentFile; const handleSuccess = (urls) => { imageUrls.value = urls; // 拿到上传的图片地址 form.icon = urls[0]; }; const rules = { @@ -517,7 +473,7 @@ nextTick(()=>{ // console.log(props.formData,'传入数据'); Object.assign(form, props.formData); // console.log(form,'表单数据'); console.log(form,'表单数据'); }) }; src/views/dmx/IntelligentAgent/index.vue
@@ -15,7 +15,7 @@ <a-divider style="margin: 10px 0" /> <a-row justify="space-between"> <a-col :span="24"> <div style="display: flex; flex-wrap: wrap"> <a-spin :loading="loading" style="display: flex; flex-wrap: wrap" :style="{height: documentHeight + 'px'}"> <!-- <div--> <!-- class="card-wrap"--> <!-- style="cursor: pointer"--> @@ -56,7 +56,7 @@ :key="item.id" > <a-card :bordered="false" hoverable> <a-avatar :style="{ backgroundColor: '#3370ff' }"> <a-avatar :style="{ backgroundColor: '#5b99da' }"> <img :style="{ width: '100%' }" alt="dessert" @@ -113,7 +113,7 @@ </div> </a-card> </div> </div> </a-spin> </a-col> </a-row> </a-card> @@ -130,7 +130,7 @@ const { loading, setLoading } = useLoading(true); import EventBus from '@/utils/EventBus'; import AgentConfig from "@/views/dmx/IntelligentAgent/components/agentConfig.vue"; let documentHeight = window.innerHeight - 360 let count = 5; const activeKey = ref(1); const addAgents = ref(); src/views/dmx/knowledgeLib/config.vue
@@ -14,49 +14,14 @@ </a-form-item> <a-form-item field="section" label="知识库图片"> <a-space direction="vertical" :style="{ width: '100%' }"> <a-upload :auto-upload="false" :fileList="file ? [file] : []" :show-file-list="false" @change="onChange" @progress="onProgress" > <template #upload-button> <div :class="`arco-upload-list-item${ file && file.status === 'error' ? ' arco-upload-list-item-error' : '' }`" > <div class="arco-upload-list-picture custom-upload-avatar" v-if="file && file.url" > <img :src="form.avatar" /> <div class="arco-upload-list-picture-mask"> <IconEdit /> </div> <a-progress v-if="file.status === 'uploading' && file.percent < 100" :percent="file.percent" type="circle" size="mini" :style="{ position: 'absolute', left: '50%', top: '50%', transform: 'translateX(-50%) translateY(-50%)', }" /> </div> <div class="arco-upload-picture-card" v-else> <div class="arco-upload-picture-card-text"> <IconPlus /> <div style="margin-top: 10px; font-weight: 600">上传</div> </div> </div> </div> </template> </a-upload> <Upload v-if="avatarShow" :action="uploadAction" :limit="1" :url="form.avatar" @update:fileList="updateFileList" @success="handleSuccess" ></Upload> </a-space> </a-form-item> <a-form-item field="section" label="描述"> @@ -131,7 +96,7 @@ <div style="width: 100%;text-align: right"> <a-space> <a-button @click="cancelConfig">取消</a-button> <a-button type="primary" html-type="submit">保存</a-button> <a-button :loading="loading" type="primary" html-type="submit">保存</a-button> </a-space> </div> </a-form-item> @@ -208,10 +173,11 @@ }); let kbObj = reactive({}); let avatarShow = ref(true); const form = reactive({ name: kbObj.name, avatar: '',// name: '', avatar: '',//头像 max_token: 600, threshold: 0.32, max_cluster: 233, @@ -226,7 +192,7 @@ language: "English", permission: "", embd_id: "BAAI/bge-large-zh-v1.5", parser_id: kbObj.parser_id, parser_id: '', layout_recognize: true }); @@ -261,26 +227,18 @@ const modelList = ref({}); const file = ref(); const onChange = (_, currentFile) => { file.value = currentFile; convertImageToBase64(file.value.file).then((result)=>{ form.avatar = result; }) const uploadAction = '/api/v1/llm/upload'; // 替换为你的上传API const fileList = ref([]); const imageUrls = ref([]); const updateFileList = (newFileList) => { fileList.value = newFileList; console.log(newFileList, 88); }; function convertImageToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsDataURL(file); }); } const onProgress = (currentFile) => { file.value = currentFile; const handleSuccess = (urls) => { imageUrls.value = urls; // 拿到上传的图片地址 form.avatar = urls[0]; }; @@ -313,7 +271,7 @@ }; } try { setLoading(true) const data = await kbUpdate(parms); if(data.code == '0'){ Message.success("配置成功"); @@ -321,10 +279,11 @@ emit('saveConfig') } // emit('upTabdateItem') setLoading(false) } catch (err) { Message.error(err.message); setLoading(false) } @@ -377,15 +336,11 @@ formRef.value.resetFields(); kbObj = value; console.log(kbObj, 'kbObj'); if(kbObj.avatar){ file.value.url = kbObj.avatar }else{ // file.value.url = ''; } let configObj = { name: kbObj.name, avatar: kbObj.avatar, pages: kbObj.parser_config.pages, chunk_token_num: kbObj.parser_config.chunk_token_num, description: kbObj.description, language: "English", permission: kbObj.permission, @@ -402,9 +357,17 @@ use_raptor: kbObj.parser_config.raptor.use_raptor, }); }else{ Object.assign(form,configObj); Object.assign(form,{ ...configObj, use_raptor: false, }); } imageUrls.value = [kbObj.avatar]; console.log(form,'配置页面表单信息'); avatarShow.value = false; setTimeout(() => { avatarShow.value = true; },100); } defineExpose({ @@ -413,6 +376,7 @@ onBeforeMount(()=>{ setLoading(false) queryModel({}) }) onMounted(()=>{ src/views/dmx/knowledgeLib/config1.vue
New file @@ -0,0 +1,510 @@ <template> <div class="main-container"> <div style="position: absolute;top: 0;left: 0;width: 100%;padding: 0 20px"> <h4 style="margin-bottom: 10px"></h4> <div style="color: #666666;">在这里更新您的知识库详细信息,尤其是解析方法。</div> <a-divider style="margin-top: 20px" /> </div> <div class="main-container-lf"> <div class="main-container-lf-down"> <a-form ref="formRef" :rules="rules" :model="form" :style="{width:'100%'}" layout="vertical" @submit="handleSubmit"> <a-form-item field="name" label="知识库名称"> <a-input v-model="form.name" placeholder="请输入" /> </a-form-item> <a-form-item field="section" label="知识库图片"> <a-space direction="vertical" :style="{ width: '100%' }"> <a-upload :auto-upload="false" :fileList="file ? [file] : []" :show-file-list="false" @change="onChange" @progress="onProgress" > <template #upload-button> <div :class="`arco-upload-list-item${ file && file.status === 'error' ? ' arco-upload-list-item-error' : '' }`" > <div class="arco-upload-list-picture custom-upload-avatar" v-if="file && file.url" > <img :src="form.avatar" /> <div class="arco-upload-list-picture-mask"> <IconEdit /> </div> <a-progress v-if="file.status === 'uploading' && file.percent < 100" :percent="file.percent" type="circle" size="mini" :style="{ position: 'absolute', left: '50%', top: '50%', transform: 'translateX(-50%) translateY(-50%)', }" /> </div> <div class="arco-upload-picture-card" v-else> <div class="arco-upload-picture-card-text"> <IconPlus /> <div style="margin-top: 10px; font-weight: 600">上传</div> </div> </div> </div> </template> </a-upload> </a-space> </a-form-item> <a-form-item field="section" label="描述"> <a-textarea placeholder="" v-model="form.description" allow-clear /> </a-form-item> <!-- <a-form-item field="section" label="语言" :rules="[{match:/section one/,message:'请选择'}]">--> <!-- <a-select v-model="form.section" placeholder="请选择" allow-clear>--> <!-- <a-option value="0">中文</a-option>--> <!-- <a-option value="1">英文</a-option>--> <!-- </a-select>--> <!-- </a-form-item>--> <a-form-item field="embd_id" label="嵌入模型"> <a-space direction="vertical" size="large"> <a-select :size="'large'" v-model="form.embd_id" :style="{width:'100%'}" placeholder="请选择 ..." :disabled="kbObj.chunk_num==0 && kbObj.token_num==0" allow-clear> <a-optgroup :label="index" v-for="(item,index) in modelList" :key=index> <a-option v-for="(obj) in item" :key='obj.fid' :value="obj.llm_name" > {{obj.llm_name}} </a-option> </a-optgroup> </a-select> </a-space> </a-form-item> <a-form-item field="parser_id" label="解析方法"> <a-select v-model="form.parser_id" placeholder="请选择" :disabled="kbObj.chunk_num==0 && kbObj.token_num==0" allow-clear> <a-option v-for="item in parser_ids" :key="item.value" :label="item.name" :value="item.value"></a-option> </a-select> </a-form-item> <a-form-item field="slider" label="块Token数"> <a-slider v-model="form.chunk_token_num" :min="0" :max="2048" show-input /> </a-form-item> <a-form-item label="布局识别" > <a-space direction="vertical"> <a-switch v-model="form.layout_recognize" size="small" /> </a-space> </a-form-item> <a-form-item field="raptor" label="使用召回增强RAPTOR策略"> <a-space direction="vertical" > <a-switch v-model="form.use_raptor" size="small" /> </a-space> </a-form-item> <div v-if="form.use_raptor"> <a-form-item field="prompt" label="提示词"> <a-textarea v-model="form.prompt" style="height: 10rem;border: 1px solid var(--color-fill-3);border-radius: 4px" placeholder="请填写提示词" /> </a-form-item> <a-form-item field="slider" label="最大token数"> <a-slider v-model="form.max_token" :min="0" :max="2048" show-input/> </a-form-item> <a-form-item field="slider" label="阈值" > <a-slider v-model="form.threshold" :step="0.01" :min="0" :max="1" show-input/> </a-form-item> <a-form-item field="slider" label="最大聚类数"> <a-slider v-model="form.max_cluster" :min="1" :max="1024" show-input/> </a-form-item> <a-form-item field="slider" label="随机种子" v-model="form.random_seed"> <a-input-number v-model="form.random_seed" :style="{width:'300px',marginRight:'1rem',borderRadius:'4px'}" placeholder="请输入" class="input-demo" :min="10" :max="100" /> <a-button type="primary" @click="randomNumber"> <icon-plus /> </a-button> </a-form-item> </div> <a-form-item> <div style="width: 100%;text-align: right"> <a-space> <a-button @click="cancelConfig">取消</a-button> <a-button type="primary" html-type="submit">保存</a-button> </a-space> </div> </a-form-item> </a-form> </div> </div> <div class="main-container-rt"> <section data-inspector-line="34" data-inspector-column="4" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx" class="categoryPanelWrapper___yI4rY"><h4 class="ant-typography topTitle___tNiB9 css-dev-only-do-not-override-1wxecgq" data-inspector-line="37" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">"General" 分块方法说明</h4> <p data-inspector-line="40" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"><p> 支持的文件格式为<b>DOCX、EXCEL、PPT、IMAGE、PDF、TXT</b>。</p> <p>此方法将简单的方法应用于块文件:</p> <p> </p> <li>系统将使用视觉检测模型将连续文本分割成多个片段。</li> <li>接下来,这些连续的片段被合并成Token数不超过“Token数”的块。</li> <p></p></p> <h4 class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="45" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"> "General" 示例</h4><span class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="48" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">提出以下屏幕截图以促进理解。</span> <div data-inspector-line="49" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx" class="ant-row imageRow___C3Xpb css-dev-only-do-not-override-1wxecgq" style="margin-left: -5px; margin-right: -5px; row-gap: 10px;display: flex; margin-top: 20px;width: 100%"> <img data-inspector-line="32" data-inspector-column="8" data-inspector-relative-path="src\components\svg-icon.tsx" src="../../../assets/images/step1.png" alt="" width="50%"> <img data-inspector-line="32" data-inspector-column="8" data-inspector-relative-path="src\components\svg-icon.tsx" src="../../../assets/images/step2.png" alt="" width="50%"> </div> <h4 class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="60" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"> General 对话示例</h4> <div class="ant-divider css-dev-only-do-not-override-1wxecgq ant-divider-horizontal" data-inspector-line="63" data-inspector-column="10" data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx" role="separator"></div> <a-divider style="margin-top: 20px" /> </section> </div> </div> </template> <script lang="ts" setup> import { onMounted, onBeforeMount, reactive, ref } from "vue"; import { Message } from "@arco-design/web-vue"; import { queryModelList,kbUpdate } from "@/api/kbList"; import message from "@arco-design/web-vue/es/message"; import useLoading from "@/hooks/loading"; const { loading,setLoading } = useLoading(true); const props = defineProps(['kbtenantInfo']) const emit = defineEmits(['cancleConfig','saveConfig']) // 解析方法列表 let parser_ids = props.kbtenantInfo.parser_ids.split(",").map((item) => { const [value1, value2] = item.split(":"); return { name: value2, value: value1 }; }); let kbObj = reactive({}); const form = reactive({ name: kbObj.name, avatar: '',// max_token: 600, threshold: 0.32, max_cluster: 233, random_seed: 1500, chunk_token_num: 384, use_raptor: false, pages: {}, prompt: "请总结以下段落。 小心数字,不要编造。 段落如下:\n" + " {cluster_content}\n" + "以上就是你需要总结的内容。", description: "", language: "English", permission: "", embd_id: "BAAI/bge-large-zh-v1.5", parser_id: kbObj.parser_id, layout_recognize: true }); const rules = { name: [ { required: true, message:'知识库名称不允许为空', }, ], embd_id: [ { required: true, message:'请选择', }, ], parser_id: [ { required: true, message:'请选择', }, ], prompt: [ { required: true, message:'提示词不允许为空', }, ], } let visible = ref(false); const formRef = ref(null); const modelList = ref({}); const file = ref(); const onChange = (_, currentFile) => { file.value = currentFile; convertImageToBase64(file.value.file).then((result)=>{ form.avatar = result; }) }; function convertImageToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsDataURL(file); }); } const onProgress = (currentFile) => { file.value = currentFile; }; const handleSubmit = async ({ values, errors }) => { if (errors){ return; } let parms = { name: form.name, avatar: form.avatar, description: form.description, language: form.language, permission: form.permission, embd_id: form.embd_id, parser_id: form.parser_id, parser_config: { chunk_token_num: form.chunk_token_num, layout_recognize: form.layout_recognize, }, kb_id: kbObj.id, } if(form.use_raptor){ parms.parser_config.raptor = { use_raptor: form.use_raptor, prompt: form.prompt, max_token: form.max_token, threshold: form.threshold, max_cluster: form.max_cluster, random_seed: form.random_seed, }; } try { const data = await kbUpdate(parms); if(data.code == '0'){ Message.success("配置成功"); // window.location.reload(); emit('saveConfig') } // emit('upTabdateItem') } catch (err) { Message.error(err.message); } }; const cancelConfig = () => { emit('cancleConfig') } function randomNumber() { // 生成一个介于min和max之间的随机整数(包含min和max) const min = 1; // 最小值 const max = 10000; // 最大值 form.random_seed = Math.floor(Math.random() * (max - min + 1)) + min; } const handleBeforeOk = (done) => { formRef.value.validate().then(res => { console.log("form:", form); if (!form.name) { done(false); } else { console.log("请求数据"); } }); }; const handleOpened =(el) => { Object.assign(form,{ }); formRef.value.resetFields(); } const queryModel = async (params) => { try { const data = await queryModelList(params); // console.log(data.data, '大模型列表'); modelList.value = data.data } catch (err) { // you can report use errorHandler or other } finally { } }; const changekbObj = (value) => { formRef.value.resetFields(); kbObj = value; console.log(kbObj, 'kbObj'); if(kbObj.avatar){ file.value.url = kbObj.avatar }else{ // file.value.url = ''; } let configObj = { name: kbObj.name, avatar: kbObj.avatar, pages: kbObj.parser_config.pages, description: kbObj.description, language: "English", permission: kbObj.permission, embd_id: props.kbtenantInfo.embd_id || kbObj.embd_id, parser_id: kbObj.parser_id, layout_recognize: true, } let raptor = {} if(kbObj.parser_config && kbObj.parser_config.raptor){ raptor = kbObj.parser_config.raptor; Object.assign(form,{ ...configObj, ...raptor, use_raptor: kbObj.parser_config.raptor.use_raptor, }); }else{ Object.assign(form,configObj); } console.log(form,'配置页面表单信息'); } defineExpose({ changekbObj }) onBeforeMount(()=>{ queryModel({}) }) onMounted(()=>{ }) </script> <script lang="ts"> import { IconEdit, IconPlus } from "@arco-design/web-vue/es/icon"; export default { name: "config", components: { IconPlus, IconEdit }, methods: {} }; </script> <style scoped lang="less"> .main-container { position: relative; display: flex; justify-content: space-between; height: 100%; overflow: auto; //background: #626aea; background: var(--color-bg-2); padding-top: 80px; &-lf { width: 40%; //height: 100%; //border: 1px solid #cccccc; border-radius: 10px; //border: 1px solid var(--color-fill-3); &-top { width: 100%; height: 60px; line-height: 60px; //background: rgb(var(--primary-6)); //color: #ffffff; //text-align: center; } &-down { padding: 20px; width: 100%; } } &-form-item-extra { width: 100%; height: 20rem; border: 1px solid var(--color-fill-3); border-radius: 6px; overflow: hidden; &-top { width: 100%; height: 40px; line-height: 40px; border-bottom: 1px solid var(--color-fill-3); //background: rgb(var(--primary-6)); color: #999999; text-align: center; } &-down { width: 92%; margin-left: 4%; margin-top: 30px; } &-btn { width: 96%; text-align: right; margin-top: 1rem; } } &-rt { width: 60%; //background: #626aea; //border: 1px solid #cccccc; border-radius: 10px; overflow: hidden; padding: 20px; section { width: 100%; //color: #333333; color: var(--color-text-1); } } } </style> src/views/dmx/knowledgeLib/index.vue
@@ -10,7 +10,7 @@ /> <addKnow @getknowledge="getknowledge" @getKbdetail="getKbdetail"></addKnow> </div> <div class="lf-container-down"> <a-spin :loading="listloading" class="lf-container-down"> <a-scrollbar style="height:56rem;overflow: auto;"> <div class="tab" @@ -23,15 +23,15 @@ <a-popover position="bl"> <icon-more :style="{position: 'absolute',top:'10px',right:'20px'}"/> <template #content> <a-popconfirm content="确定删除吗?" @ok="deleteKnowledge(tab.id)" type="warning"> <span style="cursor: pointer;color: #4977ba;font-size: 12px"><icon-delete style="font-size: 14px"/>删除</span> </a-popconfirm> <!-- <span style="cursor: pointer;color: #0960bd;font-size: 12px" @click="deleteKnowledge(tab.id)"><icon-delete />删除</span>--> <!-- <a-popconfirm content="确定删除吗?" @ok="deleteKnowledge(tab.id)" type="warning">--> <!-- <span style="cursor: pointer;color: #4977ba;font-size: 12px"><icon-delete style="font-size: 14px"/>删除</span>--> <!-- </a-popconfirm>--> <span style="cursor: pointer;color: #4977ba;font-size: 12px" @click="deleteKnowledge(tab.id)"><icon-delete style="font-size: 14px" />删除</span> </template> </a-popover> </div> </a-scrollbar> </div> </a-spin> </div> <div class="rt-container" v-if="tabs.length > 0"> <a-tabs :activeKey="activeKey" @change="handleTabChange"> @@ -257,7 +257,7 @@ </a-tab-pane> <a-tab-pane key="3" :title="t('dmx.list.disposition')"> <div class="rt-container-main"> <config ref="configForm" :kbtenantInfo="kbtenantInfo" :kbobj="kbobj" @cancleConfig="cancleConfig" @saveConfig="saveConfig"></config> <config ref="configForm" :kbtenantInfo="kbtenantInfo" @cancleConfig="cancleConfig" @saveConfig="saveConfig"></config> </div> </a-tab-pane> </a-tabs> @@ -335,8 +335,9 @@ import docx from '@/views/dmx/knowledgeLib/components/docx.vue' import excel from '@/views/dmx/knowledgeLib/components/excel.vue' import txtPdf from '@/views/dmx/knowledgeLib/components/txtPdf.vue' import { Message } from "@arco-design/web-vue"; import { Message, Modal } from "@arco-design/web-vue"; import { parseTime } from "@/utils"; import { deleteLlm } from "@/api/model"; type SizeProps = 'mini' | 'small' | 'medium' | 'large'; type Column = TableColumnData & { checked?: true }; const account = ref(null) @@ -359,6 +360,7 @@ const size = ref<SizeProps>('medium'); let visible = ref(false) let listloading = ref(false) let keywords = ref('') let activeKey = ref('1') let detailsShow = ref(false) @@ -550,7 +552,7 @@ const knowledgeData = async ( params = { page: 1, page_size: 20 } ) => { setLoading(true); listloading.value = true; try { const { data } = await queryKbList(params); // console.log(data, 'data'); @@ -576,7 +578,7 @@ } catch (err) { // you can report use errorHandler or other } finally { setLoading(false); listloading.value = false; } }; @@ -619,14 +621,24 @@ } }; const deleteKnowledge = async (id) => { let data = await deleteKnow({ kb_id:id }) if(data.code == 0){ Message.success('删除成功'); knowledgeData() } const deleteKnowledge = (id) => { Modal.confirm({ title: '提示信息', content: '确认删除吗', okText: '确定', cancelText: '取消', hideTitle: true, onOk: async () => { let data = await deleteKnow({ kb_id:id }) if(data.code == 0){ Message.success('删除成功'); knowledgeData() } }, onCancel: () => {}, }); } const reset = () => { formModel.value = generateFormModel(); src/views/dmx/knowledgeLib/test.vue
@@ -39,7 +39,7 @@ <a-textarea v-model="form.question" style="height: 10rem;border: 1px solid var(--color-fill-3);border-radius: 4px" placeholder="" allow-clear/> </div> <div class="main-container-form-item-extra-btn"> <a-button :disabled="!form.question" type="primary" html-type="submit">测试</a-button> <a-button :disabled="!form.question" :loading="loading" type="primary" html-type="submit">测试</a-button> </div> </div> </a-form-item> @@ -110,9 +110,17 @@ delete formObj.rerank_id; } try { loading.value = true; const data = await kbretrievalTest(formObj); if(data.code == 0){ Message.success('测试成功'); }else{ Message.error('测试失败'); } loading.value = false; }catch (err){ Message.error(err.message); loading.value = false; } } src/views/session/sessionRecordsManager/index.vue
@@ -306,6 +306,7 @@ import { useAppStore } from '@/store'; import { computed, nextTick, onMounted, reactive, ref } from 'vue'; import { Message } from '@arco-design/web-vue'; import { EventSourceParserStream } from 'eventsource-parser/stream'; import moment from 'moment'; import AddSession from '@/views/session/sessionManager/components/addSession.vue'; import { @@ -314,6 +315,8 @@ getSessionDetailsApi, sessionListApi, } from '@/api/session'; import { getAuthorization } from "@/utils/auth"; const sessionDetailList = ref([]); //根据会话id出来的会话详情 const sessionList = ref([]); //会话列表 @@ -353,30 +356,49 @@ return; } if (inputMsg.value) { const data = await chatApi({ conversation_id: activeSessionId.value, messages: inputMsg.value, sessionDetailList.value.push({ "content": inputMsg.value, "role": "user" }); sessionDetailList.value.push({ "role": "last" }); refreshScroll(); const response = await fetch("/api/tech/cloudminds/query?modeltype=localragflow", { method: 'POST', headers: { 'Authorization': getAuthorization(), 'Content-Type': 'application/json', }, body: JSON.stringify({ conversation_id: activeSessionId.value, messages: inputMsg.value, }), }); if (data) { chatDis.value = false; // inputMsg.value = ''; // querySessionDetail({ id: activeSessionId.value }); } const res = await getSessionDetailsApi(activeSessionId.value); if (res.code === 200) { sessionDetailList.value = res.data.message.map((item, index) => { if (index === res.data.message.length - 1) { item.role = 'last'; displayedText.value = ''; currIndex.value = 0; streamStr.value = item.content; startDisplayStr(); const reader = response?.body ?.pipeThrough(new TextDecoderStream()) .pipeThrough(new EventSourceParserStream()) .getReader(); currIndex.value = 0; while (true) { const x = await reader?.read(); if (x) { const { done, value } = x; try { const val = JSON.parse(value?.data || ''); const d = val?.data; if (typeof d !== "boolean") { console.info("data:", d); streamStr.value = d.content; startDisplayStr(); } } catch (e) { console.warn(e); } return item; }); refreshScroll(); if (done) { console.info('done'); break; } } } chatDis.value=false; inputMsg.value = ''; } else { Message.warning('消息不能为空'); @@ -428,6 +450,7 @@ displayedText.value += res[currIndex.value]; currIndex.value++; setTimeout(startDisplayStr, 100); refreshScroll(); } else { clearTimeout(timer!); timer = null; yarn.lock
@@ -3253,6 +3253,11 @@ resolved "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== eventsource-parser@^2.0.1: version "2.0.1" resolved "https://registry.npmmirror.com/eventsource-parser/-/eventsource-parser-2.0.1.tgz#6464341d64de5bea9f31d8063dd312b616146c7a" integrity sha512-gMaRLm5zejEH9mNXC54AnIteFI9YwL/q5JKMdBnoG+lEI1JWVGFVk0Taaj9Xb5SKgzIBDZoQX5IzMe44ILWODg== exec-buffer@^3.0.0: version "3.2.0" resolved "https://registry.npmmirror.com/exec-buffer/-/exec-buffer-3.2.0.tgz"