evalsuite-python 0.3.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/CHANGELOG.md +68 -0
  2. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/PKG-INFO +63 -22
  3. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/README.md +49 -20
  4. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/pyproject.toml +18 -2
  5. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/__init__.py +5 -1
  6. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/benchmarks.py +251 -9
  7. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/cli/main.py +31 -1
  8. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/validation.py +21 -0
  9. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/plot.py +146 -0
  10. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/regression/metrics.py +9 -1
  11. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/_resolve.py +29 -4
  12. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/compare.py +7 -3
  13. evalsuite_python-0.4.0/src/evalsuite/text/__init__.py +152 -0
  14. evalsuite_python-0.4.0/src/evalsuite/text/_common.py +94 -0
  15. evalsuite_python-0.4.0/src/evalsuite/text/factuality.py +469 -0
  16. evalsuite_python-0.4.0/src/evalsuite/text/generation.py +1126 -0
  17. evalsuite_python-0.4.0/src/evalsuite/text/judge.py +532 -0
  18. evalsuite_python-0.4.0/src/evalsuite/text/qa.py +108 -0
  19. evalsuite_python-0.4.0/src/evalsuite/text/rag.py +235 -0
  20. evalsuite_python-0.4.0/src/evalsuite/text/reasoning.py +215 -0
  21. evalsuite_python-0.4.0/src/evalsuite/text/report.py +158 -0
  22. evalsuite_python-0.4.0/src/evalsuite/text/retrieval.py +238 -0
  23. evalsuite_python-0.4.0/src/evalsuite/text/semantic.py +465 -0
  24. evalsuite_python-0.4.0/src/evalsuite/text/structured.py +789 -0
  25. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/version.py +1 -1
  26. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/vision/segmentation.py +9 -1
  27. evalsuite_python-0.4.0/tests/integration/test_qa.py +311 -0
  28. evalsuite_python-0.4.0/tests/integration/test_readme_examples.py +147 -0
  29. evalsuite_python-0.4.0/tests/integration/test_repo_hygiene.py +97 -0
  30. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/output/test_benchmarks.py +35 -1
  31. evalsuite_python-0.4.0/tests/text/test_against_references.py +256 -0
  32. evalsuite_python-0.4.0/tests/text/test_text_edges.py +175 -0
  33. evalsuite_python-0.4.0/tests/text/test_v040.py +835 -0
  34. evalsuite_python-0.4.0/tests/vision/__init__.py +0 -0
  35. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/vision/test_edges.py +10 -0
  36. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/.gitignore +0 -0
  37. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/CONTRIBUTING.md +0 -0
  38. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/LICENSE +0 -0
  39. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/__main__.py +0 -0
  40. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/api.py +0 -0
  41. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/calibration.py +0 -0
  42. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/classification/__init__.py +0 -0
  43. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/classification/_common.py +0 -0
  44. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/classification/metrics.py +0 -0
  45. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/cli/__init__.py +0 -0
  46. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/clinical/__init__.py +0 -0
  47. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/clinical/metrics.py +0 -0
  48. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/clinical/report.py +0 -0
  49. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/__init__.py +0 -0
  50. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/context.py +0 -0
  51. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/exceptions.py +0 -0
  52. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/export.py +0 -0
  53. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/registry.py +0 -0
  54. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/result.py +0 -0
  55. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/core/types.py +0 -0
  56. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/py.typed +0 -0
  57. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/regression/__init__.py +0 -0
  58. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/reporting.py +0 -0
  59. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/__init__.py +0 -0
  60. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/effect.py +0 -0
  61. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/hypothesis.py +0 -0
  62. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/intervals.py +0 -0
  63. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/paired.py +0 -0
  64. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/stats/results.py +0 -0
  65. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/vision/__init__.py +0 -0
  66. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/src/evalsuite/vision/detection.py +0 -0
  67. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/__init__.py +0 -0
  68. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/classification/__init__.py +0 -0
  69. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/classification/test_against_sklearn.py +0 -0
  70. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/clinical/__init__.py +0 -0
  71. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/clinical/test_outputs.py +0 -0
  72. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/clinical/test_v020.py +0 -0
  73. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/conftest.py +0 -0
  74. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/integration/__init__.py +0 -0
  75. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/output/__init__.py +0 -0
  76. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/output/test_cli.py +0 -0
  77. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/output/test_plot.py +0 -0
  78. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/output/test_reporting.py +0 -0
  79. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/regression/__init__.py +0 -0
  80. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/regression/test_against_sklearn.py +0 -0
  81. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/stats/__init__.py +0 -0
  82. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/stats/test_branches.py +0 -0
  83. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/stats/test_compare.py +0 -0
  84. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/stats/test_reference.py +0 -0
  85. {evalsuite_python-0.3.0/tests/unit → evalsuite_python-0.4.0/tests/text}/__init__.py +0 -0
  86. {evalsuite_python-0.3.0/tests/vision → evalsuite_python-0.4.0/tests/unit}/__init__.py +0 -0
  87. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/unit/test_core.py +0 -0
  88. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/unit/test_edges.py +0 -0
  89. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/vision/test_detection.py +0 -0
  90. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/vision/test_outputs.py +0 -0
  91. {evalsuite_python-0.3.0 → evalsuite_python-0.4.0}/tests/vision/test_segmentation.py +0 -0
