Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” FactEval

Find exactly which parts of your LLM output are hallucinated.

Most LLM tools tell you if an answer is "good". FactEval tells you exactly which sentence is wrong β€” and why.

FactEval doesn't give you a score β€” it shows you the exact mistake.

Input:  "Paris is the capital of Germany."
Output:  Paris is the capital of Germany ❌
         β†’ Contradicts evidence: "Paris is the capital of France."

PyPI version Hugging Face Spaces License: MIT Python 3.10+


What is FactEval?

FactEval verifies claims against provided reference context (e.g., retrieved documents in a RAG system). It helps developers debug LLM outputs by:

  • Breaking answers into atomic claims
  • Checking each claim against reference evidence
  • Highlighting hallucinated parts with explanations and diagnostics

Built for debugging real-world RAG pipelines and LLM systems.

πŸ‘₯ Who is this for?

  • RAG developers
  • LLM app builders
  • Anyone debugging hallucinations

⚑ Try it in 3 seconds

πŸ‘‰ https://huggingface.co/spaces/sahilfarib/FactEval


πŸ“¦ Install

pip install facteval

For development:

git clone https://github.com/sahilaf/FactEval.git
cd FactEval && pip install -e ".[dev]"

πŸš€ Quick Start

⚑ Note: First run loads models (~15s). After that:

  • fast_check(): ~0.3s
  • analyze(): ~1.3s

fast_check() = fastest, recommended analyze() = full pipeline (auto claim extraction)

from facteval import fast_check

result = fast_check(
    claims=["Paris is the capital of Germany.", "Paris has 5 million people."],
    contexts=["Paris is the capital of France. Population: 2.2M."],
)

for claim in result["claims"]:
    print(f'{claim["label"]:15s} {claim["claim"]}')
    print(f'                β†’ {claim["reason"]}')
contradicted    Paris is the capital of Germany.
                β†’ Contradicted by: "Paris is the capital of France."
contradicted    Paris has 5 million people.
                β†’ Contradicted by: "Population: 2.2M."

πŸ§ͺ Drop-in RAG Evaluator

Paste this into your RAG app to instantly catch hallucinations.

Think of FactEval as: LLM output β†’ broken into claims β†’ verified against truth

from facteval import fast_check

# After your LLM call
response = llm(query)

# Validate before returning to user
result = fast_check(
    claims=response.split("."),  # Simple claim splitting
    contexts=docs
)

if result["summary"]["hallucination_rate"] > 0:
    print("⚠️ Potential hallucination detected")

Full Pipeline (Automated Extraction)

If you don't want to split claims yourself, analyze() uses a lightweight LLM (Qwen 1.5B) to automatically decompose complex answers into atomic claims:

from facteval import analyze

result = analyze(
    answer="Paris is the capital of Germany and has 5 million people.",
    contexts=["Paris is the capital of France. Paris has approximately 2.2 million inhabitants."],
)

CLI (Command Line Interface)

# Quick check
facteval check --answer "The earth is flat." --context "The earth is an oblate spheroid."

# From file
facteval check input.json --output results.json

# With calibrator
facteval check input.json --calibrator calibrator.pkl

✨ Features

  • Claim-level verdicts β€” each sentence gets βœ… supported, ❌ contradicted, or ❓ unverifiable
  • Highlighted output β€” color-coded HTML showing exactly which parts are wrong
  • Human-readable reasons β€” every verdict explains why
  • Pipeline diagnostics β€” hallucination vs. retrieval gap vs. missing context
  • Calibrated confidence β€” isotonic regression for trustworthy probability scores
  • Lightweight mode β€” fast_check() runs instantly (~0.3s) without heavy models
  • Drop-in API β€” works seamlessly with LangChain, LlamaIndex, or custom pipelines
  • Batch NLI β€” all claims in a single forward pass
  • CLI β€” facteval check for scripting and CI/CD

πŸ“Š Comparison

Feature FactEval FacTool QAFactEval
Claim-level granularity βœ… βœ… ❌
Calibrated confidence scores βœ… ❌ ❌
Pipeline Diagnostics (why it failed) βœ… ❌ ❌
Sub-second mode (fast_check) βœ… ❌ ❌
HTML highlighting output βœ… ❌ ❌

πŸ“‹ Output Format

Short version:

{
  "claims": [
    {
      "claim": "Paris is the capital of Germany.",
      "label": "contradicted",
      "confidence": 0.9971,
      "reason": "Contradicts evidence: \"Paris is the capital of France.\"",
      "diagnostics": {
        "failure_type": "hallucination",
        "retrieval_quality": "strong",
        "suggestion": "Claim directly contradicts the evidence."
      }
    }
  ],
  "summary": {
    "total_claims": 2, "supported": 0, "contradicted": 2,
    "unverifiable": 0, "hallucination_rate": 1.0
  },
  "highlighted_answer": "<mark>Paris is the capital of Germany ❌</mark>..."
}
Full output includes

