refactor(eval): 重构检索配置为弹窗并优化评估界面
- 将检索配置从标签页改为弹窗形式 - 在查询区和评估区添加检索配置入口 - 优化评估历史记录显示和刷新功能 - 移除不再需要的组件和样式
This commit is contained in:
parent
e5a06405ba
commit
6d3bef49dc
@ -16,16 +16,13 @@
|
||||
- conversation 待修改为异步的版本
|
||||
- DBManager 需要将数据库修改为异步的aiosqlite或者异步mysql,缓存使用Redis存储
|
||||
- 【eval】缺少自动生成评估的功能
|
||||
- chat_model 的 call 需要异步
|
||||
|
||||
### Bugs
|
||||
- 部分异常状态下,智能体的模型名称出现重叠[#279](https://github.com/xerrors/Yuxi-Know/issues/279)
|
||||
- DeepSeek 官方接口适配会出现问题
|
||||
- 目前的知识库的图片存在公开访问风险
|
||||
- 深度分析智能体需要考虑上下文超限的问题
|
||||
- 【eval】检索评估缺少检索参数的内容
|
||||
- 【eval】总体评分替换为确定的某个指标,最好是在右侧可以选择可行的指标
|
||||
- 【eval】检索配置应该修改为一个弹窗
|
||||
- 【eval】当前的检索配置仅保存在本地,实际并没有保存在知识库的元数据中
|
||||
|
||||
### 新增
|
||||
- 优化知识库详情页面,更加简洁清晰
|
||||
|
||||
@ -1,15 +1,5 @@
|
||||
<template>
|
||||
<div class="mindmap-section">
|
||||
<div class="section-header">
|
||||
<div class="header-left">
|
||||
<BrainCircuit :size="16" />
|
||||
<span>知识导图</span>
|
||||
<a-tag v-if="!loading && mindmapData" color="blue" size="small">
|
||||
已生成
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-content">
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="loading" class="loading-state">
|
||||
@ -65,7 +55,6 @@
|
||||
import { ref, watch, nextTick, onMounted, onUnmounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import {
|
||||
BrainCircuit,
|
||||
RefreshCw,
|
||||
Network,
|
||||
Sparkles,
|
||||
@ -315,21 +304,6 @@ onUnmounted(() => {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
padding: 10px 16px;
|
||||
background: var(--gray-25);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.section-content {
|
||||
flex: 1;
|
||||
min-height: 200px;
|
||||
@ -374,7 +348,7 @@ onUnmounted(() => {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
justify-content: flex-end;
|
||||
|
||||
.toolbar-text {
|
||||
margin-left: 4px;
|
||||
@ -382,7 +356,6 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
:deep(.ant-btn-text) {
|
||||
padding: 4px 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
|
||||
@ -14,6 +14,17 @@
|
||||
/>
|
||||
<div class="search-actions">
|
||||
<div class="query-examples-compact">
|
||||
<!-- 检索配置按钮 -->
|
||||
<a-tooltip title="检索配置" placement="bottom">
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="config-label-btn"
|
||||
@click="openSearchConfigModal"
|
||||
>
|
||||
<SettingOutlined />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<div class="examples-label-group">
|
||||
<a-tooltip title="点击手动生成测试问题" placement="bottom">
|
||||
<a-button
|
||||
@ -138,6 +149,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 检索配置弹窗 -->
|
||||
<SearchConfigModal
|
||||
v-model="searchConfigModalVisible"
|
||||
:database-id="store.database?.db_id"
|
||||
@save="handleSearchConfigSave"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -148,7 +166,9 @@ import { queryApi } from '@/apis/knowledge_api';
|
||||
import {
|
||||
SearchOutlined,
|
||||
ReloadOutlined,
|
||||
SettingOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import SearchConfigModal from './SearchConfigModal.vue';
|
||||
|
||||
const store = useDatabaseStore();
|
||||
|
||||
@ -175,10 +195,24 @@ const queryExamples = ref([]);
|
||||
const currentExampleIndex = ref(0);
|
||||
const loadingQuestions = ref(false);
|
||||
const generatingQuestions = ref(false);
|
||||
const searchConfigModalVisible = ref(false);
|
||||
|
||||
// 示例轮播相关
|
||||
let exampleCarouselInterval = null;
|
||||
|
||||
// 方法定义
|
||||
|
||||
// 打开检索配置弹窗
|
||||
const openSearchConfigModal = () => {
|
||||
searchConfigModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 处理检索配置保存
|
||||
const handleSearchConfigSave = (config) => {
|
||||
console.log('查询测试中的检索配置已更新:', config);
|
||||
// 可以在这里添加配置更新后的处理逻辑,比如重新查询
|
||||
};
|
||||
|
||||
// 加载示例问题
|
||||
const loadSampleQuestions = async () => {
|
||||
if (!store.database?.db_id) return;
|
||||
@ -595,12 +629,31 @@ defineExpose({
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.config-label-btn {
|
||||
color: var(--gray-500);
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
margin-left: -4px;
|
||||
|
||||
&:hover {
|
||||
color: var(--main-color);
|
||||
background-color: var(--gray-100);
|
||||
}
|
||||
|
||||
.anticon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.examples-label-btn {
|
||||
color: var(--gray-500);
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: -8px;
|
||||
margin-right: -6px;
|
||||
|
||||
&:hover {
|
||||
color: var(--main-color);
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<a-select
|
||||
v-model:value="selectedBenchmarkId"
|
||||
placeholder="请选择评估基准"
|
||||
style="width: 300px"
|
||||
style="width: 180px"
|
||||
@change="onBenchmarkChanged"
|
||||
:loading="benchmarksLoading"
|
||||
>
|
||||
@ -22,8 +22,15 @@
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<!-- 检索配置按钮 -->
|
||||
<a-button
|
||||
size="middle"
|
||||
@click="openSearchConfigModal"
|
||||
:icon="h(SettingOutlined)"
|
||||
/>
|
||||
<!-- 开始评估按钮 -->
|
||||
<a-button
|
||||
type="primary"
|
||||
@ -84,10 +91,22 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
|
||||
<!-- 历史评估记录 -->
|
||||
<div class="history-section">
|
||||
<h4 class="section-title">历史评估记录</h4>
|
||||
<div class="section-header">
|
||||
<h4 class="section-title">历史评估记录</h4>
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
:loading="refreshingHistory"
|
||||
@click="refreshHistory"
|
||||
:icon="h('ReloadOutlined')"
|
||||
class="refresh-btn"
|
||||
>
|
||||
刷新
|
||||
</a-button>
|
||||
</div>
|
||||
<a-table
|
||||
class="history-table"
|
||||
:columns="historyColumns"
|
||||
@ -242,9 +261,9 @@
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'retrieval_score'">
|
||||
<div v-if="record.metrics && Object.keys(record.metrics).some(k => k.startsWith('recall') || k.startsWith('f1') || k.startsWith('precision') || k === 'map' || k === 'ndcg')" class="retrieval-metrics">
|
||||
<div v-if="record.metrics && Object.keys(record.metrics).some(k => k.startsWith('recall') || k.startsWith('precision') || k === 'map' || k === 'ndcg')" class="retrieval-metrics">
|
||||
<div v-for="(val, key) in record.metrics" :key="key" class="metric-item">
|
||||
<span v-if="key.startsWith('recall') || key.startsWith('f1') || key.startsWith('precision') || key === 'map' || key === 'ndcg'"
|
||||
<span v-if="key.startsWith('recall') || key.startsWith('precision') || key === 'map' || key === 'ndcg'"
|
||||
class="metric-content"
|
||||
:class="`metric-${getMetricType(key)}`">
|
||||
<span class="metric-name">{{ getMetricShortName(key) }}</span>
|
||||
@ -277,13 +296,22 @@
|
||||
</a-empty>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 检索配置弹窗 -->
|
||||
<SearchConfigModal
|
||||
v-model="searchConfigModalVisible"
|
||||
:database-id="databaseId"
|
||||
@save="handleSearchConfigSave"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { ref, reactive, onMounted, computed, h } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { evaluationApi } from '@/apis/knowledge_api';
|
||||
import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue';
|
||||
import SearchConfigModal from './SearchConfigModal.vue';
|
||||
import { SettingOutlined, ReloadOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const props = defineProps({
|
||||
databaseId: {
|
||||
@ -306,6 +334,9 @@ const selectedResult = ref(null);
|
||||
const detailedResults = ref([]);
|
||||
const evaluationStats = ref({});
|
||||
const resultsLoading = ref(false);
|
||||
const searchConfigModalVisible = ref(false);
|
||||
const refreshingHistory = ref(false);
|
||||
|
||||
|
||||
// 评估配置表单(使用知识库默认配置)
|
||||
const configForm = reactive({
|
||||
@ -358,10 +389,36 @@ const historyColumns = [
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '总体评分',
|
||||
dataIndex: 'overall_score',
|
||||
key: 'overall_score',
|
||||
width: 100
|
||||
title: 'Recall@10',
|
||||
key: 'recall_10',
|
||||
width: 100,
|
||||
customRender: ({ record }) => {
|
||||
// 使用后端返回的 metrics.recall@10 数据
|
||||
if (record.metrics && record.metrics['recall@10'] !== undefined && record.metrics['recall@10'] !== null) {
|
||||
const recallValue = record.metrics['recall@10'];
|
||||
const displayValue = formatMetricValue(recallValue);
|
||||
return h('a-tag', {
|
||||
color: getScoreTagColor(recallValue)
|
||||
}, displayValue);
|
||||
}
|
||||
|
||||
// 如果是运行中的任务,显示计算中
|
||||
if (record.status === 'running') {
|
||||
return h('a-tag', {
|
||||
color: 'processing'
|
||||
}, '计算中');
|
||||
}
|
||||
|
||||
// 已完成但没有 recall@10 数据
|
||||
if (record.status === 'completed') {
|
||||
return h('a-tag', {
|
||||
color: 'default'
|
||||
}, '无数据');
|
||||
}
|
||||
|
||||
// 其他情况显示横线
|
||||
return h('span', '-');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
@ -378,6 +435,17 @@ const currentBenchmark = computed(() => {
|
||||
return availableBenchmarks.value.find(b => b.benchmark_id === selectedBenchmarkId.value);
|
||||
});
|
||||
|
||||
// 打开检索配置弹窗
|
||||
const openSearchConfigModal = () => {
|
||||
searchConfigModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 处理检索配置保存
|
||||
const handleSearchConfigSave = (config) => {
|
||||
console.log('RAG评估中的检索配置已更新:', config);
|
||||
// 可以在这里添加配置更新后的处理逻辑
|
||||
};
|
||||
|
||||
// 加载基准列表
|
||||
const loadBenchmarks = async () => {
|
||||
if (!props.databaseId) return;
|
||||
@ -389,12 +457,19 @@ const loadBenchmarks = async () => {
|
||||
if (response && response.message === 'success' && Array.isArray(response.data)) {
|
||||
availableBenchmarks.value = response.data;
|
||||
|
||||
// 如果之前有选中的基准,重新验证其有效性
|
||||
if (selectedBenchmarkId.value) {
|
||||
// 如果没有选中的基准,且有可用基准,默认选中第一个
|
||||
if (!selectedBenchmarkId.value && response.data.length > 0) {
|
||||
selectedBenchmarkId.value = response.data[0].benchmark_id;
|
||||
selectedBenchmark.value = response.data[0];
|
||||
} else if (selectedBenchmarkId.value) {
|
||||
// 如果之前有选中的基准,重新验证其有效性
|
||||
const exists = response.data.some(b => b.benchmark_id === selectedBenchmarkId.value);
|
||||
if (!exists) {
|
||||
selectedBenchmarkId.value = null;
|
||||
selectedBenchmark.value = null;
|
||||
} else {
|
||||
// 更新选中的基准对象
|
||||
selectedBenchmark.value = response.data.find(b => b.benchmark_id === selectedBenchmarkId.value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -415,6 +490,21 @@ const onBenchmarkChanged = (benchmarkId) => {
|
||||
selectedBenchmark.value = benchmark || null;
|
||||
};
|
||||
|
||||
// 刷新历史评估记录
|
||||
const refreshHistory = async () => {
|
||||
refreshingHistory.value = true;
|
||||
try {
|
||||
await loadEvaluationHistory();
|
||||
message.success('历史记录已刷新');
|
||||
} catch (error) {
|
||||
console.error('刷新历史记录失败:', error);
|
||||
message.error('刷新历史记录失败');
|
||||
} finally {
|
||||
refreshingHistory.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 开始评估
|
||||
const startEvaluation = async () => {
|
||||
if (!selectedBenchmark.value) {
|
||||
@ -464,6 +554,7 @@ const loadEvaluationHistory = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 计算评估统计信息
|
||||
const calculateEvaluationStats = (results) => {
|
||||
if (!results || results.length === 0) {
|
||||
@ -493,7 +584,7 @@ const calculateEvaluationStats = (results) => {
|
||||
// 检索指标统计
|
||||
if (item.metrics) {
|
||||
Object.keys(item.metrics).forEach(key => {
|
||||
if (key.startsWith('recall') || key.startsWith('f1') || key.startsWith('precision') || key === 'map' || key === 'ndcg') {
|
||||
if (key.startsWith('recall') || key.startsWith('precision') || key === 'map' || key === 'ndcg') {
|
||||
if (!metricSums[key]) {
|
||||
metricSums[key] = 0;
|
||||
metricCounts[key] = 0;
|
||||
@ -643,7 +734,6 @@ const getMetricTitle = (key) => {
|
||||
const titles = {
|
||||
precision: '精确率',
|
||||
recall: '召回率',
|
||||
f1: 'F1分数',
|
||||
map: '平均精度',
|
||||
ndcg: 'NDCG',
|
||||
bleu: 'BLEU分数',
|
||||
@ -653,9 +743,8 @@ const getMetricTitle = (key) => {
|
||||
reasoning: '理由',
|
||||
overall_score: '综合评分'
|
||||
};
|
||||
// 处理 recall@k, f1@k
|
||||
// 处理 recall@k
|
||||
if (key.startsWith('recall@')) return `召回率 (${key.split('@')[1]})`;
|
||||
if (key.startsWith('f1@')) return `F1 (${key.split('@')[1]})`;
|
||||
if (key.startsWith('precision@')) return `精确率 (${key.split('@')[1]})`;
|
||||
|
||||
return titles[key] || key;
|
||||
@ -665,7 +754,6 @@ const getMetricTitle = (key) => {
|
||||
const getMetricType = (key) => {
|
||||
if (key.startsWith('recall')) return 'recall';
|
||||
if (key.startsWith('precision')) return 'precision';
|
||||
if (key.startsWith('f1')) return 'f1';
|
||||
if (key === 'map') return 'map';
|
||||
if (key === 'ndcg') return 'ndcg';
|
||||
return 'default';
|
||||
@ -675,10 +763,8 @@ const getMetricType = (key) => {
|
||||
const getMetricShortName = (key) => {
|
||||
if (key.startsWith('recall@')) return `R@${key.split('@')[1]}`;
|
||||
if (key.startsWith('precision@')) return `P@${key.split('@')[1]}`;
|
||||
if (key.startsWith('f1@')) return `F1@${key.split('@')[1]}`;
|
||||
if (key === 'precision') return 'Precision';
|
||||
if (key === 'recall') return 'Recall';
|
||||
if (key === 'f1') return 'F1';
|
||||
if (key === 'map') return 'MAP';
|
||||
if (key === 'ndcg') return 'NDCG';
|
||||
return key;
|
||||
@ -753,12 +839,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.toolbar-right {
|
||||
.ant-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1006,10 +1089,6 @@ onMounted(() => {
|
||||
color: var(--color-success-900);
|
||||
}
|
||||
|
||||
&.metric-f1 {
|
||||
background-color: var(--color-warning-50);
|
||||
color: var(--color-warning-900);
|
||||
}
|
||||
|
||||
&.metric-map,
|
||||
&.metric-ndcg {
|
||||
@ -1128,12 +1207,43 @@ onMounted(() => {
|
||||
|
||||
// 历史评估记录区域
|
||||
.history-section {
|
||||
.section-title {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--gray-700);
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.section-title {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--gray-700);
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
color: var(--gray-600);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 4px 8px;
|
||||
height: auto;
|
||||
font-size: 13px;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary-600);
|
||||
background-color: var(--color-primary-50);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--color-primary-700);
|
||||
background-color: var(--color-primary-100);
|
||||
}
|
||||
|
||||
.anticon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-table) {
|
||||
border: 1px solid var(--gray-100);
|
||||
}
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
<template>
|
||||
<div class="search-config-tab">
|
||||
<div class="config-header">
|
||||
<p class="config-title">检索配置</p>
|
||||
<div class="config-actions">
|
||||
<a-button size="small" @click="resetToDefaults">重置默认</a-button>
|
||||
<a-button size="small" type="primary" @click="saveConfig">保存配置</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="config-content">
|
||||
<a-modal
|
||||
:open="props.modelValue"
|
||||
title="检索配置"
|
||||
width="800px"
|
||||
:confirm-loading="loading"
|
||||
@ok="handleSave"
|
||||
@cancel="handleCancel"
|
||||
ok-text="保存"
|
||||
cancel-text="取消"
|
||||
>
|
||||
<div class="search-config-modal">
|
||||
<div v-if="loading" class="config-loading">
|
||||
<a-spin size="large" />
|
||||
<p>加载配置参数中...</p>
|
||||
@ -66,22 +67,28 @@
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { useDatabaseStore } from '@/stores/database';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { queryApi } from '@/apis/knowledge_api';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
databaseId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'save']);
|
||||
|
||||
const store = useDatabaseStore();
|
||||
|
||||
// 响应式数据
|
||||
@ -193,7 +200,7 @@ const resetToDefaults = () => {
|
||||
};
|
||||
|
||||
// 保存配置
|
||||
const saveConfig = async () => {
|
||||
const handleSave = async () => {
|
||||
// 确保 include_distances 始终为 true
|
||||
meta['include_distances'] = true;
|
||||
|
||||
@ -204,6 +211,13 @@ const saveConfig = async () => {
|
||||
// 服务器保存成功后,再保存到 localStorage(兼容性)
|
||||
localStorage.setItem(`search-config-${props.databaseId}`, JSON.stringify(meta));
|
||||
message.success('配置已保存');
|
||||
|
||||
// 更新 store 中的配置
|
||||
Object.assign(store.meta, meta);
|
||||
|
||||
// 触发保存事件
|
||||
emit('save', { ...meta });
|
||||
emit('update:modelValue', false);
|
||||
} else {
|
||||
throw new Error(response.message || '保存失败');
|
||||
}
|
||||
@ -211,49 +225,22 @@ const saveConfig = async () => {
|
||||
console.error('保存配置到知识库失败:', error);
|
||||
message.error('保存配置失败:' + error.message);
|
||||
}
|
||||
|
||||
// 更新 store 中的配置
|
||||
Object.assign(store.meta, meta);
|
||||
};
|
||||
|
||||
// 组件挂载时加载数据
|
||||
onMounted(() => {
|
||||
loadQueryParams();
|
||||
// 处理取消
|
||||
const handleCancel = () => {
|
||||
emit('update:modelValue', false);
|
||||
};
|
||||
|
||||
// 监听弹窗显示状态,显示时加载数据
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal && props.databaseId) {
|
||||
loadQueryParams();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.search-config-tab {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--gray-0);
|
||||
}
|
||||
|
||||
.config-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
// border-bottom: 1px solid var(--gray-200);
|
||||
flex-shrink: 0;
|
||||
|
||||
.config-title {
|
||||
margin: 0;
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.config-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.config-content {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.config-loading,
|
||||
.config-error {
|
||||
@ -261,7 +248,7 @@ onMounted(() => {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
height: 300px;
|
||||
color: var(--gray-500);
|
||||
|
||||
p {
|
||||
@ -271,10 +258,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.config-forms {
|
||||
max-width: 800px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
// 表单样式优化
|
||||
:deep(.ant-form-item) {
|
||||
margin-bottom: 16px;
|
||||
@ -41,9 +41,6 @@
|
||||
ref="mindmapSectionRef"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="config" tab="检索配置">
|
||||
<SearchConfigTab :database-id="databaseId" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="evaluation" tab="RAG评估(Beta)">
|
||||
<RAGEvaluationTab
|
||||
v-if="databaseId"
|
||||
@ -84,7 +81,6 @@ import FileDetailModal from '@/components/FileDetailModal.vue';
|
||||
import FileUploadModal from '@/components/FileUploadModal.vue';
|
||||
import KnowledgeGraphSection from '@/components/KnowledgeGraphSection.vue';
|
||||
import QuerySection from '@/components/QuerySection.vue';
|
||||
import SearchConfigTab from '@/components/SearchConfigTab.vue';
|
||||
import MindMapSection from '@/components/MindMapSection.vue';
|
||||
import RAGEvaluationTab from '@/components/RAGEvaluationTab.vue';
|
||||
import EvaluationBenchmarks from '@/components/EvaluationBenchmarks.vue';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user