truthlens 0.3.0

AI hallucination detector β€” formally verified trust scoring for LLM outputs
Documentation

TruthLens πŸ”

Crates.io Docs.rs

AI Hallucination Detector β€” Formally Verified Trust Scoring for LLM Outputs

Analyze AI-generated text for hallucination risk. No API keys needed. No LLM calls required. Fast, local, and formally verified.

Published package: https://crates.io/crates/truthlens API docs: https://docs.rs/truthlens

Quick Start

Install as CLI

cargo install truthlens

Usage

# Analyze text directly
truthlens "Einstein invented the telephone in 1876."
#  Trust: 49% [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] HIGH
#  πŸ”΄ Claim 1: 49% β€” specific verifiable claim β€” verify independently

# JSON output (for scripts/API integration)
truthlens --json "Python 4.0 has quantum computing support."

# Pipe from file or other commands
cat ai_response.txt | truthlens

# Pipe from clipboard (macOS)
pbpaste | truthlens

# Analyze ChatGPT/Claude output saved to file
curl -s "https://api.example.com/chat" | truthlens --json

# Compare multiple AI responses for contradictions
truthlens --consistency "response 1" "response 2" "response 3"

# Run built-in demo examples
truthlens --demo

Use as a Rust library

use truthlens::analyze;

let report = analyze("Einstein was born in 1879 in Ulm, Germany.");
println!("Trust: {:.0}% β€” {}", report.score * 100.0, report.risk_level);
// Trust: 52% β€” HIGH

// Access per-claim breakdown
for claim in &report.claims {
    println!("  {} β€” {}", claim.text, claim.trust.risk_level);
}

// Access trajectory analysis
println!("Pattern: {}", report.trajectory.pattern);
println!("Damping: ΞΆβ‰ˆ{:.2}", report.trajectory.damping_estimate);

// JSON serialization
let json = serde_json::to_string_pretty(&report).unwrap();

Multi-response consistency check (v0.3)

Paste N responses to the same prompt β€” TruthLens detects contradictions between them.

use truthlens::check_consistency;

let report = check_consistency(&[
    "Einstein was born in 1879 in Ulm, Germany.",
    "Einstein was born in 1879 in Munich, Germany.",  // ← contradiction
    "Einstein was born in 1879 in Ulm, Germany.",
]);

println!("Consistency: {:.0}%", report.consistency_score * 100.0);
// Consistency: 75%

// Contradictions detected
for c in &report.contradictions {
    println!("⚠️  {} vs {} β€” {}", c.claim_a, c.claim_b, c.conflict);
}
// ⚠️  "Ulm, Germany" vs "Munich, Germany"

// Claims unique to one response (potential hallucination)
for u in &report.unique_claims {
    println!("πŸ” Unique to response {}: {}", u.response_idx, u.text);
}
# CLI: compare multiple responses as separate arguments
truthlens --consistency \
  "Einstein was born in 1879 in Ulm, Germany." \
  "Einstein was born in 1879 in Munich, Germany." \
  "Einstein was born in 1879 in Ulm, Germany."
#  Consistency: 70% [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘]
#  ❌ Contradictions:
#     Response 1 vs 2: "Ulm, Germany" vs "Munich, Germany"
#  βœ… Consistent claims:
#     3/3 agree: einstein was born in: 1879

# JSON output
truthlens --consistency --json "resp1" "resp2" "resp3"

# Pipe JSON array from stdin
echo '["Python was created in 1991.", "Python was created in 1989."]' \
  | truthlens --consistency
# Cargo.toml
[dependencies]
truthlens = "0.3"

What It Does

TruthLens decomposes AI text into atomic claims and scores each for hallucination risk using linguistic signals β€” no LLM calls, no API keys, no external dependencies.

Input:  "Python 4.0 was released in December 2025 with native quantum computing support."

Output: πŸ”΄ Trust: 49% [HIGH]
        β†’ specific verifiable claim β€” verify independently
        β†’ overconfident language without hedging

How It Works

1. Claim Extraction

Text β†’ atomic sentences β†’ each is an independent claim to evaluate.

2. Signal Analysis (per claim)

Signal What It Measures Weight
Confidence Overconfident language without hedging (hallucination red flag) 35%
Hedging Uncertainty markers ("might", "possibly") β€” correlates with lower hallucination 25%
Specificity How concrete/verifiable the claim is (numbers, names, dates) 20%
Verifiability Whether the claim contains fact-checkable entities 15%
Consistency Multi-sample agreement (optional, requires LLM) 5%

3. Trust Score

Signals are aggregated into a single trust score in [0.0, 1.0]:

Score Risk Level Meaning
0.75–1.0 βœ… LOW Likely factual or appropriately hedged
0.55–0.74 ⚠️ MEDIUM Some uncertain claims, verify key facts
0.35–0.54 πŸ”΄ HIGH Multiple suspicious claims, verify everything
0.0–0.34 πŸ’€ CRITICAL Likely contains hallucinations

4. Passage Scoring

Passage score = 70% average + 30% worst claim. One bad claim drags down the whole passage.

Key Design Decisions

  • No LLM required β€” linguistic analysis only. Fast (microseconds), private (local), free.
  • Hedging = good β€” unlike most "confidence detectors", we score hedged claims HIGHER. A model that says "might" is better calibrated than one that states falsehoods with certainty.
  • Specificity is double-edged β€” specific claims are more useful but also more damaging if wrong. We flag them for independent verification.
  • Formally verified β€” Lean 4 proofs guarantee score bounds, monotonicity, and composition properties.

