评估体系
评估体系是Molore RAG 链路的质量闸:两条命令行门禁脚本(发版门禁 56 题、长文档门禁 14 题)+ 一套真实语料四层评测(realworld)+ 一套分层测试基线(1597 用例)。它解决的问题是——检索/装配/prompt 的任何改动是否造成退化,不靠手感判断,靠固定题库、固定语料、固定阈值的可重复测量裁决。
门禁总览
| 门禁 | 脚本 | 题量 | 阈值 | 何时必跑 |
|---|---|---|---|---|
| 发版门禁 | scripts/run_release_eval.py | 56 | 0.9 | 每次发版 |
| 长文档门禁 | scripts/run_mega_eval.py | 14 | 1.0 | RAG 链路改动 |
| 真实世界评测 | scripts/run_realworld_eval.py | tier0~tier4 | 报告制不设阈 | 检索机制迭代 |
三条铁律:① 门禁必须在向量口径下跑(.env 指向已安装的 bge-m3;指向未装模型会掉成关键词口径出虚分,56/56 也不作数);② 阈值按实测钉死,不许为了灯绿放水;③ 题库 expect_tokens 全部逐条在原文 grep 核实过。
发版门禁 run_release_eval.py
- 用法:
cd backend && ENV=test python scripts/run_release_eval.py,退出码 0 通过、1 不达标或流程异常。 - 流程:自检本地 Ollama 嵌入可用性 → 建独立临时库
.rag_eval_tmp.db(不碰任何真实库)→ 造评测用户 → seed 演示数据 →backfill_embeddings→ TestClient 调/api/v1/knowledge/rag-eval→ 阈值 0.9 判定。 - baseline 沉淀到
data/rag_eval_baseline.json,每次运行与既有 baseline diff,报告「哪题由过变挂」。 - 含生成质量断言:禁止客套开场、品牌名断言、[n] 引用编号必须落在 sources 范围内(越界=幻觉引用)、禁止已知编造标记、产品问答题的 sources 必须含产品指南条目。
长文档门禁 run_mega_eval.py
- 语料固定在
tests/fixtures/rag_mega/:两篇 5 万字级文档,直插 Document 行后走真实索引链(FTSsync_content+note_embedding_service.embed_document,父子块/表格行row::全量向量化)。 - 每题断言三件事:expect_doc 全部命中、expect_tokens 全部出现在当轮 sources 文本与枚举块里、expect_enum 在场时枚举通道确已开火。
- 阈值钉 1.0——14 题任何一题退化都拦,含「枚举通道该开火没开火」这类机制级退化。
- 直调
_retrieve_knowledge_sources_core(关查询改写保确定性,rerank 默认关),改 chunking/top_k/rerank/prompt 后跑本脚本即回归。 - 口径警告:无可用嵌入时纯关键词通道实测 0 分,只出报告不拦截——所以「门禁绿了」必须先确认跑在向量口径。
真实世界评测 run_realworld_eval.py
13 篇真实语料(10 篇英文 arXiv + 3 篇中文白皮书),临时库默认复用(.realworld_eval_tmp.db + manifest 校验文件名/字数/嵌入模型,一致则跳过重建与向量化;--rebuild 强制重来;复用路径走 run_schema_migrations 全量迁移而非 create_all)。四层结构:
| 层 | 内容 | 说明 |
|---|---|---|
| tier0 锚点回放 | 零人工 | 每篇按 10/30/50/70/90% 位置抽 5 个片段,exact/vague 两种查询断言源文档进 sources;另造 2 份 OCR 噪声副本独立回放 |
| tier1 人工题 | 17 题 | expect_tokens 逐条原文 grep 核实;含普查回归钉 t1c_census_904(数字索引普查通道的防退化钉) |
| tier2 多轮 | 追问形态 | 轻锚点追问保持同一文档在场;「它呢」类零锚点追问断言复用上轮源 |
| tier3 多跳 | 7 题 | 关系意图 + 图谱扩展的多跳推理题集 |
| tier4 装配分轨 | 零 LLM | TestClient 捕获 system_prompt,记录 prompt_chars/sql_count;--tier4-only 快路径是砍通道类改动的裁决工具(砍前基线→砍后退化 0 才算过) |
报告制不设门禁阈值:分数照出、baseline 照沉淀,退出码恒 0(流程异常除外)。
测试分层
- 嵌入 HTTP 由
tests/conftest.py的 autouse fixture 钉死 mock(方法层拦_embed_via_ollama返回[],只封推理面不封控制面;本机客户端一律trust_env=False防 Windows 系统代理劫持 localhost)。 - 需要真实嵌入的门禁用例打
@pytest.mark.real_ollama豁免(pytest.ini已声明该标记)。 - 日常迭代:改动域测试文件(秒级~2 分钟);提交前快速全量
pytest tests -q -m "not real_ollama"≈7 分钟;发版纪律为全量(约 11 分钟)+ 双门禁脚本。 - 当前基线:快速全量 1597 绿;前端
npx tsc --noEmit+ eslint。
评估纪律
AI 生成的复盘/审查报告中涉及具体数字的结论(归属、计数、均值),必须拿库原文直查重放后再采信——复测评判方连续出错过(整改中组误当已完成、均值算术错)。报数先报口径:「全库共 1 处」是载体口径还是出现次数,区块直接写「N 处命中(M 篇内容)」。