Skip to content

Commit 6a02ab9

Browse files
zhaowei-wang-nlpcursoragentkennymckormick
authored
[Benchmark] Add support for LongDocURL (#1595)
* [Benchmark] Add support for LongDocURL Co-authored-by: Cursor <cursoragent@cursor.com> * Fix lint errors for LongDocURL benchmark * Trigger LongDocURL CI rerun Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Haodong Duan <dhd@pku.edu.cn> Co-authored-by: kenny.alan <kenny.alan@bytedance.com>
1 parent 3fb3b5b commit 6a02ab9

9 files changed

Lines changed: 868 additions & 36 deletions

File tree

scripts/build_longdocurl_tsv.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python3
2+
"""Build a VLMEvalKit TSV for LongDocURL from the public Hugging Face JSONL."""
3+
4+
import argparse
5+
import json
6+
import os
7+
import os.path as osp
8+
9+
import pandas as pd
10+
11+
12+
REPO_ID = 'dengchao/LongDocURL'
13+
DATA_FILE = 'LongDocURL_public_with_subtask_category.jsonl'
14+
15+
16+
def hf_download(filename, download_dir, token=None):
17+
try:
18+
from huggingface_hub import hf_hub_download
19+
except ImportError as err:
20+
raise ImportError(
21+
'huggingface_hub is required to download LongDocURL. '
22+
'Install it with `pip install huggingface_hub`, or pass --jsonl.'
23+
) from err
24+
25+
return hf_hub_download(
26+
repo_id=REPO_ID,
27+
filename=filename,
28+
repo_type='dataset',
29+
local_dir=download_dir,
30+
token=token,
31+
)
32+
33+
34+
def json_dumps(value):
35+
return json.dumps(value, ensure_ascii=False)
36+
37+
38+
def relative_image_path(path):
39+
path = str(path)
40+
marker = '/pdf_pngs/'
41+
if marker in path:
42+
return path.split(marker, 1)[1]
43+
return path.lstrip('/')
44+
45+
46+
def row_from_sample(sample, idx):
47+
images = [relative_image_path(p) for p in sample.get('images', [])]
48+
answer = sample.get('answer', '')
49+
return {
50+
'index': idx,
51+
'question_id': sample.get('question_id', ''),
52+
'question': sample.get('question', ''),
53+
'answer': json_dumps(answer) if isinstance(answer, list) else answer,
54+
'image_path': json_dumps(images),
55+
'doc_no': sample.get('doc_no', ''),
56+
'total_pages': sample.get('total_pages', ''),
57+
'start_end_idx': json_dumps(sample.get('start_end_idx', [])),
58+
'question_type': sample.get('question_type', ''),
59+
'answer_format': sample.get('answer_format', ''),
60+
'task_tag': sample.get('task_tag', ''),
61+
'evidence_pages': json_dumps(sample.get('evidence_pages', [])),
62+
'evidence_sources': json_dumps(sample.get('evidence_sources', [])),
63+
'subTask': json_dumps(sample.get('subTask', [])),
64+
'detailed_evidences': sample.get('detailed_evidences', ''),
65+
'pdf_path': sample.get('pdf_path', ''),
66+
}
67+
68+
69+
def load_jsonl(path):
70+
rows = []
71+
with open(path, 'r', encoding='utf-8') as f:
72+
for line in f:
73+
if line.strip():
74+
rows.append(json.loads(line))
75+
return rows
76+
77+
78+
def main():
79+
parser = argparse.ArgumentParser(description='Build VLMEvalKit TSV for LongDocURL.')
80+
parser.add_argument('--jsonl', default=None, help='Optional local LongDocURL JSONL path.')
81+
parser.add_argument('--download-dir', default=None, help='Directory for downloaded JSONL.')
82+
parser.add_argument('--output', required=True, help='Output TSV path, e.g. LongDocURL.tsv.')
83+
parser.add_argument('--token', default=os.environ.get('HF_TOKEN'), help='Optional Hugging Face token.')
84+
parser.add_argument('--limit', type=int, default=None, help='Optional limit for debugging.')
85+
args = parser.parse_args()
86+
87+
jsonl_path = args.jsonl
88+
if jsonl_path is None:
89+
download_dir = args.download_dir or osp.join(osp.dirname(osp.abspath(args.output)), 'downloads')
90+
os.makedirs(download_dir, exist_ok=True)
91+
print(f'downloading {DATA_FILE} from {REPO_ID} ...')
92+
jsonl_path = hf_download(DATA_FILE, download_dir, token=args.token)
93+
94+
samples = load_jsonl(jsonl_path)
95+
if args.limit is not None:
96+
samples = samples[:args.limit]
97+
data = pd.DataFrame([row_from_sample(sample, i) for i, sample in enumerate(samples)])
98+
os.makedirs(osp.dirname(osp.abspath(args.output)), exist_ok=True)
99+
data.to_csv(args.output, sep='\t', index=False)
100+
print(f'wrote {len(data)} rows -> {args.output}')
101+
102+
103+
if __name__ == '__main__':
104+
main()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python3
2+
"""Download and extract LongDocURL PNG images into the VLMEvalKit cache."""
3+
4+
import argparse
5+
import os
6+
7+
from vlmeval.dataset.longdocurl import LongDocURL
8+
from vlmeval.smp import LMUDataRoot
9+
10+
11+
def main():
12+
parser = argparse.ArgumentParser(description='Prepare LongDocURL image files.')
13+
parser.add_argument(
14+
'--image-root',
15+
default=None,
16+
help='Target image root. Defaults to LMUData/images/LongDocURL/pdf_pngs.',
17+
)
18+
args = parser.parse_args()
19+
20+
if args.image_root:
21+
os.environ['LONGDOCURL_IMAGE_ROOT'] = args.image_root
22+
else:
23+
os.environ.setdefault(
24+
'LONGDOCURL_IMAGE_ROOT',
25+
os.path.join(LMUDataRoot(), 'images', 'LongDocURL', 'pdf_pngs'),
26+
)
27+
28+
dataset = LongDocURL('LongDocURL')
29+
rel_paths = []
30+
for _, row in dataset.data.iterrows():
31+
rel_paths.extend(row['image_path'])
32+
dataset._ensure_images(rel_paths)
33+
print(f'LongDocURL images are prepared under {dataset._img_root()}')
34+
35+
36+
if __name__ == '__main__':
37+
main()

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ per-file-ignores =
55
run.py: E402
66
vlmeval/vlm/__init__.py: F401, E402
77
vlmeval/dataset/video_dataset_config.py: F405, F403
8+
vlmeval/dataset/utils/longdocurl.py: E501
9+
vlmeval/dataset/utils/mmlongbench_judge_prompt.py: E501
810
vlmeval/dataset/utils/memlens_utils.py: E501
911

1012
[yapf]

vlmeval/dataset/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
QSpatial, SeePhys, TableVQABench, TallyQA, TDBenchGrounding, VGRPBench,
6464
VizWiz, VLMsAreBiased, VTCBench, WildDocBenchmark, ZEROBench)
6565
from .image_yorn import ImageYORNDataset
66+
from .longdocurl import LongDocURL
6667
from .longvideobench import LongVideoBench
6768
from .m3oralbench import M3oralBenchDataset
6869
from .m4bench import M4Bench
@@ -279,7 +280,7 @@ def evaluate(self, eval_file, **judge_kwargs):
279280
IMAGE_DATASET = [
280281
ImageCaptionDataset, ImageYORNDataset, ImageMCQDataset, ImageVQADataset,
281282
MathVision, LENS, MMMUDataset, OCRBench, MathVista, LLaVABench, LLaVABench_KO, VGRPBench, MMVet, # noqa: E501
282-
MTVQADataset, TableVQABench, MMLongBench, MemLens, MMLongBenchDoc, VCRDataset, MMDUDataset, DUDE,
283+
MTVQADataset, TableVQABench, MMLongBench, MemLens, MMLongBenchDoc, VCRDataset, MMDUDataset, DUDE, LongDocURL,
283284
SlideVQA, MUIRDataset, CCOCRDataset, GMAIMMBenchDataset, MMERealWorld,
284285
HRBenchDataset, CRPE, MathVerse, NaturalBenchDataset, MIABench,
285286
OlympiadBench, SeePhys, WildVision, MMMath, QSpatial, Dynamath, GSM8KVDataset, MMGenBench, VizWiz, # noqa: E501

0 commit comments

Comments
 (0)