feat(evaluation): 改进RAG评估功能并优化UI布局
- 添加json-repair依赖以增强JSON解析容错能力 - 移除评估标签中的Beta标识,提升用户体验 - 增加评估问题生成的最大尝试次数 - 优化评估结果页面布局,将检索配置和评估报告并排显示 - 添加任务中心状态同步功能 - 改进指标显示样式和间距
This commit is contained in:
parent
9032848450
commit
e6cfb16429
@ -62,6 +62,7 @@ dependencies = [
|
||||
"aiofiles>=24.1.0",
|
||||
"aiohttp>=3.9.0",
|
||||
"deepagents>=0.2.5",
|
||||
"json-repair>=0.54.0",
|
||||
]
|
||||
[tool.ruff]
|
||||
line-length = 120 # 代码最大行宽
|
||||
|
||||
@ -287,7 +287,9 @@ class EvaluationService:
|
||||
await context.set_progress(25, "生成样本")
|
||||
|
||||
with open(data_file_path, "w", encoding="utf-8") as f:
|
||||
while generated < count and attempts < count * 2:
|
||||
# Allow more attempts to generate enough questions
|
||||
max_attempts = max(count * 5, 50)
|
||||
while generated < count and attempts < max_attempts:
|
||||
attempts += 1
|
||||
i0 = random.randrange(len(all_chunks))
|
||||
e0 = embeddings[i0]
|
||||
@ -320,20 +322,27 @@ class EvaluationService:
|
||||
try:
|
||||
resp = await asyncio.to_thread(llm.call, prompt, False)
|
||||
content = resp.content if resp else ""
|
||||
obj = json.loads(content)
|
||||
|
||||
import json_repair
|
||||
obj = json_repair.loads(content)
|
||||
q = obj.get("query")
|
||||
a = obj.get("gold_answer")
|
||||
gids = obj.get("gold_chunk_ids")
|
||||
if not q or not a or not isinstance(gids, list):
|
||||
logger.warning(f"Generated JSON missing fields or invalid format: {obj}")
|
||||
continue
|
||||
|
||||
gids = [str(x) for x in gids if str(x) in allowed_ids]
|
||||
if not gids:
|
||||
logger.warning("Generated gold_chunk_ids not found in allowed context")
|
||||
continue
|
||||
|
||||
line = {"query": q, "gold_chunk_ids": gids, "gold_answer": a}
|
||||
f.write(json.dumps(line, ensure_ascii=False) + "\n")
|
||||
generated += 1
|
||||
await context.set_progress(0 + int(99 * generated / max(count, 1)), f"已生成 {generated}/{count}")
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.warning(f"Benchmark generation failed for one item: {e}")
|
||||
continue
|
||||
|
||||
meta = {
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<a-select
|
||||
v-model:value="selectedBenchmarkId"
|
||||
placeholder="请选择评估基准"
|
||||
style="width: 180px"
|
||||
style="width: 240px"
|
||||
@change="onBenchmarkChanged"
|
||||
:loading="benchmarksLoading"
|
||||
>
|
||||
@ -202,48 +202,53 @@
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<!-- 检索配置 -->
|
||||
<a-card size="small" title="检索配置" style="margin-bottom: 20px" v-if="selectedResult.retrieval_config">
|
||||
<div class="json-viewer-container">
|
||||
<pre class="json-viewer">{{ JSON.stringify(selectedResult.retrieval_config, null, 2) }}</pre>
|
||||
</div>
|
||||
</a-card>
|
||||
<!-- 检索配置和整体评估报告 -->
|
||||
<a-row :gutter="16" style="margin-bottom: 20px">
|
||||
<!-- 检索配置 -->
|
||||
<a-col :span="12" v-if="selectedResult.retrieval_config">
|
||||
<a-card size="small" title="检索配置">
|
||||
<div class="json-viewer-container">
|
||||
<pre class="json-viewer">{{ JSON.stringify(selectedResult.retrieval_config, null, 2) }}</pre>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<!-- 整体评估报告 -->
|
||||
<div class="evaluation-report">
|
||||
<h4 style="margin-bottom: 16px">整体评估报告</h4>
|
||||
<a-row :gutter="[16, 16]">
|
||||
<a-col :span="12">
|
||||
<a-card size="small" title="检索指标">
|
||||
<!-- 整体评估报告 -->
|
||||
<a-col :span="selectedResult.retrieval_config ? 12 : 24">
|
||||
<a-card size="small" title="整体评估报告">
|
||||
<!-- 检索指标 -->
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h5 style="margin-bottom: 12px; font-size: 14px; font-weight: 500;">检索指标</h5>
|
||||
<div v-if="Object.keys(evaluationStats.retrievalMetrics || {}).length > 0">
|
||||
<div v-for="(value, key) in evaluationStats.retrievalMetrics" :key="key" class="report-metric">
|
||||
<span class="metric-label">{{ getMetricTitle(key) }}</span>
|
||||
<span class="metric-label">{{ getMetricTitle(key) }}:</span>
|
||||
<span class="metric-value" :style="{ color: getScoreColor(value) }">
|
||||
{{ formatMetricValue(value) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else class="no-metrics">-</span>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-card size="small" title="答案准确性">
|
||||
</div>
|
||||
|
||||
<!-- 答案准确性 -->
|
||||
<div>
|
||||
<h5 style="margin-bottom: 12px; font-size: 14px; font-weight: 500;">答案准确性</h5>
|
||||
<div class="accuracy-stats">
|
||||
<div class="accuracy-item">
|
||||
<span class="accuracy-label">正确答案数</span>
|
||||
<span class="accuracy-label">正确答案数:</span>
|
||||
<span class="accuracy-value">{{ evaluationStats.correctAnswers || 0 }} / {{ evaluationStats.totalQuestions || 0 }}</span>
|
||||
</div>
|
||||
<div class="accuracy-item">
|
||||
<span class="accuracy-label">准确率</span>
|
||||
<span class="accuracy-label">准确率:</span>
|
||||
<span class="accuracy-value" :style="{ color: getScoreColor(evaluationStats.answerAccuracy) }">
|
||||
{{ (evaluationStats.answerAccuracy * 100).toFixed(1) }}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- 详细结果表格 -->
|
||||
<h4 style="margin-bottom: 16px">详细评估结果</h4>
|
||||
@ -317,6 +322,7 @@ 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';
|
||||
import { useTaskerStore } from '@/stores/tasker';
|
||||
|
||||
const props = defineProps({
|
||||
databaseId: {
|
||||
@ -327,6 +333,9 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['switch-to-benchmarks']);
|
||||
|
||||
// 使用任务中心 store
|
||||
const taskerStore = useTaskerStore();
|
||||
|
||||
// 状态
|
||||
const selectedBenchmarkId = ref(null);
|
||||
const selectedBenchmark = ref(null);
|
||||
@ -539,6 +548,8 @@ const startEvaluation = async () => {
|
||||
if (response.message === 'success') {
|
||||
message.success('评估任务已开始');
|
||||
loadEvaluationHistory();
|
||||
// 刷新任务中心的任务列表
|
||||
taskerStore.loadTasks();
|
||||
} else {
|
||||
message.error(response.message || '启动评估失败');
|
||||
}
|
||||
@ -1178,6 +1189,7 @@ onMounted(() => {
|
||||
|
||||
.metric-label {
|
||||
font-size: 14px;
|
||||
padding-right: 18px;
|
||||
color: var(--gray-700);
|
||||
}
|
||||
|
||||
|
||||
@ -42,14 +42,14 @@
|
||||
ref="mindmapSectionRef"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="evaluation" tab="RAG评估(Beta)">
|
||||
<a-tab-pane key="evaluation" tab="RAG评估">
|
||||
<RAGEvaluationTab
|
||||
v-if="databaseId"
|
||||
:database-id="databaseId"
|
||||
@switch-to-benchmarks="activeTab = 'benchmarks'"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="benchmarks" tab="评估基准管理(Beta)">
|
||||
<a-tab-pane key="benchmarks" tab="评估基准">
|
||||
<div class="benchmark-management-container">
|
||||
<div class="benchmark-content">
|
||||
<EvaluationBenchmarks
|
||||
|
||||
Loading…
Reference in New Issue
Block a user