Each claim also contains:

  • evidence β€” the matched reference sentence
  • evidence_score β€” retrieval similarity (0–1)
  • raw_nli_scores β€” per-label NLI probabilities (entailment, neutral, contradiction)
  • calibrated_confidence β€” post-calibration confidence (if calibrator provided)
  • calibration_error β€” estimated calibration error

Top-level fields:

  • calibrated β€” whether a fitted calibrator was used
  • pipeline_time_seconds β€” total processing time

Labels

Label Meaning
βœ… supported Claim is entailed by the evidence
❌ contradicted Claim contradicts the evidence
❓ unverifiable No relevant evidence, or evidence is neutral

Diagnostics

failure_type What happened What to do
verified Supported by strong evidence Nothing β€” it's correct
hallucination Contradicts strong evidence Factual error in LLM output
possible_hallucination Contradicts weak evidence Add better context to confirm
no_evidence No context for this topic Add reference passages
retrieval_gap Evidence too dissimilar Context may not cover this claim
inconclusive Evidence is neutral Cannot confirm or deny

πŸ€” When Should You Use FactEval?

Use FactEval if you are:

  • Building a RAG system and need to verify answers against retrieved documents
  • Debugging hallucinations in LLM outputs
  • Evaluating whether generated answers are grounded in context
  • Building CI/CD checks for LLM-powered features

Not intended for:

  • General fact-checking without reference context (FactEval needs ground truth documents)
  • Real-time inference on user-facing APIs (model loading adds latency)

⚑ Performance

Mode First run Subsequent runs VRAM
check() (full) ~60s (loads 3 models) ~1.3s ~3.4 GB
verify() (lightweight) ~15s (loads 2 models) ~0.3s ~0.5 GB

First run downloads and loads models from Hugging Face. After that, models are cached in memory. Use verify() when you already have claims and need low-latency evaluation.


πŸ§ͺ Built For

  • RAG pipelines β€” verify that generated answers are grounded in retrieved documents
  • LLM evaluation workflows β€” measure hallucination rates across test sets
  • AI product debugging β€” find exactly where your model is making things up

πŸ—οΈ Architecture

Answer Text ──→ Claim Extractor ──→ Evidence Retriever ──→ NLI Verifier ──→ Calibrator ──→ Output
                (Qwen 1.5B)         (MiniLM + FAISS)      (DeBERTa)        (Isotonic)
                                          β”‚                                      β”‚
                                          └── Semantic Highlighting β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                               (reuses MiniLM embeddings)
Stage Model Size Latency
Claim Extraction Qwen/Qwen2.5-1.5B-Instruct ~3 GB ~1s
Evidence Retrieval all-MiniLM-L6-v2 + FAISS ~90 MB <10ms
NLI Verification DeBERTa-v3-base-mnli-fever-anli ~370 MB <10ms/batch
Calibration Isotonic Regression (sklearn) ~1 KB <1ms

πŸ–₯️ Try It Locally

pip install -e ".[demo]"
python demo/app.py

Features:

  • Highlighted answer text with βœ…βŒβ“ annotations
  • Per-claim cards with reasons, diagnostic badges, and suggestions
  • Summary dashboard with hallucination rate
  • 4 built-in examples

Deploy to Hugging Face Spaces

git remote add hf https://huggingface.co/spaces/YOUR_USERNAME/facteval
git push hf main

πŸ“ Project Structure

FactEval/
β”œβ”€β”€ README.md
β”œβ”€β”€ ANALYSIS.md                # Development analysis & lessons learned
β”œβ”€β”€ LICENSE                    # MIT
β”œβ”€β”€ pyproject.toml             # Package config + CLI entry point
β”œβ”€β”€ app.py                     # HF Spaces entry point
β”œβ”€β”€ requirements.txt           # HF Spaces dependencies
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ basic.py               # Minimal usage example
β”‚   └── rag_debug.py           # RAG pipeline debugging example
β”œβ”€β”€ demo/
β”‚   └── app.py                 # Gradio interactive demo
└── facteval/
    β”œβ”€β”€ __init__.py            # Public API: check(), verify()
    β”œβ”€β”€ config.py              # Model names, prompts, defaults
    β”œβ”€β”€ models.py              # Claim, Evidence, ClaimWithEvidence
    β”œβ”€β”€ claim_extractor.py     # Qwen2.5-1.5B claim decomposition
    β”œβ”€β”€ retriever.py           # FAISS + MiniLM evidence retrieval
    β”œβ”€β”€ verifier.py            # DeBERTa batch NLI + reasons
    β”œβ”€β”€ calibrator.py          # Isotonic regression calibration
    β”œβ”€β”€ core.py                # Pipeline orchestration + diagnostics
    └── cli.py                 # facteval check CLI

πŸ“„ License

MIT β€” see LICENSE.

About

Find exactly which parts of your LLM output are hallucinated. Claim-level factuality verification with NLI, calibrated confidence, and pipeline diagnostics for RAG systems.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages