Files
docling-eval/tests/test_multi_evaluator.py
Nikos LivathinosandChristoph Auer dee40e8f7d feat: Consolidate multiple evaluation results and generate a comparison matrix (#64)
* feat: Introduce the pred_modalities parameter in the BasePredictionProvider and its implementations

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Refactor main:get_prediction_provider() to add parameter that controls the visualizations.
Refactor the evaluate() to return the DatasetEvaluation as object.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Introduce the MultiEvaluator that can generate ground truth and prediction datasets and also
compute the evalution across multiple providers and modalities. Add unit test.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* chore: Update toml dependencies to include pandas, openpyxl

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Introduce staticmethod MultiEvaluator.load_multi_evaluation() to load multi-evaluations from
the disk. Update unit tests.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* fix: Allow PENDING in the _accepted_status of BaseEvaluator

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* fix: Modifications in the unit test of MultiEvaluator. Code clean up.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Introduce the Consolidator class that collects evaluation results and generates one excel report

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* chore: Improve the header names of excel export

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Extend the DatasetLayoutEvaluation with DatasetStatistics for all metrics

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Extend the Consolidator to include the standard deviation for each metric

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* chore: Update the pyproject.toml to pin to the  docling branch that supports the RT-DETRv2 model

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Extend the DatasetEvaluation to contain the evaluated and rejected samples. The rejected ones
are itemized per rejection type.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Extend the Consolidator to include the samples (evaluated, rejected) in the generated excel

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Refactor the directory structure for MultiEvaluator and Consolidator classes.
- Refactor the generated excel matrix to include the experiment and provider columns.
- Refactor the BasePredictionProvider and all providers to have class attributes for the
  prediction_provider_type and prediction_modalities.
- Introduce CLI in the examples for the generation of the consolidation matrix.

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* fix: Remove ConversionStatus.PENDING accepted status from BaseEvaluator

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* fix: MultiEvaluator fix the load_multi_evaluation()

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* feat: Add the class attributes for supported modalities in all prediction providers

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* chore: Fix code typos

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* Address predictor_info TODOs

Signed-off-by: Christoph Auer <cau@zurich.ibm.com>

* fix: Add the test_multi_evaluator as a pytest dependency for test_consolidator

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>

* Repin to docling release

Signed-off-by: Christoph Auer <cau@zurich.ibm.com>

* Regenerate lock file

Signed-off-by: Christoph Auer <cau@zurich.ibm.com>

* fix: Use defaultdict for rejected_samples

Signed-off-by: Christoph Auer <cau@zurich.ibm.com>

---------

Signed-off-by: Nikos Livathinos <nli@zurich.ibm.com>
Signed-off-by: Christoph Auer <cau@zurich.ibm.com>
Co-authored-by: Christoph Auer <cau@zurich.ibm.com>
2025-04-22 12:59:21 +02:00

87 lines
2.7 KiB
Python

from pathlib import Path
import pytest
from docling_eval.aggregations.multi_evalutor import MultiEvaluator
from docling_eval.datamodels.types import (
BenchMarkNames,
EvaluationModality,
PredictionProviderType,
)
def build_real_multi_evals():
save_dir = Path("scratch/multi_test")
benchmarks = [BenchMarkNames.DPBENCH, BenchMarkNames.DOCLAYNETV1]
prediction_provider_types = [PredictionProviderType.DOCLING]
modalities = [
EvaluationModality.LAYOUT,
EvaluationModality.MARKDOWN_TEXT,
EvaluationModality.TABLE_STRUCTURE,
]
me = MultiEvaluator(save_dir, begin_index=0)
m_evals = me(prediction_provider_types, benchmarks, modalities)
assert m_evals is not None
@pytest.mark.dependency()
def test_multi_evaluator():
r""" """
save_dir = Path("scratch/multi_test")
benchmarks = [BenchMarkNames.DPBENCH]
prediction_provider_types = [PredictionProviderType.DOCLING]
modalities = [EvaluationModality.LAYOUT, EvaluationModality.MARKDOWN_TEXT]
# Create multi evaluator for 2 samples of the dataset
me = MultiEvaluator(save_dir, begin_index=0, end_index=2)
# MultiEvaluator for 1 dataset, 1 provider, 1 modality
m_evals = me(prediction_provider_types, benchmarks, modalities)
assert m_evals is not None
assert m_evals.evaluations is not None
assert BenchMarkNames.DPBENCH in m_evals.evaluations
assert PredictionProviderType.DOCLING in m_evals.evaluations[BenchMarkNames.DPBENCH]
assert (
EvaluationModality.LAYOUT
in m_evals.evaluations[BenchMarkNames.DPBENCH][PredictionProviderType.DOCLING]
)
# MultiEvaluator for 1 dataset, 1 provider, 2 modalities
modalities.append(EvaluationModality.MARKDOWN_TEXT)
m_evals2 = me(prediction_provider_types, benchmarks, modalities)
assert m_evals2 is not None
assert m_evals2.evaluations is not None
assert BenchMarkNames.DPBENCH in m_evals2.evaluations
assert (
PredictionProviderType.DOCLING in m_evals2.evaluations[BenchMarkNames.DPBENCH]
)
assert (
EvaluationModality.MARKDOWN_TEXT
in m_evals2.evaluations[BenchMarkNames.DPBENCH][PredictionProviderType.DOCLING]
)
# TODO: Test for datasets with multiple providers
# TODO: Test for datasets with external data sources
def test_loading_from_disk():
save_dir = Path("scratch/multi_test")
loaded_m_evals = MultiEvaluator.load_multi_evaluation(save_dir)
assert loaded_m_evals is not None
# if __name__ == "__main__":
# import logging
# logging.getLogger("docling").setLevel(logging.WARNING)
# logging.getLogger(__name__).setLevel(logging.INFO)
# # test_multi_evaluator()
# test_loading_from_disk()
# # build_real_multi_evals()