evalaudit 0.4.0__tar.gz → 0.6.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.6.0/.gitattributes +1 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/.gitignore +20 -20
- {evalaudit-0.4.0 → evalaudit-0.6.0}/CHANGELOG.md +383 -14
- {evalaudit-0.4.0 → evalaudit-0.6.0}/LICENSE +21 -21
- {evalaudit-0.4.0 → evalaudit-0.6.0}/PKG-INFO +45 -23
- {evalaudit-0.4.0 → evalaudit-0.6.0}/README.md +372 -350
- evalaudit-0.6.0/analysis/README.md +108 -0
- evalaudit-0.6.0/analysis/mt-bench.md +277 -0
- evalaudit-0.6.0/analysis/output/q1_comparisons_ratings.csv +7 -0
- evalaudit-0.6.0/analysis/q1_check_v021.py +97 -0
- evalaudit-0.6.0/analysis/q1_leaderboard.py +332 -0
- evalaudit-0.6.0/analysis/q2_human_agreement.py +288 -0
- evalaudit-0.6.0/analysis/q3_alignment.py +230 -0
- evalaudit-0.6.0/analysis/q5_judge_against_human_baseline.py +617 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/__init__.py +64 -64
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/_types.py +2174 -1763
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/agreement.py +605 -605
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/audit.py +61 -18
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/compare.py +25 -12
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/judge.py +1227 -783
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/pairwise.py +851 -841
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/power.py +528 -528
- {evalaudit-0.4.0 → evalaudit-0.6.0}/evalaudit/scores.py +247 -221
- evalaudit-0.6.0/examples/independent_bootstrap_coverage_study.py +139 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/pyproject.toml +47 -47
- evalaudit-0.6.0/tests/data/README.md +35 -0
- evalaudit-0.6.0/tests/data/make_mt_bench_csv.py +77 -0
- evalaudit-0.6.0/tests/data/mt_bench_gpt4_pair.csv +2401 -0
- evalaudit-0.6.0/tests/data/mt_bench_human.csv +3356 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_agreement.py +2029 -1919
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_audit.py +455 -11
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_compare.py +1137 -916
- evalaudit-0.6.0/tests/test_judge.py +6382 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_not_shown.py +13 -5
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_pairwise.py +2374 -2248
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_power.py +1307 -1025
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_scores.py +522 -453
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_version.py +3 -3
- evalaudit-0.4.0/tests/test_judge.py +0 -2588
- {evalaudit-0.4.0 → evalaudit-0.6.0}/.github/workflows/tests.yml +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/examples/.gitkeep +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/examples/interval_method_study.py +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/examples/pairwise_cluster_study.py +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/__init__.py +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_confidence.py +0 -0
- {evalaudit-0.4.0 → evalaudit-0.6.0}/tests/test_readme.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* text=auto eol=lf
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
CLAUDE.md
|
|
2
|
-
__pycache__/
|
|
3
|
-
*.py[cod]
|
|
4
|
-
.venv/
|
|
5
|
-
venv/
|
|
6
|
-
.env
|
|
7
|
-
build/
|
|
8
|
-
dist/
|
|
9
|
-
*.egg-info/
|
|
10
|
-
.pytest_cache/
|
|
11
|
-
.coverage
|
|
12
|
-
htmlcov/
|
|
13
|
-
.ipynb_checkpoints/
|
|
14
|
-
.DS_Store
|
|
15
|
-
.vscode/
|
|
16
|
-
.idea/
|
|
17
|
-
data/raw/
|
|
18
|
-
outputs/
|
|
19
|
-
*.jsonl/
|
|
20
|
-
AUDIT.md
|
|
1
|
+
CLAUDE.md
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
venv/
|
|
6
|
+
.env
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.coverage
|
|
12
|
+
htmlcov/
|
|
13
|
+
.ipynb_checkpoints/
|
|
14
|
+
.DS_Store
|
|
15
|
+
.vscode/
|
|
16
|
+
.idea/
|
|
17
|
+
data/raw/
|
|
18
|
+
outputs/
|
|
19
|
+
*.jsonl/
|
|
20
|
+
AUDIT.md
|
|
@@ -3,20 +3,386 @@
|
|
|
3
3
|
Every change to evalaudit that a caller can see is recorded here. The format
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
5
|
version numbers follow [semantic versioning](https://semver.org/). Before 1.0
|
|
6
|
-
a minor version can break things, and 0.3.0
|
|
6
|
+
a minor version can break things, and 0.3.0, 0.4.0, 0.5.0 and 0.6.0 all do.
|
|
7
7
|
|
|
8
8
|
An entry marked **Breaking** changes what a call that worked on the previous
|
|
9
9
|
release returns, raises or prints. The mark goes on the entry wherever it
|
|
10
10
|
sits, under Changed, Fixed or Removed.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
matches.
|
|
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, 0.5.0 and 0.6.0 have one too. The
|
|
14
|
+
entries below 0.3.0 were reconstructed after the fact, and their contents
|
|
15
|
+
were checked against the published wheels and the commit each wheel matches.
|
|
16
|
+
|
|
17
|
+
## [0.6.0] - 2026-10-26
|
|
18
|
+
|
|
19
|
+
Most of this release is text, and most of it changes what a summary or a
|
|
20
|
+
message prints. Missing and infinite scores are now refused where they used
|
|
21
|
+
to give NaN bounds that read as clearing zero. `audit` stops sizing the
|
|
22
|
+
power check on two unequal groups, stops raising when two systems never
|
|
23
|
+
disagree, and names the side a position-biased judge favours. The judge's
|
|
24
|
+
summary without a human baseline no longer reads Krippendorff's lines as a
|
|
25
|
+
verdict on the judge. Rates near 0% and 100% print enough digits to stay
|
|
26
|
+
off the end they have not reached. Anything that matches on the old
|
|
27
|
+
sentences will stop matching. Every entry was checked by running the same
|
|
28
|
+
calls against the v0.5.0 tag and against this tree. Three entries were first
|
|
29
|
+
written at commit 898a9cb and changed after it, and each one says how.
|
|
16
30
|
|
|
17
|
-
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Nothing.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Nothing.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **Breaking.** `JudgeValidation.summary()` without a human baseline no
|
|
42
|
+
longer reads Krippendorff's lines as a verdict on the judge. Those lines
|
|
43
|
+
were set for human coders, and `AuditConfig` already says a judge's
|
|
44
|
+
threshold should be set from the decision the judge is used for. The
|
|
45
|
+
sentence "The judge is not a stand-in for the humans at this level." is
|
|
46
|
+
gone. Every band sentence, including the one printed when there is no
|
|
47
|
+
interval, is now followed by "These lines were set for human coders, and
|
|
48
|
+
how closely a judge has to agree depends on the decision it is used for.
|
|
49
|
+
Calling judge_validation with a human_baseline measures the judge against
|
|
50
|
+
a second human instead." Judge labels with alpha 0.405 and an interval of
|
|
51
|
+
0.269 to 0.525 on 200 items printed "The whole interval sits below 0.667,
|
|
52
|
+
the conventional floor for drawing any conclusion from coded data. The
|
|
53
|
+
judge is not a stand-in for the humans at this level." They now print "The
|
|
54
|
+
whole interval sits below 0.667, the conventional floor for drawing any
|
|
55
|
+
conclusion from coded data. These lines were set for human coders, and how
|
|
56
|
+
closely a judge has to agree depends on the decision it is used for.
|
|
57
|
+
Calling judge_validation with a human_baseline measures the judge against
|
|
58
|
+
a second human instead." `audit` carries the judge's summary word for
|
|
59
|
+
word, so its judge findings carry the new sentences too. The one exception
|
|
60
|
+
is the finding for undefined agreement, which has no band sentence. The
|
|
61
|
+
action text of two judge findings, "Judge-human agreement is below the
|
|
62
|
+
working threshold" and "The data cannot show that the judge clears the
|
|
63
|
+
working threshold", was shortened, because the summary now makes the point
|
|
64
|
+
that a judge's threshold depends on the decision. `rater_agreement` and
|
|
65
|
+
the summary with a baseline are unchanged. Anything matching on the old
|
|
66
|
+
sentences will stop matching.
|
|
67
|
+
- **Breaking.** `score_ci`, `compare_paired`, `compare_independent` and
|
|
68
|
+
`audit` now raise `ValueError` on a NaN or infinite score. They used to
|
|
69
|
+
carry it into the mean and return NaN bounds. A NaN bound fails every
|
|
70
|
+
comparison with zero, so the margin read as clearing zero. `audit(scores=
|
|
71
|
+
{"A": [0.2, nan, 0.8], "B": [0.1, 0.3, 0.7]})` reported "The headline
|
|
72
|
+
margin clears zero" off a margin nobody measured. It now raises "scores for
|
|
73
|
+
A must be finite numbers, got 1 missing or infinite value, at position 1.
|
|
74
|
+
Drop or fill that item before computing an interval". With two or more
|
|
75
|
+
such values the message counts them and points at the first, as in "got 2
|
|
76
|
+
missing or infinite values, the first at position 0. Drop or fill those
|
|
77
|
+
items before computing an interval". The compare functions name the
|
|
78
|
+
argument, `a` or `b`, in place of the system. As first written for this
|
|
79
|
+
release, the message for a single value read "got 1 missing or infinite
|
|
80
|
+
value(s), the first at position 1. Drop or fill those items".
|
|
81
|
+
- **Breaking.** `audit` no longer runs the power check on two independent
|
|
82
|
+
groups of 0/1 scores with different sizes. The power arithmetic assumes
|
|
83
|
+
equal groups, and the audit passed it the total, so it split the items
|
|
84
|
+
evenly. Groups of 10 and 990 were read as 500 in each, and with an effect
|
|
85
|
+
of interest of 0.15 the report said "This eval was large enough for the
|
|
86
|
+
effect at issue". With the 990-item group at a 50% pass rate and the
|
|
87
|
+
10-item group 15 points above it, the shipped test has about 13% power.
|
|
88
|
+
The check now lands in `not_run` with "The two groups have 10 and 990
|
|
89
|
+
items. The power arithmetic here assumes equal groups, and splitting the
|
|
90
|
+
total evenly would overstate what the smaller group can find. Nothing to
|
|
91
|
+
report rather than a figure that does not apply." Equal groups are
|
|
92
|
+
unchanged. Scores that are not 0/1 keep the reason 0.5.0 gave, "The power
|
|
93
|
+
arithmetic here is for pass rates and these scores are not 0/1. Nothing to
|
|
94
|
+
report rather than a figure that does not apply.", whatever the group
|
|
95
|
+
sizes. As first written for this release, the check for unequal groups
|
|
96
|
+
ran first and gave groups of continuous scores the reason about group
|
|
97
|
+
sizes instead.
|
|
98
|
+
- `audit` no longer raises when two paired binary systems agree on every
|
|
99
|
+
item. The measured discordance rate of zero went to `detectable_effect`,
|
|
100
|
+
which refuses it, so `audit(scores={"A": [1, 0] * 50, "B": [1, 0] * 50})`
|
|
101
|
+
raised `ValueError`. The power check now lands in `not_run` with "The two
|
|
102
|
+
systems never disagree on an item, so there are no discordant pairs and
|
|
103
|
+
paired power has nothing to run on. The eval cannot say which system is
|
|
104
|
+
better from these items." The other checks report as usual.
|
|
105
|
+
- **Breaking.** The `audit` position finding now names the side the judge
|
|
106
|
+
favours. Its title was always "The judge favours whichever answer it reads
|
|
107
|
+
first", even for a judge that picked the second answer in all 100 pairs,
|
|
108
|
+
whose detail already said "second". That judge now gets "The judge
|
|
109
|
+
favours whichever answer it reads second". A judge that favours the first
|
|
110
|
+
answer gets the same title as before.
|
|
111
|
+
- **Breaking.** `JudgeValidation.summary()` on a result with no item left
|
|
112
|
+
said "One item cannot carry a reliability estimate" and printed "Plain
|
|
113
|
+
accuracy is nan%". `judge_validation` refuses such data with "no item
|
|
114
|
+
carries a label from both sides", so only a `JudgeValidation` built by
|
|
115
|
+
hand reaches this. Built with `agreement` and `accuracy` NaN, `n_items=0`
|
|
116
|
+
and `n_dropped=2`, it now reads "Judge and human agreement is undefined
|
|
117
|
+
(nominal, 0 items). No item has a label from both sides, so there is
|
|
118
|
+
nothing to compare and no number to report. Label more items and run this
|
|
119
|
+
again. 2 items were set aside because one side had no label."
|
|
120
|
+
- **Breaking.** `JudgeValidation.summary()` explained an alpha left
|
|
121
|
+
undefined by labels that never varied with "This comes from a rubric with
|
|
122
|
+
one label in it." The data shows only that one label was used, and the
|
|
123
|
+
rubric may have had others. On `judge_validation([1] * 40, [1] * 40)` it
|
|
124
|
+
now reads "This comes from both sides using one label throughout." The
|
|
125
|
+
`audit` finding for undefined judge agreement carries the new sentence.
|
|
126
|
+
- **Breaking.** `PowerResult.summary()` said "about 0 discordant pairs, and
|
|
127
|
+
McNemar reads only those" when the expected count rounded to zero.
|
|
128
|
+
`detectable_effect(2, discordance_rate=0.25)` expects 0.5 discordant
|
|
129
|
+
pairs, which rounds to 0. Its summary now reads "At a 25% discordance rate
|
|
130
|
+
that is under one discordant pair on average, and McNemar reads only
|
|
131
|
+
discordant pairs. Items where the two systems agree carry no information
|
|
132
|
+
about which one is better." Counts of one or more print as before. The
|
|
133
|
+
`audit` power finding carries the new sentence.
|
|
134
|
+
- **Breaking.** `PowerResult.summary()` printed rates to one decimal place,
|
|
135
|
+
so a positive rate could print as 0% and a rate below 1 as 100%.
|
|
136
|
+
`detectable_effect(1000, alpha=0.0004, discordance_rate=0.3)` said "a 0%
|
|
137
|
+
significance level" and now says "a 0.04% significance level".
|
|
138
|
+
`detectable_effect(1000, power=0.9996, discordance_rate=0.3)` said "At
|
|
139
|
+
100% power" and now says "At 99.96% power". A positive rate that rounds to
|
|
140
|
+
0% now prints with two significant figures. A rate below 1 that rounds to
|
|
141
|
+
100% prints its gap from 100% to two significant figures, so the float
|
|
142
|
+
just below 1 prints as 99.999999999999989%. Exactly 0 and 1 print as 0%
|
|
143
|
+
and 100%, and every other rate prints as before. The `audit` power finding
|
|
144
|
+
carries these summaries.
|
|
145
|
+
- **Breaking.** `bradley_terry` with `resample="items"` said "the first
|
|
146
|
+
between" when one comparison had no `item_id`, as if several did. With one
|
|
147
|
+
missing id it now reads "item_id is missing on 1 of 2 comparisons, the one
|
|
148
|
+
between 'a' and 'b'." Two or more missing ids keep "the first between".
|
|
149
|
+
|
|
150
|
+
### Documented
|
|
151
|
+
|
|
152
|
+
- The two-sample bootstrap in `compare_independent` covers less than it
|
|
153
|
+
claims on skewed scores with small groups. In 5,000 simulated evals per
|
|
154
|
+
setting, a 95% interval on exponential scores covered 92.6% of the time
|
|
155
|
+
with 25 and 60 items, 93.0% with 40 and 120, and 94.5% with 100 and 300,
|
|
156
|
+
each with a Monte Carlo standard error between 0.3 and 0.4 points. On
|
|
157
|
+
normal scores with 30 and 90 items it covered 94.1%. The docstring and
|
|
158
|
+
README now say so, and `examples/independent_bootstrap_coverage_study.py`
|
|
159
|
+
reproduces the figures with its seeds, settings and recorded output.
|
|
160
|
+
0.5.0's README said nothing pinned this interval's bounds. Tests now match
|
|
161
|
+
its bounds against a separate implementation and against Welch's interval
|
|
162
|
+
on a large normal sample. They also check its coverage on normal data and
|
|
163
|
+
guard the skewed-data shortfall from growing. As first written for this
|
|
164
|
+
release the figures were about 92%, about 93% and about 94.5%, from a
|
|
165
|
+
5,000-trial run whose seed was not recorded. That run cannot be repeated,
|
|
166
|
+
so those figures have no reproducible source. That does not show they were
|
|
167
|
+
wrong, and the recorded run gives the same 94.5% with 100 and 300 items.
|
|
168
|
+
- The `bradley_terry` docstring said the prompt-level spread on MT-Bench was
|
|
169
|
+
not measured, and stopped there. It now also says what was measured. On
|
|
170
|
+
the MT-Bench human votes, with the item bootstrap clustered on
|
|
171
|
+
question_id, seed 0 and 2,000 resamples, the mean gap-interval width over
|
|
172
|
+
the fifteen pairs was 1.58 times the comparison bootstrap's mean. That is
|
|
173
|
+
one run of each, a ratio of means rather than a per-pair figure, and not
|
|
174
|
+
an estimate of the spread.
|
|
175
|
+
- `analysis/mt-bench.md` said that correcting for clustering "widens every
|
|
176
|
+
gap interval by a factor of 1.58". The 1.58 is the ratio of the mean
|
|
177
|
+
gap-interval widths over the fifteen pairs, and single pairs vary around
|
|
178
|
+
it. The section now says so and carries a dated correction. No figure
|
|
179
|
+
changed.
|
|
180
|
+
|
|
181
|
+
### Removed
|
|
182
|
+
|
|
183
|
+
- Nothing.
|
|
184
|
+
|
|
185
|
+
## [0.5.0] - 2026-09-26
|
|
186
|
+
|
|
187
|
+
`judge_validation` can now measure the judge against a second human. Most
|
|
188
|
+
of the rest is text. Several printed sentences change, most of them for
|
|
189
|
+
hyphens and plurals, and one `audit` finding changes severity. Figures
|
|
190
|
+
change in one case. In the both-orders design, `position_bias` now scores a
|
|
191
|
+
pair judged more than once in an order when its first two reversed
|
|
192
|
+
judgements held a tie and a later two did not. That moves the count of
|
|
193
|
+
pairs scored, the consistency rate and its interval, and the figures on the
|
|
194
|
+
flips. A pair judged once in each order scores as before. Anything that
|
|
195
|
+
matches on the old sentences will stop matching. Every entry was checked by
|
|
196
|
+
running the same calls against the v0.4.0 tag and against this tree.
|
|
197
|
+
|
|
198
|
+
### Changed
|
|
199
|
+
|
|
200
|
+
- Nothing.
|
|
201
|
+
|
|
202
|
+
### Added
|
|
203
|
+
|
|
204
|
+
- `judge_validation(..., item_ids=None, human_baseline=None, ties=None)`
|
|
205
|
+
measures the judge against a human baseline. `human_baseline` is a frame
|
|
206
|
+
with `item_id`, `cluster_id`, `rater_id` and `rating`, one row per human
|
|
207
|
+
rating, and `item_ids` names the item at each position of `human` and
|
|
208
|
+
`judge`. The result carries judge-human and human-human alpha on the same
|
|
209
|
+
items, and a percentile interval on judge-human minus human-human that
|
|
210
|
+
resamples whole clusters. The verdict reads that interval and nothing
|
|
211
|
+
else, and is called provisional when it rests on fewer than 30 clusters.
|
|
212
|
+
The interval is refused when fewer than 90% of resamples leave both
|
|
213
|
+
alphas defined.
|
|
214
|
+
|
|
215
|
+
`ties` is required with a baseline. `"category"` keeps a tie as a label of
|
|
216
|
+
its own and `"drop"` sets it aside as no label, and the choice applies to
|
|
217
|
+
every figure in the result, the headline included. Baseline items are set
|
|
218
|
+
aside by three rules in a fixed order, and the summary counts what each
|
|
219
|
+
one took. A baseline supports only `level="nominal"`. On the MT-Bench
|
|
220
|
+
human judgements the figures reproduce `analysis/mt-bench.md` to the third
|
|
221
|
+
decimal. The new arguments are refused, each with its own message, in the
|
|
222
|
+
combinations that cannot work, such as `ties` or `item_ids` without a
|
|
223
|
+
baseline. Missing values in `item_id`, `cluster_id`, `rater_id` or
|
|
224
|
+
`item_ids` are refused, and the message names the column, the count and
|
|
225
|
+
where the first one is. Every check on the baseline runs before anything
|
|
226
|
+
is resampled.
|
|
227
|
+
|
|
228
|
+
- `JudgeValidation.n_dropped_ties`, `JudgeValidation.ties`, eleven fields
|
|
229
|
+
that start with `baseline_`, and the properties `has_baseline` and
|
|
230
|
+
`has_baseline_interval`. The new fields are the last in the dataclass and
|
|
231
|
+
have defaults, so building a `JudgeValidation` by position with 0.4.0's
|
|
232
|
+
fields still works. A call that passes none of the three new arguments
|
|
233
|
+
returns the same numbers as 0.4.0.
|
|
234
|
+
|
|
235
|
+
### Fixed
|
|
236
|
+
|
|
237
|
+
- **Breaking.** `JudgeValidation.summary()` said "No interval was computed,
|
|
238
|
+
so nothing here is placed against sampling error." when the resamples had
|
|
239
|
+
been drawn and too few of them left alpha defined. On three items, two of
|
|
240
|
+
them unanimous, with `n_boot=2000` and `seed=0`, it now reads "There is
|
|
241
|
+
no interval on that alpha. 591 of 2000 resamples left it undefined, above
|
|
242
|
+
the 10% this reports through. Those are the resamples where every label
|
|
243
|
+
was the same, so percentiles of the rest would understate the upper
|
|
244
|
+
bound." When one resample is left undefined it reads "That is the
|
|
245
|
+
resample where every label was the same", and when only one was drawn
|
|
246
|
+
the count reads "1 of 1 resample". With `n_boot=0` it still says no
|
|
247
|
+
interval was computed. The `audit` judge finding carries the new
|
|
248
|
+
sentence.
|
|
249
|
+
|
|
250
|
+
- **Breaking.** The `audit` finding on a margin whose interval clears zero
|
|
251
|
+
opened "This is the margin between new and old, and it survives the
|
|
252
|
+
fit." No model is fitted there. It now reads "This is the margin between
|
|
253
|
+
new and old, and its interval excludes zero."
|
|
254
|
+
|
|
255
|
+
- **Breaking.** A count or figure of one was printed with a plural noun, or
|
|
256
|
+
with a verb or pronoun that assumed more than one. Each now takes the
|
|
257
|
+
singular. Anything other than one prints as before.
|
|
258
|
+
|
|
259
|
+
- `ScoreCI.summary()`. "With only 1 observations" now reads "With only 1
|
|
260
|
+
observation", and "The interval spans 1 points." now reads "The
|
|
261
|
+
interval spans 1 point."
|
|
262
|
+
- `ComparisonResult.summary()`. "1 of 1 items changed between systems."
|
|
263
|
+
now reads "1 of 1 item changed between systems."
|
|
264
|
+
- `KappaResult.summary()`. "(1 items, 2 raters, 2 categories)" now reads
|
|
265
|
+
"(1 item, 2 raters, 2 categories)".
|
|
266
|
+
- `AgreementResult.summary()`. "1 of 1 items graded more than once" now
|
|
267
|
+
reads "1 of 1 item graded more than once". Where the interval is
|
|
268
|
+
refused, "1 of 1 resamples came back undefined" now reads "1 of 1
|
|
269
|
+
resample came back undefined", and after one undefined resample "Those
|
|
270
|
+
resamples are the unanimous ones" now reads "That resample is the
|
|
271
|
+
unanimous one".
|
|
272
|
+
- `BTResult.summary()`. With two models, "0 of 1 pairs is separable" now
|
|
273
|
+
reads "0 of 1 pair is separable". With one pair separable among
|
|
274
|
+
several, "1 of 3 pairs are separable" now reads "1 of 3 pairs is
|
|
275
|
+
separable", since the verb follows the separable count. Where the
|
|
276
|
+
interval is refused, "1 of 1 resamples came back undefined" now reads
|
|
277
|
+
"1 of 1 resample came back undefined".
|
|
278
|
+
- The `ValueError` from `bradley_terry` for a missing item id. "item_id is
|
|
279
|
+
missing on 1 of 1 comparisons" now reads "item_id is missing on 1 of 1
|
|
280
|
+
comparison".
|
|
281
|
+
- `PositionBias.summary()`, randomised design. "Position A won 100.0% of 1
|
|
282
|
+
judgements" now reads "of 1 judgement". "1 pairs were also run in the
|
|
283
|
+
reverse order" now reads "1 pair was also run in the reverse order".
|
|
284
|
+
"1 judgements were ties and are left out of the rates above." now reads
|
|
285
|
+
"1 judgement was a tie and is left out of the rates above."
|
|
286
|
+
- `PositionBias.summary()`, both orders. "1 of 1 pairs were run in both
|
|
287
|
+
orders" now reads "1 of 1 pair was run in both orders", and "1 of 2
|
|
288
|
+
pairs were run in both orders" now reads "1 of 2 pairs was run in both
|
|
289
|
+
orders", since the verb follows the pairs run both ways. "on 0.0% of 1
|
|
290
|
+
pairs" now reads "on 0.0% of 1 pair", and "Of the 1 pairs it flipped
|
|
291
|
+
on" now reads "Of the 1 pair it flipped on".
|
|
292
|
+
- `LengthBias.summary()`. "(1 pairs)" now reads "(1 pair)", and "(1
|
|
293
|
+
disagreements)" now reads "(1 disagreement)", with or without a fitted
|
|
294
|
+
model. A length step that prints as 1, "1 characters of extra length
|
|
295
|
+
multiplies" or "1 characters multiplies", now reads "1 character".
|
|
296
|
+
- `PowerResult.summary()`. "you need roughly 1 paired comparisons" now
|
|
297
|
+
reads "you need roughly 1 paired comparison", and "about 1 discordant
|
|
298
|
+
pairs, and McNemar reads only those." now reads "about 1 discordant
|
|
299
|
+
pair, and McNemar reads only that one." A difference that prints as 1,
|
|
300
|
+
"is 1 points" or "a difference of 1 points", now reads "1 point".
|
|
301
|
+
|
|
302
|
+
The `audit` compare, agreement, position, length and power findings carry
|
|
303
|
+
these sentences word for word.
|
|
304
|
+
|
|
305
|
+
- **Breaking.** Compound modifiers are hyphenated in printed text.
|
|
306
|
+
|
|
307
|
+
- `PowerResult.summary()`. "To detect a 5 point difference", "leaves at
|
|
308
|
+
most a 5 point difference" and "To find a 5 point difference" now read
|
|
309
|
+
"5-point", and the same holds for any figure. "the continuity
|
|
310
|
+
corrected and exact forms" now reads "continuity-corrected", and
|
|
311
|
+
"Pairing removes the item to item difficulty" now reads
|
|
312
|
+
"item-to-item". The `audit` power finding carries these sentences.
|
|
313
|
+
- The `audit` action under "Rater agreement holds up". "Keep the double
|
|
314
|
+
graded sample" now reads "Keep the double-graded sample".
|
|
315
|
+
- The `ValueError` from `detectable_effect` and `min_sample_size` when
|
|
316
|
+
power does not exceed alpha. "A two sided test" now reads "A two-sided
|
|
317
|
+
test".
|
|
318
|
+
|
|
319
|
+
- **Breaking.** `PositionBias.summary()` printed a rate, an interval and a
|
|
320
|
+
verdict when nothing could be scored.
|
|
321
|
+
|
|
322
|
+
- Randomised design. On three pairs judged once, each a tie, it printed
|
|
323
|
+
"Each pair was judged once, so this reports the position-A win rate.
|
|
324
|
+
Position A won nan% of 0 judgements (95% CI: nan% to nan%, exact
|
|
325
|
+
binomial p=nan). The interval includes 50%, so the data cannot show
|
|
326
|
+
that position moved the judge." and went on to the caveat about
|
|
327
|
+
randomised order. It now reads "Each pair was judged once, so this
|
|
328
|
+
would report the position-A win rate. Every judgement was a tie, so
|
|
329
|
+
there is no rate to report and nothing here tests position."
|
|
330
|
+
- Both orders. On two pairs run both ways, each with a tie on one side,
|
|
331
|
+
and one pair judged once, it printed "2 of 3 pairs were run in both
|
|
332
|
+
orders, so this reports the consistency rate. The judge named the same
|
|
333
|
+
output under both orderings on nan% of 0 pairs (95% CI: nan% to nan%).
|
|
334
|
+
It never flipped, so there is no direction to test and nothing here
|
|
335
|
+
points at position." It now reads "2 of 3 pairs were run in both
|
|
336
|
+
orders, so this would report the consistency rate. In every pair run
|
|
337
|
+
both ways, the judge called a tie every time in at least one of the two
|
|
338
|
+
orders, so no pair could be scored and there is no rate to report.
|
|
339
|
+
Nothing here tests position."
|
|
340
|
+
|
|
341
|
+
The randomised summary ended "3 judgements were ties and are left out of
|
|
342
|
+
the rates above." and the both-orders one ended the same way with 2.
|
|
343
|
+
There are no rates for the ties to be left out of, so that sentence is
|
|
344
|
+
gone from both. The `audit` position finding on this data was an info
|
|
345
|
+
finding titled "The data cannot show a position effect in the pairwise
|
|
346
|
+
judgements". It is now a warning titled "Position bias is undefined on
|
|
347
|
+
this data", and it carries the new summary.
|
|
348
|
+
|
|
349
|
+
- **Breaking.** In the both-orders design, `position_bias` formed each
|
|
350
|
+
pair's couple, its first two judgements that are reverses, before looking
|
|
351
|
+
at ties, and dropped the pair if either was a tie. A pair judged more than
|
|
352
|
+
once in an order was dropped for a tied first couple even when a later
|
|
353
|
+
couple had no tie, and the summary did not say so. Ties are now set aside
|
|
354
|
+
first, so the pair is scored on its first two decisive judgements that are
|
|
355
|
+
reverses. On two consistent pairs and a third judged x/y and y/x as ties
|
|
356
|
+
and then x/y for x and y/x for y, it printed "The judge named the same
|
|
357
|
+
output under both orderings on 100.0% of 2 pairs (95% CI: 34.2% to
|
|
358
|
+
100.0%). It never flipped, so there is no direction to test and nothing
|
|
359
|
+
here points at position." It now reads "The judge named the same output
|
|
360
|
+
under both orderings on 66.7% of 3 pairs (95% CI: 20.8% to 93.9%). Of the
|
|
361
|
+
1 pair it flipped on, 1 went to whichever output was shown first (100.0%,
|
|
362
|
+
95% CI: 2.5% to 100.0%, exact binomial p=1.0000)." and goes on to say the
|
|
363
|
+
data cannot show that the flips have a direction. `n_pairs_scored` goes
|
|
364
|
+
from 2 to 3 and `n_decisive` from 0 to 1. A pair judged once in each
|
|
365
|
+
order scores as before, since setting its ties aside leaves a couple
|
|
366
|
+
exactly when neither judgement was a tie. The `audit` position finding
|
|
367
|
+
carries the new figures.
|
|
368
|
+
|
|
369
|
+
- The `rater_agreement` docstring said that without an interval nothing in
|
|
370
|
+
the result would name an outlier rater. Since 0.4.0 the summary lists
|
|
371
|
+
alpha with each rater left out and names no rater either way, and the
|
|
372
|
+
docstring now says so.
|
|
373
|
+
|
|
374
|
+
- The README said scipy computes McNemar's test. It is statsmodels. It also
|
|
375
|
+
said the package builds fifteen intervals, while its own lists named
|
|
376
|
+
seventeen. It now counts eighteen, with the interval on the human baseline
|
|
377
|
+
among the eight pinned against a reference.
|
|
378
|
+
|
|
379
|
+
### Removed
|
|
380
|
+
|
|
381
|
+
- Nothing.
|
|
382
|
+
|
|
383
|
+
## [0.4.0] - 2026-09-11
|
|
18
384
|
|
|
19
|
-
|
|
385
|
+
Nearly everything in 0.4.0 changes what a
|
|
20
386
|
summary or a report prints. One rule is behind it. A result that does not
|
|
21
387
|
clear its threshold has failed to show something, and it has not shown the
|
|
22
388
|
opposite. Summaries that described such a result as if the opposite were
|
|
@@ -24,7 +390,8 @@ shown, and verdicts decided on a point estimate where an interval existed,
|
|
|
24
390
|
now say what the data did and did not show. Several `audit` findings change
|
|
25
391
|
severity on data you have already run. Each breaking entry says what it
|
|
26
392
|
was, what it is now and what to do about it. Every entry was checked by
|
|
27
|
-
running the same calls against 0.3.0 from PyPI and against
|
|
393
|
+
running the same calls against 0.3.0 from PyPI and against the code
|
|
394
|
+
released as 0.4.0.
|
|
28
395
|
|
|
29
396
|
### Changed
|
|
30
397
|
|
|
@@ -54,7 +421,7 @@ running the same calls against 0.3.0 from PyPI and against this tree.
|
|
|
54
421
|
eval's reach", because without a stated effect the audit does not know
|
|
55
422
|
what size of difference matters. Its lead says "This reports what the
|
|
56
423
|
design could find and makes no claim about the margin it measured." On 400
|
|
57
|
-
paired items with a 5.0
|
|
424
|
+
paired items with a 5.0-point margin and an interval of 1.1% to 9.0%,
|
|
58
425
|
0.3.0 opened the report with a `critical` power finding and the verdict
|
|
59
426
|
said the conclusion did not hold. Two systems with a margin of exactly
|
|
60
427
|
zero, which 0.3.0 skipped, get the same warning.
|
|
@@ -328,8 +695,8 @@ running the same calls against 0.3.0 from PyPI and against this tree.
|
|
|
328
695
|
### Known limitations
|
|
329
696
|
|
|
330
697
|
This rule is unchanged since 0.3.0 and is not fixed in this release. The
|
|
331
|
-
figures come from simulations run against 0.3.0 and against
|
|
332
|
-
give the same results.
|
|
698
|
+
figures come from simulations run against 0.3.0 and against the code released
|
|
699
|
+
as 0.4.0, which give the same results.
|
|
333
700
|
|
|
334
701
|
- `JudgeValidation` names a slice, and `audit` raises a critical finding on
|
|
335
702
|
it, only when the slice's own interval sits wholly below the interval on
|
|
@@ -386,7 +753,7 @@ breaking entry says what it was, what it is now and what to do about it.
|
|
|
386
753
|
simulated data shaped like MT-Bench's human judgements, the rating
|
|
387
754
|
intervals 0.2.1 reported covered 88% of the time at a nominal 95% once
|
|
388
755
|
prompts shifted model strength by a spread of 0.5 on the log-odds scale,
|
|
389
|
-
and
|
|
756
|
+
and 80% at a spread of 1.0. `examples/pairwise_cluster_study.py` has the
|
|
390
757
|
table for 0.3.0.
|
|
391
758
|
|
|
392
759
|
To get the ratings and rating intervals an earlier version gave on the
|
|
@@ -494,7 +861,7 @@ breaking entry says what it was, what it is now and what to do about it.
|
|
|
494
861
|
- `to_elo` stretches the gap intervals with the gaps and carries `pairs` and
|
|
495
862
|
`resample` across.
|
|
496
863
|
- `examples/pairwise_cluster_study.py`, in the source distribution, which
|
|
497
|
-
measures how narrow the comparison bootstrap runs on MT-Bench
|
|
864
|
+
measures how narrow the comparison bootstrap runs on MT-Bench-shaped data.
|
|
498
865
|
|
|
499
866
|
### Fixed
|
|
500
867
|
|
|
@@ -629,7 +996,9 @@ hour after the upload. It reported `__version__` as 0.1.0.
|
|
|
629
996
|
|
|
630
997
|
- Nothing.
|
|
631
998
|
|
|
632
|
-
[
|
|
999
|
+
[0.6.0]: https://github.com/mokayahezron/evalaudit/compare/v0.5.0...v0.6.0
|
|
1000
|
+
[0.5.0]: https://github.com/mokayahezron/evalaudit/compare/v0.4.0...v0.5.0
|
|
1001
|
+
[0.4.0]: https://github.com/mokayahezron/evalaudit/compare/v0.3.0...v0.4.0
|
|
633
1002
|
[0.3.0]: https://github.com/mokayahezron/evalaudit/compare/809a650...v0.3.0
|
|
634
1003
|
[0.2.1]: https://github.com/mokayahezron/evalaudit/compare/242e354...809a650
|
|
635
1004
|
[0.2.0]: https://github.com/mokayahezron/evalaudit/compare/c1230f1...242e354
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Hezron Mokaya
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hezron Mokaya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|