# Benchmark 开发说明 > 所属模块:Knowledge / Retrieval Core(后端,负责人 yxx)。RAG 与标准Agent Benchmark均已实现,前端入口`/benchmarks`。真实验收结果与范围见[第二阶段收尾记录](第二阶段收尾实现与验收-2026-09-07.md)。 ## 定位 Benchmark Service 用受控 Dataset 对检索引擎做可复现评测:创建即返回 queued、后台 asyncio.Task 执行、SSE 实时推送进度、结束后产出结构化报告。CLI、测试与前端报告页复用同一 Service,不各自实现指标。 ## 接口 | 方法 | 路径 | 用途 | | --- | --- | --- | | GET | `/api/benchmarks/datasets?kind=rag` | 枚举受控目录下的 Dataset 元信息 | | POST | `/api/benchmarks/rag/runs` | 创建 RAG Benchmark(202) | | GET | `/api/benchmarks/runs?kind=&status=&limit=&offset=` | 分页获取运行记录 | | GET | `/api/benchmarks/runs/{run_id}` | 状态与指标摘要 | | GET | `/api/benchmarks/runs/{run_id}/events` | SSE 进度与 Case 结果 | | POST | `/api/benchmarks/runs/{run_id}/cancel` | 取消运行 | | GET | `/api/benchmarks/runs/{run_id}/report` | 结构化完整报告 | Agent Benchmark的`POST /api/benchmarks/agent/runs`已实现并注册OpenAPI,使用正式Agent Runtime与Trace;请求/Case见[契约§9](../contracts/第二阶段接口契约-开发版.md)。默认只接受真实Provider,显式offline才允许mock,不自动批准工具权限。 ## Dataset Dataset 来自 `settings.benchmark_datasets_path`(默认 `backend/data/benchmarks`),API 不接受调用方提交任意路径。按文件名 stem 精确匹配 `{dataset_id}.json`,与请求无关文件的损坏(JSON 语法错误、UTF-8 解码错误、顶层非对象)不会阻断加载;只有目标文件本身损坏才返回 `BENCHMARK_DATASET_INVALID`。 RAG Case 结构:`case_id`、`query`、`expected_note_ids`、`expected_block_ids`、`citation_required`、`tags`。`citation_required=true` 时必须声明 `expected_block_ids`,否则无法计算 Citation Hit Rate。 ## 运行生命周期 `queued → running → completed | failed | cancelled`。 - RAG创建时校验索引兼容性:索引非空、Embedding model/dim 与当前引擎一致、vector/hybrid 时向量索引非空;不满足返回 `BENCHMARK_INDEX_INCOMPATIBLE`(409),避免把环境/索引错误误判为检索质量差。 - 内存注册表上限 `MAX_RUNS=100`,超限只淘汰终态 run;满容量且全为活动 run 时返回 `BENCHMARK_CAPACITY_EXCEEDED`(429)。 - 失败/取消只向公开响应暴露项目错误码与安全消息,详细异常进入日志,不通过 HTTP/SSE 返回。 ## 指标 RAG 按 (mode, case, repeat) 逐样本计算,再按 mode 聚合: - 质量:`hit_at_1`、`hit_at_5`、`recall_at_k`、`mrr`、`citation_hit_rate`; - 延迟:`p50_latency_ms`、`p95_latency_ms`(仅统计成功样本); - 样本构成:`total_cases`、`successful_cases`、`failed_cases`、`failure_rate`。 失败样本按零分计入质量指标分母,报告据此可知实际分母,避免把执行失败误判为检索质量差。 ## 事件与 SSE 事件流:`RunStarted → CaseCompleted* → RunCompleted | RunFailed | RunCancelled`。 `GET /api/benchmarks/runs/{run_id}/events` 支持 `Last-Event-ID` 与 `?after_sequence=` 游标恢复(复用 Agent SSE 的解析逻辑),`RunCompleted` / `RunFailed` / `RunCancelled` 为终止事件,收到后断流。 ## 错误码 ```text BENCHMARK_DATASET_NOT_FOUND BENCHMARK_DATASET_INVALID BENCHMARK_INDEX_INCOMPATIBLE BENCHMARK_CAPACITY_EXCEEDED BENCHMARK_RUN_NOT_FOUND BENCHMARK_RUN_FAILED BENCHMARK_CASE_EVALUATION_FAILED ``` ## 配置快照 报告与运行记录保存 `config_snapshot`:dataset hash/version、modes、retrieval 参数、Reranker、索引元数据、App 版本与环境、Python 版本。`local_embedding` 记录本地基线 model/version/dim;`embedding.policy = per_case` 表示实际来源以逐样本结果为准,不能把本地基线当作本次使用的模型。 每个 `RAGCaseResult.embedding`(同时出现在报告 cases 和 CaseCompleted SSE 中)记录 `source`(api/local/not_used/unavailable)、实际 `model_id` 空间标识、`dimensions`、本地 `version`、`fallback_reason`。远程路由还记录请求时的 `route_version` 和 `requested_route`(provider_id/model/endpoint/dimensions,不含凭据)、成功生成查询向量后的 `attempted_space`。FTS 标记 not_used;调用失败而未完成向量检索时标记 unavailable。API 不可用或远程索引缺失时,实际模型仍记录最终使用的本地基线。配置允许在样本间改变,逐样本记录对应实际调用;汇总指标可能包含多种空间,比较实验时需检查 cases。记录使用任务局部上下文隔离,并发评测不会相互覆盖。 ## 测试 ```powershell cd backend uv run pytest -q ``` `tests/test_benchmark.py` 覆盖数据集注册与校验、指标纯函数、端到端运行、取消、索引兼容、容量与失败样本聚合;`tests/test_retrieval.py` 覆盖 FTS 阈值与分页 total 一致性。 ## 2026-09-07 数据与复现补充 `agent-core-v1.json`为四例标准任务;`rag-phase2-v1.json`对应独立测试语料,不对应任意用户Vault,运行前必须用`phase2-quality.py`准备语料及真实索引。语料源、配置、逐例结果和冷暖缓存说明见收尾验收记录。UI支持RAG/Agent切换、Provider/模型、融合/TopK/RRF/rerank配置、取消、报告JSON与Trace入口。 Agent成功判定包含终态完成、预期工具及声明参数一一匹配、无额外调用、工具结果成功、输出子串、引用和任务数量;并非由另一个LLM主观打分。失败/取消报告保留total_cases与evaluated_cases,不能当成完成的质量测量。报告注册表最多100条且不跨进程恢复,重要结果须下载保存;持久Agent Trace独立保留。工具选择/参数准确率和无效调用率在无分母时返回null。