Most AI evaluation reduces a system to a single accuracy-style score.
But a language model used to score essays, answer questions, or make
recommendations is a measurement instrument, and psychometrics
has spent a century developing tools for exactly this: reliability,
validity, fairness, calibration, and error structure.
aiEvalR brings that toolkit to AI evaluation.
This vignette tours the package module by module with small runnable examples. Throughout, we simulate AI outputs where we need repeated model responses (there is no built-in “call an LLM” step), and use built-in R data where an ordinary regression suffices.
Treat repeated calls to the same prompt the way classical test theory treats repeated administrations of a test. Here, rows are prompts and columns are repeated response occasions.
# 12 prompts, each answered on 3 separate occasions (e.g. repeated
# sampling). Scores are stable across occasions -> high reliability.
latent <- rnorm(12, mean = 5)
responses <- sapply(1:3, function(occasion) latent + rnorm(12, sd = 0.3))
rel <- ai_reliability(responses)
rel$test_retest$icc
#> [1] 0.8310085An intraclass correlation near 1 means the system answers the same prompt consistently across occasions. A bootstrap interval expresses the uncertainty in that estimate:
If trivial rewordings of the same prompt swing the output, the system
is brittle. stress_test() compares a baseline against
perturbed versions.
baseline <- rnorm(100, mean = 5, sd = 1)
# a mild perturbation and a severe one, applied to the same prompts
mild <- baseline + rnorm(100, mean = 0.1, sd = 0.05)
severe <- baseline + rnorm(100, mean = 1.0, sd = 0.05)
st <- stress_test(baseline, list(mild = mild, severe = severe))
st$robustness_index
#> [1] 0.4790861The robustness_index is a descriptive summary (higher =
more robust); see ?stress_test for its limitations.
prompt_sensitivity() separately quantifies how much output
varies across paraphrases of the same underlying prompt.
ai_group_disparity() reports demographic parity and,
given binary decisions, equalized-odds gaps. It is named “disparity,”
not “bias,” deliberately: a group difference is not automatically
evidence of an unfair process.
outcome <- rbinom(200, 1, 0.4)
group <- sample(c("A", "B"), 200, replace = TRUE)
disp <- ai_group_disparity(outcome, group)
disp$demographic_parity_diff
#> [1] 0.06936243For item-level, IRT-based differential AI scoring bias,
aiEvalR integrates with the companion aiDIF
package rather than reimplementing it – see
?ai_fairness.
If a system says “90% confident,” it should be right about 90% of the time. Expected Calibration Error and the Brier score quantify the gap.
aiEvalR does not itself fact-check (that needs a
retrieval/NLI component). It aggregates verdicts you supply, and offers
a lexical baseline for overlap with a source.
# externally adjudicated: TRUE = claim unsupported
verdicts <- c(FALSE, FALSE, TRUE, FALSE, TRUE)
hallucination_rate(verdicts)
#> [1] 0.4
# lexical overlap is NOT factual consistency -- note the name
lexical_overlap("the treatment reduces mortality",
"the treatment does not reduce mortality")
#> [1] 0.4285714Notice the two opposite-meaning sentences score as highly similar:
lexical_overlap() measures token overlap, not agreement,
which is exactly why it is named that way.
Once you have module-level scores rescaled to [0, 1],
ai_dashboard() combines them into an overall profile.
ai_dashboard(
reliability = 0.94,
fairness = 0.82,
robustness = 0.70,
calibration = 0.88,
hallucination = 0.81
)
#> AI Evaluation Dashboard
#> ========================
#>
#> Reliability █████████░ 0.94
#> Fairness ████████░░ 0.82
#> Robustness ███████░░░ 0.70
#> Calibration █████████░ 0.88
#> Hallucination ████████░░ 0.81
#>
#> Overall: 0.83 (Grade: B)The dashboard is a descriptive profile, not a validated composite index; the “grade” is a convenience, and you should choose weights deliberately for your context.
The reliability and psychometric-quality modules are the package’s
methodological core. For the full generalizability-theory workflow
(G-studies and D-studies), see
vignette("psychometric-core").