from __future__ import annotations
import json
import pickle
import pytest
pytest.importorskip("torch")
pytest.importorskip("qwen_vl_utils")
from verl.utils.dataset import ( # noqa: E402
LocalJsonlDataset,
_align_media_placeholders,
)
def test_local_jsonl_preserves_task_specific_columns(tmp_path) -> None:
path = tmp_path / "mixed.jsonl"
rows = [
{
"problem": "temporal prompt",
"answer": "1 to 2",
"problem_type": "temporal grounding",
"videos": ["/media/a.mp4"],
"pred_span": [1.0, 2.0],
},
{
"problem": "segmentation prompt",
"answer": "{}",
"problem_type": "segmentation",
"videos": ["/media/b.mp4"],
"segmentation_output": {"object_id": 1},
},
]
path.write_text(
"".join(json.dumps(row) + "\n" for row in rows),
encoding="utf-8",
)
dataset = LocalJsonlDataset(str(path))
assert len(dataset) == 2
assert dataset[0]["pred_span"] == [1.0, 2.0]
assert dataset[1]["segmentation_output"] == {"object_id": 1}
assert "segmentation_output" not in dataset[0]
def test_local_jsonl_filter_and_pickle_keep_random_access(tmp_path) -> None:
path = tmp_path / "mixed.jsonl"
path.write_text(
"\n".join(
[
json.dumps({"problem_type": "tracking", "value": 1}),
"",
json.dumps({"problem_type": "video_qa_mc", "value": 2}),
]
)
+ "\n",
encoding="utf-8",
)
dataset = LocalJsonlDataset(str(path))
filtered = dataset.filter(lambda row: row["value"] == 2)
restored = pickle.loads(pickle.dumps(filtered))
assert len(dataset) == 2
assert len(restored) == 1
assert restored[0] == {"problem_type": "video_qa_mc", "value": 2}
def test_surplus_media_placeholders_are_removed() -> None:
prompt = " Question with literal tail"
aligned = _align_media_placeholders(prompt, "", media_count=2)
assert aligned.count("") == 2
assert "Question with" in aligned
assert "literal tail" in aligned
def test_missing_media_placeholders_are_rejected() -> None:
with pytest.raises(ValueError, match="1