--- title: "Getting Started with aiEvalR" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with aiEvalR} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) set.seed(2026) ``` ```{r setup} library(aiEvalR) ``` ## Why evaluate an AI system like a test? 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. ## Reliability: is the system consistent? 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. ```{r reliability} # 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 ``` An intraclass correlation near 1 means the system answers the same prompt consistently across occasions. A bootstrap interval expresses the uncertainty in that estimate: ```{r reliability-boot} boot <- ai_bootstrap_reliability(responses, n_boot = 200, seed = 1) c(estimate = boot$estimate, lower = boot$ci_lower, upper = boot$ci_upper) ``` ## Robustness: does the answer survive small changes? If trivial rewordings of the same prompt swing the output, the system is brittle. `stress_test()` compares a baseline against perturbed versions. ```{r robustness} 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 ``` The `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. ## Fairness: do outcomes differ by group? `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. ```{r fairness} outcome <- rbinom(200, 1, 0.4) group <- sample(c("A", "B"), 200, replace = TRUE) disp <- ai_group_disparity(outcome, group) disp$demographic_parity_diff ``` For item-level, IRT-based differential AI scoring bias, `aiEvalR` integrates with the companion `aiDIF` package rather than reimplementing it -- see `?ai_fairness`. ## Calibration: are stated confidences trustworthy? 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. ```{r calibration} # Well-calibrated: predicted probabilities match empirical frequencies confidence <- runif(500) outcome <- rbinom(500, 1, confidence) cal <- ai_calibration(outcome, confidence, n_bins = 10) c(ECE = cal$ece, Brier = cal$brier) ``` ## Hallucination: aggregating adjudicated labels `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. ```{r hallucination} # externally adjudicated: TRUE = claim unsupported verdicts <- c(FALSE, FALSE, TRUE, FALSE, TRUE) hallucination_rate(verdicts) # lexical overlap is NOT factual consistency -- note the name lexical_overlap("the treatment reduces mortality", "the treatment does not reduce mortality") ``` Notice 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. ## An integrated dashboard Once you have module-level scores rescaled to `[0, 1]`, `ai_dashboard()` combines them into an overall profile. ```{r dashboard} ai_dashboard( reliability = 0.94, fairness = 0.82, robustness = 0.70, calibration = 0.88, hallucination = 0.81 ) ``` 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. ## Where to next 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")`.