diff --git a/server/routers/evaluation_router.py b/server/routers/evaluation_router.py index 913eb7b6..6036e1e3 100644 --- a/server/routers/evaluation_router.py +++ b/server/routers/evaluation_router.py @@ -149,7 +149,7 @@ async def run_evaluation(db_id: str, params: dict = Body(...), current_user: Use task_id = await service.run_evaluation( db_id=db_id, benchmark_id=params.get("benchmark_id"), - retrieval_config=params.get("retrieval_config", {}), + model_config=params.get("model_config", {}), created_by=current_user.user_id, ) return {"message": "success", "data": {"task_id": task_id}} diff --git a/server/routers/knowledge_router.py b/server/routers/knowledge_router.py index e579f204..2ccc83aa 100644 --- a/server/routers/knowledge_router.py +++ b/server/routers/knowledge_router.py @@ -702,13 +702,20 @@ async def update_knowledge_base_query_params( if db_id not in knowledge_base.global_databases_meta: knowledge_base.global_databases_meta[db_id] = {} - # 保存查询参数到元数据 + # 初始化 query_params 结构 if "query_params" not in knowledge_base.global_databases_meta[db_id]: knowledge_base.global_databases_meta[db_id]["query_params"] = {} - knowledge_base.global_databases_meta[db_id]["query_params"].update(params) + # 将参数保存到 options 下,与评估服务期望的结构一致 + if "options" not in knowledge_base.global_databases_meta[db_id]["query_params"]: + knowledge_base.global_databases_meta[db_id]["query_params"]["options"] = {} + + # 更新 options + knowledge_base.global_databases_meta[db_id]["query_params"]["options"].update(params) knowledge_base._save_global_metadata() + logger.info(f"更新知识库 {db_id} 查询参数: {params}") + return {"message": "success", "data": params} except Exception as e: @@ -926,6 +933,22 @@ async def get_knowledge_base_query_params(db_id: str, current_user: User = Depen ], } + # 获取用户保存的配置 + saved_options = {} + try: + if db_id in knowledge_base.global_databases_meta: + query_params_meta = knowledge_base.global_databases_meta[db_id].get("query_params", {}) + saved_options = query_params_meta.get("options", {}) + except Exception as saved_error: + logger.warning(f"获取保存的配置失败: {saved_error}") + + # 将保存的值合并到默认配置中 + if saved_options: + for option in params.get("options", []): + key = option.get("key") + if key in saved_options: + option["default"] = saved_options[key] + return {"params": params, "message": "success"} except Exception as e: diff --git a/src/services/evaluation_service.py b/src/services/evaluation_service.py index 0ba5eb2b..ea0c0a36 100644 --- a/src/services/evaluation_service.py +++ b/src/services/evaluation_service.py @@ -241,7 +241,7 @@ class EvaluationService: raise NotImplementedError("自动生成基准功能暂时不可用,请手动上传基准文件。") async def run_evaluation( - self, db_id: str, benchmark_id: str, retrieval_config: dict[str, Any], created_by: str + self, db_id: str, benchmark_id: str, model_config: dict[str, Any] = None, created_by: str = "system" ) -> str: """运行RAG评估""" try: @@ -253,6 +253,21 @@ class EvaluationService: with open(meta_file_path, encoding="utf-8") as f: benchmark_meta = json.load(f) + # 从知识库元数据中获取检索配置 + retrieval_config = {} + try: + kb_meta = knowledge_base.global_databases_meta.get(db_id, {}) + query_params = kb_meta.get("query_params", {}) + retrieval_config = query_params.get("options", {}) + logger.info(f"从知识库 {db_id} 加载检索配置: {list(retrieval_config.keys())}") + except Exception as e: + logger.error(f"获取知识库检索配置失败: {e}") + # 使用空配置作为默认值 + + # 合并前端传递的模型配置 + if model_config: + retrieval_config.update(model_config) + # 初始化结果文件 (Status: running) result_dir = self._get_result_dir(db_id) result_file_path = os.path.join(result_dir, f"{task_id}.json") @@ -581,6 +596,8 @@ class EvaluationService: "total_questions": data.get("total_questions"), "completed_questions": data.get("completed_questions"), "overall_score": data.get("overall_score"), + # 包含检索配置 + "retrieval_config": data.get("retrieval_config", {}), # 也可以带上部分 metrics 摘要 "metrics": data.get("metrics"), } diff --git a/web/src/apis/knowledge_api.js b/web/src/apis/knowledge_api.js index 195fd736..2894e6d0 100644 --- a/web/src/apis/knowledge_api.js +++ b/web/src/apis/knowledge_api.js @@ -390,7 +390,7 @@ export const evaluationApi = { return apiAdminPost(`/api/evaluation/databases/${dbId}/run`, params) }, - + /** * 获取评估结果 * @param {string} taskId - 任务ID diff --git a/web/src/components/RAGEvaluationTab.vue b/web/src/components/RAGEvaluationTab.vue index 4efd301a..6c8def84 100644 --- a/web/src/components/RAGEvaluationTab.vue +++ b/web/src/components/RAGEvaluationTab.vue @@ -183,6 +183,13 @@ + + +
+
{{ JSON.stringify(selectedResult.retrieval_config, null, 2) }}
+
+
+

整体评估报告

@@ -417,22 +424,10 @@ const startEvaluation = async () => { startingEvaluation.value = true; - // 获取检索配置 - let retrievalConfig = {}; - try { - const savedConfig = localStorage.getItem(`search-config-${props.databaseId}`); - if (savedConfig) { - retrievalConfig = JSON.parse(savedConfig); - } - } catch (error) { - console.error('获取检索配置失败:', error); - } - - // 合并配置,优先使用评估页面的模型配置 + // 只传递模型配置,检索配置由服务器从知识库读取 const params = { benchmark_id: selectedBenchmark.value.benchmark_id, - retrieval_config: { - ...retrievalConfig, // 包含所有检索参数如 top_k, similarity_threshold 等 + model_config: { answer_llm: configForm.answer_llm, // 传递答案生成模型 judge_llm: configForm.judge_llm // 传递评判模型 } @@ -544,9 +539,15 @@ const viewResults = async (taskId) => { completed_at: resultData.completed_at, total_questions: resultData.total_questions || 0, completed_questions: resultData.completed_questions || 0, - overall_score: resultData.overall_score + overall_score: resultData.overall_score, + retrieval_config: resultData.retrieval_config }; + // 如果是从历史记录获取的,确保也有 retrieval_config + if (selectedResult.value && !selectedResult.value.retrieval_config) { + selectedResult.value.retrieval_config = resultData.retrieval_config; + } + // 计算总耗时 if (resultData.started_at && resultData.completed_at) { const startTime = new Date(resultData.started_at); @@ -705,6 +706,7 @@ const formatDuration = (seconds) => { } }; + // 组件挂载时加载数据 onMounted(() => { loadBenchmarks(); @@ -1137,4 +1139,25 @@ onMounted(() => { } } +// JSON 查看器样式 +.json-viewer-container { + max-height: 400px; + overflow: auto; + + .json-viewer { + margin: 0; + padding: 0; + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Menlo', monospace; + font-size: 13px; + line-height: 1.5; + color: var(--gray-800); + white-space: pre-wrap; + word-wrap: break-word; + background: var(--gray-50); + border: 1px solid var(--gray-200); + border-radius: 6px; + padding: 12px; + } +} + \ No newline at end of file diff --git a/web/src/components/SearchConfigTab.vue b/web/src/components/SearchConfigTab.vue index 23356a52..40ee6d33 100644 --- a/web/src/components/SearchConfigTab.vue +++ b/web/src/components/SearchConfigTab.vue @@ -197,21 +197,19 @@ const saveConfig = async () => { // 确保 include_distances 始终为 true meta['include_distances'] = true; - // 保存到 localStorage(兼容性) - localStorage.setItem(`search-config-${props.databaseId}`, JSON.stringify(meta)); - - // 保存到知识库元数据 + // 先保存到知识库元数据 try { - const { knowledgeApi } = await import('@/apis/knowledge_api'); - const response = await knowledgeApi.updateKnowledgeBaseQueryParams(props.databaseId, meta); + const response = await queryApi.updateKnowledgeBaseQueryParams(props.databaseId, meta); if (response.message === 'success') { - message.success('配置已保存到知识库'); + // 服务器保存成功后,再保存到 localStorage(兼容性) + localStorage.setItem(`search-config-${props.databaseId}`, JSON.stringify(meta)); + message.success('配置已保存'); } else { - message.warning('配置已保存到本地,但同步到知识库失败'); + throw new Error(response.message || '保存失败'); } } catch (error) { console.error('保存配置到知识库失败:', error); - message.warning('配置已保存到本地,但同步到知识库失败'); + message.error('保存配置失败:' + error.message); } // 更新 store 中的配置