Multi-document contract review with grounded answers by Abdulhamid SonaikeMulti-document contract review with grounded answers by Abdulhamid Sonaike

Multi-document contract review with grounded answers

Abdulhamid Sonaike

Abdulhamid Sonaike

The problem

A legal team with forty contracts and one question, say what the liability cap is, has two bad options. Read all forty, or ask a chatbot that cannot show its working. The second is worse. A confident wrong answer about an indemnity clause is not a bad search result, it is a liability.

What I built

An AI workspace for legal document review. You create a matter, drop PDFs or DOCX files onto it, and run a grid of questions across every document at once. Each cell holds an answer, and every answer links straight through to the exact source text it came from.

Architecture

Next.js and TypeScript on the front. A Python FastAPI service handles ingestion, retrieval and answering. PostgreSQL stores matters, documents and answers, and MinIO holds the uploaded files. The model backend is pluggable: with no API key configured a placeholder model runs, so the whole system stays testable without spending anything on tokens.

The hard part was never extraction

Getting a model to pull a number out of a contract is the easy half. Knowing when it is wrong is the job. So every answer carries the span it came from and is checked against the source file before it is displayed. Not present is a first class answer, so the system says so rather than inventing a clause that is not there.
The API tests also run against a real Postgres rather than mocks. They create and migrate a test database, then truncate every table between tests, because a retrieval bug that only shows up with real rows is exactly the kind that reaches production.

What it demonstrates

Retrieval that cites its source, structured extraction across a whole document set, and the discipline of making a model's uncertainty visible instead of hiding it. That is the same shape as most of the production AI work I take on.
The path a contract takes, and the two points where the system is allowed to refuse.
The path a contract takes, and the two points where the system is allowed to refuse.
Extraction demos well and proves little. Knowing when the model is wrong is the product.
Extraction demos well and proves little. Knowing when the model is wrong is the product.
Like this project

Posted Sep 15, 2026

Upload contracts, run a grid of questions across all of them, and click any answer through to the verified source text. Next.js, FastAPI, Postgres, MinIO.