Question answering over 180,000 pages of procedures, circulars and contracts, where every answer cites the exact source page and respects per-department access control.
roleAI Engineer
team4 people
timeline7 months, 2025-2026
statusin production
## context
Operations staff spent an average of 18 minutes on each procedure lookup: open the intranet, guess at keywords, download a few hundred-page PDFs and skim. Legal fielded roughly 400 repeat questions a month, most of them already answered somewhere in the documents.
Two constraints were non-negotiable from day one: no answer ships without a verifiable citation, and nobody sees a document outside their clearance. Those two conditions shaped the whole architecture.
## what I did
01
Ingest and normalization layer
Re-OCR'd 40,000 scanned pages, separated tables from prose, and merged circular amendments into a single timeline.
02
Two-stage retrieval
BM25 for coarse filtering, embeddings for reranking, with access control applied inside the query rather than after results.
03
Eval set and feedback loop
200 questions with reference answers written by the legal team, run automatically on every prompt or model change.
04
Operations and handover
vLLM on two on-prem GPUs, a dashboard tracking citation error rate, and runbooks for the client's infra team.
Fig 1How a document travels from the internal store to a cited answer.
## three decisions worth recording
Enforce permissions in the query, not after retrieval
The first version filtered results post-retrieval, so users saw result counts shift with their clearance and could infer that confidential documents existed. We turned department labels into predicates inside the pgvector query.
-> inference side channel closed, 90ms latency saved
Keep tables as tables
Fee schedules and limits drive most real questions, but flattened into prose the model read across the wrong columns. Tables are extracted separately, stored as markdown and returned whole.
-> fee-question accuracy: 61% -> 94%
Cite page numbers, not filenames
Operators need to open the exact page to verify. We carry page coordinates through the entire chunking pipeline, which is more expensive to store, and it bought trust.
-> 94% of answers verified and accepted by users
## what I would do differently
We built the eval set after the prototype and paid for it with six weeks of arguing about answer quality on gut feel. Next time, 200 questions with reference answers get written first, before an embedding model is even chosen.
Need something similar on your own data? Send a few lines of context.