RAGSpine
指南

评估

QA 与抽取评估工具链——四门 QA 指标、按通道的抽取准确率,以及只升不降、绝不静默下调的基线回归门。

eval 领域(src/ragspine/eval/)是 RAGSpine 的评估闭环:两套工具链 (QA 与抽取)以版本控制的黄金集为准给引擎打分,外加一个 在回归时让 CI 失败的基线门。它的指导性不变量:

基线门只升不降——回归必须让门失败,绝不能 静默地调低它。绝不为了让某个用例通过而弱化黄金数据或基线。

目录结构

qa_eval.py
extraction_eval.py

黄金数据与基线数据位于 data/golden/(强制纳入版本控制), 抽取的 ground-truth fixture 位于 data/fixtures/

QA 评估——四道门

qa_eval.py 是问答闭环工具链。入口:

def run_qa_eval(
    golden_path: str | Path,
    mode: str = "tool",
    kb_dir: str | Path | None = None,
) -> QAEvalReport: ...

它加载并校验黄金集,构建一个确定性的合成知识库 (build_eval_kb,来自模块内的 _EVAL_FACT_ROWS + _EVAL_NARRATIVE_DOCS),以两种模式之一 (EVAL_MODES = ("tool", "agent"))运行每个用例,并返回一份四门报告。

tool 模式

零 LLM、直连工具:parse_intent → clarify_scope → execute_query_metric / 叙事检索。确定性。

agent 模式

完整编排器:使用确定性的 MockProvider(reference_date=...) 运行 answer_question。

每个用例(GoldenCaseidquestioncase_typeexpectedtagsreference_date)都被运行为一个归一化的 CaseOutcome(路由、澄清模式、found 值/单位/来源、拒答标志、来源列表、工具状态),然后按四道 门打分——保持为四个独立的通过率,绝不合并成一个数字:

属性

类型

GATE_METRICS 是这四项的元组。第五个独立指标跟踪拒答用例上的 编造情况:

FABRICATION = "fabrication" 仅在拒答用例上通过 detect_fabricated_numbers(answer) 计算:它剥离期间 token(从当前 profile 的时间维度加入白名单),并把剩余的任何数字都视为编造。目标是 0。 它被刻意并入四道门。

报告类型:

  • GateMetricnametotalpassedpass_ratetotal == 0 时为 1.0,否则为 passed / total)、failuresby_tag
  • QAEvalReportmoden_casesmetrics: dict[str, GateMetric],以及独立的 fabrication: GateMetric(带 fabrication_count 属性)。evaluate(cases, outcomes, mode) 对每个用例应用全部四条门规则。

忠实度与有据性门(0.7.0+)

上面的四道门对引用匹配、拒答和澄清打分——但它们从未检查 叙事回答是否真的_被其检索片段所蕴含_,而这恰恰是 幻觉发生之处。eval/groundedness.py两道新的棘轮 门补上了这个缺口:

属性

类型

GROUNDEDNESS_METRICS = (faithfulness, answer_accuracy)同一个 report.metrics 中的新键,因此它们并入与四道门相同的基线棘轮(见下文)—— 以 1.0 重新设定基线,并在 --mode tool--mode agent 两种模式下都参与把关。四个 GATE_METRICS 保持其完全一致的语义;没有任何合并。

默认方法是离线确定性的词法重叠蕴含判定LexicalOverlapJudge:当且仅当断言的内容 token 被上下文覆盖的比例超过 阈值时视为被蕴含)——无模型、无网络,因此 make ci 可以完全离线把关。上下文只在 评估侧被观测;默认的 answer_question 循环逐字节不变。

默认判定器是词法代理,不是真正的 NLI——对改写、否定和 数值反转都是盲的;它捕捉最常见的编造形态(上下文中不存在的 新 token),并通过一个反向测试得到验证:无蕴含的断言会未通过该门,而 忠实的复述则通过。真正的 ONNX-NLI 判定器([eval])和位于 EntailmentJudge 缝(make_entailment_judge)之后的 LLM 判定器([llm]),以及上下文精确率 / 召回率 / 答案相关性,都是诚实的后续计划。

