Legal services

Retrieval That Lawyers Would Actually Trust

A document assistant produced fluent answers but could not show that it had found the controlling source or current revision. The work rebuilt ingestion, retrieval and evaluation around provenance, permissions and evidence before changing the generative layer.

Engagement
RAG and document search
Duration
A little over a quarter
Team
AI and application engineers with a product analyst
A wireframe drawing of a document plate with leader lines running back from its lines to specific drawers in an archive.

This account is anonymised. The client is described by sector rather than by name, and outcomes are described in words rather than figures — no percentage or saving is quoted because none can be independently evidenced here.

Before the work

Fluency was obscuring retrieval failure

The initial proof of concept could summarise a document placed directly into its prompt, yet behaved unpredictably when asked to search the wider repository. Near-identical clause names displaced the relevant source, scanned appendices disappeared during extraction and superseded guidance appeared beside current material without distinction. Answers sounded complete even when the retrieved passages were merely topical. Lawyers responded by opening the cited documents and repeating the search manually, which removed the intended benefit and made the assistant another surface to verify. Prompt revisions changed style but did not resolve whether the necessary evidence entered the context at all.

The engagement reframed the product as an information-retrieval system with a constrained generative interface. Success meant retrieving authorised, current and answer-bearing passages, preserving their exact provenance and declining where the indexed evidence was insufficient. The corpus included word-processing files, text PDFs, scans, email attachments and tables, each with different extraction failure modes. Repository access rules and matter restrictions had to apply before content reached a model. An evaluation set built from real research questions and approved evidence became the contract for the pipeline, allowing parsing, chunking, lexical search, embeddings, reranking and answer construction to be assessed separately.

Constraints

What shaped the build

Matter confidentiality

Repository and matter permissions had to be enforced before retrieval, including cached results and generated answer context.

Mixed document quality

Scans, tables, footnotes and inconsistent templates meant successful file conversion could not be assumed to preserve legal meaning.

Versioned authority

Superseded and draft material needed to remain discoverable where permitted without being presented as the current controlling source.

Citation requirement

Every substantive answer needed stable references to the exact document revision and passage supplied to the model.

Approach

How the engagement ran

  1. 01

    Label the evidence

    Representative questions were paired with approved passages, acceptable alternatives and cases where the corpus could not support an answer.

  2. 02

    Repair ingestion

    Extraction outputs were inspected by document class, with provenance, hierarchy, tables and failure states made explicit.

  3. 03

    Establish retrieval

    Lexical and dense candidates were combined, filtered by access and lifecycle metadata, then reranked against the labelled set.

  4. 04

    Constrain generation

    Context assembly removed duplication, preserved citations and required the answer layer to distinguish evidence from inference.

  5. 05

    Operationalise evaluation

    Regression cases, trace logging, reviewer feedback and index lifecycle checks became release controls rather than a one-off benchmark.

01

Make ingestion inspectable

The repository connector captured a stable document identifier, version, source location, content type, access attributes and lifecycle state before extraction. Parsers produced structured blocks rather than one undifferentiated string, retaining headings, list scope, page anchors and table relationships where the format allowed. Optical character recognition outputs carried confidence and were never silently substituted for a failed native extraction. Quality checks identified empty pages, repeated headers, suspicious character sequences and abrupt loss of content. A document with an ingestion failure remained visibly absent from search; it was not marked indexed merely because a processing job had completed.

Chunks followed document structure before applying a token ceiling. Definitions stayed with their terms, headings with their subordinate text and table rows with the headers needed to interpret them. Each chunk retained offsets into the immutable extracted version, permitting a citation to resolve to the exact evidence shown during answer generation. Re-indexing created a new index version and preserved the previous evaluation result until comparison completed. Deletes and permission changes propagated through lexical, vector and cache layers. This lifecycle prevented an old vector from surviving after its source had been restricted or replaced, a failure that answer-time instructions could not safely repair.

02

Optimise candidate retrieval before answer wording

A transparent lexical baseline exposed questions driven by exact terms, authorities and clause references. Dense retrieval added semantic candidates for questions phrased differently from the source, but it did not replace term search. Candidate sets were fused and passed to a cross-encoder reranker, with document status, effective date and source class available as explicit signals or filters. The retrieval stage favoured evidence coverage; context assembly later controlled volume. Tests were sliced by query intent and document type because a single average could conceal consistent failure on tables, defined terms or superseded policies.

