ForcePilot/backend/server/routers/evaluation_router.py
Wenjie Zhang 410dd47c14 refactor: 将后端代码迁移至 backend 目录
- 将 server/, src/, scripts/, test/ 等目录移动到 backend/ 目录下
- 使用 git rename 保留文件历史记录
- 更新 docker-compose.yml 和 api.Dockerfile 配置

WIP: 项目结构重构进行中
2026-03-24 11:08:12 +08:00

227 lines
9.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import traceback
from fastapi import APIRouter, HTTPException, Depends, File, Form, Body, UploadFile
from fastapi.responses import FileResponse
from yuxi.storage.postgres.models_business import User
from server.utils.auth_middleware import get_admin_user
from yuxi.utils import logger
# 创建路由器
evaluation = APIRouter(prefix="/evaluation", tags=["evaluation"])
# 移除旧详情接口,统一使用带 db_id 的接口
# ============================================================================
# 评估基准
# ============================================================================
@evaluation.get("/databases/{db_id}/benchmarks/{benchmark_id}")
async def get_evaluation_benchmark_by_db(
db_id: str, benchmark_id: str, page: int = 1, page_size: int = 10, current_user: User = Depends(get_admin_user)
):
"""根据 db_id 获取评估基准详情(支持分页)"""
from yuxi.services.evaluation_service import EvaluationService
try:
# 验证分页参数
if page < 1:
raise HTTPException(status_code=400, detail="页码必须大于0")
if page_size < 1 or page_size > 100:
raise HTTPException(status_code=400, detail="每页大小必须在1-100之间")
service = EvaluationService()
benchmark = await service.get_benchmark_detail_by_db(db_id, benchmark_id, page, page_size)
return {"message": "success", "data": benchmark}
except HTTPException:
raise
except Exception as e:
logger.error(f"获取评估基准详情失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"获取评估基准详情失败: {str(e)}")
@evaluation.delete("/benchmarks/{benchmark_id}")
async def delete_evaluation_benchmark(benchmark_id: str, current_user: User = Depends(get_admin_user)):
"""删除评估基准"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
await service.delete_benchmark(benchmark_id)
return {"message": "success", "data": None}
except Exception as e:
logger.error(f"删除评估基准失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"删除评估基准失败: {str(e)}")
@evaluation.get("/benchmarks/{benchmark_id}/download")
async def download_evaluation_benchmark(benchmark_id: str, current_user: User = Depends(get_admin_user)):
"""下载评估基准文件"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
download_info = await service.get_benchmark_download_info(benchmark_id)
return FileResponse(
path=download_info["file_path"],
filename=download_info["filename"],
media_type="application/x-ndjson",
)
except ValueError as e:
if "not found" in str(e).lower():
raise HTTPException(status_code=404, detail=str(e))
logger.error(f"下载评估基准失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"下载评估基准失败: {str(e)}")
except Exception as e:
logger.error(f"下载评估基准失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"下载评估基准失败: {str(e)}")
@evaluation.get("/databases/{db_id}/results/{task_id}")
async def get_evaluation_results_by_db(
db_id: str,
task_id: str,
page: int = 1,
page_size: int = 20,
error_only: bool = False,
current_user: User = Depends(get_admin_user),
):
"""获取评估结果(带 db_id支持分页"""
from yuxi.services.evaluation_service import EvaluationService
try:
# 验证分页参数
if page < 1:
raise HTTPException(status_code=400, detail="页码必须大于0")
if page_size < 1 or page_size > 100:
raise HTTPException(status_code=400, detail="每页大小必须在1-100之间")
service = EvaluationService()
results = await service.get_evaluation_results_by_db(
db_id, task_id, page=page, page_size=page_size, error_only=error_only
)
return {"message": "success", "data": results}
except Exception as e:
logger.error(f"获取评估结果失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"获取评估结果失败: {str(e)}")
@evaluation.delete("/databases/{db_id}/results/{task_id}")
async def delete_evaluation_result_by_db(db_id: str, task_id: str, current_user: User = Depends(get_admin_user)):
"""删除评估结果(带 db_id"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
await service.delete_evaluation_result_by_db(db_id, task_id)
return {"message": "success", "data": None}
except Exception as e:
logger.error(f"删除评估结果失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"删除评估结果失败: {str(e)}")
# ============================================================================
# RAG评估
# ============================================================================
@evaluation.post("/databases/{db_id}/benchmarks/upload")
async def upload_evaluation_benchmark(
db_id: str,
file: UploadFile = File(...),
name: str = Form(...),
description: str = Form(""),
current_user: User = Depends(get_admin_user),
):
"""上传评估基准文件"""
from yuxi.services.evaluation_service import EvaluationService
try:
# 验证文件格式
if not file.filename.endswith(".jsonl"):
raise HTTPException(status_code=400, detail="仅支持JSONL格式文件")
# 读取文件内容
content = await file.read()
# 调用评估服务处理上传
service = EvaluationService()
result = await service.upload_benchmark(
db_id=db_id,
file_content=content,
filename=file.filename,
name=name,
description=description,
created_by=current_user.user_id,
)
return {"message": "success", "data": result}
except HTTPException:
raise
except Exception as e:
logger.error(f"上传评估基准失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"上传评估基准失败: {str(e)}")
@evaluation.get("/databases/{db_id}/benchmarks")
async def get_evaluation_benchmarks(db_id: str, current_user: User = Depends(get_admin_user)):
"""获取知识库的评估基准列表"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
benchmarks = await service.get_benchmarks(db_id)
return {"message": "success", "data": benchmarks}
except Exception as e:
logger.error(f"获取评估基准列表失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"获取评估基准列表失败: {str(e)}")
@evaluation.post("/databases/{db_id}/benchmarks/generate")
async def generate_evaluation_benchmark(
db_id: str, params: dict = Body(...), current_user: User = Depends(get_admin_user)
):
"""自动生成评估基准"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
result = await service.generate_benchmark(db_id=db_id, params=params, created_by=current_user.user_id)
return {"message": "success", "data": result}
except Exception as e:
logger.error(f"生成评估基准失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"生成评估基准失败: {str(e)}")
@evaluation.post("/databases/{db_id}/run")
async def run_evaluation(db_id: str, params: dict = Body(...), current_user: User = Depends(get_admin_user)):
"""运行RAG评估"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
task_id = await service.run_evaluation(
db_id=db_id,
benchmark_id=params.get("benchmark_id"),
model_config=params.get("model_config", {}),
created_by=current_user.user_id,
)
return {"message": "success", "data": {"task_id": task_id}}
except Exception as e:
logger.error(f"启动评估失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"启动评估失败: {str(e)}")
@evaluation.get("/databases/{db_id}/history")
async def get_evaluation_history(db_id: str, current_user: User = Depends(get_admin_user)):
"""获取知识库的评估历史记录"""
from yuxi.services.evaluation_service import EvaluationService
try:
service = EvaluationService()
history = await service.get_evaluation_history(db_id)
return {"message": "success", "data": history}
except Exception as e:
logger.error(f"获取评估历史失败: {e}, {traceback.format_exc()}")
raise HTTPException(status_code=500, detail=f"获取评估历史失败: {str(e)}")