Projects

Live demo

Enterprise Search. Cited answers, or an honest I don't know.

Ask the company a plain-language question and get a streamed answer grounded only in internal documents, every claim cited, with sources that open to the exact passage. If retrieval finds nothing you may see, it says so, and the model is never even called.

RAG · Permission-aware retrieval 6 steps · synthetic data

Walk through it, six steps

Step 1 of 6

Ingestion is governed, not casual

An uploader drops a document and must scope it on the spot: who can find it, what class it is (Official Policy, Approved SOP, Draft, Note), and its effective date. Authority is computed server-side from class and uploader role, never client-supplied. Same content twice dedupes by hash; same source with new content becomes version n+1 and supersedes the old one.

Scope this documentSynthetic data
Who can find itACL
  • Everyone
  • or specific groups: engineering, finance, restricted-alpha
Document classgovernance
  • Approved SOP
  • authority computed server-side
Effective date
  • 2026-06-01
  • newer effective date wins ties
Versioning
  • Same source, new content → v2
  • v1 stamped superseded, linked both ways
Step 1 of 6

Every name, number, transcript and document in this tour is synthetic. The mechanisms, thresholds and architecture are real. The production system and its data stay private.

The problem.

Years of policies, SOPs, and specs lived across drives where the only search was asking a colleague. Worse, documents disagree: the 2025 schedule says Thursday, the 2026 one says Friday. A useful system has to know who may see what, which version is current, and when to admit it does not know.

  • Eval recall@8 1.0 floor 0.80, seeded eval harness
  • Retrieval hybrid + RRF dense 50 ‖ BM25 50 → rerank to 8
  • Tests 122 96 backend, 26 frontend
  • Abstention 0 tokens no eligible sources = no model call

How it fits together.

4 layers, left to right
  1. Store

    • One Postgres + pgvector for chunks, vectors, tsvectors, ACLs, versions, audit
    • Similarity AND permission AND currency collapse into one query plan
    • Originals in Cloud Storage behind signed URLs
  2. Retrieval

    • HNSW cosine top-50 ‖ BM25 top-50
    • Reciprocal Rank Fusion, k=60
    • Cross-encoder rerank to 8, with graceful fallback
  3. Generation

    • Gemini 2.5 Flash default, Pro selectable
    • Cite-or-abstain system prompt, streamed over SSE
    • No eligible retrieval → no model call at all
  4. Governance

    • Server-side authority from class + role
    • Version chains with supersede links
    • Deny-by-default ACL, audit log, Terraform infra

Where it landed.

The retrieval stack scores recall@8 of 1.0 and MRR 0.42 on a seeded eval harness with deterministic fakes, honest framing: those are eval-rig numbers, not production traffic. The design decisions that matter survived adversarial review, which caught a permission-sentinel bug, an authority-scoring bug, and a race that would have wiped the first streamed answer. Attachments, voice input, and doc-type facets ship in the real UI as visibly disabled, coming-soon controls rather than pretending.

Concepts

RAGHybrid retrievalReciprocal Rank FusionRerankingACL pre-filteringGrounded generationCite or abstainDocument versioning

Stack

PythonFastAPIPostgres + pgvectorgemini-embedding-001 (768d)Gemini 2.5 Flash/ProReact 19Cloud RunTerraform