Skip to main content

reliability-lab

Status: alpha (0.1.0). The API may still change between releases.

reliability-lab is a study-design library for measuring the reliability of LLM and human judgments. It is built on Krippendorff's alpha. Alpha implementations already exist in Python. This package adds the workflow around the coefficient:

  • a validated long-form ratings schema in which every rating has an explicit status (observed, abstained, inapplicable, parse_error, provider_error);
  • declared measurement semantics: level, value domain, coder definition and design label;
  • white-box output: observed and expected disagreement, coincidence matrices and per-unit contributions;
  • explicit missing-data policies, because LLM failures are rarely unrelated to the item;
  • bootstrap intervals by a scheme you name: whole units or groups resampled (scheme="units"), or Krippendorff's KALPHA algorithm (scheme="kalpha");
  • paired comparisons of two configurations on the same units, with the interval on the difference;
  • group-safe train/test splits that work with any scikit-learn splitter, with a saved manifest that reproduces the split;
  • versioned JSON and Parquet reports with provenance;
  • LLM judge workflows: a trace sidecar of judge configurations, declared retry handling, and evidence specific to each design (run agreement, order swaps and position bias).

Mixed human-LLM panels and coverage simulations for the bootstrap schemes are next on the roadmap (design document).

Reliability is not validity. Coders can agree consistently and still be wrong in the same way, for example because of a flawed rubric or a bias they share. When results come from different designs (repeatability, inter-model agreement, human panels), they are reported as different quantities and are never pooled.

Install

pip install "reliability-lab[sklearn,parquet]"

The extras are optional. sklearn provides the splitters, although any object with a scikit-learn style split method works; parquet enables to_parquet. For development, run uv sync and then uv run pytest.

Example

import pandas as pd
from reliability_lab import CoderSpec, RatingFrame, ReliabilityStudy

df = pd.DataFrame(
    {
        "item": ["u1", "u1", "u2", "u2", "u3", "u3"],
        "annotator": ["ann", "bob", "ann", "bob", "ann", "bob"],
        "label": ["pos", "pos", "neg", "pos", "neg", "neg"],
    }
)

ratings = RatingFrame.from_long(df, unit="item", rater="annotator", value="label")
study = ReliabilityStudy(
    ratings,
    measurement="nominal",
    values=["neg", "pos"],
    coders=CoderSpec(by="rater_id"),
    design="human_panel",
)
result = study.alpha()
print(result.summary())

Intervals and comparisons

Every interval names its scheme, because the two schemes answer different questions. scheme is a required argument.

boot = result.bootstrap(scheme="units", n_resamples=2000, random_state=7)
print(boot.summary())  # 95% percentile intervals for every missing-data policy
  • scheme="units" resamples whole units, and whole groups when a group column is declared. It can also resample within declared strata (strata=True), and it recomputes the expected disagreement in every replicate. method="bca" is available as an experimental option.
  • scheme="kalpha" reproduces Krippendorff's KALPHA algorithm. It resamples pairs of values and holds the expected disagreement fixed.

To compare two configurations of a judge, for example two prompts, select each one's rows. Both must cover the same units. Every replicate resamples the same units for both, and the interval is on the difference:

diff = study.compare(
    a={"condition_id": "prompt_v1"},
    b={"condition_id": "prompt_v2"},
    n_resamples=2000,
    random_state=7,
)
print(diff.summary())  # alpha_b - alpha_a with a paired interval

Splits and reports

Teams tune the judge (prompt, few-shot examples, rubric) and should report reliability on units the tuning never saw. So split before tuning, freeze the judge, then estimate on the test partition.

When groups are declared, the splitter sees one sample per group (a conversation, say), so groups and repeated LLM calls never cross partitions:

from sklearn.model_selection import StratifiedGroupKFold

dev, test = study.holdout(
    StratifiedGroupKFold(n_splits=4, shuffle=True, random_state=7),
    group_stratum="majority",  # needed only when a group's units span several strata
)
test.save_manifest("split.json")  # the ids of every partition, not just the seed

