Drift Detection
What PSI actually measures, how to monitor an embedding distribution, and how to detect quality regressions when the labels arrive weeks late or never.
Four things called drift
Write for the input distribution and for the relationship being modelled.
| Name | What changed | Example | Remedy |
|---|---|---|---|
| Covariate shift | new customer segment asks different questions | retrain or extend coverage | |
| Prior shift | fraud rate triples | recalibrate thresholds | |
| Concept drift | the refund policy changed, so the right answer changed | update the corpus, retrain | |
| Upstream corruption | itself is wrong | a field stopped being populated | fix the pipeline |
The fourth is not drift at all and is the most common in practice. It is listed here because it presents identically on every monitoring dashboard, and because treating it as drift leads to retraining a model on corrupted data — which converts a fixable bug into a permanent one.
Key idea
Distinguish them by what else moved. Upstream corruption shows a discontinuity — a step change at a deploy boundary, often with a null rate jumping. Covariate shift is gradual and shows in the input distribution with the output relationship intact. Concept drift shows no input change at all and is only visible in outcomes, which is why it is the hardest and needs labels or proxies.
PSI, and what it is
Bin a variable into buckets. Let be the fraction of the reference sample in bucket and the fraction of the current sample. Then
Buckets are built from the reference distribution — usually deciles — and held fixed thereafter.
the Jeffreys divergence. Consequently , with equality if and only if for every , and it is symmetric in its arguments.
Key idea
Knowing PSI is Jeffreys divergence explains two things practitioners hit and usually treat as quirks. It diverges when a bucket empties: with sends the term to infinity, which is why implementations add an epsilon — and that epsilon silently sets the maximum detectable drift. And it is symmetric, so it cannot tell you which direction the distribution moved; that needs the per-bucket contributions, which are worth logging individually since they localise the change.
Heuristic — a reasoning shortcut that predicts the right answer in the regimes discussed here. It is not a proof and can fail outside them.
| PSI | Conventional reading |
|---|---|
| no significant change | |
| moderate change, investigate | |
| significant change, act |
Assumptions
These figures are industry convention with no distributional derivation, and they are not scale-free: PSI depends on the number of buckets and on sample size, so the same underlying shift produces different values under 10 buckets and 20, and a small sample produces a positive PSI against an identical distribution purely from sampling noise. Calibrate thresholds by computing PSI between two samples drawn from the same period — the reference against itself — and set the alarm above the noise floor that produces. Using 0.25 without doing this is guessing.
Embedding distributions
For an LLM system the input is text, and the useful distributional handle is its embedding.
def embedding_drift(reference: np.ndarray, current: np.ndarray) -> dict:
"""Three complementary views of how an embedding cloud has moved."""
mu_r, mu_c = reference.mean(0), current.mean(0)
centroid_shift = np.linalg.norm(mu_c - mu_r) / np.linalg.norm(mu_r)
# Spread: has the cloud changed shape as well as position?
spread_ratio = current.std(0).mean() / reference.std(0).mean()
# Coverage: what fraction of current queries land far from everything we have seen?
d = pairwise_min_distance(current, reference) # nearest reference neighbour
tail = float(np.mean(d > np.quantile(pairwise_min_distance(reference, reference), 0.99)))
return {"centroid_shift": centroid_shift, "spread_ratio": spread_ratio, "novel_fraction": tail}
The third number is the operationally useful one: the fraction of current queries that are unlike anything in the reference set. A rising novel fraction is the earliest signal that the retrieval corpus no longer covers what people are asking, and unlike PSI it points at specific examples you can read.
Alerting on many things at once
Run an independent level- test on each of features every period. Under the null — no drift anywhere — the probability of at least one alarm in a single period is , and over periods
With features at , the daily false-alarm probability is , and over a 30-day month it is .
When the labels are late
Heuristic — a reasoning shortcut that predicts the right answer in the regimes discussed here. It is not a proof and can fail outside them.
Ground truth for a generative system arrives weeks later, incompletely, or never. These move earlier and are available immediately:
| Proxy | Reads on | Typical failure it catches |
|---|---|---|
| refusal rate | outputs | prompt or policy change, safety filter regression |
| mean output length | outputs | truncation bugs, model swap, prompt regression |
| tool-call rate and failure rate | outputs | tool schema drift, broken integration |
| retrieval score distribution | retrieval | index staleness, embedding mismatch |
| "no relevant documents" rate | retrieval | corpus coverage gap |
| user retry / rephrase rate | behaviour | answer quality, broadly |
| escalation-to-human rate | behaviour | the closest thing to a quality label |
| thumbs-down rate | behaviour | quality, heavily biased in sampling |
Each is weak individually. Together, and with per-segment breakdowns, they catch most regressions before any labelled data exists.
Assumptions
Every proxy is confounded. Output length moves when the prompt changes for good reasons; retry rate moves when the UI changes; thumbs-down is dominated by a small unrepresentative population. They are leading indicators for investigation, not evidence for a decision. Treating a proxy movement as proof of a regression is how teams roll back improvements.
Key idea
The one genuinely reliable answer to delayed labels is to create labels deliberately: sample a small, fixed fraction of production traffic, run it through the evaluation harness in Evaluation Harnesses, and treat the result as a continuously refreshed quality estimate. It costs a percent or two of traffic and it converts drift detection from inference to measurement.
What this does not say
Detecting drift says nothing about responding to it. Automatic retraining on drifted data is tempting and dangerous: if the drift is upstream corruption, retraining bakes the corruption into the model; if it is concept drift, the recent data may be too sparse to retrain on; and a retraining loop triggered by a monitor is a feedback system whose stability nobody has analysed. The defensible default is that drift detection pages a human and retraining is a deliberate act.
References
- SurveyJ. Gama, I. Žliobaitė, A. Bifet, M. Pechenizkiy, A. Bouchachia (2014). A Survey on Concept Drift AdaptationThe taxonomy of drift types and detection strategies this page follows.
- PaperA. Gretton, K. Borgwardt, M. Rasch, B. Schölkopf, A. Smola (2012). A Kernel Two-Sample TestMaximum mean discrepancy, the test used below for embedding distributions.
These works are cited as sources to read, not reproduced. All exposition, examples and problems on this site are written independently; where an argument is standard, the citation points to a canonical treatment.
Results stated on this page
- DefinitionFour things called driftCovariate shift, prior shift, concept drift and upstream corruption have the same symptom and different remedies.
- DefinitionThe population stability indexA binned comparison of two distributions, summing the signed difference of bin masses times the log of their ratio.
- PropositionPSI is the symmetrised KL divergenceproof includedThe population stability index is exactly KL(p,q) plus KL(q,p), so it is non-negative and zero only when the distributions agree.
- HeuristicThe conventional PSI thresholdsValues below 0.1, between 0.1 and 0.25, and above 0.25 are conventionally read as stable, moderate and significant, with no distributional justification.
- PropositionMonitoring many features guarantees false alarmsproof includedIndependent tests on m features at level alpha, repeated each period, produce alarms at a rate that approaches certainty as m or the number of periods grows.
- HeuristicMonitor proxies when labels are lateRefusal rate, output length, tool-call rate, retry rate and escalation rate move before ground truth arrives and are available immediately.