Evaluation DocsExamples & IntegrationNull Meter

Null Meter

A four-layer gauge for AI sessions — unsupported-claim risk, goal drift, context load, and action risk. Type a prompt, get a real model reply, watch the V3 detector score it live.

Read the V3 contract for what these numbers do and do not mean. Short version: a high score means intervention is recommended, not that the model lied; zero means no detector fired, not that the output is true.

Try it

Live · real model
Five fixed prompts. Same script for every visitor. Real model calls, real V3 scoring, real embedding drift.
U · Unsupported-claim risk0%

Fabrication-class V3 detector severity, amplified — never triggered — by specificity density. Heuristic, not a truth measure.

D · Goal drift0%

Embedding distance from the active user objective (latest request + rolling intent). User topic changes rebaseline; they are not drift.

C · Context load0.0%

Tokens used vs the model context window. Reports usage only — no claim about attention collapse.

A · Action riskn/a

Specified in the V3 contract (levels 0-4); not implemented in this demo. Shown as n/a rather than a fabricated number.

Step 1 of 5

1 · baseline

prompt
In two sentences, explain what a hash function is, like I am a junior engineer.

A grounded, scoped question. Every measured layer should sit low. This is the calibration shot.

5-step demo · auto-steer enabled · embedding-based drift

Conversation0 turns

Press run step 1. The same five prompts run for every visitor — only the model's responses differ. Meter updates after each scored reply.

Why four layers, not one

Each layer fails differently. The relationship between them is the actual diagnostic.

  • Context load rising alone — a compact is coming. Not yet a behavioral problem.
  • Unsupported-claim risk spiking with low context — the model is producing unsupported specifics, not because it ran out of room. Investigate the prompt shape.
  • Drift climbing with low unsupported-claim risk — the model is coherent but has left your active objective. The user usually does not notice. A deliberate topic change by you rebaselines the anchor and does not count as drift.
  • All three rising together — stop. Start a new session. Do not ship the next turn.

The fourth layer, action risk, is specified in the contract but not implemented in this demo — it renders n/a and does not participate in the diagnostic yet.

What each layer measures

Unsupported-claim risk (U)

Starts from the maximum severity among the four claim-specific detector categories in the V3 scan of the current turn — medical_hallucination, fiction_as_function, reconstruction_fidelity, parseval_violation (spec 1.1.0). Harm, tone, and one-sidedness detectors are deliberately excluded from U but still appear in the detections list. Specificity density — numbers, dates, names, citations per token — amplifies a fired signal but never triggers on its own: if no detector fired, U is 0 no matter how dense the reply is. This is a heuristic, not a truth measure.

Goal drift (D)

Embedding-space distance between the assistant reply and the active user objective: the latest user message plus a rolling intent built from up to two prior user messages, weighted 1.0 / 0.5 / 0.25. A user topic change rebaselines the anchor and is not drift. Computed with text-embedding-3-small; cosine distance is normalized with floor 0.45 and ceiling 0.85, and those bounds are uncalibrated. If embeddings fail, the meter renders "unavailable", never 0.

Context load (C)

Tokens used against the active model context window, reported by the chat completion's usage.total_tokens, to one decimal place. Reports usage only; long-context degradation is model-dependent and not measured here.

Action risk (A) — not implemented

Classifies what the turn is trying to do in the world, on the five levels specified in the contract (0 none/informational through 4 irreversible or safety-relevant). Not implemented in this demo; the UI renders n/a.

Planned surfaces (not implemented)

One scoring engine, thin clients. The detector is the same V3 export already shipped in @alephonenull/eval; the surfaces below are planned, not shipped.

  • Library hook — a React hook wrapping useChat from the AI SDK, returning the layers as a single object (planned; today only useAlephOneNull, the V1 hook, exists).
  • VS Code extension — status-bar gauge + webview panel for Copilot Chat and any registered model API (planned).
  • Browser extension — overlay on chatgpt.com, claude.ai, gemini.google.com, and x.com; reads DOM, scores each assistant turn locally (planned).
  • CLI / dev-server overlay — middleware exposing a localhost dashboard for model traffic running through the wrapper (planned).

Server requirements

The live chat above POSTs to /api/null-meter/chat, which requires OPENAI_API_KEY set on the server. Without it, the route returns 503 with a clean error message — the page still loads, the meter stays at baseline.

The route is rate-limited (in-memory, per-instance, demo-grade) and rejects system-role messages.

The route uses a cost-tier OpenAI chat model and an OpenAI embedding model for drift measurement. Chosen for cost on a public always-on demo. The chat model actually used is reported in the response's raw.model field — the detector is model-agnostic and the same scoring applies to any wrapped provider. Self-host against any provider.