1. 页面概览
评测管理是 AIP 管理后台面向管理员的 NLQ 离线评测页,路由为 /admin/eval。它用「测试用例 → 评测运行 → 历史与回归」三个 Tab 覆盖完整闭环:先维护黄金测试集(自然语言问题 + 期望 SQL),再触发 NLQ→SQL 生成与执行校验,最后查看指标与回归趋势。
核心指标包括执行准确率(EA)、精确匹配率(EM)、语法有效率(SV)与通过用例数;回归报告按历次运行对比执行准确率,下降时标红告警,便于定位 Prompt/RAG/SQL 逻辑劣化。
一句话总结:评测管理把「用例集维护、评测执行、回归监控」串成一条流水线,让 NLQ 质量可度量、可回归。
2. 访问入口
2.1 路由与菜单
| 项目 | 值 |
|---|---|
| 路由 path | /admin/eval |
| 路由 name | AdminEval |
| 路由 title | 评测管理 |
| requiresAuth | true(父级 /admin 另有 requiresAdmin) |
| 菜单位置 | AdminLayout 侧边栏菜单项「评测管理」 |
| 前端源码 | action/web/src/views/EvalPage.vue |
| 路由注册 | action/web/src/router/index.js |
2.2 认证与权限
守卫校验 aip_is_admin='1',否则跳 /chat;请求走 action/web/src/api/aipClient.js(aip_token Bearer JWT),401 清 token 跳登录。
2.3 端口与 API 前缀
AIP 后端 18080,前缀 /aip-api(实际 /aip-api/v1/...,Vite 代理重写为 /api/v1)。
3. 界面布局
+------------------------------+
| 评测管理 [刷新] [alert 提示] |
| Tab:测试用例|评测运行|历史与回归
+------------------------------+
| 测试用例 Tab:[类别▾][难度▾][重置筛选]
| [新建测试用例][导出评测集]
| 表格:ID|类别|难度|问题|期望SQL|数据源|操作
| 分页:[上一页] 第 X / Y 页(共 N 条)
| [下一页] 每页[20/50/100]
| 评测运行 Tab:[运行评测](spinner + 进度)
| 指标卡:执行准确率|精确匹配率|语法有效率|
| 通过用例|平均延迟|平均Tokens
| 通过率进度条 + 用例结果表(展开 SQL)
| 历史与回归 Tab:评测历史(分页)+
| 运行详情+回归报告(横幅+趋势折线+指标表)
+------------------------------+
各板块职责:测试用例 Tab 维护黄金集(服务端分页);评测运行 Tab 触发评测并按任务化语义展示结果(快路径直接出结果、受理转后台轮询);历史与回归 Tab 提供详情(服务端分页)与回归检测。
4. 交互元素
| 控件 | 位置 | 含义与作用 |
|---|---|---|
| 类别下拉筛选 | 测试用例工具栏 | 服务端过滤:以 category query 重新请求 GET /evaluation/test-cases;候选取自后端写入期校验枚举(simple_select/join/aggregation/subquery/window)并并入本次已加载数据中出现过的取值(只增不减);切换即重新请求 |
| 难度下拉筛选 | 测试用例工具栏 | 服务端过滤:以 difficulty query 重新请求(easy/medium/hard),候选来源同上 |
| 重置筛选 | 测试用例工具栏 | 清空两个筛选条件并重新请求第一页 |
| 新建测试用例 / 编辑、删除 | 测试用例表 | 弹窗:类别下拉(简单查询/多表连接/聚合统计/子查询/窗口函数,值 simple_select/join/aggregation/subquery/window)、难度(简单/中等/困难,easy/medium/hard)、问题*、期望 SQL*、数据源可选;删除有 confirm |
| 导出评测集 | 测试用例表工具栏 | GET /evaluation/test-cases/export,下载 eval_test_cases_<日期>.json |
| 用例分页 | 测试用例表底部 | 服务端分页:page/page_size(档位 20/50/100,后端上限 100);「上一页 / 第 X / Y 页(共 N 条) / 下一页」+ 每页档位;切换类别/难度/重置筛选时页码复位为 1 |
| 运行评测 | 评测运行 Tab | POST /evaluation/runs(timeout 放宽 120s),执行中按钮显示「评测运行中...」并禁用。HTTP 200 快路径直接渲染完整结果;HTTP 202 受理转后台任务,显示任务 id/进度/状态并轮询 GET /tasks/:id 至终态 |
| 查看 SQL / 收起 SQL | 用例结果表 | 展开/收起该用例生成的 SQL(pre 代码块) |
| 历史分页 | 评测历史表底部 | 服务端分页:page/page_size(档位同上),文案「第 X / Y 页(共 N 次)」 |
| 查看详情 | 评测历史表 | 打开该次运行详情(指标卡 + 用例结果表) |
5. 后端关联
API 端点(/evaluation 前缀,全部 admin 组):
| 方法 | 路径 | 用途 |
|---|---|---|
| GET / POST | /evaluation/test-cases | 用例列表(分页 data.items,query 支持 category/difficulty/page/page_size,响应 data.total 为过滤后总数)/ 创建 |
| GET | /evaluation/test-cases/export | 导出完整评测集 DTO(供制品分发/同源复用) |
| PUT / DELETE | /evaluation/test-cases/:id | 编辑 / 删除用例 |
| POST | /evaluation/runs | 触发评测运行(已任务化:HTTP 200 快路径返回完整结果 + task_id;超窗受理 HTTP 202 返回 data={task_id,status:"running",type:"evaluation_run"}) |
| GET | /evaluation/runs | 历史运行列表(分页 data.items + data.total) |
| GET | /evaluation/runs/:id | 运行详情(data 含 run 与 results) |
| GET | /evaluation/reports | 历次指标趋势 + regression_alerts |
| GET | /tasks/:id | 平台通用任务查询(用于 202 受理后的终态轮询;data 为任务响应体,含 status/progress/message/result/error) |
5.1 关键机制
- 运行结果结构:
run_id/status/execution_accuracy/exact_match_rate/syntax_validity_rate/passed_cases/total_cases/avg_latency_ms/avg_tokens/results[](含generated_sql/execution_status/result_match/exact_match/syntax_valid/error)。 - 用例服务端过滤与分页:
ListTestCases读取category/difficultyquery 并逐条Where(空值不过滤);同时读取page(默认 1)与page_size(默认 20、>100 归 20)做Offset/Limit,响应data={total,page,page_size,items};列表标题显示data.total为过滤后总条数与本页条数;写入期校验枚举见validCategory/validDifficulty(页面筛选候选的来源之一)。 POST /evaluation/runs已任务化(V5 Stage 0):submitAndWaitTask在等待窗口内完成则走快路径 HTTP 200(data= 完整EvalRunResult字段 +task_id);超窗则受理 HTTP 202,data={task_id,status:"running",type:"evaluation_run"}。前端把 200 结果直接渲染,把 202 转入后台轮询GET /tasks/:id(间隔 1.8s,上限 10 分钟)——success时以t.result渲染并刷新历史,failed/cancelled时以t.error||t.message如实提示;连续 5 次查询失败或超时则停止轮询并提示「仍在后台执行,可稍后刷新历史查看」。- 任务状态枚举(
platform/task/models.go):queued|running|success|failed|cancelled;任务响应体字段id/type/payload/status/progress/message/result/error/created_by/created_at/updated_at/started_at/finished_at,其中result为 json.RawMessage(前端直接得到结构化对象)。 - 回归检测:后端
reports返回regression_alerts(EA/EM/SV 较上次下降 >2% 告警);前端按时间序比较执行准确率标记「下降」并显示红色横幅。 - 状态/百分比映射:PASSED/SUCCESS/COMPLETED→成功,FAILED/ERROR→失败,PENDING/RUNNING→运行中,SKIPPED→跳过;百分比兼容 0-1 与 0-100。
后端实现:action/products/aip/evaluation/handler.go、service.go(RunEval/SeedTestCases)、server/handlers.go(任务化)。
6. 权限与安全
- 认证与角色:
aip_token+ 管理员;/evaluation/*全部 admin 组,普通用户 403、无 token 401。 - 数据安全:测试用例含期望 SQL 与数据源信息,仅管理员可见。
- 写操作防护:删除用例有 confirm;「运行评测」真实执行 NLQ→SQL 生成与校验,无二次确认。
7. 常见问题与排错
问题 1:点「运行评测」后按钮长时间显示「评测运行中...」,或提示「评测仍在后台执行」
原因:后端已任务化——超过同步等待窗口会返回 202 受理,由页面轮询 GET /tasks/:id 等待后台完成;用例多/LLM 慢时轮询会持续较久(页面等待上限 10 分钟)。
处理:保持页面打开等待(任务完成会自动展示结果并刷新历史);若超过等待上限,任务通常仍在后台执行,可稍后到「历史与回归」Tab 点「刷新」查看新记录;持续异常时看后端日志定位 RunEval 报错并确认 LLM 网关可用。
问题 2:提示「任务状态查询失败,评测可能仍在后台执行」
原因:轮询 GET /tasks/:id 连续 5 次失败(网络抖动/后端重启),页面停止轮询以避免永久空转。
处理:稍后到「历史与回归」Tab 刷新,若后台任务已成功会出现在历史列表;必要时重新发起一次评测。
问题 3:保存测试用例报「category 必须为 simple_select/join/aggregation/subquery/window 之一」
原因:类别下拉值被清空或传了非法值。
处理:从下拉重新选择类别(默认 simple_select)再保存。
问题 4:导出评测集失败或下载文件无内容
原因:/evaluation/test-cases/export 未返回 items 数组,或浏览器拦截自动下载。
处理:检查 Network 返回结构;放行自动下载;确认管理员权限。
问题 5:回归报告显示「暂无回归数据」
原因:GetReports 只统计 status=completed 的运行记录,历史为空。
处理:先运行一次评测产生 completed 记录;确认 /evaluation/reports 返回非空 items。
问题 6:删除用例后列表少了一条,页码自动回退
原因:删除使当前页变空且页码大于 1 时,页面会回退一页重新请求(避免停在空页)。
处理:属预期行为;如需核对总数以分页区「共 N 条」为准。
8. 已知缺陷与边界
| 项 | 说明 |
|---|---|
| 运行同步等待 | 已收口:202 受理分支已按任务化语义轮询 GET /tasks/:id(间隔 1.8s、上限 10 分钟),success 用 t.result 渲染、failed/cancelled 用 t.error||t.message 如实提示;仅超时/连续 5 次查询失败时停止轮询并提示「仍在后台执行,可稍后刷新历史查看」(任务本身不受影响) |
| 用例筛选候选非独立枚举端点 | 后端无 /evaluation/test-cases/categories 类字典端点;下拉候选取自后端写入期校验枚举(evaluation/handler.go:238-257,取值即 simple_select/join/aggregation/subquery/window 与 easy/medium/hard)并并入本次已加载数据中实际出现的取值,页面已如实标注。筛选本身为服务端过滤(不是前端过滤) |
| 用例列表无翻页 UI | 已收口:接口支持 page/page_size(handler.go:80-87,page_size 默认 20、上限 100),页面已补服务端分页(档位 20/50/100 + 上下页 + 总数);切换筛选复位第 1 页,删除致当前页为空时自动回退一页 |
| 运行历史无翻页 UI | 已收口:GET /evaluation/runs 同为服务端分页(handler.go:271-293),页面已补同构分页控件与「共 N 次」总数 |
| 评测中刷新页面 | 轮询状态(runTaskId/progress)为页面本地状态,刷新/关闭页面会丢失轮询;后台任务不受影响,重新进入后可从「历史与回归」Tab 查看结果(前端未持久化在途任务 id) |
| 平均延迟 / Tokens | 无耗时数据时显示 '-' |
| 种子用例默认集 | bootstrap 会写入默认评测集,删除后需手动维护 |
注:回归检测读错字段(横幅依赖 payload.regression_detected,后端实际返回 regression_alerts,横幅不显示)已于 2026-09-06 修复(改读 regression_alerts,兼容旧字段)。