evalaudit 0.3.0__tar.gz → 0.5.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.
- evalaudit-0.5.0/CHANGELOG.md +840 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/PKG-INFO +57 -33
- {evalaudit-0.3.0 → evalaudit-0.5.0}/README.md +56 -32
- evalaudit-0.5.0/analysis/README.md +108 -0
- evalaudit-0.5.0/analysis/mt-bench.md +270 -0
- evalaudit-0.5.0/analysis/output/q1_comparisons_ratings.csv +7 -0
- evalaudit-0.5.0/analysis/q1_check_v021.py +97 -0
- evalaudit-0.5.0/analysis/q1_leaderboard.py +332 -0
- evalaudit-0.5.0/analysis/q2_human_agreement.py +288 -0
- evalaudit-0.5.0/analysis/q3_alignment.py +230 -0
- evalaudit-0.5.0/analysis/q5_judge_against_human_baseline.py +617 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/_types.py +640 -211
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/agreement.py +12 -7
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/audit.py +1182 -910
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/compare.py +713 -712
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/judge.py +496 -13
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/pairwise.py +12 -10
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/power.py +14 -14
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/scores.py +6 -4
- {evalaudit-0.3.0 → evalaudit-0.5.0}/pyproject.toml +1 -1
- evalaudit-0.5.0/tests/data/README.md +35 -0
- evalaudit-0.5.0/tests/data/make_mt_bench_csv.py +77 -0
- evalaudit-0.5.0/tests/data/mt_bench_gpt4_pair.csv +2401 -0
- evalaudit-0.5.0/tests/data/mt_bench_human.csv +3356 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_agreement.py +340 -33
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_audit.py +2444 -1464
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_compare.py +20 -4
- evalaudit-0.5.0/tests/test_judge.py +6182 -0
- evalaudit-0.5.0/tests/test_not_shown.py +367 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_pairwise.py +131 -4
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_power.py +141 -21
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_scores.py +56 -3
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_version.py +84 -84
- evalaudit-0.3.0/CHANGELOG.md +0 -255
- evalaudit-0.3.0/tests/test_judge.py +0 -2395
- {evalaudit-0.3.0 → evalaudit-0.5.0}/.github/workflows/tests.yml +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/.gitignore +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/LICENSE +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/evalaudit/__init__.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/examples/.gitkeep +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/examples/interval_method_study.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/examples/pairwise_cluster_study.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/__init__.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_confidence.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.5.0}/tests/test_readme.py +0 -0
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Every change to evalaudit that a caller can see is recorded here. The format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
|
+
version numbers follow [semantic versioning](https://semver.org/). Before 1.0
|
|
6
|
+
a minor version can break things, and 0.3.0, 0.4.0 and 0.5.0 all do.
|
|
7
|
+
|
|
8
|
+
An entry marked **Breaking** changes what a call that worked on the previous
|
|
9
|
+
release returns, raises or prints. The mark goes on the entry wherever it
|
|
10
|
+
sits, under Changed, Fixed or Removed.
|
|
11
|
+
|
|
12
|
+
Every release is dated by the day PyPI received its upload, in UTC. 0.3.0 is
|
|
13
|
+
the first release with a tag, and 0.4.0 and 0.5.0 have one too. The entries
|
|
14
|
+
below 0.3.0 were reconstructed after the fact, and their contents were
|
|
15
|
+
checked against the published wheels and the commit each wheel matches.
|
|
16
|
+
|
|
17
|
+
## [Unreleased]
|
|
18
|
+
|
|
19
|
+
## [0.5.0] - 2026-09-26
|
|
20
|
+
|
|
21
|
+
`judge_validation` can now measure the judge against a second human. Most
|
|
22
|
+
of the rest is text. Several printed sentences change, most of them for
|
|
23
|
+
hyphens and plurals, and one `audit` finding changes severity. Figures
|
|
24
|
+
change in one case. In the both-orders design, `position_bias` now scores a
|
|
25
|
+
pair judged more than once in an order when its first two reversed
|
|
26
|
+
judgements held a tie and a later two did not. That moves the count of
|
|
27
|
+
pairs scored, the consistency rate and its interval, and the figures on the
|
|
28
|
+
flips. A pair judged once in each order scores as before. Anything that
|
|
29
|
+
matches on the old sentences will stop matching. Every entry was checked by
|
|
30
|
+
running the same calls against the v0.4.0 tag and against this tree.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Nothing.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- `judge_validation(..., item_ids=None, human_baseline=None, ties=None)`
|
|
39
|
+
measures the judge against a human baseline. `human_baseline` is a frame
|
|
40
|
+
with `item_id`, `cluster_id`, `rater_id` and `rating`, one row per human
|
|
41
|
+
rating, and `item_ids` names the item at each position of `human` and
|
|
42
|
+
`judge`. The result carries judge-human and human-human alpha on the same
|
|
43
|
+
items, and a percentile interval on judge-human minus human-human that
|
|
44
|
+
resamples whole clusters. The verdict reads that interval and nothing
|
|
45
|
+
else, and is called provisional when it rests on fewer than 30 clusters.
|
|
46
|
+
The interval is refused when fewer than 90% of resamples leave both
|
|
47
|
+
alphas defined.
|
|
48
|
+
|
|
49
|
+
`ties` is required with a baseline. `"category"` keeps a tie as a label of
|
|
50
|
+
its own and `"drop"` sets it aside as no label, and the choice applies to
|
|
51
|
+
every figure in the result, the headline included. Baseline items are set
|
|
52
|
+
aside by three rules in a fixed order, and the summary counts what each
|
|
53
|
+
one took. A baseline supports only `level="nominal"`. On the MT-Bench
|
|
54
|
+
human judgements the figures reproduce `analysis/mt-bench.md` to the third
|
|
55
|
+
decimal. The new arguments are refused, each with its own message, in the
|
|
56
|
+
combinations that cannot work, such as `ties` or `item_ids` without a
|
|
57
|
+
baseline. Missing values in `item_id`, `cluster_id`, `rater_id` or
|
|
58
|
+
`item_ids` are refused, and the message names the column, the count and
|
|
59
|
+
where the first one is. Every check on the baseline runs before anything
|
|
60
|
+
is resampled.
|
|
61
|
+
|
|
62
|
+
- `JudgeValidation.n_dropped_ties`, `JudgeValidation.ties`, eleven fields
|
|
63
|
+
that start with `baseline_`, and the properties `has_baseline` and
|
|
64
|
+
`has_baseline_interval`. The new fields are the last in the dataclass and
|
|
65
|
+
have defaults, so building a `JudgeValidation` by position with 0.4.0's
|
|
66
|
+
fields still works. A call that passes none of the three new arguments
|
|
67
|
+
returns the same numbers as 0.4.0.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- **Breaking.** `JudgeValidation.summary()` said "No interval was computed,
|
|
72
|
+
so nothing here is placed against sampling error." when the resamples had
|
|
73
|
+
been drawn and too few of them left alpha defined. On three items, two of
|
|
74
|
+
them unanimous, with `n_boot=2000` and `seed=0`, it now reads "There is
|
|
75
|
+
no interval on that alpha. 591 of 2000 resamples left it undefined, above
|
|
76
|
+
the 10% this reports through. Those are the resamples where every label
|
|
77
|
+
was the same, so percentiles of the rest would understate the upper
|
|
78
|
+
bound." When one resample is left undefined it reads "That is the
|
|
79
|
+
resample where every label was the same", and when only one was drawn
|
|
80
|
+
the count reads "1 of 1 resample". With `n_boot=0` it still says no
|
|
81
|
+
interval was computed. The `audit` judge finding carries the new
|
|
82
|
+
sentence.
|
|
83
|
+
|
|
84
|
+
- **Breaking.** The `audit` finding on a margin whose interval clears zero
|
|
85
|
+
opened "This is the margin between new and old, and it survives the
|
|
86
|
+
fit." No model is fitted there. It now reads "This is the margin between
|
|
87
|
+
new and old, and its interval excludes zero."
|
|
88
|
+
|
|
89
|
+
- **Breaking.** A count or figure of one was printed with a plural noun, or
|
|
90
|
+
with a verb or pronoun that assumed more than one. Each now takes the
|
|
91
|
+
singular. Anything other than one prints as before.
|
|
92
|
+
|
|
93
|
+
- `ScoreCI.summary()`. "With only 1 observations" now reads "With only 1
|
|
94
|
+
observation", and "The interval spans 1 points." now reads "The
|
|
95
|
+
interval spans 1 point."
|
|
96
|
+
- `ComparisonResult.summary()`. "1 of 1 items changed between systems."
|
|
97
|
+
now reads "1 of 1 item changed between systems."
|
|
98
|
+
- `KappaResult.summary()`. "(1 items, 2 raters, 2 categories)" now reads
|
|
99
|
+
"(1 item, 2 raters, 2 categories)".
|
|
100
|
+
- `AgreementResult.summary()`. "1 of 1 items graded more than once" now
|
|
101
|
+
reads "1 of 1 item graded more than once". Where the interval is
|
|
102
|
+
refused, "1 of 1 resamples came back undefined" now reads "1 of 1
|
|
103
|
+
resample came back undefined", and after one undefined resample "Those
|
|
104
|
+
resamples are the unanimous ones" now reads "That resample is the
|
|
105
|
+
unanimous one".
|
|
106
|
+
- `BTResult.summary()`. With two models, "0 of 1 pairs is separable" now
|
|
107
|
+
reads "0 of 1 pair is separable". With one pair separable among
|
|
108
|
+
several, "1 of 3 pairs are separable" now reads "1 of 3 pairs is
|
|
109
|
+
separable", since the verb follows the separable count. Where the
|
|
110
|
+
interval is refused, "1 of 1 resamples came back undefined" now reads
|
|
111
|
+
"1 of 1 resample came back undefined".
|
|
112
|
+
- The `ValueError` from `bradley_terry` for a missing item id. "item_id is
|
|
113
|
+
missing on 1 of 1 comparisons" now reads "item_id is missing on 1 of 1
|
|
114
|
+
comparison".
|
|
115
|
+
- `PositionBias.summary()`, randomised design. "Position A won 100.0% of 1
|
|
116
|
+
judgements" now reads "of 1 judgement". "1 pairs were also run in the
|
|
117
|
+
reverse order" now reads "1 pair was also run in the reverse order".
|
|
118
|
+
"1 judgements were ties and are left out of the rates above." now reads
|
|
119
|
+
"1 judgement was a tie and is left out of the rates above."
|
|
120
|
+
- `PositionBias.summary()`, both orders. "1 of 1 pairs were run in both
|
|
121
|
+
orders" now reads "1 of 1 pair was run in both orders", and "1 of 2
|
|
122
|
+
pairs were run in both orders" now reads "1 of 2 pairs was run in both
|
|
123
|
+
orders", since the verb follows the pairs run both ways. "on 0.0% of 1
|
|
124
|
+
pairs" now reads "on 0.0% of 1 pair", and "Of the 1 pairs it flipped
|
|
125
|
+
on" now reads "Of the 1 pair it flipped on".
|
|
126
|
+
- `LengthBias.summary()`. "(1 pairs)" now reads "(1 pair)", and "(1
|
|
127
|
+
disagreements)" now reads "(1 disagreement)", with or without a fitted
|
|
128
|
+
model. A length step that prints as 1, "1 characters of extra length
|
|
129
|
+
multiplies" or "1 characters multiplies", now reads "1 character".
|
|
130
|
+
- `PowerResult.summary()`. "you need roughly 1 paired comparisons" now
|
|
131
|
+
reads "you need roughly 1 paired comparison", and "about 1 discordant
|
|
132
|
+
pairs, and McNemar reads only those." now reads "about 1 discordant
|
|
133
|
+
pair, and McNemar reads only that one." A difference that prints as 1,
|
|
134
|
+
"is 1 points" or "a difference of 1 points", now reads "1 point".
|
|
135
|
+
|
|
136
|
+
The `audit` compare, agreement, position, length and power findings carry
|
|
137
|
+
these sentences word for word.
|
|
138
|
+
|
|
139
|
+
- **Breaking.** Compound modifiers are hyphenated in printed text.
|
|
140
|
+
|
|
141
|
+
- `PowerResult.summary()`. "To detect a 5 point difference", "leaves at
|
|
142
|
+
most a 5 point difference" and "To find a 5 point difference" now read
|
|
143
|
+
"5-point", and the same holds for any figure. "the continuity
|
|
144
|
+
corrected and exact forms" now reads "continuity-corrected", and
|
|
145
|
+
"Pairing removes the item to item difficulty" now reads
|
|
146
|
+
"item-to-item". The `audit` power finding carries these sentences.
|
|
147
|
+
- The `audit` action under "Rater agreement holds up". "Keep the double
|
|
148
|
+
graded sample" now reads "Keep the double-graded sample".
|
|
149
|
+
- The `ValueError` from `detectable_effect` and `min_sample_size` when
|
|
150
|
+
power does not exceed alpha. "A two sided test" now reads "A two-sided
|
|
151
|
+
test".
|
|
152
|
+
|
|
153
|
+
- **Breaking.** `PositionBias.summary()` printed a rate, an interval and a
|
|
154
|
+
verdict when nothing could be scored.
|
|
155
|
+
|
|
156
|
+
- Randomised design. On three pairs judged once, each a tie, it printed
|
|
157
|
+
"Each pair was judged once, so this reports the position-A win rate.
|
|
158
|
+
Position A won nan% of 0 judgements (95% CI: nan% to nan%, exact
|
|
159
|
+
binomial p=nan). The interval includes 50%, so the data cannot show
|
|
160
|
+
that position moved the judge." and went on to the caveat about
|
|
161
|
+
randomised order. It now reads "Each pair was judged once, so this
|
|
162
|
+
would report the position-A win rate. Every judgement was a tie, so
|
|
163
|
+
there is no rate to report and nothing here tests position."
|
|
164
|
+
- Both orders. On two pairs run both ways, each with a tie on one side,
|
|
165
|
+
and one pair judged once, it printed "2 of 3 pairs were run in both
|
|
166
|
+
orders, so this reports the consistency rate. The judge named the same
|
|
167
|
+
output under both orderings on nan% of 0 pairs (95% CI: nan% to nan%).
|
|
168
|
+
It never flipped, so there is no direction to test and nothing here
|
|
169
|
+
points at position." It now reads "2 of 3 pairs were run in both
|
|
170
|
+
orders, so this would report the consistency rate. In every pair run
|
|
171
|
+
both ways, the judge called a tie every time in at least one of the two
|
|
172
|
+
orders, so no pair could be scored and there is no rate to report.
|
|
173
|
+
Nothing here tests position."
|
|
174
|
+
|
|
175
|
+
The randomised summary ended "3 judgements were ties and are left out of
|
|
176
|
+
the rates above." and the both-orders one ended the same way with 2.
|
|
177
|
+
There are no rates for the ties to be left out of, so that sentence is
|
|
178
|
+
gone from both. The `audit` position finding on this data was an info
|
|
179
|
+
finding titled "The data cannot show a position effect in the pairwise
|
|
180
|
+
judgements". It is now a warning titled "Position bias is undefined on
|
|
181
|
+
this data", and it carries the new summary.
|
|
182
|
+
|
|
183
|
+
- **Breaking.** In the both-orders design, `position_bias` formed each
|
|
184
|
+
pair's couple, its first two judgements that are reverses, before looking
|
|
185
|
+
at ties, and dropped the pair if either was a tie. A pair judged more than
|
|
186
|
+
once in an order was dropped for a tied first couple even when a later
|
|
187
|
+
couple had no tie, and the summary did not say so. Ties are now set aside
|
|
188
|
+
first, so the pair is scored on its first two decisive judgements that are
|
|
189
|
+
reverses. On two consistent pairs and a third judged x/y and y/x as ties
|
|
190
|
+
and then x/y for x and y/x for y, it printed "The judge named the same
|
|
191
|
+
output under both orderings on 100.0% of 2 pairs (95% CI: 34.2% to
|
|
192
|
+
100.0%). It never flipped, so there is no direction to test and nothing
|
|
193
|
+
here points at position." It now reads "The judge named the same output
|
|
194
|
+
under both orderings on 66.7% of 3 pairs (95% CI: 20.8% to 93.9%). Of the
|
|
195
|
+
1 pair it flipped on, 1 went to whichever output was shown first (100.0%,
|
|
196
|
+
95% CI: 2.5% to 100.0%, exact binomial p=1.0000)." and goes on to say the
|
|
197
|
+
data cannot show that the flips have a direction. `n_pairs_scored` goes
|
|
198
|
+
from 2 to 3 and `n_decisive` from 0 to 1. A pair judged once in each
|
|
199
|
+
order scores as before, since setting its ties aside leaves a couple
|
|
200
|
+
exactly when neither judgement was a tie. The `audit` position finding
|
|
201
|
+
carries the new figures.
|
|
202
|
+
|
|
203
|
+
- The `rater_agreement` docstring said that without an interval nothing in
|
|
204
|
+
the result would name an outlier rater. Since 0.4.0 the summary lists
|
|
205
|
+
alpha with each rater left out and names no rater either way, and the
|
|
206
|
+
docstring now says so.
|
|
207
|
+
|
|
208
|
+
- The README said scipy computes McNemar's test. It is statsmodels. It also
|
|
209
|
+
said the package builds fifteen intervals, while its own lists named
|
|
210
|
+
seventeen. It now counts eighteen, with the interval on the human baseline
|
|
211
|
+
among the eight pinned against a reference.
|
|
212
|
+
|
|
213
|
+
### Removed
|
|
214
|
+
|
|
215
|
+
- Nothing.
|
|
216
|
+
|
|
217
|
+
## [0.4.0] - 2026-09-11
|
|
218
|
+
|
|
219
|
+
Nearly everything in 0.4.0 changes what a
|
|
220
|
+
summary or a report prints. One rule is behind it. A result that does not
|
|
221
|
+
clear its threshold has failed to show something, and it has not shown the
|
|
222
|
+
opposite. Summaries that described such a result as if the opposite were
|
|
223
|
+
shown, and verdicts decided on a point estimate where an interval existed,
|
|
224
|
+
now say what the data did and did not show. Several `audit` findings change
|
|
225
|
+
severity on data you have already run. Each breaking entry says what it
|
|
226
|
+
was, what it is now and what to do about it. Every entry was checked by
|
|
227
|
+
running the same calls against 0.3.0 from PyPI and against the code
|
|
228
|
+
released as 0.4.0.
|
|
229
|
+
|
|
230
|
+
### Changed
|
|
231
|
+
|
|
232
|
+
- **Breaking.** `audit` reads rater agreement and judge agreement off the
|
|
233
|
+
interval on alpha. An interval wholly above the threshold keeps "Rater
|
|
234
|
+
agreement holds up" or "The judge tracks the humans", and one wholly below
|
|
235
|
+
it keeps the "below the working threshold" title. An interval running both
|
|
236
|
+
sides of the threshold, or no interval at all, is now a `warning` titled
|
|
237
|
+
"The data cannot show that rater agreement clears the working threshold"
|
|
238
|
+
or "The data cannot show that the judge clears the working threshold".
|
|
239
|
+
0.3.0 decided on the point estimate. Ratings with alpha 0.730 and an
|
|
240
|
+
interval of 0.466 to 0.933 came back `info` as "Rater agreement holds up",
|
|
241
|
+
and so did any ratings audited with `n_boot=0`. Judge labels with alpha
|
|
242
|
+
0.581 and an interval of 0.467 to 0.691 came back "Judge-human agreement
|
|
243
|
+
is below the working threshold". Rerun any audit you have sent. A finding
|
|
244
|
+
that moved from `info` to `warning` also changes the report's verdict.
|
|
245
|
+
|
|
246
|
+
- **Breaking.** Without an `effect_of_interest`, `audit` no longer sizes
|
|
247
|
+
power on the margin it measured. 0.3.0 made the observed margin the effect
|
|
248
|
+
at issue, as in "The effect at issue is 5.0 points, the margin this eval
|
|
249
|
+
reports." Power computed on an observed effect is a monotone function of
|
|
250
|
+
the p-value, so on a margin whose interval includes zero the finding came
|
|
251
|
+
out `critical` almost every time and repeated the comparison. The finding
|
|
252
|
+
now reports the design's reach, the smallest difference the eval could
|
|
253
|
+
find at the configured power, and makes no claim about the margin. It is
|
|
254
|
+
a `warning` titled "No effect of interest was stated, so this reports the
|
|
255
|
+
eval's reach", because without a stated effect the audit does not know
|
|
256
|
+
what size of difference matters. Its lead says "This reports what the
|
|
257
|
+
design could find and makes no claim about the margin it measured." On 400
|
|
258
|
+
paired items with a 5.0-point margin and an interval of 1.1% to 9.0%,
|
|
259
|
+
0.3.0 opened the report with a `critical` power finding and the verdict
|
|
260
|
+
said the conclusion did not hold. Two systems with a margin of exactly
|
|
261
|
+
zero, which 0.3.0 skipped, get the same warning.
|
|
262
|
+
|
|
263
|
+
With one system and no stated effect the check is still skipped, and its
|
|
264
|
+
reason no longer offers the observed margin as a stand-in. It read
|
|
265
|
+
"Nothing to size the eval against. Pass effect_of_interest in the config,
|
|
266
|
+
or scores for two systems so the observed margin can stand in for it."
|
|
267
|
+
and now reads "No effect of interest was stated and there is no comparison
|
|
268
|
+
whose reach could be reported. Pass effect_of_interest in the config, or
|
|
269
|
+
scores for two systems."
|
|
270
|
+
|
|
271
|
+
An audit of two pass-rate systems with no stated effect now always
|
|
272
|
+
carries this warning, so its report never comes back with no warnings.
|
|
273
|
+
Set `effect_of_interest` to the difference the decision turns on.
|
|
274
|
+
|
|
275
|
+
- **Breaking.** With an `effect_of_interest` stated, `audit` puts a power
|
|
276
|
+
finding at `info` in two cases where 0.3.0 made it `critical`, because the
|
|
277
|
+
margin's interval already answers the question power asks.
|
|
278
|
+
|
|
279
|
+
- The margin's interval clears zero. The finding is titled "The margin is
|
|
280
|
+
established, and a tighter estimate would take more items". 0.3.0
|
|
281
|
+
titled it "This eval could not have detected the effect at issue".
|
|
282
|
+
- The margin's interval includes zero and stops short of the stated
|
|
283
|
+
effect in both directions. The finding is titled "The interval on the
|
|
284
|
+
margin rules out the effect at issue".
|
|
285
|
+
|
|
286
|
+
Rerun any audit whose report carried a power finding.
|
|
287
|
+
|
|
288
|
+
- **Breaking.** With an `effect_of_interest` stated, `audit` rewords the
|
|
289
|
+
power finding on a margin whose interval includes zero. Its title is now
|
|
290
|
+
"This eval had under 80% power for the effect at issue", with the
|
|
291
|
+
percentage taken from `power`, because a design
|
|
292
|
+
short of that power can still find the effect, only less often. Its action
|
|
293
|
+
no longer says "No conclusion about an effect this size can be drawn from
|
|
294
|
+
this data, in either direction. A null result here says the eval was too
|
|
295
|
+
small and says nothing about the systems." It reads the margin's interval
|
|
296
|
+
one side at a time and says one of three things. Either "The interval on
|
|
297
|
+
the margin runs past an effect this size in both directions, so the data
|
|
298
|
+
cannot show an effect this size and cannot rule one out.", or "The
|
|
299
|
+
interval on the margin rules out old ahead by this much, and it cannot
|
|
300
|
+
rule out new ahead by this much." with your system names, or for a single
|
|
301
|
+
system "No margin was measured here, so there is no interval to read
|
|
302
|
+
against an effect this size." Anything matching on the old title or action
|
|
303
|
+
will stop matching.
|
|
304
|
+
|
|
305
|
+
- **Breaking.** `AuditReport.summary()` rewords its verdict, which is the
|
|
306
|
+
first line of every report.
|
|
307
|
+
|
|
308
|
+
- With critical findings, "the conclusion this data is being asked to
|
|
309
|
+
support does not hold as stated." is now "this data cannot support the
|
|
310
|
+
conclusion as stated. That does not mean the conclusion is wrong."
|
|
311
|
+
- With warnings and no criticals, "The result stands and the design
|
|
312
|
+
weakens it, so report it with what the warning say attached." is now
|
|
313
|
+
"The checks that ran did not find a problem that leaves the conclusion
|
|
314
|
+
unsupported. That does not mean the eval is sound. Report the result
|
|
315
|
+
with what the warning says attached."
|
|
316
|
+
- With neither, "All 4 checks that ran came back clean, so the eval holds
|
|
317
|
+
up on everything this report could test." is now "The 3 checks that ran
|
|
318
|
+
did not find a problem in what they could test. That does not mean the
|
|
319
|
+
eval is sound." The number changed too. 0.3.0 counted findings, and the
|
|
320
|
+
score check gives one finding per system, so two systems made three
|
|
321
|
+
checks read as four. A single check reads "The one check that ran", and
|
|
322
|
+
a report where nothing could run reads "No check could run, so this
|
|
323
|
+
report has tested nothing."
|
|
324
|
+
|
|
325
|
+
Anything matching on the old verdicts will stop matching. The severity
|
|
326
|
+
counts are unchanged by this entry.
|
|
327
|
+
|
|
328
|
+
- **Breaking.** `audit` rewords several titles and actions.
|
|
329
|
+
|
|
330
|
+
- "No position effect in the pairwise judgements" is now "The data cannot
|
|
331
|
+
show a position effect in the pairwise judgements". Its action opens
|
|
332
|
+
"The data has not cleared the judge of position bias." where it opened
|
|
333
|
+
"Nothing to do here."
|
|
334
|
+
- "No length effect in the judge's choices" is now "The data cannot show
|
|
335
|
+
a length effect in the judge's choices". Its action "Nothing to do
|
|
336
|
+
here." is now "The data has not cleared the judge of rewarding length."
|
|
337
|
+
- An alpha that does not exist is titled "Rater agreement is undefined on
|
|
338
|
+
this data" or "Judge-human agreement is undefined on this data", and the
|
|
339
|
+
lead ends "and this data gives no alpha to hold against it." 0.3.0
|
|
340
|
+
titled it "Rater agreement is below the working threshold" or
|
|
341
|
+
"Judge-human agreement is below the working threshold", and said the
|
|
342
|
+
grades "reproduce less well than the 0.667".
|
|
343
|
+
- The action on a margin that clears zero said "The lower bound is the
|
|
344
|
+
size of the win the data actually supports." When the second system
|
|
345
|
+
leads, the lower bound is the far end of the interval. It now says "The
|
|
346
|
+
end of the interval nearer zero is the smallest margin this data
|
|
347
|
+
supports."
|
|
348
|
+
- The length lead "Two models run here and they point opposite ways." now
|
|
349
|
+
also needs the preference fit's interval to clear zero. 0.3.0 printed it
|
|
350
|
+
off the sign of a preference coefficient whose interval ran over zero,
|
|
351
|
+
and said the judge "picks the longer answer more often" beside an odds
|
|
352
|
+
ratio of 0.94 to 1.40. Such data now gets the plain lead for the
|
|
353
|
+
direction the finding reports.
|
|
354
|
+
|
|
355
|
+
- **Breaking.** Module summaries put every result that falls short of its
|
|
356
|
+
threshold in one form, "so the data cannot show that" followed by "That
|
|
357
|
+
does not mean".
|
|
358
|
+
|
|
359
|
+
- `ComparisonResult.summary()`. "The interval crosses zero, so the data
|
|
360
|
+
cannot confirm that either system is better." is now "The interval
|
|
361
|
+
includes zero, so the data cannot show that either system is better.
|
|
362
|
+
That does not mean the two are level."
|
|
363
|
+
- `PositionBias.summary()`, randomised design. "The interval covers 50%,
|
|
364
|
+
so the data cannot show that position moved the judge." is now "The
|
|
365
|
+
interval includes 50%, so the data cannot show that position moved the
|
|
366
|
+
judge. That does not mean the judge ignores position."
|
|
367
|
+
- `PositionBias.summary()`, both orders. "The flips split evenly across
|
|
368
|
+
the two positions, so this is an unsteady judge rather than a
|
|
369
|
+
position-biased one." is now "That share is not clear of 50% at this
|
|
370
|
+
many flips, so the data cannot show that the flips have a direction.
|
|
371
|
+
That does not mean the judge is free of position bias." 0.3.0 printed
|
|
372
|
+
the old sentence at 7 flips of 9 toward the answer shown first.
|
|
373
|
+
- `LengthBias.summary()`. "The interval covers no effect, so the data
|
|
374
|
+
cannot show that length moved the judge." is now "The interval includes
|
|
375
|
+
an odds ratio of 1, so the data cannot show that length moved the
|
|
376
|
+
judge. That does not mean length plays no part in its choices." For the
|
|
377
|
+
disagreement fit, "That interval covers no effect, so the judge does
|
|
378
|
+
not depart from the humans in the direction of length." is now "That
|
|
379
|
+
interval includes an odds ratio of 1, so the data cannot show that the
|
|
380
|
+
judge breaks with the humans toward longer or shorter answers. That does
|
|
381
|
+
not mean it follows them on length."
|
|
382
|
+
- `AgreementResult.summary()`. "so the data cannot distinguish the raters"
|
|
383
|
+
is now "so the data cannot show that any one rater is pulling alpha
|
|
384
|
+
down" where every leave-one-out alpha is undefined. Where there are
|
|
385
|
+
leave-one-out figures the summary no longer judges the raters at all,
|
|
386
|
+
as the entry on rater dropout below says.
|
|
387
|
+
- `JudgeValidation.summary()`. "the data cannot single out a slice" is now
|
|
388
|
+
"the data cannot show that the judge does worse on any one slice".
|
|
389
|
+
Where the intervals overlap it adds "That does not mean it does equally
|
|
390
|
+
well on all of them."
|
|
391
|
+
|
|
392
|
+
Anything matching on the old sentences will stop matching.
|
|
393
|
+
|
|
394
|
+
- **Breaking.** `AgreementResult.summary()` and `JudgeValidation.summary()`
|
|
395
|
+
name one of Krippendorff's bands only when the whole interval sits in it.
|
|
396
|
+
0.3.0 named the band from the point estimate, with "That is at or above
|
|
397
|
+
0.800, the conventional bar for treating coded data as reliable.", "That
|
|
398
|
+
sits between 0.667 and 0.800, which supports tentative conclusions and no
|
|
399
|
+
firm ones." and "That is below 0.667, the conventional floor for drawing
|
|
400
|
+
any conclusion from coded data." These now read "The whole interval sits
|
|
401
|
+
above 0.800", "The whole interval sits between 0.667 and 0.800" and "The
|
|
402
|
+
whole interval sits below 0.667". An interval running over 0.667 reads
|
|
403
|
+
"The interval runs both sides of 0.667, the conventional floor for drawing
|
|
404
|
+
any conclusion from coded data, so the data cannot show that rater
|
|
405
|
+
agreement clears it. That does not mean it falls short of it." In
|
|
406
|
+
`JudgeValidation` the subject is "the judge's agreement with the humans".
|
|
407
|
+
An interval that clears 0.667 and runs over 0.800 gets the same form at
|
|
408
|
+
0.800, and a summary with no interval names no band. Judge labels with
|
|
409
|
+
alpha 0.801 and an interval of 0.601 to 0.951 printed "That is at or
|
|
410
|
+
above 0.800" in 0.3.0. Anything matching on the old sentences will stop
|
|
411
|
+
matching.
|
|
412
|
+
|
|
413
|
+
- **Breaking.** `AgreementResult.summary()` no longer names a rater. 0.3.0
|
|
414
|
+
named one when dropping them raised alpha by more than half the width of
|
|
415
|
+
the interval on alpha. That compares the shift with the sampling error on
|
|
416
|
+
alpha, and the shift has a sampling error of its own that can be much
|
|
417
|
+
larger. Across simulated evals with three raters who differed only by
|
|
418
|
+
chance, the rule named a rater in 4.2% of 500 when everyone graded every
|
|
419
|
+
item. When the third rater graded a fifth of the items it named one in
|
|
420
|
+
32.0% of 500, always one of the two who graded everything. In one of those
|
|
421
|
+
evals 0.3.0 printed "Dropping r2 raises alpha to 0.878, a shift of 0.326
|
|
422
|
+
against a sampling error of 0.200." about a rater who graded all 60 items.
|
|
423
|
+
The same rule caught a rater wrong three times as often as the others in
|
|
424
|
+
72.4% of 500.
|
|
425
|
+
|
|
426
|
+
The summary now lists alpha with each rater left out, as in "Leaving one
|
|
427
|
+
rater out at a time gives alpha of 0.878 without r2 (+0.326), 0.524
|
|
428
|
+
without r3 (-0.028), and 0.483 without r1 (-0.069).", and says "The
|
|
429
|
+
package does not judge whether any of these shifts is larger than noise,
|
|
430
|
+
so it names no rater. A rater near the top of this list is a lead to check
|
|
431
|
+
rather than a finding." It lists five raters at most and points to
|
|
432
|
+
`rater_dropout` for the rest. `top_dropout_rater` always returns None.
|
|
433
|
+
`dropout_is_distinguishable` still computes the old rule, its docstring
|
|
434
|
+
says why the rule was withdrawn, and nothing in the package reads it.
|
|
435
|
+
|
|
436
|
+
The `audit` agreement finding carries the new sentence. Its severity never
|
|
437
|
+
came from this rule, so no finding changes severity. If you acted on a
|
|
438
|
+
rater a summary named, check that rater by hand.
|
|
439
|
+
|
|
440
|
+
- **Breaking.** `PositionBias` puts the Clopper-Pearson interval, the exact
|
|
441
|
+
binomial interval, on the rate it tests against a half, in both designs,
|
|
442
|
+
and decides on it. The exact binomial p-value printed beside it comes from
|
|
443
|
+
the same test, so the two cannot disagree about 50%. 0.3.0 used a Wilson
|
|
444
|
+
interval in the randomised design. Wilson and the exact test disagree at
|
|
445
|
+
50% in 188 of 20,300 (n, k) cells up to 200 judgements, and in every one
|
|
446
|
+
the Wilson interval clears 50% while the p-value does not. At 11 of 14 in
|
|
447
|
+
the randomised design 0.3.0 printed "(95% CI: 52.4% to 92.4%, exact
|
|
448
|
+
binomial p=0.0574)" and then "The interval clears 50%, so the judge
|
|
449
|
+
favours whichever output it sees first." It now prints "(95% CI: 49.2% to
|
|
450
|
+
95.3%, exact binomial p=0.0574)" and "The interval includes 50%, so the
|
|
451
|
+
data cannot show that position moved the judge." Every randomised interval
|
|
452
|
+
moves, and a randomised verdict flips wherever the two used to disagree.
|
|
453
|
+
|
|
454
|
+
In the both-orders design 0.3.0 printed the share of flips with a bare
|
|
455
|
+
p-value, "(77.8%, exact binomial p=0.1797).", and decided on that p-value.
|
|
456
|
+
It now prints "(77.8%, 95% CI: 40.0% to 97.2%, exact binomial p=0.1797)."
|
|
457
|
+
and decides on the interval, which gives the same answer as the p-value in
|
|
458
|
+
every case. The consistency rate has no test beside it and keeps its
|
|
459
|
+
Wilson interval. Rerun any position check near the line.
|
|
460
|
+
|
|
461
|
+
### Added
|
|
462
|
+
|
|
463
|
+
- `BTResult.n_missing_item_ids`, the number of comparisons with no item id.
|
|
464
|
+
It is the last field of the dataclass and defaults to 0, so building a
|
|
465
|
+
`BTResult` by position with 0.3.0's fields still works. `to_elo` carries
|
|
466
|
+
it across.
|
|
467
|
+
- `PositionBias.position_a_ci_low` and `PositionBias.position_a_ci_high`,
|
|
468
|
+
the Clopper-Pearson interval on `position_a_rate`. In the randomised
|
|
469
|
+
design they
|
|
470
|
+
equal `ci_low` and `ci_high`. They are the last two fields and default to
|
|
471
|
+
NaN, so building a `PositionBias` by position with 0.3.0's fields still
|
|
472
|
+
works. A both-orders result built that way has no interval, so its
|
|
473
|
+
`has_position_effect` is False.
|
|
474
|
+
|
|
475
|
+
### Fixed
|
|
476
|
+
|
|
477
|
+
- **Breaking.** `KappaResult.summary()` said "Krippendorff's alpha does not
|
|
478
|
+
have that problem and handles missing data, so prefer rater_agreement for
|
|
479
|
+
anything you report." Alpha has the problem too. Two raters who agree on
|
|
480
|
+
90 of 100 items score kappa 0.444 and alpha 0.447 when one category takes
|
|
481
|
+
90% of the ratings, and 0.800 and 0.801 when both are used equally often.
|
|
482
|
+
It now says "Krippendorff's alpha moves the same way, because it also
|
|
483
|
+
corrects for chance using how often each category is used." and gives
|
|
484
|
+
missing ratings, more than two raters and ordered scales as the reasons to
|
|
485
|
+
prefer `rater_agreement`. The `cohens_kappa` docstring made the same claim
|
|
486
|
+
and now quotes the four figures.
|
|
487
|
+
|
|
488
|
+
- **Breaking.** `ScoreCI.summary()` told the reader to "treat differences
|
|
489
|
+
smaller than that as unresolved." A paired comparison resolves
|
|
490
|
+
differences far smaller than either score's own interval. The sentence
|
|
491
|
+
now reads "To compare this score with another, read the interval on the
|
|
492
|
+
difference, which compare_paired and compare_independent report. Two
|
|
493
|
+
score intervals that overlap do not show the systems are level." The
|
|
494
|
+
`scores` module docstring made the same claim and no longer does.
|
|
495
|
+
|
|
496
|
+
- **Breaking.** `PowerResult.summary()` from `detectable_effect` said
|
|
497
|
+
"anything smaller was out of reach before the first item was graded". A
|
|
498
|
+
difference below the reach can still reach significance, only less often.
|
|
499
|
+
It now says "A smaller difference could still reach significance here,
|
|
500
|
+
with a chance below 80%." Where no difference reaches the requested power,
|
|
501
|
+
"This eval could not have found anything, whatever the two systems really
|
|
502
|
+
do." and, for independent samples, "and this eval could not have found
|
|
503
|
+
anything." are now "A null result from this eval says little about the
|
|
504
|
+
systems." The `detectable_effect` docstring said "An eval could not have
|
|
505
|
+
found anything smaller" and now says "No smaller difference reaches the
|
|
506
|
+
requested power".
|
|
507
|
+
|
|
508
|
+
- **Breaking.** `JudgeValidation.summary()` on a single item said "Every
|
|
509
|
+
label that could be compared was identical" whatever the labels were,
|
|
510
|
+
beside a plain accuracy of 0.0% when they differed, and counted "1 items".
|
|
511
|
+
It now reads "(nominal, 1 item). One item cannot carry a reliability
|
|
512
|
+
estimate, so there is no number to report and no interval around it." The
|
|
513
|
+
count of items set aside reads "1 item was set aside" where it read "1
|
|
514
|
+
items were set aside".
|
|
515
|
+
|
|
516
|
+
- **Breaking.** `BTResult.summary()` under `resample="comparisons"` said
|
|
517
|
+
"these 240 comparisons share 239 items" when one comparison had no item
|
|
518
|
+
id and no two shared anything. Sharing is now counted among the
|
|
519
|
+
comparisons that carry an id. When none share, the sentence is left out.
|
|
520
|
+
When some share and ids are missing, it reads "the 239 comparisons that
|
|
521
|
+
carry an item id share 26 items".
|
|
522
|
+
|
|
523
|
+
- The README example and the prose under it show the new wording.
|
|
524
|
+
|
|
525
|
+
### Removed
|
|
526
|
+
|
|
527
|
+
- Nothing.
|
|
528
|
+
|
|
529
|
+
### Known limitations
|
|
530
|
+
|
|
531
|
+
This rule is unchanged since 0.3.0 and is not fixed in this release. The
|
|
532
|
+
figures come from simulations run against 0.3.0 and against the code released
|
|
533
|
+
as 0.4.0, which give the same results.
|
|
534
|
+
|
|
535
|
+
- `JudgeValidation` names a slice, and `audit` raises a critical finding on
|
|
536
|
+
it, only when the slice's own interval sits wholly below the interval on
|
|
537
|
+
the overall figure. That reads a difference off two separate intervals
|
|
538
|
+
instead of an interval on the difference, and it is conservative. With
|
|
539
|
+
five slices of 60 items that differ only by chance, it named a slice in
|
|
540
|
+
0.5% of 200 simulated evals. It misses real differences. A slice where the
|
|
541
|
+
judge flipped 25% of the labels, against 10% in the other four, was named
|
|
542
|
+
in 32.5% of 200. When the summary says the data cannot show that the
|
|
543
|
+
judge does worse on any one slice, this rule is what did not show it.
|
|
544
|
+
|
|
545
|
+
## [0.3.0] - 2026-09-10
|
|
546
|
+
|
|
547
|
+
0.3.0 changes what `bradley_terry` reports on data you have already run, and
|
|
548
|
+
it turns several calls that used to return numbers into errors. Each
|
|
549
|
+
breaking entry says what it was, what it is now and what to do about it.
|
|
550
|
+
|
|
551
|
+
### Changed
|
|
552
|
+
|
|
553
|
+
- **Breaking.** `bradley_terry` reads separability off the interval on the
|
|
554
|
+
gap between two ratings. Before, a pair was separable when its two rating
|
|
555
|
+
intervals did not overlap. Now a pair is separable when the percentile
|
|
556
|
+
interval on the difference between the two ratings excludes zero. Two
|
|
557
|
+
rating intervals can overlap while the gap between them is well measured,
|
|
558
|
+
because both ratings carry the error of the field average they are
|
|
559
|
+
measured against and that error cancels in the gap. So the old test
|
|
560
|
+
undercounted the pairs the data orders, and the pairs it left out were
|
|
561
|
+
never shown to be unordered. There is no option to bring the old rule
|
|
562
|
+
back. `n_separable` and `separable_pairs` can change on data you have
|
|
563
|
+
already run. On the README example they go from 5 of 15 pairs to 7. On
|
|
564
|
+
twelve simulated leaderboards where every item carried one comparison,
|
|
565
|
+
the count went up on five and stayed the same on seven. Nothing changes
|
|
566
|
+
in your code. Rerun, and replace any separability count you have
|
|
567
|
+
published.
|
|
568
|
+
|
|
569
|
+
- **Breaking.** `separable_pairs` has two new columns, `ci_low` and
|
|
570
|
+
`ci_high`, the interval on `difference`. They sit between `difference` and
|
|
571
|
+
`p_a_beats_b`, so code that reads columns by position will read the wrong
|
|
572
|
+
ones. Code that selects columns by name is unaffected.
|
|
573
|
+
|
|
574
|
+
- **Breaking.** `bradley_terry` resamples items by default. Before, the
|
|
575
|
+
bootstrap drew single comparisons, which treats judgements of the same
|
|
576
|
+
prompt as independent. Now it draws item ids with replacement and takes
|
|
577
|
+
every comparison made on each drawn item.
|
|
578
|
+
|
|
579
|
+
Where every item carries one comparison the default draws the same
|
|
580
|
+
resamples from the same seed as 0.2.1, and the ratings, their intervals
|
|
581
|
+
and the win matrix come out identical. Separability can still change,
|
|
582
|
+
for the reason in the entry above.
|
|
583
|
+
|
|
584
|
+
Where items carry several comparisons the intervals widen and fewer pairs
|
|
585
|
+
may separate. On a simulated board of 60 items with 20 comparisons each,
|
|
586
|
+
the rating intervals came out 1.1 to 1.5 times as wide as 0.2.1's. On
|
|
587
|
+
simulated data shaped like MT-Bench's human judgements, the rating
|
|
588
|
+
intervals 0.2.1 reported covered 88% of the time at a nominal 95% once
|
|
589
|
+
prompts shifted model strength by a spread of 0.5 on the log-odds scale,
|
|
590
|
+
and 80% at a spread of 1.0. `examples/pairwise_cluster_study.py` has the
|
|
591
|
+
table for 0.3.0.
|
|
592
|
+
|
|
593
|
+
To get the ratings and rating intervals an earlier version gave on the
|
|
594
|
+
same data and seed, pass `resample="comparisons"`. They come out
|
|
595
|
+
identical to 0.2.1's. `separable_pairs`, `n_separable` and the summary
|
|
596
|
+
follow the 0.3.0 rules, so those can differ.
|
|
597
|
+
|
|
598
|
+
- **Breaking.** `bradley_terry` raises `ValueError` in two cases that 0.2.1
|
|
599
|
+
accepted. Both apply only when `n_boot` is above zero and `resample` is
|
|
600
|
+
left at its default of `"items"`.
|
|
601
|
+
|
|
602
|
+
- Some row has no `item_id`. The item bootstrap has to know which item
|
|
603
|
+
each comparison belongs to.
|
|
604
|
+
- Every row has the same `item_id`, an empty string included. With one
|
|
605
|
+
item, every resample is the full data and every interval would have
|
|
606
|
+
width zero.
|
|
607
|
+
|
|
608
|
+
This is the change most likely to break a working script, so here is what
|
|
609
|
+
to do. Earlier versions required `item_id` and read it for nothing but a
|
|
610
|
+
count, so a constant, a blank or the row number got past the check and
|
|
611
|
+
changed nothing. Look at what yours holds.
|
|
612
|
+
|
|
613
|
+
- It names the prompt each comparison was made on. Fill in any gaps and
|
|
614
|
+
change nothing else. Your intervals now account for comparisons sharing
|
|
615
|
+
a prompt, which is the reason for the change.
|
|
616
|
+
- It is the row number, or anything else unique per row. Nothing raises,
|
|
617
|
+
and the ratings and their intervals come out as they did in 0.2.1.
|
|
618
|
+
- It is a constant or a blank. Record the prompt if you can. If you
|
|
619
|
+
cannot, pass `resample="comparisons"` to keep the intervals you had.
|
|
620
|
+
They come out identical to 0.2.1's on the same seed. They treat every
|
|
621
|
+
judgement as independent and run narrow wherever prompts carry several.
|
|
622
|
+
The summary says so when the column holds a constant or an empty
|
|
623
|
+
string. It says nothing when every `item_id` is missing, since then
|
|
624
|
+
nothing records which comparisons share a prompt.
|
|
625
|
+
|
|
626
|
+
With `n_boot=0` no resampling happens and any `item_id` is accepted.
|
|
627
|
+
|
|
628
|
+
- **Breaking.** `score_ci(method="t")` raises `ValueError` on three kinds of
|
|
629
|
+
input it used to return numbers for. What to do depends on the input.
|
|
630
|
+
|
|
631
|
+
- 0/1 data, including all passes, all fails and a single pass or fail.
|
|
632
|
+
The interval could run past 100%, as 49 passes in 50 did at 94.0% to
|
|
633
|
+
102.0%, come back with width zero on all passes or all fails, or come
|
|
634
|
+
back as NaN on a single pass. Use `method="wilson"`, which
|
|
635
|
+
`method="auto"` already picks for 0/1 data and which works on a single
|
|
636
|
+
item.
|
|
637
|
+
- A single score that is not 0 or 1. It came back as NaN bounds behind two
|
|
638
|
+
RuntimeWarnings. One score has no spread, and the bootstrap returns
|
|
639
|
+
width zero on it too. Score more items.
|
|
640
|
+
- Continuous scores that are all the same. The interval came back with
|
|
641
|
+
width zero, which claims the observations fixed the mean exactly. Check
|
|
642
|
+
that the scorer is not returning a constant.
|
|
643
|
+
|
|
644
|
+
- **Breaking.** `score_ci(method="wilson")` raises `ValueError` on scores
|
|
645
|
+
that are not 0 or 1. Wilson counts passes, and on other scores it took the
|
|
646
|
+
count by truncating the sum of the scores. Ten scores of 0.99 printed a
|
|
647
|
+
mean of 0.990 beside an interval of 0.596 to 0.982. For scores that vary,
|
|
648
|
+
use `method="bootstrap"`, the interval on a mean, which `method="auto"`
|
|
649
|
+
already picks. Scores that are all the same, like that example, get width
|
|
650
|
+
zero from the bootstrap too, and 0.3.0 does not refuse that.
|
|
651
|
+
|
|
652
|
+
- **Breaking.** `score_ci`, `compare_paired` and `compare_independent`
|
|
653
|
+
raise `ValueError` for a confidence level that is not strictly between 0
|
|
654
|
+
and 1, with the message `confidence must be in (0, 1), got ...` that
|
|
655
|
+
`bradley_terry`, `rater_agreement`, `judge_validation` and `audit` already
|
|
656
|
+
used. Before, what came back at `confidence=1.5` depended on the method.
|
|
657
|
+
The bootstrap in all three raised from inside numpy. Wilson and both t
|
|
658
|
+
intervals returned NaN bounds. The two score intervals returned bounds
|
|
659
|
+
clipped to -100% and 100%. The signed-rank interval in `compare_paired`
|
|
660
|
+
returned an ordinary-looking interval under a "150% CI" label, which is
|
|
661
|
+
the case nothing would have flagged. Pass a level strictly between 0 and
|
|
662
|
+
1.
|
|
663
|
+
|
|
664
|
+
- **Breaking.** Several summary strings are reworded, so any test or
|
|
665
|
+
pipeline that matches on them will fail.
|
|
666
|
+
|
|
667
|
+
- `BTResult.summary()` defines separable as "the interval on the gap
|
|
668
|
+
between the two ratings excludes zero". For pairs that do not separate
|
|
669
|
+
it says the data does not establish an order for them, that this does
|
|
670
|
+
not mean the models are level, and that more comparisons could separate
|
|
671
|
+
them. The phrases "meaning their intervals do not overlap", "cannot be
|
|
672
|
+
ordered", "an order the data does not carry" and "a ranking of noise"
|
|
673
|
+
are gone.
|
|
674
|
+
- `BTResult.summary()` adds a sentence when `resample="comparisons"` was
|
|
675
|
+
used on data where items carry several comparisons.
|
|
676
|
+
- `AgreementResult.summary()` for a scale nobody varied now reads "This
|
|
677
|
+
comes from a scale nobody varied. It is not perfect agreement." where it
|
|
678
|
+
read "That is not perfect agreement, it is a scale nobody varied."
|
|
679
|
+
- `JudgeValidation.summary()` for a rubric with one label now reads "This
|
|
680
|
+
comes from a rubric with one label in it. It is not perfect agreement."
|
|
681
|
+
where it read "That is not perfect agreement, it is a rubric with one
|
|
682
|
+
label in it."
|
|
683
|
+
|
|
684
|
+
- The Development Status classifier moved from Alpha to Beta.
|
|
685
|
+
|
|
686
|
+
### Added
|
|
687
|
+
|
|
688
|
+
- `bradley_terry(..., resample="items")`, with `"comparisons"` as the other
|
|
689
|
+
choice.
|
|
690
|
+
- `BTResult.pairs`, one row per pair of models with the gap, the interval on
|
|
691
|
+
the gap and a `separable` column. `separable_pairs` is its separable rows.
|
|
692
|
+
- `BTResult.resample`, recording which unit the bootstrap drew. It and
|
|
693
|
+
`pairs` are the last two fields of the dataclass, so building a
|
|
694
|
+
`BTResult` by position with 0.2.1's fields still works.
|
|
695
|
+
- `to_elo` stretches the gap intervals with the gaps and carries `pairs` and
|
|
696
|
+
`resample` across.
|
|
697
|
+
- `examples/pairwise_cluster_study.py`, in the source distribution, which
|
|
698
|
+
measures how narrow the comparison bootstrap runs on MT-Bench-shaped data.
|
|
699
|
+
|
|
700
|
+
### Fixed
|
|
701
|
+
|
|
702
|
+
- The `scores` module docstring said the interval at n=50 is roughly plus or
|
|
703
|
+
minus 10 points. It is about 10 at an 85% pass rate and about 13 at 50%.
|
|
704
|
+
- The README said every interval in the package is tested by simulation.
|
|
705
|
+
Several were not. It now says which intervals are tested by simulation,
|
|
706
|
+
which are checked against a reference implementation instead, and which
|
|
707
|
+
one is checked by neither.
|
|
708
|
+
- The README said `audit` runs five checks. It runs seven, drawn from five
|
|
709
|
+
modules.
|
|
710
|
+
|
|
711
|
+
### Removed
|
|
712
|
+
|
|
713
|
+
- `AUDIT.md`, an internal review of the package, is no longer tracked, so
|
|
714
|
+
it is not in the source distribution.
|
|
715
|
+
|
|
716
|
+
## [0.2.1] - 2026-09-08
|
|
717
|
+
|
|
718
|
+
Reconstructed after the fact. The published files match commit `809a650`.
|
|
719
|
+
|
|
720
|
+
### Changed
|
|
721
|
+
|
|
722
|
+
- `__version__` is read from the installed package metadata. 0.0.1 and
|
|
723
|
+
0.2.0 both reported `__version__` as 0.1.0, because a literal in
|
|
724
|
+
`__init__.py` had drifted from `pyproject.toml`.
|
|
725
|
+
|
|
726
|
+
### Added
|
|
727
|
+
|
|
728
|
+
- `AUDIT.md`, an internal review of the package, in the source
|
|
729
|
+
distribution.
|
|
730
|
+
|
|
731
|
+
### Fixed
|
|
732
|
+
|
|
733
|
+
- **Breaking.** The length-bias check read every coefficient as a
|
|
734
|
+
preference for long answers. In 0.2.0 a judge that preferred shorter
|
|
735
|
+
answers got the `audit` title "The judge is pulled by how long the answer
|
|
736
|
+
is", and `LengthBias.summary()` printed "A positive coefficient here is
|
|
737
|
+
not bias on its own" beside a negative coefficient. The `audit` finding
|
|
738
|
+
now takes its title, lead, action and verdict from the fit that decides,
|
|
739
|
+
with its own lead for when the two fits point opposite ways, and
|
|
740
|
+
`LengthBias.summary()` has its own sentence for a negative coefficient.
|
|
741
|
+
Anything matching on the old title or sentence will stop matching.
|
|
742
|
+
|
|
743
|
+
### Removed
|
|
744
|
+
|
|
745
|
+
- Nothing.
|
|
746
|
+
|
|
747
|
+
## [0.2.0] - 2026-09-07
|
|
748
|
+
|
|
749
|
+
Reconstructed after the fact. The wheel matches commit `242e354`. It was
|
|
750
|
+
uploaded twelve seconds before that commit was made, so it was built from
|
|
751
|
+
the working tree the commit then recorded.
|
|
752
|
+
|
|
753
|
+
### Changed
|
|
754
|
+
|
|
755
|
+
- The project URLs point at github.com/mokayahezron/evalaudit. 0.1.0 pointed
|
|
756
|
+
at github.com/ondibahezron-glitch/evalaudit.
|
|
757
|
+
- `choix` is a development dependency on Python 3.10 and later, used to
|
|
758
|
+
check the Bradley-Terry fit.
|
|
759
|
+
|
|
760
|
+
### Added
|
|
761
|
+
|
|
762
|
+
- The `pairwise` module, with `bradley_terry`, `to_elo` and `BTResult`.
|
|
763
|
+
Ratings come with bootstrap intervals and a count of separable pairs.
|
|
764
|
+
Models that fall into groups that never met, and models that never lost
|
|
765
|
+
or never won, get no ratings and a summary naming them. Ties are split or
|
|
766
|
+
dropped, and `ties="davidson"` is refused by name.
|
|
767
|
+
- The README code blocks are run by the test suite and checked against the
|
|
768
|
+
output they show.
|
|
769
|
+
|
|
770
|
+
### Fixed
|
|
771
|
+
|
|
772
|
+
- Nothing.
|
|
773
|
+
|
|
774
|
+
### Removed
|
|
775
|
+
|
|
776
|
+
- Nothing.
|
|
777
|
+
|
|
778
|
+
## [0.1.0] - 2026-09-07
|
|
779
|
+
|
|
780
|
+
Reconstructed after the fact. The wheel matches commit `c1230f1`.
|
|
781
|
+
|
|
782
|
+
### Changed
|
|
783
|
+
|
|
784
|
+
- Nothing.
|
|
785
|
+
|
|
786
|
+
### Added
|
|
787
|
+
|
|
788
|
+
- `compare_paired` and `compare_independent`. McNemar with Tango's score
|
|
789
|
+
interval for paired binary data, the paired bootstrap, and the signed-rank
|
|
790
|
+
test with the Hodges-Lehmann interval. The score interval, the bootstrap
|
|
791
|
+
and Welch's t for independent samples.
|
|
792
|
+
- `rater_agreement`, Krippendorff's alpha with a bootstrap interval, an item
|
|
793
|
+
disagreement table and a rater dropout table. `cohens_kappa` and
|
|
794
|
+
`fleiss_kappa`.
|
|
795
|
+
- `judge_validation`, `position_bias` and `length_bias`.
|
|
796
|
+
- `detectable_effect` and `min_sample_size`.
|
|
797
|
+
- `audit`, which runs every check the supplied data supports and ranks the
|
|
798
|
+
findings by severity.
|
|
799
|
+
- The result types are exported from the package, `ScoreCI` among them.
|
|
800
|
+
|
|
801
|
+
### Fixed
|
|
802
|
+
|
|
803
|
+
- Nothing.
|
|
804
|
+
|
|
805
|
+
### Removed
|
|
806
|
+
|
|
807
|
+
- Nothing.
|
|
808
|
+
|
|
809
|
+
## [0.0.1] - 2026-09-04
|
|
810
|
+
|
|
811
|
+
Reconstructed after the fact. The wheel's package files match commits
|
|
812
|
+
`aa8ad97`, `8a4cab0` and `b090c66`, which do not differ in them. Its version
|
|
813
|
+
number first appears in `pyproject.toml` at `b090c66`, committed about an
|
|
814
|
+
hour after the upload. It reported `__version__` as 0.1.0.
|
|
815
|
+
|
|
816
|
+
### Changed
|
|
817
|
+
|
|
818
|
+
- Nothing.
|
|
819
|
+
|
|
820
|
+
### Added
|
|
821
|
+
|
|
822
|
+
- `score_ci`, with Wilson, bootstrap and Student-t intervals, and a default
|
|
823
|
+
that picks Wilson for 0/1 data and the bootstrap otherwise.
|
|
824
|
+
|
|
825
|
+
### Fixed
|
|
826
|
+
|
|
827
|
+
- Nothing.
|
|
828
|
+
|
|
829
|
+
### Removed
|
|
830
|
+
|
|
831
|
+
- Nothing.
|
|
832
|
+
|
|
833
|
+
[Unreleased]: https://github.com/mokayahezron/evalaudit/compare/v0.5.0...main
|
|
834
|
+
[0.5.0]: https://github.com/mokayahezron/evalaudit/compare/v0.4.0...v0.5.0
|
|
835
|
+
[0.4.0]: https://github.com/mokayahezron/evalaudit/compare/v0.3.0...v0.4.0
|
|
836
|
+
[0.3.0]: https://github.com/mokayahezron/evalaudit/compare/809a650...v0.3.0
|
|
837
|
+
[0.2.1]: https://github.com/mokayahezron/evalaudit/compare/242e354...809a650
|
|
838
|
+
[0.2.0]: https://github.com/mokayahezron/evalaudit/compare/c1230f1...242e354
|
|
839
|
+
[0.1.0]: https://github.com/mokayahezron/evalaudit/compare/b090c66...c1230f1
|
|
840
|
+
[0.0.1]: https://github.com/mokayahezron/evalaudit/tree/b090c66
|