知识库功能增强,支持Milvus,并优化相关逻辑
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"modified": "Modified",
|
||||
"modifiedBy": "ModifiedBy",
|
||||
"options": "Options",
|
||||
"rerankEnable": "Enable rerank model",
|
||||
"rerankLlmId": "RerankLlm",
|
||||
"searchEngineEnable": "SearchEngineEnable",
|
||||
"englishName": "EnglishName",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"modified": "最后一次修改时间",
|
||||
"modifiedBy": "最后一次修改用户ID",
|
||||
"options": "其他配置",
|
||||
"rerankEnable": "是否启用重排模型",
|
||||
"rerankLlmId": "重排模型",
|
||||
"searchEngineEnable": "是否启用搜索引擎",
|
||||
"englishName": "英文名称",
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { InfoFilled } from '@element-plus/icons-vue';
|
||||
import type {FormInstance} from 'element-plus';
|
||||
import {
|
||||
ElButton,
|
||||
ElForm,
|
||||
@@ -17,9 +13,13 @@ import {
|
||||
ElTooltip,
|
||||
} from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import {computed, onMounted, ref, watch} from 'vue';
|
||||
|
||||
import {InfoFilled} from '@element-plus/icons-vue';
|
||||
|
||||
import {api} from '#/api/request';
|
||||
import UploadAvatar from '#/components/upload/UploadAvatar.vue';
|
||||
import { $t } from '#/locales';
|
||||
import {$t} from '#/locales';
|
||||
|
||||
const props = defineProps({
|
||||
detailData: {
|
||||
@@ -39,6 +39,7 @@ const props = defineProps({
|
||||
vectorEmbedModelId: '',
|
||||
options: {
|
||||
canUpdateEmbeddingModel: true,
|
||||
rerankEnable: false,
|
||||
},
|
||||
rerankModelId: '',
|
||||
searchEngineEnable: false,
|
||||
@@ -50,12 +51,26 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['reload']);
|
||||
|
||||
const entity = ref<any>({ ...props.detailData });
|
||||
const normalizeEntity = (raw: any) => {
|
||||
const options = {
|
||||
canUpdateEmbeddingModel: true,
|
||||
...(raw?.options || {}),
|
||||
};
|
||||
if (options.rerankEnable === undefined || options.rerankEnable === null) {
|
||||
options.rerankEnable = !!raw?.rerankModelId;
|
||||
}
|
||||
return {
|
||||
...raw,
|
||||
options,
|
||||
};
|
||||
};
|
||||
|
||||
const entity = ref<any>(normalizeEntity(props.detailData));
|
||||
|
||||
watch(
|
||||
() => props.detailData,
|
||||
(newVal) => {
|
||||
entity.value = { ...newVal };
|
||||
entity.value = normalizeEntity(newVal);
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
@@ -63,7 +78,7 @@ watch(
|
||||
const embeddingLlmList = ref<any>([]);
|
||||
const rerankerLlmList = ref<any>([]);
|
||||
const vecotrDatabaseList = ref<any>([
|
||||
// { value: 'milvus', label: 'Milvus' },
|
||||
{ value: 'milvus', label: 'Milvus' },
|
||||
{ value: 'redis', label: 'Redis' },
|
||||
{ value: 'opensearch', label: 'OpenSearch' },
|
||||
{ value: 'elasticsearch', label: 'ElasticSearch' },
|
||||
@@ -71,6 +86,20 @@ const vecotrDatabaseList = ref<any>([
|
||||
{ value: 'qcloud', label: $t('documentCollection.tencentCloud') },
|
||||
]);
|
||||
|
||||
const milvusVectorStoreConfigPlaceholder =
|
||||
'uri=http://127.0.0.1:19530\n' +
|
||||
'databaseName=default\n' +
|
||||
'token=\n' +
|
||||
'username=\n' +
|
||||
'password=\n' +
|
||||
'autoCreateCollection=true';
|
||||
|
||||
const vectorStoreConfigPlaceholder = computed(() => {
|
||||
return entity.value?.vectorStoreType === 'milvus'
|
||||
? milvusVectorStoreConfigPlaceholder
|
||||
: '';
|
||||
});
|
||||
|
||||
const getEmbeddingLlmListData = async () => {
|
||||
try {
|
||||
const url = `/api/v1/model/list?modelType=embeddingModel`;
|
||||
@@ -131,6 +160,11 @@ async function save() {
|
||||
const valid = await saveForm.value?.validate();
|
||||
if (!valid) return;
|
||||
|
||||
if (!entity.value.options) {
|
||||
entity.value.options = {};
|
||||
}
|
||||
entity.value.options.rerankEnable = !!entity.value.options.rerankEnable;
|
||||
|
||||
btnLoading.value = true;
|
||||
const res = await api.post(
|
||||
'/api/v1/documentCollection/update',
|
||||
@@ -233,6 +267,7 @@ async function save() {
|
||||
v-model.trim="entity.vectorStoreConfig"
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
:placeholder="vectorStoreConfigPlaceholder"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="vectorEmbedModelId">
|
||||
@@ -302,12 +337,19 @@ async function save() {
|
||||
type="number"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="options.rerankEnable"
|
||||
:label="$t('documentCollection.rerankEnable')"
|
||||
>
|
||||
<ElSwitch v-model="entity.options.rerankEnable" />
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="rerankModelId"
|
||||
:label="$t('documentCollection.rerankLlmId')"
|
||||
>
|
||||
<ElSelect
|
||||
v-model="entity.rerankModelId"
|
||||
clearable
|
||||
:placeholder="$t('documentCollection.placeholder.rerankLlm')"
|
||||
>
|
||||
<ElOption
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { InfoFilled } from '@element-plus/icons-vue';
|
||||
import type {FormInstance} from 'element-plus';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
@@ -18,10 +14,14 @@ import {
|
||||
ElTooltip,
|
||||
} from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import {onMounted, ref} from 'vue';
|
||||
|
||||
import {InfoFilled} from '@element-plus/icons-vue';
|
||||
|
||||
import {api} from '#/api/request';
|
||||
import DictSelect from '#/components/dict/DictSelect.vue';
|
||||
import UploadAvatar from '#/components/upload/UploadAvatar.vue';
|
||||
import { $t } from '#/locales';
|
||||
import {$t} from '#/locales';
|
||||
|
||||
const emit = defineEmits(['reload']);
|
||||
const embeddingLlmList = ref<any>([]);
|
||||
@@ -83,12 +83,28 @@ const defaultEntity = {
|
||||
dimensionOfVectorModel: undefined,
|
||||
options: {
|
||||
canUpdateEmbeddingModel: true,
|
||||
rerankEnable: false,
|
||||
},
|
||||
rerankModelId: '',
|
||||
searchEngineEnable: '',
|
||||
englishName: '',
|
||||
};
|
||||
const entity = ref<any>({ ...defaultEntity });
|
||||
const normalizeEntity = (raw: any = {}) => {
|
||||
const options = {
|
||||
canUpdateEmbeddingModel: true,
|
||||
...(raw.options || {}),
|
||||
};
|
||||
if (options.rerankEnable === undefined || options.rerankEnable === null) {
|
||||
options.rerankEnable = !!raw.rerankModelId;
|
||||
}
|
||||
return {
|
||||
...defaultEntity,
|
||||
...raw,
|
||||
options,
|
||||
};
|
||||
};
|
||||
|
||||
const entity = ref<any>(normalizeEntity(defaultEntity));
|
||||
|
||||
const btnLoading = ref(false);
|
||||
const rules = ref({
|
||||
@@ -119,14 +135,10 @@ const rules = ref({
|
||||
function openDialog(row: any = {}) {
|
||||
if (row.id) {
|
||||
isAdd.value = false;
|
||||
entity.value = {
|
||||
...defaultEntity,
|
||||
...row,
|
||||
options: { ...defaultEntity.options, ...row.options },
|
||||
};
|
||||
entity.value = normalizeEntity(row);
|
||||
} else {
|
||||
isAdd.value = true;
|
||||
entity.value = { ...defaultEntity };
|
||||
entity.value = normalizeEntity(defaultEntity);
|
||||
}
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
@@ -136,6 +148,11 @@ async function save() {
|
||||
const valid = await saveForm.value?.validate();
|
||||
if (!valid) return;
|
||||
|
||||
if (!entity.value.options) {
|
||||
entity.value.options = {};
|
||||
}
|
||||
entity.value.options.rerankEnable = !!entity.value.options.rerankEnable;
|
||||
|
||||
btnLoading.value = true;
|
||||
const res = await api.post(
|
||||
isAdd.value
|
||||
@@ -162,7 +179,7 @@ async function save() {
|
||||
function closeDialog() {
|
||||
saveForm.value?.resetFields();
|
||||
isAdd.value = true;
|
||||
entity.value = { ...defaultEntity };
|
||||
entity.value = normalizeEntity(defaultEntity);
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
|
||||
@@ -339,12 +356,19 @@ defineExpose({
|
||||
type="number"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="options.rerankEnable"
|
||||
:label="$t('documentCollection.rerankEnable')"
|
||||
>
|
||||
<ElSwitch v-model="entity.options.rerankEnable" />
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="rerankModelId"
|
||||
:label="$t('documentCollection.rerankLlmId')"
|
||||
>
|
||||
<ElSelect
|
||||
v-model="entity.rerankModelId"
|
||||
clearable
|
||||
:placeholder="$t('documentCollection.placeholder.rerankLlm')"
|
||||
>
|
||||
<ElOption
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
|
||||
import { $t } from '@easyflow/locales';
|
||||
import {$t} from '@easyflow/locales';
|
||||
|
||||
import { InfoFilled } from '@element-plus/icons-vue';
|
||||
import {InfoFilled} from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElForm,
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
ElTooltip,
|
||||
} from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import {api} from '#/api/request';
|
||||
|
||||
const props = defineProps({
|
||||
documentCollectionId: {
|
||||
@@ -29,18 +29,21 @@ onMounted(() => {
|
||||
getDocumentCollectionConfig();
|
||||
});
|
||||
const searchEngineEnable = ref(false);
|
||||
const baseOptions = ref<Record<string, any>>({});
|
||||
const getDocumentCollectionConfig = () => {
|
||||
api
|
||||
.get(`/api/v1/documentCollection/detail?id=${props.documentCollectionId}`)
|
||||
.then((res) => {
|
||||
const { data } = res;
|
||||
searchConfig.docRecallMaxNum = data.options.docRecallMaxNum
|
||||
? Number(data.options.docRecallMaxNum)
|
||||
const options = data.options || {};
|
||||
baseOptions.value = { ...options };
|
||||
searchConfig.docRecallMaxNum = options.docRecallMaxNum
|
||||
? Number(options.docRecallMaxNum)
|
||||
: 5;
|
||||
searchConfig.simThreshold = data.options.simThreshold
|
||||
? Number(data.options.simThreshold)
|
||||
searchConfig.simThreshold = options.simThreshold
|
||||
? Number(options.simThreshold)
|
||||
: 0.5;
|
||||
searchConfig.searchEngineType = data.options.searchEngineType || 'lucene';
|
||||
searchConfig.searchEngineType = options.searchEngineType || 'lucene';
|
||||
searchEngineEnable.value = !!data.searchEngineEnable;
|
||||
});
|
||||
};
|
||||
@@ -55,6 +58,7 @@ const submitConfig = () => {
|
||||
const submitData = {
|
||||
id: props.documentCollectionId,
|
||||
options: {
|
||||
...baseOptions.value,
|
||||
docRecallMaxNum: searchConfig.docRecallMaxNum,
|
||||
simThreshold: searchConfig.simThreshold,
|
||||
searchEngineType: searchConfig.searchEngineType,
|
||||
@@ -65,6 +69,7 @@ const submitConfig = () => {
|
||||
api
|
||||
.post('/api/v1/documentCollection/update', submitData)
|
||||
.then(() => {
|
||||
baseOptions.value = { ...submitData.options };
|
||||
ElMessage.success($t('documentCollectionSearch.message.saveSuccess'));
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
Reference in New Issue
Block a user