What's Proven (Lean 4)

Score Bounds

  • signal_nonneg β€” all signals β‰₯ 0
  • weighted_contrib_bounded β€” wΒ·s ≀ wΒ·max when s ≀ max
  • clamped_score_in_range β€” final score ∈ [0, 100] after clamp
  • truthlens_weights_sum β€” weights sum to 100%

Monotonicity

  • signal_increase_improves_score β€” improving a signal improves the score
  • total_score_improves β€” better signal + same rest = better total
  • good_claim_improves_passage β€” adding a good claim raises the average

Composition

  • passage_score_bounded β€” 70%Β·avg + 30%Β·min ≀ 100%Β·max
  • passage_at_least_worst β€” passage score β‰₯ 30% of worst claim
  • score_order_independent β€” claim order doesn't affect passage score
  • score_deterministic β€” same inputs β†’ same output (functional purity)

Examples

Factual text

"Albert Einstein was born on March 14, 1879, in Ulm, Germany."
β†’ πŸ”΄ 52% HIGH β€” specific verifiable claim, verify independently

Well-hedged text

"Climate change might be linked to increased hurricane frequency."
β†’ ⚠️ 65% MEDIUM β€” appropriately hedged

Overconfident hallucination

"The Great Wall is exactly 21,196.18 kilometers long."
β†’ πŸ”΄ 52% HIGH β€” overconfident without hedging; highly specific

Vague filler

"Various factors contribute to the situation."
β†’ πŸ”΄ 40% HIGH β€” vague claim with low specificity

JSON Output

{
  "score": 0.49,
  "risk_level": "High",
  "summary": "1 claims analyzed. 1 high-risk claims detected.",
  "claims": [
    {
      "text": "Einstein invented the telephone in 1876.",
      "trust": {
        "score": 0.49,
        "signals": {
          "confidence": 0.5,
          "specificity": 0.3,
          "hedging": 0.5,
          "verifiability": 0.7,
          "consistency": null
        },
        "risk_level": "High"
      }
    }
  ]
}

Repository Structure

truthlens/
β”œβ”€β”€ rust/                       # Core library + CLI
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ lib.rs              # Public API: analyze(), check_consistency()
β”‚   β”‚   β”œβ”€β”€ claim.rs            # Claim extraction + linguistic analysis
β”‚   β”‚   β”œβ”€β”€ scorer.rs           # Trust scoring + signal aggregation
β”‚   β”‚   β”œβ”€β”€ trajectory.rs       # Confidence trajectory analysis (v0.2)
β”‚   β”‚   β”œβ”€β”€ consistency.rs      # Multi-response consistency checker (v0.3)
β”‚   β”‚   └── main.rs             # CLI: analyze, --consistency, --demo
β”‚   └── Cargo.toml
β”œβ”€β”€ lean/                       # Formal proofs
β”‚   β”œβ”€β”€ TruthLens/
β”‚   β”‚   β”œβ”€β”€ ScoreBounds.lean    # Score ∈ [0, 1], weight sum, clamp
β”‚   β”‚   β”œβ”€β”€ Monotonicity.lean   # Better signals β†’ better score
β”‚   β”‚   β”œβ”€β”€ Composition.lean    # Passage aggregation properties
β”‚   β”‚   └── Trajectory.lean     # Trajectory modifier bounds + correctness
β”‚   └── lakefile.lean
β”œβ”€β”€ bridge/                     # Lean ↔ Rust mapping (coming)
└── README.md

Build

# Rust
cd rust
cargo test       # 22 tests (21 unit + 1 doc)
cargo run         # demo with examples

# Lean
cd lean
lake build        # compile all proofs

Roadmap

  • v0.1 β€” Linguistic analysis: claim extraction, hedging detection, specificity scoring
  • v0.2 β€” Confidence trajectory: detects oscillating, flat, or convergent confidence patterns using second-order dynamical system modeling
  • v0.3 β€” Multi-response consistency: paste N responses to the same prompt, detect contradictions via semantic divergence analysis
  • v0.4 β€” Entity cross-reference: verify extracted entities, dates, and numbers against knowledge bases (optional network, offline cache)
  • v0.5 β€” Python bindings (PyO3) β†’ pip install truthlens
  • v0.6 β€” Browser extension (Chrome/Firefox) β€” highlight suspicious claims inline
  • v0.7 β€” CLI tool: truthlens check "paste AI text here" with colored terminal output
  • v1.0 β€” API server + dashboard + enterprise features

Design Principles (all versions)

  • Zero API calls by default β€” every version works offline, locally, for free
  • Formally verified β€” Lean 4 proofs for all scoring properties
  • Hedging = trustworthy β€” a model that says "might" is more honest than one stating falsehoods with certainty
  • Fast β€” microsecond analysis, no model inference required

Why TruthLens?

Every existing hallucination detector either requires multiple LLM API calls (expensive, slow) or access to model logprobs (grey-box only). TruthLens works on any AI output with zero API calls β€” you paste text, you get a trust score. And the scoring properties are formally proven in Lean 4, which nobody else does.

License

Apache-2.0