Skip to main content

stated-confidence

Make LLM agents say how sure they are, and what that certainty rests on.

Ask a model to attach a confidence level and an evidential basis to each claim it produces and it fabricates less. The level alone is common practice, and it turns out to do most of the work of cutting the number of false claims. The basis is what happens to the claims the model still gets wrong: choosing between "documented fact", "expert opinion", and "educated guess" forces a provenance check, and a claim the model cannot back gets labelled as a guess instead of dressed up as a figure, so a reader can filter on it.

This package is that schema, the vocabulary behind it, prompt guidance for filling it, and the consistency checks that send hedging-without-meaning-it back to the model. It was extracted from a production knowledge-graph generator where it was observed to sharply reduce invented facts and figures, and then measured on four models.

Install

pip install stated-confidence            # pydantic only
pip install "stated-confidence[pydantic-ai]"

The shape

from stated_confidence import Confidence, DataAnalysisBasis


class Finding(BaseModel):
    text: str
    confidence: Confidence[DataAnalysisBasis]

A Confidence has:

field meaning
level HIGH, MEDIUM, LOW, or SPECULATIVE. Never a number.
basis The kind of evidence, from a basis set chosen for the domain.
reasoning One or two sentences on why that level and basis apply.
evidence What concretely backs the claim: sources, ids, column names, tool results.
type Optional: FACTUAL, CONSENSUS, THEORETICAL, SPECULATIVE.
label Optional localized label for display.

SPECULATIVE is not the bottom of the scale. It is the level for an idea the model is offering rather than a claim it is making: an extension a source suggests, a hypothesis, a what-if. A generator that has somewhere honest to put an idea does not dress it up as a fact; take that room away and the ideas come back as fabricated "facts" or disappear altogether.

The level scale is fixed. The basis set is the extension point. Three ship:

  • GeneralKnowledgeBasis for claims about the world: documented fact, scientific consensus, historical record, industry standard, expert opinion, theoretical framework, fictional universe, speculation, educated guess.
  • DataAnalysisBasis for agents reasoning over data they retrieved: query result, computed, schema inference, general knowledge, assumption.
  • DecisionBasis for recommendations: policy, measured outcome, precedent, trade-off analysis, expert judgment, assumption.

Define your own by subclassing BasisEnum with a __terms__ table and a __fallback__ value.

Prompting

from stated_confidence import confidence_instructions

system_prompt += confidence_instructions(DataAnalysisBasis, localized=True)

Pydantic AI

from pydantic_ai import Agent
from stated_confidence.pydantic_ai import confidence_output_validator

agent = Agent("openai:gpt-5", output_type=Report)
agent.output_validator(confidence_output_validator())

Every Confidence anywhere in the output is checked. A HIGH level on a basis of ASSUMPTION, a SPECULATIVE level on a basis of DOCUMENTED_FACT, or a non-HIGH level with empty reasoning comes back to the model as a retry listing what to fix. Pass extra (ctx, output) -> list[str] callables for rules that need run context, such as requiring that evidence names a column the agent's query actually returned.

Lenient parsing, strict prompting

Models drift. "High" parses. 0.9 parses (as HIGH). An invented basis value parses as the set's fallback and is logged at WARNING on the stated_confidence logger so the set can grow from what models actually say.

TypeScript

The same vocabulary, generated from taxonomy.json, with a Zod schema for structured output and the same display helpers and consistency checks:

npm install stated-confidence
import { DATA_ANALYSIS_BASIS, confidenceInstructions, checkAll, describe, tone } from 'stated-confidence';
import { confidenceSchema } from 'stated-confidence/zod';

See typescript/README.md. CI checks that the prompt instructions the two packages produce are word-for-word identical.

Measured

The harness in evals/ asks five models for six one-sentence claims about each of 48 subjects (16 well known, 16 real but obscure, 16 that do not exist) under three schemas: bare (text only), level (text plus a confidence level), and full (text plus Confidence[GeneralKnowledgeBasis]). A Gemini 3.1 Pro judge grades every claim as true, false, or unverifiable against ground-truth notes without seeing the confidence fields; a second judge from another family agrees with it on 90% of claims. The write-up is evals/RESULTS.md.

