Colonial Archives
A research interface that turns scanned CO 273 archive PDFs into source-grounded answers, graph exploration, and exact page-level citations.
Makes messy colonial records searchable without letting the AI drift away from the documents it can prove.


Colonial Archives
Ingests CO 273 scanned PDFs through Document AI OCR, Vertex AI embeddings and search, Gemini entity extraction, and Neo4j MERGE to build a traceable knowledge graph for archive-first Q&A.
corpus
28 PDFs
graph
1,463 entities
links
6,843 relationships
Quick read
A source-grounded Graph-RAG research tool for colonial-era archive documents, combining OCR, vector search, Neo4j graph traversal, and page-level citations.
Making Scanned Archives Searchable
Colonial Archives started from a practical research frustration. The CO 273 Straits Settlements records contain valuable administrative, economic, and social history, but the source material is locked inside scanned PDFs. A historian looking for one officer, commodity, or regulation has to scan page after page and then keep track of where each claim came from.
The project turns that workflow into a source-grounded research assistant. It ingests archive PDFs, extracts text and entities, builds a knowledge graph, and lets users ask natural-language questions. Every answer is tied back to exact archive pages, so the interface is not asking researchers to trust an AI summary without evidence.
A Nine-Step Ingestion Pipeline
The backend is a FastAPI system that processes PDFs through a nine-step pipeline: download from Cloud Storage, OCR with Google Document AI, clean and chunk the text, embed chunks with Vertex AI, upsert vectors, extract entities with Gemini, normalize duplicate names, merge entities and relationships into Neo4j, and classify documents into archive categories.
The graph steps are intentionally non-blocking. If Neo4j is temporarily unavailable, vector ingestion can still succeed and the graph can catch up later. That choice keeps long-running OCR and embedding work from being wasted just because the graph database has a cold start or a transient outage.
Hybrid Retrieval With Citations
Querying the archive uses two retrieval paths at once. Vector search finds the most semantically relevant chunks, while graph traversal follows entity hints through related people, places, institutions, and events. The two paths have independent timeouts and fault isolation, so one slow service does not bring the whole answer down.
The answer generator is archive-first. Gemini receives only the retrieved archive context and emits numbered [archive:N] markers. The frontend turns those markers into citation badges, and clicking a badge opens the original PDF page in a viewer. If the archive cannot answer, the system can fall back to web search, but the UI labels that fallback separately instead of pretending it came from the archive.
Normalizing Messy Historical Names
One of the hardest parts was entity normalization. Historical documents and OCR output rarely name things consistently: the same person can appear with initials, titles, spelling variants, or OCR mistakes. Exact matching alone would split one historical actor into several graph nodes.
I handled that with three stages: exact and alias matching first, embedding similarity second, and fuzzy string matching third. The pipeline catches simple duplicates cheaply, then uses semantic similarity and spelling tolerance only when they are needed. Re-ingestion is safe because graph writes use MERGErather than blind creates.
The Interface: Graph Beside Chat
The frontend is a React 19 research workspace with a graph panel, chat panel, citation badges, PDF modal, and category controls. The overview graph shows the archive by community, while query mode narrows the view to the entities and relationships that support a specific answer.
At the current scale, the system has processed 28 PDFs into 1,463 entities and 6,843 relationships. The product lesson was that digital humanities tools need more than a good answer box. They need source visibility, uncertainty boundaries, and an interface that lets researchers inspect the evidence rather than just consume a summary.
The next engineering frontier is operational: keeping the graph and vector services warm enough for demos, improving PDF reopen performance, and making the deployment path boringly repeatable. The core research loop is already there: ask, retrieve, cite, inspect, and return to the archive page that proves the claim.
Next case study
DG Website