Permission filters were incorporated into each search plan. Applying them after nearest-neighbour retrieval could leave an authorised user with poor candidates even where relevant permitted evidence existed, so filter behaviour was measured against realistic matter scopes. Query traces recorded normalisation, candidate identifiers, scores, filters, index version and selected chunks without copying unrestricted content into general telemetry. Failure analysis separated absent source, extraction damage, boundary error, vocabulary mismatch, permission error and ranking error. Engineers could then repair the earliest failing stage instead of compensating with a larger model or a prompt that merely sounded more cautious.

03

Assemble evidence, not a pile of chunks

Top-ranked passages frequently overlapped or repeated the same source. Context assembly grouped adjacent material where continuity improved meaning, removed near-duplicates and limited dominance by one document when independent sources were relevant. It preserved the heading path, document status and citation anchor alongside each passage. The token budget was allocated to evidence rather than repository boilerplate. Contradictory current passages were retained and flagged to the answer layer rather than arbitrarily selecting one. Superseded material could support a historical question, but its status travelled into the context and display so it could not appear as present guidance by omission.

The answer contract required claims to be supported by supplied passages and separated quoted source meaning from synthesis. Where labelled evidence was absent or conflicting, abstention was an accepted outcome. Citation verification checked that the referenced passage entailed the nearby claim, not simply that it came from a relevant document. Stable identifiers resolved citations through the user’s current access, and the display named the exact revision used. If access had since changed, the historical trace remained in controlled logs without disclosing the content. Generation settings, prompt version, chosen chunks and model version were recorded so a disputed answer could be replayed against the same inputs.

04

Use evaluation as a release boundary

The evaluation corpus paired each question with the smallest passages sufficient to answer it and recorded acceptable alternatives. It also contained similarly named matters, obsolete guidance, missing-source questions and requests that crossed access boundaries. Retrieval was measured independently through evidence coverage and ordering, while reviewers assessed answer support, citation accuracy and appropriate abstention. A model answer that happened to be correct from prior knowledge did not rescue failed retrieval. Likewise, stylistic disagreement did not count as a factual failure where the response remained grounded and complete. This separation made changes to embeddings, parsers and prompts comparable rather than anecdotal.

Production feedback entered a triage process rather than an automatic training loop. Reviewers could identify a wrong source, damaged extraction, missed qualification, unsupported claim or access concern against the recorded trace. Approved cases joined the regression set after sensitive details were handled under the same corpus controls. Index freshness, deletion propagation, parsing failures and permission-sync lag were monitored as product health, because retrieval quality degrades as sources change. The delivered system therefore made trust a property of inspectable evidence and controlled failure. It did not ask lawyers to trust the language model, and it did not present an eloquent answer as proof that research had succeeded.

Outcomes

What changed

  • Answer review began with the exact retrieved evidence and document revision rather than an opaque model response.
  • Superseded material remained available for historical research without presenting as current authority.
  • Restricted content was excluded before candidate retrieval and prompt construction.
  • Parsing and ranking defects could be assigned to a reproducible failure stage.
  • Insufficient evidence produced a visible abstention instead of a plausible completion.

Stack

  • Python
  • FastAPI
  • PostgreSQL
  • OpenSearch
  • pgvector
  • React
  • TypeScript
FAQ

Common questions

Can a legal RAG system respect matter permissions?

Yes, if access attributes are indexed and enforced during candidate retrieval. Filtering or redacting after generation is too late because restricted text has already reached the model.

How do you know whether legal document retrieval is accurate?

Representative questions are labelled with the passages required to answer them. Candidate retrieval, ranking, answer support, citations and abstention are then evaluated as separate stages.

How are superseded documents handled?

Lifecycle and effective-date metadata travel with every indexed passage. Current queries can prefer or require active material while historical questions retain controlled access to older revisions.

Does improving the prompt fix unreliable citations?

Not when the relevant evidence was never retrieved or its anchor was lost during parsing. Citation reliability begins with versioned sources, preserved offsets and claim-level verification.

Describe your version of this.

The constraints are never identical, and that is usually where the interesting engineering is. Tell us what yours are.