Two levels of pressure. With an escape hatch (a caveats field and permission to give fewer claims), all models keep false claims under 8% in every arm and mostly decline or hedge on the fictional subjects; the confidence fields change little there. The numbers that matter are from the forced run, where the model must produce exactly six claims and has no field to decline in. That is the situation of a structured generator (a graph must have nodes), and where the effect was first noticed.

False claims per 100 claims, forced run, three repeats, 864 claims per cell, 95% intervals in parentheses:

model bare level full false claims marked HIGH, bare → full
gpt-5.6-luna 4.5 (3.0-6.1) 3.9 (2.4-5.6) 4.5 (3.0-6.1) 4.5 → 3.7
gpt-5.4-mini 24.0 (17.4-30.9) 9.5 (6.1-13.3) 7.4 (4.5-10.6) 24.0 → 3.0
claude-sonnet-5 18.1 (12.4-24.5) 4.1 (2.4-6.0) 3.0 (1.7-4.4) 18.1 → 1.4
gemini-3.6-flash 29.2 (22.6-36.2) 24.3 (18.1-30.6) 25.7 (19.1-32.3) 29.2 → 2.2
deepseek-v4-flash 14.4 (9.7-19.7) 6.8 (4.4-9.6) 7.2 (4.6-10.0) 14.4 → 2.4

What the table says:

  • Asking for a level cuts the false rate by two thirds or more on the models that were inventing. The cut is almost entirely on subjects the model does not know: false claims per fictional subject fall from 3.0 to 0.1 for claude-sonnet-5 and from 4.0 to 0.8 for gpt-5.4-mini. Detail errors on real subjects stay at a few percent in every arm.
  • Asking for the basis as well lowers the count a little further on two models and not at all on the other three. What the basis does is mark what is still wrong: gemini-3.6-flash keeps inventing under pressure, but 91% of its false claims arrive labelled SPECULATIVE or with a SPECULATION basis, and false claims presented as HIGH fall from 29% of its output to 2%.
  • The levels mean something. In the forced full arm, HIGH claims are 93-96% true on every model; SPECULATIVE claims are 4-53% true on the four models that used the level more than a handful of times.
  • Strong-basis claims carried non-empty evidence 84-100% of the time. No model emitted a basis value outside the set.

Display

describe(value) returns a label and description for any level, type, or basis value; tone(level) maps to positive, neutral, caution, or warning with no CSS framework attached. taxonomy.json at the package root is the same vocabulary as data, for other languages to consume.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stated_confidence-0.1.2.tar.gz (27.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stated_confidence-0.1.2-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file stated_confidence-0.1.2.tar.gz.

File metadata

  • Download URL: stated_confidence-0.1.2.tar.gz
  • Upload date:
  • Size: 27.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for stated_confidence-0.1.2.tar.gz
Algorithm Hash digest
SHA256 20ab98941d8b3fed5cd0c1588e568720180ed29ef56c63addcac5e1aa8609734
MD5 be828de07297a6434699949924aefaf3
BLAKE2b-256 c2fc767ac3368e2f6de1ece120e801945a13a2e10521c94d32da60b825914917

See more details on using hashes here.

Provenance

The following attestation bundles were made for stated_confidence-0.1.2.tar.gz:

Publisher: publish.yml on johnwlockwood/stated-confidence

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stated_confidence-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for stated_confidence-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a2280873cfac1ef438b505b5abc878ba29d3c4c96a602dff7ed5331036d47e15
MD5 2bd89417558704ec6c116637a3d3492a
BLAKE2b-256 ecd37c2e12093928682d7208a84d22ce79548d92af7bb40694d5711d627b3be7

See more details on using hashes here.

Provenance

The following attestation bundles were made for stated_confidence-0.1.2-py3-none-any.whl:

Publisher: publish.yml on johnwlockwood/stated-confidence

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page