@@ -6,6 +6,74 @@ All notable changes to this project are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.0] - 2026-10-09
10
+
11
+ LLM evaluation (the v0.4.0 roadmap). No existing API changed.
12
+
13
+ ### Added
14
+ - `es.text` and top-level functions for language-model evaluation; 69 new registered metrics, each checked
15
+ against a reference implementation where one exists:
16
+ - Text generation: BLEU, sentence BLEU, chrF/chrF++, TER (sacreBLEU), ROUGE-1/2/L/Lsum (rouge-score),
17
+ METEOR (NLTK, synonyms pluggable), CIDEr-D (pycocoevalcap), perplexity, cross-entropy, Distinct-n,
18
+ Self-BLEU, MAUVE (mauve-text divergence frontier, NumPy k-means).
19
+ - Semantic: BERTScore, embedding cosine / Euclidean / Manhattan, MoverScore (exact transport, = POT), and
20
+ `model_score` to run COMET, BLEURT, BARTScore, AlignScore or any scorer with intervals and comparison.
21
+ - Factuality: faithfulness, hallucination (unsupported-claim) rate, groundedness, citation precision and
22
+ recall (ALCE), claim-verification accuracy, knowledge consistency, answer correctness and relevance
23
+ (RAGAS), abstention accuracy, exact match and token F1 (SQuAD).
24
+ - LLM-as-a-judge: win rate, Bradley–Terry (= choix), Elo, Krippendorff's alpha (= krippendorff), Fleiss'
25
+ kappa (= statsmodels), judge–human agreement, position consistency, verbosity and self-preference bias,
26
+ rubric scores.
27
+ - Reasoning: pass@k, majority-vote accuracy, answer extraction and benchmark accuracy (GSM8K, MATH,
28
+ multiple choice).
29
+ - RAG: Precision/Recall/Hit rate@k, MRR, MAP, NDCG (= ranx), context precision, recall and relevance,
30
+ latency summary, task success rate, failure attribution.
31
+ - Structured output: JSON validity, JSON Schema compliance (built-in validator, agrees with jsonschema),
32
+ XML validity, required-field accuracy, tool selection / argument accuracy and tool-call F1, API-call
33
+ success, instruction compliance, constraint satisfaction, format compliance, multi-turn retention,
34
+ extra-content rate.
35
+ - `es.text_report` and `evalsuite text` (CLI) for the reference-based text metrics in one report.
36
+ - `bootstrap_ci`, `compare` and the paired tests resample whole items (texts, reference lists, rankings) for
37
+ these metrics, so corpus metrics such as BLEU get proper intervals.
38
+ - Benchmark suite `llm` against sacreBLEU, rouge-score, NLTK, ranx, krippendorff and jsonschema.
39
+ - `llm` extra (`nltk`) for METEOR's default Porter stemmer.
40
+ - Plots: `es.plot.ratings` (Bradley–Terry or Elo leaderboard with bootstrap intervals), `es.plot.win_matrix`
41
+ (pairwise win rates) and `es.plot.text_scores` (per-example score distributions by system).
42
+ - Benchmark overall summary counts cases without their size suffixes.
43
+
44
+ ### Not included
45
+ - SPICE (needs a Java scene-graph parser); BLEURT, COMET, BARTScore and AlignScore run through
46
+ `es.model_score` with your model rather than being bundled.
47
+
48
+ ## [0.3.1] - 2026-10-09
49
+
50
+ Quality-assurance release: release pipeline, packaging checks, edge-case fixes and an overall benchmark.
51
+ No API was removed or renamed; code written for 0.3.0 runs unchanged.
52
+
53
+ ### Fixed
54
+ - Labels that mix numbers and strings (`[0, "a"]`, or string `y_true` with integer `y_pred`) now raise
55
+ `InputValidationError` instead of being silently compared as text.
56
+ - `rmse` no longer overflows to `inf` when errors exceed ~1e154; the value is computed with rescaling.
57
+ - `bootstrap_ci`, `paired_bootstrap_test` and `compare` raise `StatisticalTestError` for fewer than two
58
+ observations instead of returning a zero-width interval.
59
+ - A 2-D mask given as a nested Python list (`[[1, 1], [0, 0]]`) is read as one image, as a NumPy array is.
60
+ - Release workflow: the GitHub release step no longer fails when the release already exists (for example
61
+ when the tag was created from the GitHub UI); it attaches the files instead.
62
+
63
+ ### Added
64
+ - Benchmarks: an overall summary first (per suite and in total: cases, agreement with the reference,
65
+ how many are faster, geometric-mean and range of speed-ups) and rows in alphabetical order;
66
+ `BenchmarkResult.overall()`, `overall_markdown()` and `sorted_rows()`; `overall` in the JSON export.
67
+ - Release workflow: refuses a tag that does not match the package version or a version already on PyPI,
68
+ checks the built files, uses `--verify-tag`, and can be run by hand to attach a version's PyPI files
69
+ (hash-verified) to its GitHub release.
70
+ - CI: wheel and sdist installed in clean environments with `pip check` and a smoke test that must give the
71
+ same results for both, a distribution check (metadata, forbidden files, credentials), a minimum-dependency
72
+ job (NumPy 1.22, SciPy 1.8, pandas 1.4), README examples run as tests, and repository hygiene tests
73
+ (no credentials, no unsafe calls, least-privilege workflows, single version source).
74
+ - QA tests against scikit-learn and statsmodels for the edge cases in the release checklist.
75
+ - `SECURITY.md` with the reporting process.
76
+
9
77
  ## [0.3.0] - 2026-10-09
10
78
 
11
79
  Computer vision (the v0.3.0 roadmap), with comparison, plots, reporting and benchmarks extended to it.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: evalsuite-python
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: A unified Python framework for machine-learning, clinical, statistical, segmentation, object-detection, uncertainty, and model evaluation.
5
5
  Project-URL: Homepage, https://evalsuite-nine.vercel.app
6
6
  Project-URL: Documentation, https://evalsuite-nine.vercel.app/docs
@@ -36,22 +36,34 @@ Requires-Dist: pandas>=1.4
36
36
  Requires-Dist: scipy>=1.8
37
37
  Provides-Extra: all
38
38
  Requires-Dist: matplotlib>=3.5; extra == 'all'
39
+ Requires-Dist: nltk>=3.8; extra == 'all'
39
40
  Requires-Dist: pillow>=9; extra == 'all'
40
41
  Provides-Extra: dev
41
42
  Requires-Dist: build; extra == 'dev'
43
+ Requires-Dist: choix>=0.3; extra == 'dev'
42
44
  Requires-Dist: hypothesis>=6.80; extra == 'dev'
45
+ Requires-Dist: jsonschema>=4.18; extra == 'dev'
46
+ Requires-Dist: krippendorff>=0.6; extra == 'dev'
43
47
  Requires-Dist: matplotlib>=3.5; extra == 'dev'
44
48
  Requires-Dist: mypy>=1.10; extra == 'dev'
49
+ Requires-Dist: nltk>=3.8; extra == 'dev'
45
50
  Requires-Dist: pandas-stubs; extra == 'dev'
46
51
  Requires-Dist: pillow>=9; extra == 'dev'
47
52
  Requires-Dist: pip-audit; extra == 'dev'
53
+ Requires-Dist: pot>=0.9; (python_version < '3.14') and extra == 'dev'
54
+ Requires-Dist: pycocoevalcap>=1.2; extra == 'dev'
48
55
  Requires-Dist: pycocotools>=2.0.7; extra == 'dev'
49
56
  Requires-Dist: pytest-cov>=4; extra == 'dev'
