Loading documents…
Retrieved passages (hybrid search, top 5 — cited ones are highlighted)
Loaded documents are searched together. Uploaded files are chunked and embedded in your browser; nothing is stored. Only the 5 passages retrieved for a question are sent to the model.
| Document | Source | Chunks |
|---|
10 hand-written questions about the sample documents: 8 have an answer in the docs, 2 don't (the right behaviour there is to refuse). Each row shows whether retrieval found the right passage, whether the answer cited it, whether it refused correctly, and whether a second model judged the answer faithful to the sources.
| # | Question | Retrieval hit@5 | Cited the right passage | Refusal correct | Faithful | Model |
|---|
- Chunking. Documents are split by heading (PDFs by page), then packed into passages of up to ~900 characters, so a passage never mixes two topics.
- Embeddings. Each passage is turned into a 384-number vector with
all-MiniLM-L6-v2, running in your browser via transformers.js. The sample docs were embedded ahead of time with the same model. - Hybrid retrieval. A question is scored two ways: BM25 keyword match (catches exact terms like "OPG" or "Koramangala") and vector similarity (catches paraphrases like "fee" vs "costs"). The two rankings are merged with Reciprocal Rank Fusion and the top 5 passages are kept.
- Answering. Only those 5 passages go to a free LLM (via OpenRouter) with strict rules: cite every fact as [n], never use outside knowledge, and reply "I can't find that in the documents" when the answer isn't there.
- Guards. After the model replies, citations to passages it wasn't given are removed, and an answer with no valid citation is withheld and replaced by the refusal. The Eval tab measures how well all this works.
Source code and write-up: github.com/yashharkawat/rag-docs-qa. The sample clinic handbook is fictional.