...
tags. Use| Year | Value |
|---|---|
| 1900 | 42 |
Paragraph with reference.
' + "Checked item
| Year | ' + "Value |
|---|---|
| 1900 | 42 |
Paragraph with reference.
' + "Checked item
| Year | ' + "Value |
|---|---|
| 1900 | 42 |
Decoded ' + 'output.
Decoded ' + 'output.
| Year | Value |
|---|---|
| 1900 | 42 |
| Year | Value |
|---|---|
| 1900 | 42 |
Paragraph with note.
| Year | ' + "Value |
|---|---|
| 1900 | 42 |
Paragraph with note.
| Year | ' + "Value |
|---|---|
| 1900 | 42 |
prediction
"}}] monkeypatch.setattr(benchmark, "_predict_texts", fake_predict) @@ -366,7 +538,7 @@ def fake_compute_metrics(ds, predictions, output_prefix, elapsed_time): # noqa: assert result == 0 assert captured["dataset"] == [benchmark._build_evaluation_example(dataset[1])] - assert captured["predictions"] == ["prediction"] + assert captured["predictions"] == [{"text": "prediction", "metadata": {"raw_html": "prediction
"}}] assert captured["output_prefix"] == str(tmp_path / "outputs") assert captured["elapsed_time"] == pytest.approx(3.5) @@ -507,10 +679,20 @@ async def test_predict_texts_updates_progress_and_preserves_order(monkeypatch) - ] class FakeProgressBar: - def __init__(self, *, total: int | None, desc: str, unit: str) -> None: + def __init__( + self, + *, + total: int | None, + desc: str, + unit: str, + mininterval: float, + smoothing: float, + ) -> None: self.total = total self.desc = desc self.unit = unit + self.mininterval = mininterval + self.smoothing = smoothing self.updates: list[int] = [] self.postfixes: list[dict[str, int]] = [] self.refresh_count = 0 @@ -538,19 +720,33 @@ def refresh(self) -> None: progress_bars: list[FakeProgressBar] = [] - def fake_tqdm(*, total: int | None, desc: str, unit: str) -> FakeProgressBar: - progress_bar = FakeProgressBar(total=total, desc=desc, unit=unit) + def fake_tqdm( + *, + total: int | None, + desc: str, + unit: str, + mininterval: float, + smoothing: float, + ) -> FakeProgressBar: + progress_bar = FakeProgressBar( + total=total, + desc=desc, + unit=unit, + mininterval=mininterval, + smoothing=smoothing, + ) progress_bars.append(progress_bar) return progress_bar - class FakeOCRResult: - def __init__(self, text: str) -> None: - self.text = text - class FakeOCRBackend: async def ocr(self, page): # noqa: ANN001 await asyncio.sleep(page.width / 1000) - return FakeOCRResult(text=f"page-{page.width}") + return OCRResult( + text=f"page-{page.width}", + provider_name="fake", + model_name="fake-model", + metadata={"page_width": page.width}, + ) monkeypatch.setattr(benchmark, "tqdm", fake_tqdm) monkeypatch.setattr(benchmark, "_build_ocr_backend", lambda _: FakeOCRBackend()) @@ -569,12 +765,18 @@ async def ocr(self, page): # noqa: ANN001 total_pages=3, ) - assert predictions == ["page-3", "page-1", "page-2"] + assert predictions == [ + {"text": "page-3", "metadata": {"page_width": 3}}, + {"text": "page-1", "metadata": {"page_width": 1}}, + {"text": "page-2", "metadata": {"page_width": 2}}, + ] assert evaluation_examples == [benchmark._build_evaluation_example(example) for example in dataset] assert len(progress_bars) == 1 assert progress_bars[0].total == 3 assert progress_bars[0].desc == "OCR" assert progress_bars[0].unit == "page" + assert progress_bars[0].mininterval == benchmark.PROGRESS_BAR_MININTERVAL_SECONDS + assert progress_bars[0].smoothing == benchmark.PROGRESS_BAR_SMOOTHING assert progress_bars[0].updates == [1, 1, 1] assert progress_bars[0].postfixes[-1] == { "submitted": 3, @@ -607,14 +809,18 @@ async def test_predict_texts_uses_batch_backend_with_max_concurrency_as_batch_si ] captured_batch_sizes: list[int] = [] - class FakeOCRResult: - def __init__(self, text: str) -> None: - self.text = text - class FakeBatchBackend: async def ocr_batch(self, pages): # noqa: ANN001 captured_batch_sizes.append(len(pages)) - return [FakeOCRResult(text=f"page-{page.width}") for page in pages] + return [ + OCRResult( + text=f"page-{page.width}", + provider_name="fake", + model_name="fake-model", + metadata={"page_width": page.width}, + ) + for page in pages + ] monkeypatch.setattr(benchmark, "_build_ocr_backend", lambda _: FakeBatchBackend()) @@ -632,7 +838,11 @@ async def ocr_batch(self, pages): # noqa: ANN001 ) assert captured_batch_sizes == [2, 1] - assert predictions == ["page-3", "page-1", "page-2"] + assert predictions == [ + {"text": "page-3", "metadata": {"page_width": 3}}, + {"text": "page-1", "metadata": {"page_width": 1}}, + {"text": "page-2", "metadata": {"page_width": 2}}, + ] assert evaluation_examples == [benchmark._build_evaluation_example(example) for example in dataset] @@ -648,13 +858,17 @@ class FakeLogger: def info(self, message: str, *args: object) -> None: logged_messages.append(message % args if args else message) - class FakeOCRResult: - def __init__(self, text: str) -> None: - self.text = text - class FakeBatchBackend: async def ocr_batch(self, pages): # noqa: ANN001 - return [FakeOCRResult(text=f"page-{page.width}") for page in pages] + return [ + OCRResult( + text=f"page-{page.width}", + provider_name="fake", + model_name="fake-model", + metadata={"page_width": page.width}, + ) + for page in pages + ] monkeypatch.setattr(benchmark, "logger", FakeLogger()) monkeypatch.setattr(benchmark, "_build_ocr_backend", lambda _: FakeBatchBackend()) @@ -672,49 +886,15 @@ async def ocr_batch(self, pages): # noqa: ANN001 total_pages=2, ) - assert predictions == ["page-3", "page-1"] + assert predictions == [ + {"text": "page-3", "metadata": {"page_width": 3}}, + {"text": "page-1", "metadata": {"page_width": 1}}, + ] assert logged_messages == [ "First benchmark OCR output for backend=hf model=kristaller486/dots.ocr-1.5:\npage-3" ] -@pytest.mark.asyncio -async def test_predict_texts_uses_max_concurrency_for_vllm_batch_backend(monkeypatch) -> None: - dataset = [ - _benchmark_example(str(index), size=(index + 1, index + 1), transcription=f"text-{index}") - for index in range(10) - ] - captured_batch_sizes: list[int] = [] - - class FakeOCRResult: - def __init__(self, text: str) -> None: - self.text = text - - class FakeBatchBackend: - async def ocr_batch(self, pages): # noqa: ANN001 - captured_batch_sizes.append(len(pages)) - return [FakeOCRResult(text=f"page-{page.width}") for page in pages] - - monkeypatch.setattr(benchmark, "_build_ocr_backend", lambda _: FakeBatchBackend()) - - options = benchmark.BenchmarkOptions( - backend="vllm", - dataset_split="dev", - model="Qwen/Qwen3.5-0.8B", - max_concurrency=2, - ) - - evaluation_examples, predictions = await benchmark._predict_texts( - dataset, - options, - total_pages=10, - ) - - assert captured_batch_sizes == [2, 2, 2, 2, 2] - assert predictions == [f"page-{index + 1}" for index in range(10)] - assert evaluation_examples == [benchmark._build_evaluation_example(example) for example in dataset] - - @pytest.mark.asyncio async def test_predict_texts_logs_first_submitted_output_once_for_non_batch_backend(monkeypatch) -> None: dataset: list[BenchmarkDatasetExample] = [ @@ -728,14 +908,15 @@ class FakeLogger: def info(self, message: str, *args: object) -> None: logged_messages.append(message % args if args else message) - class FakeOCRResult: - def __init__(self, text: str) -> None: - self.text = text - class FakeOCRBackend: async def ocr(self, page): # noqa: ANN001 await asyncio.sleep(page.width / 1000) - return FakeOCRResult(text=f"page-{page.width}") + return OCRResult( + text=f"page-{page.width}", + provider_name="fake", + model_name="fake-model", + metadata={"page_width": page.width}, + ) monkeypatch.setattr(benchmark, "logger", FakeLogger()) monkeypatch.setattr(benchmark, "_build_ocr_backend", lambda _: FakeOCRBackend()) @@ -754,5 +935,9 @@ async def ocr(self, page): # noqa: ANN001 total_pages=3, ) - assert predictions == ["page-3", "page-1", "page-2"] + assert predictions == [ + {"text": "page-3", "metadata": {"page_width": 3}}, + {"text": "page-1", "metadata": {"page_width": 1}}, + {"text": "page-2", "metadata": {"page_width": 2}}, + ] assert logged_messages == ["First benchmark OCR output for backend=azure model=