AgentEvalTool/backend/agenteval/web/routers/reports.py
sinohqb 739d586aec feat(backend): v0.4 triggered_by tracking, login gate, compare guard, dashboard stats
- EvalRun.triggered_by 全链路(manual/ai_assistant/cli)+ 迁移 b7d4e6f81c22
- 标准 agenteval-run SKILL.md 纳入版本管理,deploy 脚本同步 + API Key 注入
- 简单登录:AGENTEVAL_ADMIN_PASSWORD + HMAC 会话 token,require_auth 双凭据
- 对比报告限同场景(400)+ 空 results 误判修复
- /api/stats/dashboard 扩展聚合;/api/runs 返回场景/对象名
- 测试 218 → 232
2026-07-28 17:40:54 +08:00

74 lines
2.5 KiB
Python

"""API routes for evaluation reports."""
from fastapi import APIRouter, Depends, HTTPException, Query, Response
from sqlmodel import Session
from agenteval.evaluation.report import (
generate_compare_report,
generate_report,
render_html_report,
render_json_report,
render_markdown_report,
)
from agenteval.storage.repository import RunRepository
from agenteval.web.deps import get_db
router = APIRouter()
@router.get("/compare")
def get_compare_report(
run1: str = Query(..., description="First run ID"),
run2: str = Query(..., description="Second run ID"),
session: Session = Depends(get_db),
) -> dict:
repo = RunRepository(session)
run_a = repo.get(run1)
run_b = repo.get(run2)
if not run_a:
raise HTTPException(status_code=404, detail=f"run not found: {run1}")
if not run_b:
raise HTTPException(status_code=404, detail=f"run not found: {run2}")
if run_a.scenario_id != run_b.scenario_id:
raise HTTPException(status_code=400, detail="对比报告要求两个运行使用相同场景")
return generate_compare_report(run1, run2, session)
@router.get("/{run_id}")
def get_report(run_id: str, session: Session = Depends(get_db)) -> dict:
run = RunRepository(session).get(run_id)
if not run:
raise HTTPException(status_code=404, detail="run not found")
return generate_report(run_id, session)
@router.get("/{run_id}/html")
def get_html_report(run_id: str, session: Session = Depends(get_db)) -> Response:
run = RunRepository(session).get(run_id)
if not run:
raise HTTPException(status_code=404, detail="run not found")
html = render_html_report(run_id, session)
return Response(content=html, media_type="text/html")
@router.get("/{run_id}/json")
def get_json_report(run_id: str, session: Session = Depends(get_db)) -> Response:
run = RunRepository(session).get(run_id)
if not run:
raise HTTPException(status_code=404, detail="run not found")
json_text = render_json_report(run_id, session)
return Response(content=json_text, media_type="application/json")
@router.get("/{run_id}/markdown")
def get_markdown_report(run_id: str, session: Session = Depends(get_db)) -> Response:
run = RunRepository(session).get(run_id)
if not run:
raise HTTPException(status_code=404, detail="run not found")
md = render_markdown_report(run_id, session)
return Response(
content=md,
media_type="text/markdown; charset=utf-8",
headers={"Content-Disposition": f'attachment; filename="report-{run_id}.md"'},
)