犀牛鸟 2026 研究笔记 estelledc.github.io

Ch20: 中文 RAG Benchmark 动手——RAGAS 与 WeKnora 评估闭环

Part 7: 评估实战 前置:Ch08 评估方法论Ch14 动手实验室 后续:Ch11–Ch15 进阶专题WeKnora 实战 完整方法论:RAG 评估方法论


结论先行:WeKnora 无官方 eval 工具——这正是高价值竞赛贡献。本章带你用 50 条中文金标准 QA + RAGAS 四维 + 消融实验,建立「改代码 → 用数字证明有效」的闭环;产出的脚本与数据集可直接作为 PR 素材。

一、为什么中文 Benchmark 是缺口

英文有 MS MARCO、Natural Questions;中文 RAG 缺少广泛认可的公开集。贡献一个可复现的 weknora-zh-benchmark 对社区与竞赛评审都是硬通货。

RAGAS 四维(复习):

指标 问什么
Faithfulness 答案是否忠于检索上下文?
Answer Relevancy 答案是否答所问?
Context Precision 检索到的 chunk 是否相关?
Context Recall 是否漏掉该召回的 chunk?

二、数据集格式(JSONL)

{
  "id": "zh-001",
  "question": "WeKnora 三路检索分别是什么?",
  "ground_truth": "向量语义检索、BM25 关键词检索、PMI 知识图谱检索,经 RRF 融合。",
  "relevant_doc_ids": ["weknora-arch.md"],
  "difficulty": "easy",
  "query_type": "factual",
  "language": "zh"
}

规模建议

阶段 条数 用途
冒烟 10 本地脚本调试
竞赛 PR 50 首版 benchmark
社区 200+ 分 domain 扩展

三、构建 50 条的实操流程(4 步)

Step 1:选 corpus

从你已上传 WeKnora 的知识库导出 chunk,或固定 3–5 篇 Markdown(架构 doc、API doc、FAQ)。

Step 2:LLM 辅助生成 + 人工审核

PROMPT = """根据以下文档段落,生成 1 个中文问答对。
要求:问题像真实用户提问;答案仅来自段落;标注引用的段落编号。
段落:{chunk}
输出 JSON:{"question":"","ground_truth":"","chunk_id":""}
"""

人工审核清单:答案是否可验证、问题是否自然、是否泄露多 chunk 推理(hard 题除外)。

Step 3:划分难度

类型 比例 示例
factual 40% 「支持几个向量库?」
reasoning 35% 「为什么用 RRF 不用加权平均?」
multi_hop 25% 「图谱路如何补 BM25 盲区?」

Step 4:冻结版本

benchmark/v0.1.jsonl + corpus/ + README 说明构建日期与 WeKnora commit。

仓库已含冒烟集benchmark/smoke-10.jsonl + lab/corpus/ — 可直接 --dry-run 校验:

python3 guide/scripts/eval_weknora_ragas.py \
  --benchmark benchmark/smoke-10.jsonl \
  --out benchmark/runs/dry.json --dry-run

四、RAGAS 评估脚本(最小可运行)

"""eval_weknora_ragas.py — 需 pip install ragas datasets openai httpx"""
import json, os, httpx
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision, context_recall

WEKNORA_URL = os.environ["WEKNORA_CHAT_URL"]  # 你的问答 API
WEKNORA_KEY = os.environ.get("WEKNORA_KEY", "")

def weknora_qa(question: str) -> dict:
    r = httpx.post(
        WEKNORA_URL,
        headers={"Authorization": f"Bearer {WEKNORA_KEY}"},
        json={"query": question},
        timeout=120,
    )
    r.raise_for_status()
    data = r.json()
    return {
        "answer": data["answer"],
        "contexts": [c["text"] for c in data.get("citations", [])],
    }

rows = []
for item in open("benchmark/v0.1.jsonl", encoding="utf-8"):
    ex = json.loads(item)
    out = weknora_qa(ex["question"])
    rows.append({
        "question": ex["question"],
        "ground_truth": ex["ground_truth"],
        "answer": out["answer"],
        "contexts": out["contexts"],
    })

ds = Dataset.from_list(rows)
result = evaluate(ds, metrics=[faithfulness, answer_relevancy, context_precision, context_recall])
print(result)

注意:按 WeKnora 实际 API 字段调整 citations 解析;Faithfulness 需配置 Judge LLM(OpenAI/DeepSeek)。


五、消融实验设计(证明 PR 有效)

改检索模块后,跑同一 benchmark,对比:

实验 改动 预期
baseline main 分支
+RRF k k=60→40 Precision↑ 或 Recall↓
+表格 chunk docparser 修复 表格题 Recall↑
+QA 索引 摄入增强 FAQ faithfulness↑

报告格式:

| 指标 | baseline | PR-xxx | Δ |
|------|----------|--------|---|
| context_recall | 0.72 | 0.81 | +0.09 |

六、贡献路径(WeKnora)

级别 交付物 工时
L2 scripts/eval_ragas.py + 10 条样例 3–5 天
L2+ 50 条 benchmark/zh-v0.1.jsonl +1 周
L3 CI 回归(PR 自动跑 smoke 10 条) +1 周
L4 EvalPlugin + Dashboard 2–3 周

Ch10 竞赛速查 L2 路径对齐。


七、常见坑

处理
Judge LLM 与业务 LLM 不一致 固定 eval 用 gpt-4o-mini 或 DeepSeek
检索空 context RAGAS 分异常 → 脚本先断言 len(contexts)>0
数据泄漏 benchmark 问题勿进训练 chunk
波动大 每配置跑 3 次取均值

章末自检


延伸阅读