这使防编造机制成为叙事通道上被度量的回归锁,而不只是 被声称的——该不变量如今在它真正失效的地方得到检查。

QA 基线回归把关

qa_eval.py 还负责基线比较:

  • make_baseline_entry(report) -> dict{"metrics": {name: pass_rate}, "fabrication_count": int, "n_cases": int}
  • compare_to_baseline(report, baseline) -> BaselineComparison当任何一道 门的 pass_rate 低于其基线阈值,或 fabrication_count 高于 基线时,门失败。 只检查基线中列出的指标;恰好相等则通过。每条 回归记录 metricbaselinecurrentdelta

没有硬编码阈值——阈值就是先前存储在 data/golden/qa_baseline.json 中的按模式通过率。基线通过实际观测到的 运行结果棘轮式上升。

QA 工具链——CLI

scripts/run_qa_eval.py 从项目根目录驱动工具链:

.venv/bin/python scripts/run_qa_eval.py --mode tool
.venv/bin/python scripts/run_qa_eval.py --mode agent --report out/qa_report.json
.venv/bin/python scripts/run_qa_eval.py --mode tool --update-baseline

参数:--mode {tool,agent}(默认 tool)、--golden(默认 data/golden/qa_golden_set.jsonl)、--report--baseline(默认 data/golden/qa_baseline.json)、--update-baseline。门按模式分别设键:没有基线的 模式在首次运行时自动生成基线并通过(exit 0);有基线时,任何一道 门回归或编造计数上升都会以 exit 1 退出。

黄金数据格式

data/golden/qa_golden_set.jsonl 每行一个 JSON 对象。每个用例携带 idquestioncase_typenumeric / clarification / refusal / narrative / composite 之一)、expected(总是包含 clarification{none, ask_first, answer_with_assumptions}refuse: bool;numeric/composite 额外有 value + unit + source;narrative/composite 额外有 narrative_doc)、tags 和一个 reference_date

{
  "id": "num-001",
  "question": "香港FY2025的REVENUE是多少",
  "case_type": "numeric",
  "expected": {
    "clarification": "none",
    "refuse": false,
    "value": 1702.0,
    "unit": "USD_M",
    "source": { "doc": "ACME_FY2025_Results.pptx", "locator": "slide=5,table=1,row=2,col=3" }
  },
  "tags": { "topic": "FIN", "scope": "ACME_HK", "qtype": "must_not_clarify" },
  "reference_date": "2026-06-12"
}

黄金集使用虚构的 ACME 公司与合成数字。data/golden/ 被强制跟踪,以确保基线不会漂移出版本控制。

抽取评估

extraction_eval.py 按通道给办公文档抽取打分:

def run_eval(
    facts: list[dict[str, object]],
    ground_truth: dict[str, object] | list[dict[str, object]],
) -> EvalReport: ...

它按 sheet!cell_ref 将抽取出的 facts 与 ground truth 对齐,只评估 双方都存在的单元格,并在三个通道上计算准确率:

通道常量比较的事实字段
单元格值CELL_VALUE = "cell_value"value
颜色映射COLOR_MAPPING = "color_mapping"tags
表头归属HEADER_ATTRIBUTION = "header_attribution"merge_span

类型:ChannelMetricnametotalcorrectaccuracymismatches)、EvalReportchannels: dict[str, ChannelMetric]n_facts)。回归门是 compare_to_baseline(metrics, baseline) -> BaselineComparison:任何 accuracy 低于其阈值的通道都失败(passed=False);只检查基线中列出的 通道;恰好相等则通过。Ground-truth fixture 位于 data/fixtures/(如 fixtures_ground_truth.jsonpdf/pdf_ground_truth.jsonpptx/pptx_ground_truth.json)。

相关阅读

本页目录