feat: 收敛知识库检索调度与评分语义

- 固定 rag.engine 与 Milvus 配置,补齐启动期检索基础设施校验

- 支持调用方配置 retrievalMode,并统一知识库检索入口与结果来源展示

- 修正关键词检索 knowledgeId 过滤、混合检索评分归一化与本地 ES 默认配置
This commit is contained in:
2026-04-05 20:23:05 +08:00
parent 2592a1f09d
commit b5dd427920
41 changed files with 1260 additions and 600 deletions

View File

@@ -3,20 +3,40 @@ import { ref } from 'vue';
import { $t } from '@easyflow/locales';
import { ElButton, ElInput, ElMessage } from 'element-plus';
import { ElButton, ElInput, ElMessage, ElOption, ElSelect } from 'element-plus';
import { api } from '#/api/request';
import PreviewSearchKnowledge from '#/views/ai/documentCollection/PreviewSearchKnowledge.vue';
type RetrievalMode = 'HYBRID' | 'KEYWORD' | 'VECTOR';
interface SearchResultItem {
sorting: number;
content: string;
score?: number;
hitSource?: 'BOTH' | 'KEYWORD' | 'VECTOR';
vectorScore?: number;
keywordScore?: number;
}
const props = defineProps({
knowledgeId: {
type: String,
required: true,
},
});
const searchDataList = ref([]);
const searchDataList = ref<SearchResultItem[]>([]);
const keyword = ref('');
const retrievalMode = ref<RetrievalMode>('HYBRID');
const previewSearchKnowledgeRef = ref();
const retrievalModeOptions = [
{ label: $t('bot.retrievalModes.hybrid'), value: 'HYBRID' },
{ label: $t('bot.retrievalModes.vector'), value: 'VECTOR' },
{ label: $t('bot.retrievalModes.keyword'), value: 'KEYWORD' },
];
const handleSearch = () => {
if (!keyword.value) {
ElMessage.error($t('message.pleaseInputContent'));
@@ -24,12 +44,22 @@ const handleSearch = () => {
}
previewSearchKnowledgeRef.value.loadingContent(true);
api
.get(
`/api/v1/documentCollection/search?knowledgeId=${props.knowledgeId}&keyword=${keyword.value}`,
)
.get('/api/v1/documentCollection/search', {
params: {
knowledgeId: props.knowledgeId,
keyword: keyword.value,
retrievalMode: retrievalMode.value,
},
})
.then((res) => {
previewSearchKnowledgeRef.value.loadingContent(false);
searchDataList.value = res.data;
})
.catch(() => {
ElMessage.error($t('documentCollection.searchFailed'));
searchDataList.value = [];
})
.finally(() => {
previewSearchKnowledgeRef.value.loadingContent(false);
});
};
</script>
@@ -40,7 +70,16 @@ const handleSearch = () => {
<ElInput
v-model="keyword"
:placeholder="$t('common.searchPlaceholder')"
@keyup.enter="handleSearch"
/>
<ElSelect v-model="retrievalMode" class="retrieval-select">
<ElOption
v-for="item in retrievalModeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</ElSelect>
<ElButton type="primary" @click="handleSearch">
{{ $t('button.query') }}
</ElButton>
@@ -48,6 +87,7 @@ const handleSearch = () => {
<div class="search-result">
<PreviewSearchKnowledge
:data="searchDataList"
:retrieval-mode="retrievalMode"
ref="previewSearchKnowledgeRef"
/>
</div>
@@ -68,6 +108,12 @@ const handleSearch = () => {
justify-content: space-between;
gap: 12px;
}
.retrieval-select {
width: 180px;
flex-shrink: 0;
}
.search-result {
padding-top: 20px;
flex: 1;