Skip to content

Repository files navigation

Grounded

A production-grade RAG starter that answers from your sources, cites them, and says "I don't know" instead of hallucinating.

Most RAG demos look great until real users hit them — then they hallucinate, double-charge on retries, re-embed everything on every deploy, and you have no way to tell if a prompt change made things worse. Grounded is the boring, reliable parts done right, in a small codebase you can read in 20 minutes and ship on.

  • Cited answers — every answer references the source chunks it used.
  • "I don't know" guardrail — if nothing relevant is retrieved, it refuses instead of guessing.
  • Idempotent ingestion — only new/changed chunks get embedded (content-hash dedup); re-ingesting is a near-no-op. No wasted API spend.
  • Retries with backoff — transient API errors retried; 4xx fail fast.
  • Eval harness — a labelled Q&A set scores retrieval + answers, so you catch regressions in CI.
  • Pluggable + offline-testable — swap embedder/store/LLM via env; the default runs with no API key and no database (great for demos, tests, and CI).

Stack: TypeScript · Fastify · Postgres + pgvector · OpenAI (swappable).


Quick start (zero setup — no API key, no DB)

npm install
npm start            # offline mode: in-memory store + extractive answers
# ingest some docs
curl -XPOST localhost:3000/ingest -H 'content-type: application/json' \
  -d '{"docs":[{"id":"faq","source":"faq.md","text":"Refunds are allowed within 30 days."}]}'

# ask — grounded answer with citations
curl -XPOST localhost:3000/ask -H 'content-type: application/json' \
  -d '{"question":"What is the refund window?"}'

# ask something off-topic — it refuses instead of making things up
curl -XPOST localhost:3000/ask -H 'content-type: application/json' \
  -d '{"question":"How do I train a neural net?"}'   # → grounded:false

Run the eval + tests:

npm run eval         # scores the bundled Q&A set (offline)
npm test             # 10 tests, no API key / DB needed

Production (OpenAI + pgvector)

cp .env.example .env
# set PROVIDER=openai, STORE=pgvector, OPENAI_API_KEY=..., DATABASE_URL=...
docker compose up -d            # Postgres with pgvector
npm run migrate                 # create the vector table + cosine index
npm run ingest -- ./your-docs   # embed your corpus (idempotent)
npm start

Works with Azure OpenAI / proxies via OPENAI_BASE_URL.


How the reliability works

Idempotent ingestion (src/core/pipeline.ts): each chunk is keyed by a sha256 of its text. On ingest we embed only chunks whose hash isn't already stored, and prune chunks that no longer exist. Change one paragraph → only that chunk re-embeds.

The guardrail (ask()): we retrieve top-k, and if the best cosine similarity is below RAG_MIN_SCORE, we return a refusal — the model is never even called, so it can't hallucinate (and you don't pay for it).

Citations: the answer ships with the exact source chunks + scores it was built from, so users (and you) can verify it.

Evals (src/eval/run.ts): a JSON dataset of questions with expected sources / grounded-ness / answer substrings. npm run eval scores retrieval hit-rate and answer correctness — run it in CI to catch regressions from a prompt/model/chunking change.

Architecture (swap any piece)

ingest/ask  →  Embedder        ×  VectorStore     ×  Chat
               ├ OpenAI (prod)    ├ pgvector (prod)   ├ OpenAI (prod)
               └ Hash (offline)   └ Memory (offline)  └ Extractive (offline)

Same pipeline code regardless — only the adapters change. That's why the whole thing is testable offline.

API

Method Path
POST /ingest { docs: [{id, source?, text}] } → ingest summary
POST /ask { question, k?, minScore? }{ answer, citations, grounded }
GET /stats chunk count + active providers
GET /health liveness

Why this exists / who built it

Built by Exavel — we build AI features that hold up in production. If your AI feature is flaky, hallucinating, or expensive, that's what we do. (See also Holdfast, an oversell-proof, chaos-tested reservation engine.)

MIT licensed — use it, fork it, ship it.

About

Production-grade RAG starter: cited answers, idempotent ingestion, an 'I don't know' guardrail, and an eval harness. Provider/store-agnostic, fully testable offline (no API key/DB).

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages