architecture · Personal project

DocuMind — A Production RAG Platform

A multi-tenant RAG platform with streamed, cited answers — hybrid BM25 + embedding retrieval with reranking, a Redis semantic cache, and RAGAS scoring on every change.

Role
Sole designer and builder — ingestion, retrieval, caching, evaluation, and the app
Team
Solo
Scope
Multi-tenant question answering over PDFs and wiki pages, with streamed answers that cite their sources
Level
Personal project

Retrieval

vector-onlyhybrid + rerank

Method: BM25 and embedding retrieval merged and reranked with a cross-encoder, compared with a vector-only baseline on the evaluation set.
Window: by design

Quality tracking

spot checksRAGAS every change

Method: Faithfulness and context recall are scored with RAGAS on an evaluation set for every change.
Window: every change

Repeated questions

full pipelinesemantic cache

Method: Redis semantic cache returns answers for semantically repeated questions, cutting latency and token cost.
Window: by design

Context

"Chat with your documents" is easy to demo and hard to make good. DocuMind is a personal project to build it the way a production system needs to be built: multi-tenant, answers streamed and cited, retrieval quality measured, and costs kept under control. It answers questions over PDFs and wiki pages.

Code: repository link coming soon.

Retrieval is the product

Vector search is good at meaning and bad at exact terms — error codes, product names, section titles. Keyword search is the opposite. DocuMind uses hybrid retrieval: BM25 and embeddings run together, and a cross-encoder reranker scores each candidate against the actual question before anything reaches the model. That improves relevance over vector-only search.

One store for vectors and tenants

Embeddings live in PostgreSQL with pgvector, next to tenant and document metadata. Every query must only ever see the asking tenant's documents, and keeping both in one store means tenant scoping is part of the same query that does the search.

Cheaper repeats

People ask the same question in different words. A Redis semantic cache catches those rephrasings, so repeats come back faster and cost no generation tokens.

Measured, not guessed

Every change — chunking, retrieval, reranking, prompts — is scored with RAGAS on an evaluation set: faithfulness (does the answer stick to the sources?) and context recall (did retrieval find what was needed?). Separating the two tells you whether to fix retrieval or generation.

What broke

The first cache matched only on question similarity, which meant a similar question from one tenant could in principle get another tenant's cached answer. I caught it in testing, and cache keys are now scoped by tenant and document-set version, with a test that tries to read across tenants. Separately, fixed-size chunking split tables and headings from their content, and context recall made that visible — so chunking now follows document structure.

Outcomes

Streamed, cited answers over PDFs and wiki pages; hybrid retrieval with reranking; a tenant-safe semantic cache cutting latency and token cost; and answer quality tracked with RAGAS on every change.

Decision Records

Where I Got It Wrong

Failure 1

The first version of the semantic cache matched only on question similarity, so in principle a similar question from one tenant could be served another tenant's cached answer — caught in testing before it shipped

Cost: A redesign of the cache keys, and a reminder that in a multi-tenant system every shortcut is a potential data leak

Lesson: In a multi-tenant system, scope every cache key by tenant and by the version of the document set — and write a test that tries to read across tenants

Failure 2

Fixed-size chunking split tables and section headings away from their content, which showed up as low context recall on questions about structured parts of documents

Cost: Answers that missed information sitting just across a chunk boundary

Lesson: Chunk along document structure — headings, sections, tables — and let the context-recall metric tell you when chunking is the problem rather than the prompt

Long-Term Impact

A reference implementation for production RAG: hybrid retrieval, tenant-safe caching, cited answers, and quality measured on every change.