Skip to main content

groundedrag

A hard gate that stops your RAG from answering without evidence.

Leia em português

Status: early development (Phase 3 — packaging). Not yet published on PyPI — see docs/RELEASING.md for what's left.

Docs site · Benchmark · Changelog

The problem

Most RAG (retrieval-augmented generation) pipelines always call the LLM, even when retrieval finds nothing relevant. The model fills the gap with invented information — confidently. In domains where a wrong answer has a real cost (compliance, internal support, technical documentation, safety procedures), that is not a UX bug, it is a liability.

What groundedrag does

groundedrag is a small, opinionated Python library that adds two things on top of whatever retrieval stack you already have:

  1. Documentary gate. Before the LLM is ever called, groundedrag checks whether there is real coverage for the topic of the question, using an auditable topic → documents map that a non-engineer can read and edit. No coverage → the LLM is never called, and the caller gets an explicit "not documented, here's what to add" response instead of a guess.
  2. Verified citations. Every factual claim the LLM makes must cite [n]. A verifier runs after generation and checks that every citation points to a chunk that was actually retrieved, flagging or stripping any claim that isn't traceable. A prompt asking the model to cite its sources is an instruction, not a guarantee — the verification in code is what makes it one.

groundedrag does not replace your retrieval stack, your vector database, or your LLM provider. It sits in front of the LLM call and after the generation step, as a thin, provider-agnostic layer.

Why not just use LangChain / LlamaIndex / Guardrails AI?

Those are large, general-purpose frameworks. groundedrag is deliberately narrow: it does two things — the gate and the citation check — and is meant to drop into a stack you already have, including one built on LangChain or LlamaIndex, without asking you to adopt a whole new framework.

Status

Phase 3 (packaging) in progress. The library, CLI, docs site, and release automation are all in place; the one thing left is the two one-time manual steps on PyPI's and GitHub's side described in docs/RELEASING.md and below — until then, install from source (pip install -e . or uv sync), not from PyPI. See docs/architecture.md for the full design and docs/adr/ for the reasoning behind each decision.

Try it in two minutes — no API key needed

uv sync --extra dev --extra chroma
uv run python examples/helpdesk_bot/demo.py

This shows groundedrag's two core guarantees with sample documents bundled in the repo: a documented question retrieves real chunks, and an undocumented one is refused before any LLM would be called. See examples/ for both runnable examples.

CLI

groundedrag init my-project && cd my-project
# put a few .txt/.md/.pdf files in documents/, then:
groundedrag ingest documents --topic hr-policy
groundedrag ask "how many remote days are allowed?" --topic hr-policy

By default ingest/ask use the dependency-free HashingEmbedder (no API key, but lower retrieval quality — see docs/adr/0003) and a local Chroma store persisted under .groundedrag/chroma. Pass --embedder openai (with OPENAI_API_KEY set) for real retrieval quality, and --provider anthropic|openai|ollama to pick the LLM that generates the final answer.

As a library

from groundedrag.coverage import CoverageMap
from groundedrag.gate import DocumentGate
from groundedrag.retriever import GatedRetriever
from groundedrag.guardrails import build_answer
from groundedrag.prompting import build_prompt
from groundedrag.stores.memory import InMemoryStore
from groundedrag.embeddings.openai import OpenAIEmbedder
from groundedrag.providers.anthropic import AnthropicProvider

gate = DocumentGate(CoverageMap.from_file("coverage.yaml"))
retriever = GatedRetriever(gate, InMemoryStore(), OpenAIEmbedder())

question = "when do I get paid?"
decision, chunks = retriever.retrieve("payroll", question)
if not decision.allowed:
    print(decision.missing_documents_hint)
else:
    raw_answer = AnthropicProvider().generate(build_prompt(question, chunks))
    answer = build_answer(raw_answer, [c.id for c in chunks])

Benchmark

uv run python scripts/benchmark.py

On out-of-scope questions (no matching documentation), a pipeline with no gate answers 100% of the time — it has no way to know it shouldn't. groundedrag refuses 100% of the time, and tests/test_benchmark.py holds that number as a regression check, not just a demo. See docs/benchmark.md for methodology and ADR-0005 for why it's scoped this way.

Project layout

src/groundedrag/
├── gate.py            # decides: call the LLM, or refuse with a reason
├── coverage.py         # topic → documents map, auditable (YAML/JSON)
├── retriever.py        # retrieval + gate integration
├── guardrails.py        # citation extraction and verification
├── prompting.py          # builds the citation-required LLM prompt
├── chunking.py           # pure-Python, whitespace-safe text chunking
├── ingestion.py          # walks a directory into (Document, Chunk) pairs
├── factories.py          # name -> instance wiring for the CLI's flags
├── schemas.py          # Pydantic contracts
├── cli.py               # groundedrag init / ingest / ask / doctor
├── providers/           # LLM providers: anthropic, openai, ollama
├── stores/              # vector stores: chroma, pgvector, memory
├── embeddings/           # embedding backends, incl. the zero-setup HashingEmbedder
├── loaders/              # document loaders (PDF, OCR fallback, text)
└── api/                  # optional thin FastAPI wrapper

Elsewhere in the repo: examples/ (the two runnable demos), scripts/benchmark.py (the hallucination-rate benchmark), docs/ (the mkdocs site source — architecture, ADRs, benchmark methodology, quickstart), and CHANGELOG.md.

Development

Requires Python 3.11+ and uv.

# Skips sentence-transformers on purpose — it pulls in a multi-GB PyTorch
# download. Add --extra sentence-transformers if you need that backend.
uv sync --extra dev --extra anthropic --extra openai --extra ollama --extra chroma --extra pdf
uv run pytest
uv run ruff check .
uv run mypy src/groundedrag

To build the docs site locally: uv sync --extra docs && uv run mkdocs serve.

License

Apache 2.0.

Contributing

See CONTRIBUTING.md.

Metadata

Release files for groundedrag 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for groundedrag 0.1.0
File Size Uploaded Provenance Actions
groundedrag-0.1.0.tar.gz 393.1 kB With provenance Details for groundedrag-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for groundedrag 0.1.0
File Interpreter ABI Platform Actions
groundedrag-0.1.0-py3-none-any.whl Python 3 none any Details for groundedrag-0.1.0-py3-none-any.whl

Total release size: 426.6 kB

Release files / groundedrag-0.1.0.tar.gz

Download URL groundedrag-0.1.0.tar.gz
Size 393.1 kB
Tags Source
SHA-256 checksum
How to use checksums
93e0c8af3ed9e067481eff02934655e89e65443aa5ee109a6c2a46bd5d3f9ecc
BLAKE2b-256 checksum
How to use checksums
090495be1895cc27b0384a8e6a8bf0960976a0a270266b3c474f0f077cce22a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / groundedrag-0.1.0-py3-none-any.whl

Download URL groundedrag-0.1.0-py3-none-any.whl
Size 33.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6a0de3b330011dcd9e562a1e968a287ce34b1f0b9fd4d5d6596406a361c51eb
BLAKE2b-256 checksum
How to use checksums
44466297a1d4d616e4202bcd400dee0d45f40a5891fa26d8bd2e2dae8e12604d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Security for groundedrag 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for groundedrag-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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