2026-07-08 08:57:50 +00:00

5.9 KiB
Raw Permalink Blame History

自定义文本检索评测数据集

概述

当你需要在特定领域(如法律、医疗、金融)或私有数据上评估 Embedding 模型的检索能力时可以构建自定义数据集进行评测。EvalScope 基于 MTEB 框架,支持通过简单的 JSONL 文件定义语料库、查询和相关性标注,快速完成端到端的检索评测。

第一步:准备数据

目录结构

创建一个目录,包含以下三个 JSONL 文件:

my_retrieval_data/
├── corpus.jsonl
├── queries.jsonl
└── qrels.jsonl

corpus.jsonl

语料库文件,每行一个 JSON 对象,表示一篇待检索文档。

字段 类型 必填 说明
_id str 文档唯一标识
text str 文档正文内容
title str 文档标题,用于辅助检索
{"_id": "doc1", "text": "气候变化正在导致更极端的天气模式。", "title": "气候变化"}
{"_id": "doc2", "text": "今天股市大幅上涨,科技股领涨。"}
{"_id": "doc3", "text": "人工智能正在通过自动化任务和提供见解来改变各种行业。"}

queries.jsonl

查询文件,每行一个 JSON 对象,表示一条检索查询。

字段 类型 必填 说明
_id str 查询唯一标识
text str 查询文本
{"_id": "query1", "text": "气候变化的影响是什么?"}
{"_id": "query2", "text": "今天股市上涨的原因是什么?"}
{"_id": "query3", "text": "人工智能如何改变行业?"}

qrels.jsonl

相关性标注文件,每行一个 JSON 对象,定义查询与文档之间的相关性。

字段 类型 必填 说明
query-id str 对应 queries.jsonl 中的 _id
corpus-id str 对应 corpus.jsonl 中的 _id
score int/float 相关性分数
{"query-id": "query1", "corpus-id": "doc1", "score": 1}
{"query-id": "query2", "corpus-id": "doc2", "score": 1}
{"query-id": "query3", "corpus-id": "doc3", "score": 1}

score 含义说明:

  • 二值标注0/11 表示相关,0 表示不相关。适用于大多数检索场景。
  • 连续分数:使用多级相关性(如 0、1、2、3数值越大表示越相关。适用于需要区分"部分相关"和"高度相关"的精细评测。

数据质量建议

- 推荐语料库至少包含 **100** 篇文档,查询至少 **50** 条,以获得统计上有意义的评测结果。
- 确保每个查询至少有 **1** 个相关文档标注。
- 如果使用二值标注建议同时标注负样本score=0以更准确地评估模型区分能力。
- 语料库中应包含足够多与查询无关的"干扰"文档,模拟真实检索场景。

第二步:配置并运行评测

完整配置示例

from evalscope.run import run_task

task_cfg = {
    "work_dir": "outputs",
    "eval_backend": "RAGEval",
    "eval_config": {
        "tool": "MTEB",
        "models": [
            {
                "model_name_or_path": "AI-ModelScope/m3e-base",
                "pooling_mode": None,
                "max_seq_length": 512,
                "prompt": "",
                "model_kwargs": {"torch_dtype": "auto"},
                "encode_kwargs": {
                    "batch_size": 128,
                },
            }
        ],
        "eval": {
            "custom_tasks": [
                {
                    "name": "CustomRetrieval",
                    "data_path": "my_retrieval_data",
                }
            ],
            "overwrite_results": True,
            "limits": 500,
        },
    },
}

run_task(task_cfg=task_cfg)

运行命令

将上述代码保存为 run_eval.py,然后执行:

python run_eval.py

结果解读

评测完成后,结果保存在 outputs/ 目录下,主要指标包括:

  • NDCG@k归一化折损累计增益衡量排序质量k=1,3,5,10
  • MAP@k:平均精度均值
  • Recall@k:召回率
  • Precision@k:精确率

分数范围为 0~1越高表示检索效果越好。

参数参考

custom_tasks 列表中每个任务对应一个 CustomTaskConfig,可配置字段如下:

参数 类型 默认值 说明
name str "CustomRetrieval" 任务名称,用于标识评测结果
data_path str (必填) 数据集目录路径,需包含 corpus.jsonlqueries.jsonlqrels.jsonl
eval_splits List[str] ["test"] 评测分割列表
其他评测参数(如 `models`、`limits`、`overwrite_results` 等)与默认配置一致,详见 [MTEB 评测参数说明](../../user_guides/backend/rageval_backend/mteb.md#参数说明)。

常见问题

字段格式错误

  • 数据文件必须是 JSONL 格式(每行一个独立的 JSON 对象),不是标准 JSON 数组格式。
  • _id 字段值必须是字符串类型,即使是数字 ID 也应写为 "123" 而非 123
  • qrels.jsonl 中的字段名带连字符:query-idcorpus-id,不是下划线。

数据量太少的影响

  • 语料库文档过少(如少于 10 篇Recall@10 等指标可能始终为 1.0,无法有效区分模型好坏。
  • 查询过少会导致评测结果方差较大,不具备统计显著性。
  • 建议根据实际业务场景,准备至少百条量级的数据。

从其他格式转换

如果已有 TSV 或 CSV 格式的数据,可以使用以下方式转换为 JSONL

import csv
import json

# TSV/CSV 转 corpus.jsonl 示例
with open("corpus.tsv", "r") as fin, open("corpus.jsonl", "w") as fout:
    reader = csv.DictReader(fin, delimiter="\t")  # CSV 使用 delimiter=","
    for row in reader:
        obj = {"_id": row["id"], "text": row["text"]}
        fout.write(json.dumps(obj, ensure_ascii=False) + "\n")