Custom Text Retrieval Evaluation Dataset#
Overview#
When you need to evaluate the retrieval capabilities of Embedding models on domain-specific data (e.g., legal, medical, financial) or private datasets, you can build a custom dataset for evaluation. EvalScope, built on the MTEB framework, supports defining corpus, queries, and relevance judgments through simple JSONL files for end-to-end retrieval evaluation.
Step 1: Prepare Data#
Directory Structure#
Create a directory containing the following three JSONL files:
my_retrieval_data/
├── corpus.jsonl
├── queries.jsonl
└── qrels.jsonl
corpus.jsonl#
The corpus file, with one JSON object per line representing a document to be retrieved.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
str |
Yes |
Unique document identifier |
|
str |
Yes |
Document body content |
|
str |
No |
Document title, used to assist retrieval |
{"_id": "doc1", "text": "Climate change is leading to more extreme weather patterns.", "title": "Climate Change"}
{"_id": "doc2", "text": "The stock market surged today, led by tech stocks."}
{"_id": "doc3", "text": "Artificial intelligence is transforming industries by automating tasks and providing insights."}
queries.jsonl#
The queries file, with one JSON object per line representing a retrieval query.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
str |
Yes |
Unique query identifier |
|
str |
Yes |
Query text |
{"_id": "query1", "text": "What are the impacts of climate change?"}
{"_id": "query2", "text": "What caused the stock market to rise today?"}
{"_id": "query3", "text": "How is artificial intelligence changing industries?"}
qrels.jsonl#
The relevance judgments file, with one JSON object per line defining the relevance between a query and a document.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
str |
Yes |
Corresponds to |
|
str |
Yes |
Corresponds to |
|
int/float |
Yes |
Relevance score |
{"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 semantics:
Binary (0/1):
1means relevant,0means not relevant. Suitable for most retrieval scenarios.Graded relevance: Use multi-level scores (e.g., 0, 1, 2, 3), where higher values indicate greater relevance. Suitable for fine-grained evaluation that distinguishes “partially relevant” from “highly relevant”.
Data Quality Recommendations#
Tip
The corpus should contain at least 100 documents and at least 50 queries for statistically meaningful evaluation results.
Ensure each query has at least 1 relevant document annotation.
When using binary labels, consider also annotating negative samples (score=0) to more accurately assess the model’s discrimination ability.
Include enough irrelevant “distractor” documents in the corpus to simulate real retrieval scenarios.
Step 2: Configure and Run Evaluation#
Complete Configuration Example#
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 Command#
Save the above code as run_eval.py, then execute:
python run_eval.py
Interpreting Results#
After evaluation completes, results are saved in the outputs/ directory. Key metrics include:
NDCG@k: Normalized Discounted Cumulative Gain, measuring ranking quality (k=1,3,5,10)
MAP@k: Mean Average Precision
Recall@k: Recall rate
Precision@k: Precision rate
Scores range from 0 to 1, with higher values indicating better retrieval performance.
Parameter Reference#
Each task in the custom_tasks list corresponds to a CustomTaskConfig with the following fields:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
str |
|
Task name, used to identify evaluation results |
|
str |
(required) |
Dataset directory path, must contain |
|
List[str] |
|
Evaluation splits list |
Note
Other evaluation parameters (such as models, limits, overwrite_results, etc.) are consistent with the default configuration. See MTEB Evaluation Parameter Reference for details.
FAQ#
Field Format Errors#
Data files must be in JSONL format (one independent JSON object per line), not standard JSON array format.
The
_idfield value must be a string type. Even numeric IDs should be written as"123"rather than123.Field names in
qrels.jsonluse hyphens:query-idandcorpus-id, not underscores.
Impact of Insufficient Data#
When the corpus has too few documents (e.g., fewer than 10), metrics like Recall@10 may always be 1.0, making it impossible to effectively differentiate between models.
Too few queries lead to high variance in evaluation results, lacking statistical significance.
It is recommended to prepare at least hundreds of samples based on your actual business scenario.
Converting from Other Formats#
If you already have data in TSV or CSV format, you can convert it to JSONL as follows:
import csv
import json
# Example: TSV/CSV to corpus.jsonl
with open("corpus.tsv", "r") as fin, open("corpus.jsonl", "w") as fout:
reader = csv.DictReader(fin, delimiter="\t") # For CSV, use delimiter=","
for row in reader:
obj = {"_id": row["id"], "text": row["text"]}
fout.write(json.dumps(obj, ensure_ascii=False) + "\n")