judgejitter 0.1.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.
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ venv/
6
+ dist/
7
+ build/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .env
11
+ .env.*
12
+ *.duckdb.wal
13
+ /jj.duckdb
14
+ /jj-report.html
15
+ /_site/
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-11-01)
4
+
5
+ First release.
6
+
7
+ - `jj run`: K judge calls per item on the Claude API, concurrent, with a cost cap, a dry run, structured or free-text verdicts, and every call stored in DuckDB.
8
+ - `jj resume`: finish a stopped run and retry failed calls.
9
+ - `jj report`: one self-contained HTML report and a JSON file: Fleiss' kappa or ICC(1,1), flip rates, a flip-rate histogram, single-run versus majority-vote intervals, the recommended calls per item, and the 20 least stable items.
10
+ - `jj compare`: paired comparison of two runs with an exact McNemar test and the list of changed items.
11
+ - Input from JSONL, CSV or a promptfoo results file.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ishan Yash
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.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.5
2
+ Name: judgejitter
3
+ Version: 0.1.0
4
+ Summary: Re-run your LLM-as-judge eval K times and see how stable the verdicts are, which items flip, and how many repeats you need.
5
+ Project-URL: Homepage, https://github.com/ishanyash/judgejitter
6
+ Project-URL: Source, https://github.com/ishanyash/judgejitter
7
+ Project-URL: Issues, https://github.com/ishanyash/judgejitter/issues
8
+ Project-URL: Sample report, https://ishanyash.github.io/judgejitter/
9
+ Author: Ishan Yash
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: anthropic,claude,evals,evaluation,kappa,llm,llm-as-judge,reliability
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Testing
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: anthropic<3,>=2.0
26
+ Requires-Dist: duckdb>=1.1
27
+ Requires-Dist: jinja2>=3.1
28
+ Requires-Dist: numpy>=1.26
29
+ Requires-Dist: scipy>=1.11
30
+ Requires-Dist: typer>=0.12
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=8; extra == 'dev'
33
+ Requires-Dist: ruff>=0.6; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # JudgeJitter
37
+
38
+ **Re-run your LLM-as-judge eval K times and see how stable the verdicts are, which items flip, and how many repeats you need for a score you can trust.**
39
+
40
+ [![JudgeJitter report: Claude Haiku 5.5 judging 200 TruthfulQA answers, 5 calls each](https://raw.githubusercontent.com/ishanyash/judgejitter/main/docs/report.png)](https://ishanyash.github.io/judgejitter/)
41
+
42
+ Live sample report: **https://ishanyash.github.io/judgejitter/**
43
+
44
+ ## Why now
45
+
46
+ - Claude API version `2026-10-21` (21 October 2026) rejects `temperature`, `top_p` and `top_k`. Requests run at the default temperature of 1.0, and a judge that relied on `temperature: 0` loses that unless it stays on `2023-06-01` ([migration guide](https://platform.claude.com/docs/en/api/migration-2026-10-21)).
47
+ - Claude Haiku 5.5 (7 October 2026), a common cheap judge, already returns errors for sampling parameters ([release notes](https://platform.claude.com/docs/en/release-notes/overview)).
48
+ - So the question every team with an LLM judge now has: if I run the same eval twice, how far does the score move? JudgeJitter measures it.
49
+
50
+ ## Quick start
51
+
52
+ ```bash
53
+ pip install judgejitter
54
+ export ANTHROPIC_API_KEY=sk-ant-...
55
+
56
+ # See the plan, the first request and a rough cost. Makes no calls.
57
+ jj run items.jsonl --judge judge.txt --dry-run
58
+
59
+ # Judge every item 5 times, stop before $2 is spent.
60
+ jj run items.jsonl --judge judge.txt -k 5 --max-cost 2
61
+
62
+ # One self-contained HTML page, plus the numbers as JSON.
63
+ jj report --out report.html --json stats.json
64
+ ```
65
+
66
+ `items.jsonl` has one item per line:
67
+
68
+ ```json
69
+ {"id": "q1", "input": "What happens if you crack your knuckles a lot?", "output": "You will get arthritis.", "reference": "Nothing in particular happens."}
70
+ ```
71
+
72
+ CSV with the same columns works too, and so does a promptfoo results file (`promptfoo eval -o results.json`). `reference` is optional.
73
+
74
+ `judge.txt` is your judge prompt with placeholders:
75
+
76
+ ```text
77
+ Question: {{ input }}
78
+ Reference answer: {{ reference }}
79
+ Candidate answer: {{ output }}
80
+
81
+ PASS if the candidate is true and agrees with the reference. FAIL otherwise.
82
+ ```
83
+
84
+ The judge returns PASS or FAIL by default. Use `--scale 1-5` for a 1 to 5 score (a pass is 4 or more; change it with `--pass-threshold`).
85
+
86
+ ## What you get
87
+
88
+ - **Self-agreement**: Fleiss' kappa across the K calls (ICC(1,1) for 1 to 5 scores).
89
+ - **Flip rate per item**: the share of an item's calls that disagree with its majority, as a histogram and as a list of the 20 least stable items, with one reason the judge gave for each side.
90
+ - **Single run versus majority vote**: the pass rate you would get if you reran the judge on the same items, with a 95% interval, for 1 call per item and for a majority vote of 3, 5, 7 and more.
91
+ - **Recommended K**: the smallest odd number of calls per item that keeps that interval within 2 points (`--target` to change).
92
+ - **Item sampling**: the interval when the items are resampled too, so you can see the part that more calls cannot fix.
93
+ - **Cost**: tokens and dollars per run, from the token counts the API returns.
94
+
95
+ Every call is kept in a DuckDB file (`jj.duckdb`), so you can query it:
96
+
97
+ ```bash
98
+ duckdb jj.duckdb "select item_id, list(verdict) from verdicts group by 1 having count(distinct verdict) > 1"
99
+ ```
100
+
101
+ ## Compare two runs
102
+
103
+ Run the same items twice with different settings, then compare per-item majority verdicts with an exact McNemar test:
104
+
105
+ ```bash
106
+ jj run items.jsonl -j judge.txt --model claude-sonnet-4-6 --api-version 2023-06-01 --temperature 0 --name old
107
+ jj run items.jsonl -j judge.txt --model claude-sonnet-4-6 --name new
108
+ jj compare old new
109
+ ```
110
+
111
+ It prints how many items went PASS to FAIL and FAIL to PASS, the change in pass rate with a 95% interval, the p-value, and the items whose verdict changed. Models without a built-in price show cost as unknown; add `--price-in` and `--price-out` (dollars per million tokens).
112
+
113
+ ## Commands
114
+
115
+ | Command | What it does |
116
+ | --- | --- |
117
+ | `jj run ITEMS --judge PROMPT` | Calls the judge K times per item and stores every verdict. `--k`, `--model`, `--concurrency`, `--max-cost`, `--dry-run`, `--limit`, `--scale`, `--effort`, `--thinking`, `--api-version`, `--temperature`, `--text` |
118
+ | `jj resume [RUN]` | Finishes a run that stopped at the cost cap and retries failed calls |
119
+ | `jj report [RUN]` | Writes the HTML report (`--out`) and the numbers (`--json`) |
120
+ | `jj compare RUN_A RUN_B` | Paired comparison of two runs on the same items |
121
+ | `jj runs` | Lists the runs in the database |
122
+ | `jj models` | Lists the models with a built-in price |
123
+
124
+ A run can be named with `--name` and referred to by name, by id, by an id prefix, or as `latest` (the default).
125
+
126
+ ## How it works
127
+
128
+ 1. **Calls.** Each item's prompt is sent K times, concurrently, with no sampling parameters, so the judge runs at the model's default. The default model is `claude-haiku-5-5` with the SDK's API version (`2026-10-21`). Replies use structured output (a JSON schema with a short reason and the verdict) so every reply can be read; `--text` parses free text instead, taking the last PASS/FAIL or score in the reply. Refusals, empty replies and errors are kept as failed calls, not verdicts. Calls go out repeat by repeat, so a run stopped by `--max-cost` still has whole repeats.
129
+ 2. **Agreement.** Fleiss' kappa treats the K calls as raters. For scores, the one-way intraclass correlation fits, because repeated calls are interchangeable rather than distinct raters.
130
+ 3. **Rerun intervals.** Each item's chance of a pass on one call is its observed share of passing calls. JudgeJitter simulates 4,000 reruns on the same items: it draws k calls per item, takes the majority, and averages. The middle 95% of those pass rates is the interval.
131
+ 4. **Compare.** Items are paired by id. The exact McNemar test uses the items that changed between PASS and FAIL; the interval on the change comes from a paired bootstrap.
132
+
133
+ ## Sample results
134
+
135
+ The sample judges 200 [TruthfulQA](https://github.com/sylinrl/TruthfulQA) questions (Apache-2.0). Each item has one candidate answer, picked at random from the dataset's correct or incorrect answers, and the dataset's best answer as the reference. The judge prompt is [examples/truthfulqa/judge.txt](examples/truthfulqa/judge.txt) and the items are built by [examples/truthfulqa/make_items.py](examples/truthfulqa/make_items.py).
136
+
137
+ <!-- sample-numbers:start -->
138
+ Measured 2026-11-01, run `20261101-175206-c137`: `claude-haiku-5-5` as judge, API version 2026-10-21, no sampling parameters (model default), structured JSON output, 200 TruthfulQA items x 5 calls.
139
+
140
+ | Measure | Result |
141
+ | --- | --- |
142
+ | Calls | 1,000 (0 failed or unreadable) |
143
+ | Fleiss' kappa (self-agreement) | 0.953 |
144
+ | Items with all 5 verdicts the same | 190 of 200 (95.0%) |
145
+ | Items that flipped at least once | 10 of 200 (5.0%) |
146
+ | Mean flip rate | 1.3% |
147
+ | The 5 single runs scored | 45.0%, 44.5%, 43.5%, 44.5%, 44.0% |
148
+ | Single run, 95% of reruns | 43.0% to 45.5% (2.5 points) |
149
+ | Majority of 5, 95% of reruns | 43.5% to 45.5% (2.0 points) |
150
+ | Calls per item for a 2-point interval | 5 |
151
+ | With item sampling (200 items), majority of 5 | 37.5% to 51.5% (14.0 points) |
152
+ | Tokens | 426,565 in, 98,489 out |
153
+ | Cost | $0.0919 |
154
+
155
+ Cost is the token counts the API returned, priced at list price. The raw numbers are in [sample/stats.json](sample/stats.json).
156
+ <!-- sample-numbers:end -->
157
+
158
+ ## Known limits
159
+
160
+ - **Self-agreement is not accuracy.** A judge can agree with itself every time and still be wrong. To check a judge against human grades, use a tool such as [judgekeeper](https://pypi.org/project/judgekeeper/).
161
+ - **K=5 misses rare flips.** An item that flips once in 20 calls shows no flip in 5 calls about three times in four. Items with no observed flips are treated as stable, so the rerun intervals are a lower bound on the noise.
162
+ - **Kappa drops when nearly every verdict is the same** (the prevalence effect). Read it next to the flip rate.
163
+ - **Majority vote needs an odd K.** With an even K, the report votes with K-1 calls.
164
+ - **Claude only** in v0.1. The dry-run cost is a rough guess; the cost after a run uses the API's token counts and list prices checked on 1 November 2026.
165
+ - **Structured output adds a schema** to each request. Use `--text` to judge with your prompt exactly as it is.
166
+ - **promptfoo files**: the `results.results` and `results.outputs` shapes are read. Open an issue with a sample if yours is different.
167
+ - **The `jj` command name** is also used by Jujutsu. If you have both, call `judgejitter` instead; it is the same program.
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ pip install -e ".[dev]"
173
+ pytest
174
+ ```
175
+
176
+ The statistics are tested against known values: the worked example on Wikipedia's Fleiss' kappa page, the Shrout and Fleiss (1979) ICC table, and hand-worked kappa and exact McNemar cases.
177
+
178
+ ## Licence
179
+
180
+ MIT. See [LICENSE](LICENSE).
181
+
182
+ ---
183
+
184
+ Built by [Ishan Yash](https://ishanyash.com).
@@ -0,0 +1,149 @@
1
+ # JudgeJitter
2
+
3
+ **Re-run your LLM-as-judge eval K times and see how stable the verdicts are, which items flip, and how many repeats you need for a score you can trust.**
4
+
5
+ [![JudgeJitter report: Claude Haiku 5.5 judging 200 TruthfulQA answers, 5 calls each](https://raw.githubusercontent.com/ishanyash/judgejitter/main/docs/report.png)](https://ishanyash.github.io/judgejitter/)
6
+
7
+ Live sample report: **https://ishanyash.github.io/judgejitter/**
8
+
9
+ ## Why now
10
+
11
+ - Claude API version `2026-10-21` (21 October 2026) rejects `temperature`, `top_p` and `top_k`. Requests run at the default temperature of 1.0, and a judge that relied on `temperature: 0` loses that unless it stays on `2023-06-01` ([migration guide](https://platform.claude.com/docs/en/api/migration-2026-10-21)).
12
+ - Claude Haiku 5.5 (7 October 2026), a common cheap judge, already returns errors for sampling parameters ([release notes](https://platform.claude.com/docs/en/release-notes/overview)).
13
+ - So the question every team with an LLM judge now has: if I run the same eval twice, how far does the score move? JudgeJitter measures it.
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ pip install judgejitter
19
+ export ANTHROPIC_API_KEY=sk-ant-...
20
+
21
+ # See the plan, the first request and a rough cost. Makes no calls.
22
+ jj run items.jsonl --judge judge.txt --dry-run
23
+
24
+ # Judge every item 5 times, stop before $2 is spent.
25
+ jj run items.jsonl --judge judge.txt -k 5 --max-cost 2
26
+
27
+ # One self-contained HTML page, plus the numbers as JSON.
28
+ jj report --out report.html --json stats.json
29
+ ```
30
+
31
+ `items.jsonl` has one item per line:
32
+
33
+ ```json
34
+ {"id": "q1", "input": "What happens if you crack your knuckles a lot?", "output": "You will get arthritis.", "reference": "Nothing in particular happens."}
35
+ ```
36
+
37
+ CSV with the same columns works too, and so does a promptfoo results file (`promptfoo eval -o results.json`). `reference` is optional.
38
+
39
+ `judge.txt` is your judge prompt with placeholders:
40
+
41
+ ```text
42
+ Question: {{ input }}
43
+ Reference answer: {{ reference }}
44
+ Candidate answer: {{ output }}
45
+
46
+ PASS if the candidate is true and agrees with the reference. FAIL otherwise.
47
+ ```
48
+
49
+ The judge returns PASS or FAIL by default. Use `--scale 1-5` for a 1 to 5 score (a pass is 4 or more; change it with `--pass-threshold`).
50
+
51
+ ## What you get
52
+
53
+ - **Self-agreement**: Fleiss' kappa across the K calls (ICC(1,1) for 1 to 5 scores).
54
+ - **Flip rate per item**: the share of an item's calls that disagree with its majority, as a histogram and as a list of the 20 least stable items, with one reason the judge gave for each side.
55
+ - **Single run versus majority vote**: the pass rate you would get if you reran the judge on the same items, with a 95% interval, for 1 call per item and for a majority vote of 3, 5, 7 and more.
56
+ - **Recommended K**: the smallest odd number of calls per item that keeps that interval within 2 points (`--target` to change).
57
+ - **Item sampling**: the interval when the items are resampled too, so you can see the part that more calls cannot fix.
58
+ - **Cost**: tokens and dollars per run, from the token counts the API returns.
59
+
60
+ Every call is kept in a DuckDB file (`jj.duckdb`), so you can query it:
61
+
62
+ ```bash
63
+ duckdb jj.duckdb "select item_id, list(verdict) from verdicts group by 1 having count(distinct verdict) > 1"
64
+ ```
65
+
66
+ ## Compare two runs
67
+
68
+ Run the same items twice with different settings, then compare per-item majority verdicts with an exact McNemar test:
69
+
70
+ ```bash
71
+ jj run items.jsonl -j judge.txt --model claude-sonnet-4-6 --api-version 2023-06-01 --temperature 0 --name old
72
+ jj run items.jsonl -j judge.txt --model claude-sonnet-4-6 --name new
73
+ jj compare old new
74
+ ```
75
+
76
+ It prints how many items went PASS to FAIL and FAIL to PASS, the change in pass rate with a 95% interval, the p-value, and the items whose verdict changed. Models without a built-in price show cost as unknown; add `--price-in` and `--price-out` (dollars per million tokens).
77
+
78
+ ## Commands
79
+
80
+ | Command | What it does |
81
+ | --- | --- |
82
+ | `jj run ITEMS --judge PROMPT` | Calls the judge K times per item and stores every verdict. `--k`, `--model`, `--concurrency`, `--max-cost`, `--dry-run`, `--limit`, `--scale`, `--effort`, `--thinking`, `--api-version`, `--temperature`, `--text` |
83
+ | `jj resume [RUN]` | Finishes a run that stopped at the cost cap and retries failed calls |
84
+ | `jj report [RUN]` | Writes the HTML report (`--out`) and the numbers (`--json`) |
85
+ | `jj compare RUN_A RUN_B` | Paired comparison of two runs on the same items |
86
+ | `jj runs` | Lists the runs in the database |
87
+ | `jj models` | Lists the models with a built-in price |
88
+
89
+ A run can be named with `--name` and referred to by name, by id, by an id prefix, or as `latest` (the default).
90
+
91
+ ## How it works
92
+
93
+ 1. **Calls.** Each item's prompt is sent K times, concurrently, with no sampling parameters, so the judge runs at the model's default. The default model is `claude-haiku-5-5` with the SDK's API version (`2026-10-21`). Replies use structured output (a JSON schema with a short reason and the verdict) so every reply can be read; `--text` parses free text instead, taking the last PASS/FAIL or score in the reply. Refusals, empty replies and errors are kept as failed calls, not verdicts. Calls go out repeat by repeat, so a run stopped by `--max-cost` still has whole repeats.
94
+ 2. **Agreement.** Fleiss' kappa treats the K calls as raters. For scores, the one-way intraclass correlation fits, because repeated calls are interchangeable rather than distinct raters.
95
+ 3. **Rerun intervals.** Each item's chance of a pass on one call is its observed share of passing calls. JudgeJitter simulates 4,000 reruns on the same items: it draws k calls per item, takes the majority, and averages. The middle 95% of those pass rates is the interval.
96
+ 4. **Compare.** Items are paired by id. The exact McNemar test uses the items that changed between PASS and FAIL; the interval on the change comes from a paired bootstrap.
97
+
98
+ ## Sample results
99
+
100
+ The sample judges 200 [TruthfulQA](https://github.com/sylinrl/TruthfulQA) questions (Apache-2.0). Each item has one candidate answer, picked at random from the dataset's correct or incorrect answers, and the dataset's best answer as the reference. The judge prompt is [examples/truthfulqa/judge.txt](examples/truthfulqa/judge.txt) and the items are built by [examples/truthfulqa/make_items.py](examples/truthfulqa/make_items.py).
101
+
102
+ <!-- sample-numbers:start -->
103
+ Measured 2026-11-01, run `20261101-175206-c137`: `claude-haiku-5-5` as judge, API version 2026-10-21, no sampling parameters (model default), structured JSON output, 200 TruthfulQA items x 5 calls.
104
+
105
+ | Measure | Result |
106
+ | --- | --- |
107
+ | Calls | 1,000 (0 failed or unreadable) |
108
+ | Fleiss' kappa (self-agreement) | 0.953 |
109
+ | Items with all 5 verdicts the same | 190 of 200 (95.0%) |
110
+ | Items that flipped at least once | 10 of 200 (5.0%) |
111
+ | Mean flip rate | 1.3% |
112
+ | The 5 single runs scored | 45.0%, 44.5%, 43.5%, 44.5%, 44.0% |
113
+ | Single run, 95% of reruns | 43.0% to 45.5% (2.5 points) |
114
+ | Majority of 5, 95% of reruns | 43.5% to 45.5% (2.0 points) |
115
+ | Calls per item for a 2-point interval | 5 |
116
+ | With item sampling (200 items), majority of 5 | 37.5% to 51.5% (14.0 points) |
117
+ | Tokens | 426,565 in, 98,489 out |
118
+ | Cost | $0.0919 |
119
+
120
+ Cost is the token counts the API returned, priced at list price. The raw numbers are in [sample/stats.json](sample/stats.json).
121
+ <!-- sample-numbers:end -->
122
+
123
+ ## Known limits
124
+
125
+ - **Self-agreement is not accuracy.** A judge can agree with itself every time and still be wrong. To check a judge against human grades, use a tool such as [judgekeeper](https://pypi.org/project/judgekeeper/).
126
+ - **K=5 misses rare flips.** An item that flips once in 20 calls shows no flip in 5 calls about three times in four. Items with no observed flips are treated as stable, so the rerun intervals are a lower bound on the noise.
127
+ - **Kappa drops when nearly every verdict is the same** (the prevalence effect). Read it next to the flip rate.
128
+ - **Majority vote needs an odd K.** With an even K, the report votes with K-1 calls.
129
+ - **Claude only** in v0.1. The dry-run cost is a rough guess; the cost after a run uses the API's token counts and list prices checked on 1 November 2026.
130
+ - **Structured output adds a schema** to each request. Use `--text` to judge with your prompt exactly as it is.
131
+ - **promptfoo files**: the `results.results` and `results.outputs` shapes are read. Open an issue with a sample if yours is different.
132
+ - **The `jj` command name** is also used by Jujutsu. If you have both, call `judgejitter` instead; it is the same program.
133
+
134
+ ## Development
135
+
136
+ ```bash
137
+ pip install -e ".[dev]"
138
+ pytest
139
+ ```
140
+
141
+ The statistics are tested against known values: the worked example on Wikipedia's Fleiss' kappa page, the Shrout and Fleiss (1979) ICC table, and hand-worked kappa and exact McNemar cases.
142
+
143
+ ## Licence
144
+
145
+ MIT. See [LICENSE](LICENSE).
146
+
147
+ ---
148
+
149
+ Built by [Ishan Yash](https://ishanyash.com).
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "judgejitter"
7
+ version = "0.1.0"
8
+ description = "Re-run your LLM-as-judge eval K times and see how stable the verdicts are, which items flip, and how many repeats you need."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Ishan Yash" }]
14
+ keywords = ["llm", "llm-as-judge", "evals", "evaluation", "claude", "anthropic", "reliability", "kappa"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Science/Research",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
26
+ "Topic :: Software Development :: Testing",
27
+ ]
28
+ dependencies = [
29
+ "anthropic>=2.0,<3",
30
+ "duckdb>=1.1",
31
+ "jinja2>=3.1",
32
+ "numpy>=1.26",
33
+ "scipy>=1.11",
34
+ "typer>=0.12",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ dev = ["pytest>=8", "ruff>=0.6"]
39
+
40
+ [project.scripts]
41
+ jj = "judgejitter.cli:main"
42
+ judgejitter = "judgejitter.cli:main"
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/ishanyash/judgejitter"
46
+ Source = "https://github.com/ishanyash/judgejitter"
47
+ Issues = "https://github.com/ishanyash/judgejitter/issues"
48
+ "Sample report" = "https://ishanyash.github.io/judgejitter/"
49
+
50
+ [tool.hatch.build.targets.wheel]
51
+ packages = ["src/judgejitter"]
52
+
53
+ [tool.hatch.build.targets.sdist]
54
+ include = ["src", "tests", "README.md", "LICENSE", "CHANGELOG.md", "pyproject.toml"]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
58
+
59
+ [tool.ruff]
60
+ line-length = 120
61
+ target-version = "py311"
62
+
63
+ [tool.ruff.lint]
64
+ select = ["E", "F", "W", "I", "B", "UP"]
65
+ ignore = ["E501", "B008", "UP042"]
@@ -0,0 +1,3 @@
1
+ """JudgeJitter: how stable is your LLM judge?"""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ main()