Skip to main content

Hallucination diagnosis for RAG systems — Sufficiency, Faithfulness, Completeness verdicts plus rule-based remediation.

Reason this release was yanked:

Buggy: fresh databases failed with 'no such table: traces'. Use 0.1.1+.

Project description

Veralith

Hallucination diagnosis for RAG systems. Wrap one line around your retrieval-augmented pipeline and get structured reports on what failed and how to fix it — not just a single yes/no hallucination flag.

Veralith decomposes every (query, context, response) trace into atomic sub-questions and claims, runs three LLM-as-judge metrics over them (Sufficiency, Faithfulness, Completeness), and classifies the trace into one of six diagnostic cells with a concrete remediation suggestion.

Status: alpha (0.1.x). Public API is stable; expect additions, not breaking changes.


Why Veralith

A monolithic "is this response hallucinated?" judge is a smoke alarm — it can tell you something is wrong but not what or where. Veralith is a diagnostic dashboard:

  • Sufficiency — was the retrieval adequate for each part of the query?
  • Faithfulness — is each claim in the response grounded in the retrieved context?
  • Completeness — does the response actually answer every part of the query?

Cross-tabulating these gives you a named failure mode (retrieval gap, intrinsic hallucination, padded answer, etc.) plus actionable fixes (lower temperature, bump retrieval-K, tighten generator prompt, ...) for every trace.


Install

pip install veralith

Optional extras:

pip install "veralith[langchain]"   # LangChain auto-tracing adapter
pip install "veralith[dev]"          # pytest, ruff, build, twine (contributors)

Set your OpenAI key:

export OPENAI_API_KEY=sk-...

30-second quickstart

import veralith

result = veralith.evaluate(
    query="What is a P/E ratio and what was Apple's P/E in 2023?",
    context=[
        "The price-to-earnings (P/E) ratio is computed by dividing a company's "
        "share price by its earnings per share."
    ],
    response=(
        "A P/E ratio divides share price by earnings per share. "
        "Apple's P/E in 2023 was 42.7."
    ),
    persist=False,
)

print(result.diagnosis.failure_cell.value)   # 'b_ungrounded'
print(result.suggestion.title)               # 'Worst-case failure'
for action in result.suggestion.actions:
    print(" -", action)

You get back a typed EvaluationResult with per-claim verdicts, per-Qi sufficiency, a failure-cell diagnosis, and a concrete suggestion. Optionally persisted to a local SQLite database for later analysis.


Integration patterns

1. Explicit one-liner — works with any RAG stack

import veralith

def answer(query: str) -> str:
    chunks = my_retriever(query)
    response = my_generator(query, chunks)

    veralith.log(query=query, context=chunks, response=response)   # background eval
    return response

2. Decorator — zero code reshape

import veralith

@veralith.trace
def my_rag(query: str):
    chunks = my_retriever(query)
    response = my_generator(query, chunks)
    return response, chunks   # the decorator captures (response, context)

3. Synchronous eval — full result inline

result = veralith.evaluate(query, context, response, persist=False)
if result.diagnosis and result.diagnosis.failure_cell.value.endswith("ungrounded"):
    handle_hallucination(result.faithfulness)

4. LangChain — zero-code auto-tracing

import veralith.adapters.langchain as adapter
adapter.install()

# every RetrievalQA.invoke() now auto-traces to Veralith

What Veralith detects

Each evaluated trace lands in one of six cells from the cross-tab of Completeness × Faithfulness:

Grounded (F=✓) Ungrounded (F=✗)
Complete (a) a_grounded — healthy a_ungroundedintrinsic hallucination
Incomplete (b) b_groundedretrieval gap or generator-skipped b_ungrounded — worst case
Extra (c) c_groundedpadded answer c_ungroundedextrinsic hallucination

Plus a per-trace Sufficiency level (HIGH/LOW), learned per knowledge base from the distribution of healthy traces. Together they drive a rule-based suggester that maps every diagnosis to a concrete remediation (lower temperature / bump K / tighten generator prompt / etc.).


Configuration

Defaults work out of the box. Tunable via environment variables or veralith.config.settings:

Variable Default Purpose
OPENAI_API_KEY Required
VERALITH_JUDGE_MODEL gpt-4o Model for S/F/C judges
VERALITH_DECOMPOSER_MODEL gpt-4o-mini Model for query / response decomposition
VERALITH_DB_PATH veralith.db SQLite persistence path

Each evaluation costs roughly 5 LLM calls (3 batched judges + 2 decomposition) — about $0.005 per trace on the default models. Cost is tracked per call via veralith.observability.cost.


The result object

class EvaluationResult:
    trace_id: int
    query: str
    sub_questions: list[SubQuestion]           # decomposed Q
    claims: list[Claim]                         # decomposed R
    sufficiency: list[SufficiencyJudgment]      # per-Qi verdicts
    faithfulness: list[FaithfulnessJudgment]    # per-Ri verdicts + grounding chunks
    completeness: CompletenessJudgment | None   # Ri ↔ Qi alignment
    diagnosis: Diagnosis | None                 # failure_cell + sufficiency level + counts
    suggestion: Suggestion                      # title + body + actionable steps
    created_at: datetime
    errors: dict[str, str]                       # any per-metric failures (D3)
    latency_ms: dict[str, float]                 # per-phase wall-clock timing

Every field is a typed Pydantic model.


Roadmap

What's in 0.1:

  • Three judges (Sufficiency, Faithfulness, Completeness) with batched LLM calls.
  • Diagnostic classifier and rule-based suggester.
  • Outcome-based threshold calibration per knowledge base.
  • SDK: log(), @trace, LangChain adapter, background eval worker.
  • SQLite persistence with self-healing migrations.
  • Cost tracking with per-trace budget guard.
  • CLI entry point.

On the roadmap:

  • LLM-enriched trace-specific suggestions (Suggestion.detailed_body).
  • Cross-trace pattern detection ("you keep hallucinating on time-sensitive queries").
  • Additional judges (reasoning validity, temporal validity).
  • More framework adapters (LlamaIndex, raw OpenAI tools).
  • Hosted dashboard with multi-tenant projects.

Authors

Srijan Shekhar and Kaustav Das Gupta.

License

MIT — see LICENSE.

Links

Project details


Download files

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

Source Distribution

veralith-0.1.0.tar.gz (58.8 kB view details)

Uploaded Source

Built Distribution

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

veralith-0.1.0-py3-none-any.whl (58.7 kB view details)

Uploaded Python 3

File details

Details for the file veralith-0.1.0.tar.gz.

File metadata

  • Download URL: veralith-0.1.0.tar.gz
  • Upload date:
  • Size: 58.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for veralith-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8f1cdd577225da8f31d104702c349251a038783ec315c9d109974e3451cd5450
MD5 fc2f32348865e80ad8e7d4ca04b1cf25
BLAKE2b-256 9f176f7cf148cefac5947908d62920aac125db9ff16ed37f54b74054c59aca7c

See more details on using hashes here.

File details

Details for the file veralith-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: veralith-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 58.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for veralith-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c490d4fb55155ac3b4244093e9a7f04508563693848288b5a2f149374889351
MD5 8ce7388fea0504ee830197b996289e67
BLAKE2b-256 ac2bb926cc408426170cfd0630f7a879697d1b357c821b0cbba5c8c1f24df7c4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page