|
| 1 | +"""Aggregator specs embedded in per-datapoint classification evaluator configs. |
| 2 | +
|
| 3 | +Each aggregator is a run-level metric (precision / recall / f-score) attached |
| 4 | +to a classification evaluator. Classes are declared once on the parent evaluator |
| 5 | +config — every aggregator on the same evaluator operates on the same class |
| 6 | +vocabulary, so the field is not repeated per spec. Only the metric-shape fields |
| 7 | +(``averaging`` and, for fscore, ``f_value``) live on the spec itself. |
| 8 | +""" |
| 9 | + |
| 10 | +from __future__ import annotations |
| 11 | + |
| 12 | +from typing import Annotated, Literal, Union |
| 13 | + |
| 14 | +from pydantic import BaseModel, ConfigDict, Field |
| 15 | +from pydantic.alias_generators import to_camel |
| 16 | + |
| 17 | + |
| 18 | +class _AggregatorSpecBase(BaseModel): |
| 19 | + """Shared pydantic config for every aggregator variant.""" |
| 20 | + |
| 21 | + model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True) |
| 22 | + |
| 23 | + |
| 24 | +class PrecisionAggregatorSpec(_AggregatorSpecBase): |
| 25 | + """Run-level precision aggregator (multiclass, micro or macro averaged).""" |
| 26 | + |
| 27 | + type: Literal["precision"] = "precision" |
| 28 | + averaging: Literal["macro", "micro"] |
| 29 | + |
| 30 | + |
| 31 | +class RecallAggregatorSpec(_AggregatorSpecBase): |
| 32 | + """Run-level recall aggregator (multiclass, micro or macro averaged).""" |
| 33 | + |
| 34 | + type: Literal["recall"] = "recall" |
| 35 | + averaging: Literal["macro", "micro"] |
| 36 | + |
| 37 | + |
| 38 | +class FScoreAggregatorSpec(_AggregatorSpecBase): |
| 39 | + """Run-level F-beta aggregator (multiclass, micro or macro averaged).""" |
| 40 | + |
| 41 | + type: Literal["fscore"] = "fscore" |
| 42 | + averaging: Literal["macro", "micro"] |
| 43 | + # Upper bound keeps beta² finite — a huge beta overflows to inf and the |
| 44 | + # F-score becomes NaN, which is not representable in JSON. |
| 45 | + f_value: float = Field(default=1.0, gt=0, le=1000) |
| 46 | + |
| 47 | + |
| 48 | +class ConfusionMatrixAggregatorSpec(_AggregatorSpecBase): |
| 49 | + """Run-level raw k×k confusion matrix — no scalar headline, no averaging.""" |
| 50 | + |
| 51 | + type: Literal["confusion_matrix"] = "confusion_matrix" |
| 52 | + |
| 53 | + |
| 54 | +AggregatorSpec = Annotated[ |
| 55 | + Union[ |
| 56 | + PrecisionAggregatorSpec, |
| 57 | + RecallAggregatorSpec, |
| 58 | + FScoreAggregatorSpec, |
| 59 | + ConfusionMatrixAggregatorSpec, |
| 60 | + ], |
| 61 | + Field(discriminator="type"), |
| 62 | +] |
0 commit comments