50
57
  Requires-Dist: pytest>=7; extra == 'dev'
58
+ Requires-Dist: ranx>=0.3.19; (python_version < '3.14') and extra == 'dev'
59
+ Requires-Dist: rouge-score>=0.1.2; extra == 'dev'
51
60
  Requires-Dist: ruff>=0.6; extra == 'dev'
52
- Requires-Dist: scikit-learn>=1.2; extra == 'dev'
61
+ Requires-Dist: sacrebleu>=2.4; extra == 'dev'
62
+ Requires-Dist: scikit-learn>=1.4; extra == 'dev'
53
63
  Requires-Dist: statsmodels>=0.13; extra == 'dev'
54
64
  Requires-Dist: twine; extra == 'dev'
65
+ Provides-Extra: llm
66
+ Requires-Dist: nltk>=3.8; extra == 'llm'
55
67
  Provides-Extra: plot
56
68
  Requires-Dist: matplotlib>=3.5; extra == 'plot'
57
69
  Provides-Extra: vision
@@ -65,12 +77,14 @@ Description-Content-Type: text/markdown
65
77
  [![Python](https://img.shields.io/pypi/pyversions/evalsuite-python)](https://pypi.org/project/evalsuite-python/)
66
78
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
67
79
 
68
- **Unified, reproducible evaluation for machine learning and research.**
80
+ **Unified, reproducible evaluation for machine learning, LLM and research.**
69
81
 
70
82
  EvalSuite brings classification, regression, clinical, statistical, segmentation and object-detection
71
83
  evaluation into one consistent, validated, documented framework.
72
84
 
73
- > **Status: stable (0.3.0).** Every item on the 0.1.0, 0.2.0 and 0.3.0 roadmaps is implemented and verified.
85
+ > **Status: stable (0.4.0).** Every item on the 0.1.0, 0.2.0, 0.3.0 and 0.4.0 roadmaps is implemented and verified
86
+ > (except SPICE, which needs a Java scene-graph parser).
87
+ > **LLM evaluation is available from 0.4.0**; LLM systems, safety and operations are planned for 0.5.0.
74
88
 
75
89
  ## Installation
76
90
 
@@ -226,6 +240,22 @@ Models can be compared over the same images with intervals and paired tests, as
226
240
  `es.compare(y_true, {"unet": masks_a, "deeplab": masks_b})` resamples images; for detection it compares
227
241
  mAP.
228
242
 
243
+ ## LLM evaluation
244
+
245
+ ```python
246
+ es.bleu(references, predictions) # sacreBLEU-identical; also chrf, ter, rouge_l, meteor, cider
247
+ es.text_report(references, predictions) # BLEU, chrF(++), TER, ROUGE, METEOR, EM, token F1 at once
248
+ es.bertscore(ref_token_embs, pred_token_embs) # from your encoder's embeddings; also mauve, moverscore
249
+ es.model_score(refs, preds, scorer=comet_fn) # any learned metric or judge, with intervals and compare
250
+ es.faithfulness(claim_verdicts) # also hallucination_rate, citation_recall, answer_correctness
251
+ es.bradley_terry(comparisons, scale="elo") # also win_rate, elo_ratings, krippendorff_alpha
252
+ es.ndcg_at_k(relevant, retrieved, k=10) # also mrr, context_precision, context_recall
253
+ es.json_schema_compliance(outputs, schema) # also tool_call_f1, instruction_compliance_rate
254
+ es.pass_at_k(n_samples, n_correct, k=10) # also benchmark_accuracy(..., style="gsm8k")
255
+ es.compare(references, {"a": preds_a, "b": preds_b}, metrics=["bleu", "rouge_l"]) # paired over examples
256
+ es.plot.ratings(comparisons) # Bradley–Terry leaderboard with intervals; also win_matrix, text_scores
257
+ ```
258
+
229
259
  ## Classification report
230
260
 
231
261
  ```python
@@ -283,24 +313,35 @@ Input files can be CSV, TSV, Parquet or JSON. Output format follows `--format` o
283
313
  ## Performance
284
314
 
285
315
  Benchmarked against reference implementations on the same data (fastest of 5 runs; Python 3.12, NumPy 2.5,
286
- Linux x86_64). Every result agrees with the reference to floating-point rounding (largest difference
287
- 1.4e-14).
288
-
289
- | Case | n | Reference | EvalSuite (ms) | Reference (ms) | Speed-up |
290
- | --- | ---: | --- | ---: | ---: | ---: |
291
- | 8 binary label metrics via `evaluate()` | 1,000,000 | scikit-learn | 30.2 | 1020.2 | **33.8×** |
292
- | macro F1, 10 classes | 1,000,000 | scikit-learn | 22.4 | 128.7 | **5.8×** |
293
- | ROC AUC, binary | 1,000,000 | scikit-learn | 173.2 | 300.6 | **1.7×** |
294
- | MAE, MSE, RMSE, R² via `evaluate()` | 1,000,000 | scikit-learn | 19.1 | 9.7 | 0.51× |
295
- | sensitivity, specificity, LR+, LR− | 1,000,000 | scikit-learn | 66.2 | 392.8 | **5.9×** |
296
- | calibration slope and intercept | 1,000,000 | statsmodels | 178.0 | 1014.8 | **5.7×** |
297
- | decision curve, 99 thresholds | 1,000,000 | NumPy loop | 155.2 | 174.3 | **1.1×** |
298
- | diagnostic report (7 CIs) | 1,000,000 | statsmodels | 16.6 | 4.6 | 0.28× |
299
- | Welch t-test | 1,000,000 | SciPy | 14.5 | 7.3 | 0.51× |
300
- | Hochberg correction | 1,000,000 | statsmodels | 75.4 | 81.9 | **1.1×** |
301
- | segmentation Dice and IoU per class | 1,000,000 px | scikit-learn | 40.2 | 282.0 | **7.0×** |
302
- | COCO detection evaluation (12 numbers) | 1,000 images | pycocotools | 967.4 | 980.6 | **1.0×** |
303
- | Hausdorff distance | 50 images | SciPy | 26.2 | 20.8 | 0.79× |
316
+ Linux x86_64). **Overall: 63 of 63 rows agree with the reference** (largest
317
+ difference 1.8e-14), 42 are faster, and the geometric-mean speed-up across all
318
+ 21 cases and three sizes is **2.12×**. At 1,000,000 samples (pixels for
319
+ segmentation; 1,000 images for detection and 50 for Hausdorff; 10,000 examples for the LLM cases), in
320
+ alphabetical order:
321
+
322
+ | Case | Reference | EvalSuite (ms) | Reference (ms) | Speed-up |
323
+ | --- | --- | ---: | ---: | ---: |
324
+ | 10 classes: macro F1 | scikit-learn | 23.8 | 135.5 | **5.7×** |
325
+ | agreement: Krippendorff's alpha, interval (4 raters × 10000 items) | krippendorff | 3.5 | 3.4 | 0.96× |
326
+ | binary: 8 label metrics via evaluate() | scikit-learn | 28.5 | 1023.8 | **36.0×** |
327
+ | binary: ROC AUC | scikit-learn | 187.4 | 327.3 | **1.7×** |
328
+ | calibration: slope and intercept | statsmodels | 205.7 | 1173.7 | **5.7×** |
329
+ | clinical: diagnostic report (7 CIs) | statsmodels | 19.6 | 4.9 | 0.25× |
330
+ | clinical: sensitivity, specificity, LR+, LR− | scikit-learn | 75.2 | 411.5 | **5.5×** |
331
+ | decision curve: 99 thresholds | NumPy loop | 165.0 | 201.9 | **1.2×** |
332
+ | detection: COCO evaluation (1000 images) | pycocotools | 838.7 | 848.6 | **1.0×** |
333
+ | multiple testing: Hochberg (n p-values) | statsmodels | 72.1 | 79.0 | **1.1×** |
334
+ | regression: MAE, MSE, RMSE, R² via evaluate() | scikit-learn | 22.9 | 10.6 | 0.47× |
335
+ | retrieval: MRR, MAP@20, NDCG@10 (10000 queries) | ranx | 170.4 | 861.0 | **5.1×** |
336
+ | segmentation: Dice and IoU per class (n = pixels) | scikit-learn | 34.3 | 256.0 | **7.5×** |
337
+ | segmentation: Hausdorff distance (50 images) | SciPy | 24.2 | 19.8 | 0.82× |
338
+ | statistics: Cramér's V (5×5 table) | SciPy | 0.2 | 0.2 | **1.0×** |
339
+ | statistics: Mann–Whitney U | SciPy | 353.5 | 340.6 | 0.96× |
340
+ | statistics: Welch t-test | SciPy | 16.1 | 8.3 | 0.52× |
341
+ | structured: JSON Schema compliance (10000 documents) | jsonschema | 144.6 | 330.5 | **2.3×** |
342
+ | text: corpus BLEU and chrF (10000 sentences) | sacreBLEU | 2789.8 | 3051.8 | **1.1×** |
343
+ | text: METEOR, exact and stem matches (10000 sentences) | NLTK | 488.1 | 626.7 | **1.3×** |
344
+ | text: ROUGE-1, ROUGE-2, ROUGE-L (10000 sentences) | rouge-score | 1290.1 | 1095.6 | 0.85× |
304
345
 
305
346
  `evaluate()` validates inputs once and builds the confusion matrix once for all metrics, which is where most
306
347
  of the speed-up comes from. Hypothesis tests use SciPy underneath, so they match its speed at best; rows
@@ -5,12 +5,14 @@
5
5
  [![Python](https://img.shields.io/pypi/pyversions/evalsuite-python)](https://pypi.org/project/evalsuite-python/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
7
 
8
- **Unified, reproducible evaluation for machine learning and research.**
8
+ **Unified, reproducible evaluation for machine learning, LLM and research.**
9
9
 
10
10
  EvalSuite brings classification, regression, clinical, statistical, segmentation and object-detection
11
11
  evaluation into one consistent, validated, documented framework.
12
12
 
13
- > **Status: stable (0.3.0).** Every item on the 0.1.0, 0.2.0 and 0.3.0 roadmaps is implemented and verified.
13
+ > **Status: stable (0.4.0).** Every item on the 0.1.0, 0.2.0, 0.3.0 and 0.4.0 roadmaps is implemented and verified
14
+ > (except SPICE, which needs a Java scene-graph parser).
15
+ > **LLM evaluation is available from 0.4.0**; LLM systems, safety and operations are planned for 0.5.0.
14
16
 
15
17
  ## Installation
16
18
 
@@ -166,6 +168,22 @@ Models can be compared over the same images with intervals and paired tests, as
166
168
  `es.compare(y_true, {"unet": masks_a, "deeplab": masks_b})` resamples images; for detection it compares
167
169
  mAP.
168
170
 
171
+ ## LLM evaluation
172
+
173
+ ```python
174
+ es.bleu(references, predictions) # sacreBLEU-identical; also chrf, ter, rouge_l, meteor, cider
175
+ es.text_report(references, predictions) # BLEU, chrF(++), TER, ROUGE, METEOR, EM, token F1 at once
176
+ es.bertscore(ref_token_embs, pred_token_embs) # from your encoder's embeddings; also mauve, moverscore
177
+ es.model_score(refs, preds, scorer=comet_fn) # any learned metric or judge, with intervals and compare
178
+ es.faithfulness(claim_verdicts) # also hallucination_rate, citation_recall, answer_correctness
179
+ es.bradley_terry(comparisons, scale="elo") # also win_rate, elo_ratings, krippendorff_alpha
180
+ es.ndcg_at_k(relevant, retrieved, k=10) # also mrr, context_precision, context_recall
181
+ es.json_schema_compliance(outputs, schema) # also tool_call_f1, instruction_compliance_rate
182
+ es.pass_at_k(n_samples, n_correct, k=10) # also benchmark_accuracy(..., style="gsm8k")
183
+ es.compare(references, {"a": preds_a, "b": preds_b}, metrics=["bleu", "rouge_l"]) # paired over examples
184
+ es.plot.ratings(comparisons) # Bradley–Terry leaderboard with intervals; also win_matrix, text_scores
185
+ ```
186
+
169
187
  ## Classification report
170
188
 
171
189
  ```python
@@ -223,24 +241,35 @@ Input files can be CSV, TSV, Parquet or JSON. Output format follows `--format` o
223
241
  ## Performance
224
242
 
225
243
  Benchmarked against reference implementations on the same data (fastest of 5 runs; Python 3.12, NumPy 2.5,
226
- Linux x86_64). Every result agrees with the reference to floating-point rounding (largest difference
227
- 1.4e-14).
228
-
229
- | Case | n | Reference | EvalSuite (ms) | Reference (ms) | Speed-up |
230
- | --- | ---: | --- | ---: | ---: | ---: |
231
- | 8 binary label metrics via `evaluate()` | 1,000,000 | scikit-learn | 30.2 | 1020.2 | **33.8×** |
232
- | macro F1, 10 classes | 1,000,000 | scikit-learn | 22.4 | 128.7 | **5.8×** |
233
- | ROC AUC, binary | 1,000,000 | scikit-learn | 173.2 | 300.6 | **1.7×** |
234
- | MAE, MSE, RMSE, R² via `evaluate()` | 1,000,000 | scikit-learn | 19.1 | 9.7 | 0.51× |
235
- | sensitivity, specificity, LR+, LR− | 1,000,000 | scikit-learn | 66.2 | 392.8 | **5.9×** |
236
- | calibration slope and intercept | 1,000,000 | statsmodels | 178.0 | 1014.8 | **5.7×** |
237
- | decision curve, 99 thresholds | 1,000,000 | NumPy loop | 155.2 | 174.3 | **1.1×** |
238
- | diagnostic report (7 CIs) | 1,000,000 | statsmodels | 16.6 | 4.6 | 0.28× |
239
- | Welch t-test | 1,000,000 | SciPy | 14.5 | 7.3 | 0.51× |
240
- | Hochberg correction | 1,000,000 | statsmodels | 75.4 | 81.9 | **1.1×** |
241
- | segmentation Dice and IoU per class | 1,000,000 px | scikit-learn | 40.2 | 282.0 | **7.0×** |
242
- | COCO detection evaluation (12 numbers) | 1,000 images | pycocotools | 967.4 | 980.6 | **1.0×** |
243
- | Hausdorff distance | 50 images | SciPy | 26.2 | 20.8 | 0.79× |
244
+ Linux x86_64). **Overall: 63 of 63 rows agree with the reference** (largest
245
+ difference 1.8e-14), 42 are faster, and the geometric-mean speed-up across all
246
+ 21 cases and three sizes is **2.12×**. At 1,000,000 samples (pixels for
247
+ segmentation; 1,000 images for detection and 50 for Hausdorff; 10,000 examples for the LLM cases), in
248
+ alphabetical order:
249
+
250
+ | Case | Reference | EvalSuite (ms) | Reference (ms) | Speed-up |
251
+ | --- | --- | ---: | ---: | ---: |
252
+ | 10 classes: macro F1 | scikit-learn | 23.8 | 135.5 | **5.7×** |
253
+ | agreement: Krippendorff's alpha, interval (4 raters × 10000 items) | krippendorff | 3.5 | 3.4 | 0.96× |
254
+ | binary: 8 label metrics via evaluate() | scikit-learn | 28.5 | 1023.8 | **36.0×** |
255
+ | binary: ROC AUC | scikit-learn | 187.4 | 327.3 | **1.7×** |
256
+ | calibration: slope and intercept | statsmodels | 205.7 | 1173.7 | **5.7×** |
257
+ | clinical: diagnostic report (7 CIs) | statsmodels | 19.6 | 4.9 | 0.25× |
258
+ | clinical: sensitivity, specificity, LR+, LR− | scikit-learn | 75.2 | 411.5 | **5.5×** |
259
+ | decision curve: 99 thresholds | NumPy loop | 165.0 | 201.9 | **1.2×** |
260
+ | detection: COCO evaluation (1000 images) | pycocotools | 838.7 | 848.6 | **1.0×** |
261
+ | multiple testing: Hochberg (n p-values) | statsmodels | 72.1 | 79.0 | **1.1×** |
262
+ | regression: MAE, MSE, RMSE, R² via evaluate() | scikit-learn | 22.9 | 10.6 | 0.47× |
263
+ | retrieval: MRR, MAP@20, NDCG@10 (10000 queries) | ranx | 170.4 | 861.0 | **5.1×** |
264
+ | segmentation: Dice and IoU per class (n = pixels) | scikit-learn | 34.3 | 256.0 | **7.5×** |
265
+ | segmentation: Hausdorff distance (50 images) | SciPy | 24.2 | 19.8 | 0.82× |
266
+ | statistics: Cramér's V (5×5 table) | SciPy | 0.2 | 0.2 | **1.0×** |
267
+ | statistics: Mann–Whitney U | SciPy | 353.5 | 340.6 | 0.96× |
268
+ | statistics: Welch t-test | SciPy | 16.1 | 8.3 | 0.52× |
269
+ | structured: JSON Schema compliance (10000 documents) | jsonschema | 144.6 | 330.5 | **2.3×** |
270
+ | text: corpus BLEU and chrF (10000 sentences) | sacreBLEU | 2789.8 | 3051.8 | **1.1×** |
271
+ | text: METEOR, exact and stem matches (10000 sentences) | NLTK | 488.1 | 626.7 | **1.3×** |
272
+ | text: ROUGE-1, ROUGE-2, ROUGE-L (10000 sentences) | rouge-score | 1290.1 | 1095.6 | 0.85× |
244
273
 
245
274
  `evaluate()` validates inputs once and builds the confusion matrix once for all metrics, which is where most
246
275
  of the speed-up comes from. Hypothesis tests use SciPy underneath, so they match its speed at best; rows
@@ -38,16 +38,26 @@ dependencies = ["numpy>=1.22", "scipy>=1.8", "pandas>=1.4"]
38
38
  [project.optional-dependencies]
39
39
  plot = ["matplotlib>=3.5"]
40
40
  vision = ["pillow>=9"]
41
- all = ["matplotlib>=3.5", "pillow>=9"]
41
+ llm = ["nltk>=3.8"]
42
+ all = ["matplotlib>=3.5", "pillow>=9", "nltk>=3.8"]
42
43
  dev = [
43
44
  "pytest>=7",
44
45
  "pytest-cov>=4",
45
46
  "hypothesis>=6.80",
46
- "scikit-learn>=1.2",
47
+ "scikit-learn>=1.4",
47
48
  "statsmodels>=0.13",
48
49
  "matplotlib>=3.5",
49
50
  "pillow>=9",
50
51
  "pycocotools>=2.0.7",
52
+ "nltk>=3.8",
53
+ "sacrebleu>=2.4",
54
+ "rouge-score>=0.1.2",
55
+ "pycocoevalcap>=1.2",
56
+ "jsonschema>=4.18",
57
+ "choix>=0.3",
58
+ "krippendorff>=0.6",
59
+ "pot>=0.9; python_version < '3.14'",
60
+ "ranx>=0.3.19; python_version < '3.14'",
51
61
  "ruff>=0.6",
52
62
  "mypy>=1.10",
53
63
  "pandas-stubs",
@@ -99,6 +109,12 @@ files = ["src/evalsuite"]
99
109
  module = ["scipy.*", "matplotlib.*"]
100
110
  ignore_missing_imports = true
101
111
 
112
+ [[tool.mypy.overrides]]
113
+ # optional reference libraries used only by the benchmarks and METEOR's default stemmer
114
+ module = ["sacrebleu.*", "rouge_score.*", "nltk.*", "ranx.*", "krippendorff.*", "jsonschema.*", "pycocotools.*"]
115
+ ignore_missing_imports = true
116
+ follow_untyped_imports = false
117
+
102
118
  [tool.pytest.ini_options]
103
119
  testpaths = ["tests"]
104
120
  addopts = "-q --strict-markers"
@@ -5,7 +5,7 @@
5
5
  >>> print(result.summary()) # doctest: +SKIP
6
6
  """
7
7
 
8
- from . import calibration, classification, clinical, plot, regression, stats, vision
8
+ from . import calibration, classification, clinical, plot, regression, stats, text, vision
9
9
  from .api import evaluate
10
10
  from .calibration import (
11
11
  CalibrationReport,
@@ -110,6 +110,8 @@ from .stats import (
110
110
  t_test,
111
111
  wilcoxon_test,
112
112
  )
113
+ from .text import * # noqa: F403 (every LLM-evaluation function, listed in text.__all__)
114
+ from .text import __all__ as _text_all
113
115
  from .version import __version__
114
116
  from .vision import (
115
117
  DetectionReport,
@@ -134,6 +136,7 @@ from .vision import (
134
136
  )
135
137
 
136
138
  __all__ = [
139
+ "text",
137
140
  "SegmentationReport",
138
141
  "segmentation_report",
139
142
  "detection_pr_curve",
@@ -258,3 +261,4 @@ __all__ = [
258
261
  "specificity",
259
262
  "top_k_accuracy",
260
263
  ]
264
+ __all__ += list(_text_all)