"I said the heart rate peaked at 190. Then I remembered I still had the waveform. I recomputed. It peaked at 148. I deleted my sentence before anyone read it, which is the only honest thing a language model can do with a number it can check."
A Self-Auditing AI Agent
The big picture
A sensor-language model can produce fluent, confident, physically impossible prose. It will report a respiration rate no lungs can sustain, invent a transient that never fired, or attach a units error that turns 0.9 m/s² into a fall. Text hallucination is annoying; signal hallucination is a safety hazard, because a clinician, an operator, or an autonomous controller may act on the sentence. Grounding means every claim the model makes is traceable to the samples that license it. Verification means we do not trust the model's word: we recompute the claimed quantity, check it against physics and provenance, and force the model to abstain when the check fails. The distinctive advantage of sensor reasoning is that the ground truth sits in the buffer. Unlike a historical fact the model half-remembers, a dominant frequency or a peak amplitude can be recalculated in microseconds and compared number to number.
This section builds on the reasoning systems of Section 21.4 and the retrieval machinery of Section 21.5: those sections make a model say something about a signal, and this one decides whether to believe it. You will need the estimation and error vocabulary of Chapter 4, the measurement-model view of what a sensor can physically report from Chapter 2, and the sampling facts of Chapter 3. No training is required; verification wraps whatever generator you already have.
What grounding means when the ground is a signal
What grounding requires is a defensible chain from token to sample. A grounded claim like "the accelerometer shows a 2 Hz gait" must point at the window, the axis, and the spectral estimate that produced the 2. An ungrounded claim asserts the same 2 Hz with no computable support, which is exactly what an LLM does when it pattern-matches "walking" to a number soup and confabulates a frequency to justify the label. Why the physical setting is special: the reference is not an external corpus you must retrieve and trust, it is the input itself. In text QA you cannot cheaply re-derive whether a treaty was signed in 1648; with a signal you can re-derive the stated frequency, amplitude, or event count deterministically. When grounding is non-negotiable: any decision that triggers an action (an alarm, a dose, a brake, a maintenance dispatch), and any report a human will quote without re-inspecting the trace. For an exploratory caption seen by an analyst with the waveform on screen, a lighter touch suffices.
Key insight: the signal is the oracle, so verification is cheap
The central asymmetry of physical-signal hallucination is that checking is far cheaper than generating. Producing a fluent multi-step explanation costs a full LLM forward pass; verifying its numeric claims costs one FFT, one peak count, or one threshold comparison. This inverts the usual trust economics of language models. You should never accept a stated number you could have recomputed. Treat every quantitative clause the model emits as a hypothesis to be falsified against the buffer, and reserve the model's authority for the qualitative synthesis that no formula gives you.
A taxonomy of physical-signal hallucination
Grounding failures are not a single bug; naming them lets you build a targeted check for each. Fabricated features: the model reports a transient, a spike, or a periodicity absent from the samples, often to justify a label it committed to early. Numeric drift: the claimed value (heart rate, RMS, dominant frequency) is in the right category but quantitatively wrong, the failure the epigraph describes. Unit and scale errors: g versus m/s², Hz versus rpm, °C versus K, or a missing sampling-rate conversion that misreads sample index as seconds. Physical impossibility: a value outside what the sensor or the physics allows, such as a 400 bpm human heart rate or a respiration signal above the Nyquist limit set by the sampling rate. Provenance confusion: attributing a feature to the wrong channel, the wrong time window, or the wrong device in a multi-sensor stream. Correlation-as-causation: a fluent causal story ("motion caused the PPG artifact") that the data supports only as co-occurrence. Each class maps to a mechanical guard, and the first four are catchable by recomputation and range checks alone.
Verification by recomputation: the signal is the oracle
How to operationalize the insight: extract the model's quantitative claims as structured assertions, recompute each from the raw window, and flag any claim whose recomputed value falls outside a tolerance. Force the generator to emit claims in a parseable form (JSON with a quantity, a value, a unit, and a channel). The verifier owns a small library of estimators, one per claimable quantity, plus a physical-range table per sensor type from Chapter 2. A claim passes only if it is recomputable, within tolerance of the recomputation, and inside the admissible range. Anything else is downgraded to a flagged hypothesis, and if a load-bearing claim fails, the whole answer is withheld and the model asked to abstain. This is the sensor analogue of self-consistency, except the check is against physics rather than a second sample of the same fallible model.
import numpy as np
def verify_claims(window, fs_hz, claims, tol=0.15, ranges=None):
"""Check LLM-stated numeric claims against the raw signal.
`claims`: list of {"quantity","value","unit","channel"} dicts.
Returns each claim tagged pass / fail / unverifiable, plus a verdict."""
ranges = ranges or {"dominant_freq_hz": (0.0, fs_hz / 2)} # Nyquist cap
def recompute(q, x):
if q == "dominant_freq_hz":
f = np.fft.rfftfreq(len(x), 1 / fs_hz)
return f[np.argmax(np.abs(np.fft.rfft(x - x.mean()))[1:]) + 1]
if q == "peak_to_peak":
return float(np.ptp(x))
if q == "rms":
return float(np.sqrt(np.mean(x ** 2)))
return None
out, load_bearing_ok = [], True
for c in claims:
x = window[:, c["channel"]]
est = recompute(c["quantity"], x)
lo, hi = ranges.get(c["quantity"], (-np.inf, np.inf))
if est is None:
tag = "unverifiable"
elif not (lo <= c["value"] <= hi):
tag, load_bearing_ok = "fail:impossible", False
elif abs(c["value"] - est) > tol * max(abs(est), 1e-9):
tag, load_bearing_ok = "fail:drift", False
else:
tag = "pass"
out.append({**c, "recomputed": est, "tag": tag})
return {"claims": out, "trust": "answer" if load_bearing_ok else "abstain"}
The verify_claims loop turns the model from an unaccountable narrator into a source of falsifiable hypotheses. Note the two failure tags: fail:impossible catches physical-range violations that need no reference at all, while fail:drift catches quantitatively wrong numbers by direct recomputation. Both are cheap, and both fire before the sentence reaches a human.
Practical example: a units error caught on a factory gearbox
An industrial condition-monitoring copilot summarizes vibration spectra for a plant maintenance team. A frozen-LLM captioner reports "bearing fault tone at 3.2 kHz, amplitude 47 g, well above the 8 g alarm limit," and drafts an emergency shutdown recommendation. The verifier recomputes from the raw accelerometer buffer: the dominant tone is real at 3.2 kHz, but the amplitude is 4.7 g, not 47. The model dropped a decimal and inflated a healthy machine into a crisis. Because 47 g exceeds the sensor's own full-scale range, the physical-range guard alone would have rejected it even without recomputation. The copilot withholds the shutdown draft, tags the amplitude claim fail:impossible, and returns the corrected 4.7 g with a note. This is the change-detection discipline of Chapter 12 acting as a guard on a language model rather than as a detector in its own right.
Grounding by construction: retrieval, abstention, and calibrated confidence
Recomputation catches wrong numbers, but two more layers make the whole system trustworthy. First, ground the qualitative claims by retrieval. When the model asserts "this matches a known outer-race fault," require it to cite a retrieved reference exemplar or a knowledge-base rule (Section 21.5), so the interpretive leap rests on evidence rather than fluency. Second, make abstention a first-class output. The system must be able to say "the window is too noisy to answer" instead of manufacturing a guess, and the verifier's abstain verdict is the trigger. Third, calibrate and bound the confidence. The conformal-prediction machinery of Chapter 18 converts a raw score into a set-valued answer with a guaranteed coverage rate, so "heart rate is 70 to 76 bpm at 90% coverage" replaces a bare, overconfident point estimate. Together these turn a plausible narrator into an auditable instrument whose every claim is recomputed, retrieved, or explicitly hedged.
Library shortcut: structured claims and guards without the plumbing
Hand-rolling claim extraction, a per-quantity estimator registry, retry-on-invalid-JSON, range tables, and abstention routing is easily 400 to 600 lines once you add schema validation and logging. Pairing a constrained-decoding or structured-output SDK (for example Pydantic-typed function calls or an instructor-style wrapper) with a validation library collapses claim extraction and schema enforcement to a typed model definition plus one call, and the estimator registry reduces to a dict of functions like the one above. Roughly a 15-to-1 reduction: the SDK owns JSON coercion, retries, and type validation, so you own only the physics, meaning the estimators and the admissible ranges.
Research frontier: faithful, verifiable sensor reasoning (2024-2026)
Benchmarks such as SensorBench and OpenSQA (Section 21.3) increasingly score not just answer accuracy but grounding and faithfulness, asking whether the stated reasoning actually reflects the signal. The live problems are faithful chains (does the explanation cause the answer, or merely rationalize it), automatic hallucination detection for physical claims, and coupling LLM verdicts with formal guarantees. The most promising direction pairs the recompute-and-check pattern of this section with the conformal coverage of Chapter 18 and the safety cases of Chapter 68, so a deployed sensor-language system carries a machine-checkable warrant for each claim rather than a stylistic promise of care. A reasoning chain you cannot verify against physics is a liability, not a feature.
Exercise
Extend verify_claims into a deployable guard. (1) Add a per-sensor range table (heart rate 30 to 220 bpm, human respiration 0.1 to 0.7 Hz, accelerometer within full scale) and a unit-normalization step that canonicalizes g/m·s⁻², Hz/rpm, and °C/K before comparison. (2) Prompt a hosted LLM to caption 100 labeled windows in the structured claim schema, run the verifier, and report how many answers are downgraded to abstain and how many hallucinations each tag class catches. (3) Wrap the surviving numeric claims in a split-conformal interval and check that the empirical coverage matches the target. Report the precision and recall of your guard at catching injected errors, where you deliberately corrupt a fraction of the model's numbers.
Self-check
1. Why is hallucination cheaper to detect for a physical signal than for an open-domain text fact? 2. Give one hallucination class that a physical-range table catches with no recomputation, and one that requires recomputation. 3. Why should a verified numeric answer still carry a conformal interval rather than a single point value?
What's Next
In Section 21.7, we turn from guarding a single answer to measuring a whole system: how to evaluate sensor-language models end to end, which metrics capture grounding and faithfulness rather than mere fluency, and how leakage-safe protocols keep a benchmark from rewarding a model that memorized the answer instead of reasoning to it.