# ... tune and freeze the judge on dev ...

result = test.alpha()
result.to_json("alpha_test.json")  # strict JSON with provenance
result.to_parquet("alpha_test/")  # tidy tables

dev2, test2 = later_study.apply_manifest("split.json")  # same units, new judge runs
test.manifest.assert_no_leakage(few_shot_units)  # raises LeakageError

See examples/splits.py for a full run. Releases are described in docs/releasing.md.

LLM judge workflows

A condition_id names a frozen judge configuration. A trace sidecar records what each configuration was: provider, prompt hash, rubric and parser versions, temperature, seed, and candidate order for pairwise judges. With it, a study checks that its coders differ only in what the design compares. For example, if prompt-robustness conditions also differ in temperature, it raises a TraceWarning. Whatever the trace leaves out is listed among the provenance gaps.

from reliability_lab import TraceSidecar

trace = TraceSidecar.from_frame(
    configs,
    condition="condition_id",
    prompt_hash="prompt_sha",
    temperature="temperature",
    candidate_order="order",  # "A,B" / "B,A"
)
study = ReliabilityStudy(
    ratings,  # RatingFrame.from_long(..., attempt="attempt")
    measurement="nominal",
    values=["A", "tie", "B"],  # labels name the winning candidate, not its position
    coders="condition_id",
    design="order_robustness",
    trace=trace,
    retries="last",  # required when calls were retried
)
result = study.alpha()
result.diagnostics["order_swap"].values  # reversal rate, P(first shown wins) with a Wilson interval
result.trace_findings  # confounds and caveats from the trace
Design Coders are Evidence beside alpha
repeatability repeated runs of one configuration (run_id) run agreement: units where every run agrees
prompt_robustness prompt conditions of one model pairwise agreement between conditions
inter_model different models pairwise agreement; family and configuration checks
order_robustness candidate orders of one pairwise judge reversal rate and position bias
configuration change two configurations, via study.compare(a=..., b=...) paired interval on the difference; the model and trace fields that changed

The single-configuration designs (repeatability, prompt robustness, order robustness) can hold several configurations to compare, such as an old and a new judge. Each configuration is checked on its own. alpha() refuses to pool them; study.compare(a={"condition_id": "old"}, b={"condition_id": "new"}) reports each one's alpha and diagnostics, with a paired interval on the difference.

Retried calls are never resolved silently. Number the attempts with an attempt column, then declare retries="last" or retries="first_observed". Coverage then reports error rates both per attempt and for the attempts that count. See examples/llm_judge.py.

Licence

BSD-3-Clause. Alpha is implemented independently from Krippendorff's papers. The GPL-licensed krippendorff package is used only in the test suite, as a parity check.

Metadata

Release files for reliability-lab 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for reliability-lab 0.1.0
File Size Uploaded Provenance
reliability_lab-0.1.0.tar.gz 199.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for reliability-lab 0.1.0
File Interpreter ABI Platform
reliability_lab-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 257.9 kB

Release files / reliability_lab-0.1.0.tar.gz

Download URL reliability_lab-0.1.0.tar.gz
Size 199.4 kB
Tags Source
SHA-256 checksum
How to use checksums
74c09788f86d6ac9a511a117bfe392caac11daa96fa0a49fc1332da753081813
BLAKE2b-256 checksum
How to use checksums
36c440ba98f4ddf366716d5af754ddaa0fefc3731bbb6b8326f264f1804dae43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Release files / reliability_lab-0.1.0-py3-none-any.whl

Download URL reliability_lab-0.1.0-py3-none-any.whl
Size 58.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4fe52a10f3f71137902ac4025d6337216e6d2491ec7277311a570e3991d11cde
BLAKE2b-256 checksum
How to use checksums
92fd862425c1add55dc31661e77282e3ae4ff455d4ced46beb0680778a232c3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Security for reliability-lab 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for reliability_lab-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page