Skip to content
Ayush Gupta

Atlas

Ask a question about a 400-page filing and get an answer with the exact region highlighted on the original page, verified before it's shown and priced in dollars.

Status
Open source (MIT)
Role
Solo: design, build, evaluation
Timeline
Jun to Aug 2026

Question → the relevant region resolves on the page → a grounded, cited answer with its cost.

The problem

The answer is often in the layout

Due-diligence teams search data rooms full of scanned PDFs, contracts, financial tables and charts. The answer to a question often lives in the layout: a number in a table cell, a signature block, a stamp.

Text-only RAG flattens the page and loses that structure. It also answers with a page number at best, so every answer still has to be checked by hand.

Constraints

A laptop and a small budget

  • A 16 GB Mac as the development machine, with a 3B-parameter visual retrieval model that needs a GPU
  • Designed to run on roughly $3 of model credit without surprises
  • A real public corpus: Uber's 407-page SEC S-1 filing from EDGAR

Architecture

Retrieve, answer, then verify

The query pipeline is a LangGraph state machine. The interesting part is what happens after the verifier.

Atlas query pipelinePlanner, then retriever (visual, dense and graph channels, reranked), then answerer, then verifier. Grounded answers, or questions with no evidence, go to finalize. Unverified answers with retries left go to replan, which widens retrieval and loops back to the retriever. Unverified answers with the budget spent go to a human review queue, then finalize.plannerLangGraphretrievervisual + dense + graphanswererreads page imagesverifierchecks each claimfinalizeanswer + citation + costreplanwidenhumanreview queuegrounded, orno evidenceretries leftbudget spent
Drawn from the pipeline in the Atlas repository. Nothing added for effect.

Retrieval fuses three channels (ColPali over page images, bge-m3 dense text vectors, and a GLiNER entity graph in Neo4j) with Reciprocal Rank Fusion, then reranks with a cross-encoder. The citation highlight is the per-patch term of the same MaxSim score used for retrieval, so it needs no extra model.

Decisions

What I chose, and what it cost

DecisionWhyTrade-off
Retrieve over page imagesKeeps layout; enables pixel-level citationsHeavier per-page storage than text
ColPali on a hosted GPU SpaceA 16 GB Mac can't host a 3B model; keeps torch out of the coreNetwork hop and cold starts
One Postgres for everythingDense vectors, page multivectors, ANN index and cost ledger in one storeA dedicated vector store is the documented scale path
Two-stage visual searchExact MaxSim over every page grows linearlyApproximate shortlist; exact rescoring recovers precision
Cost-aware verifier loopRecall without runaway spendExtra latency on hard questions, capped by max retries

What broke

Two things that didn't work first time

Structured output came back empty

JSON-schema structured output returned empty on the chosen model. Switched to function-calling structured output.

Entities went missing

Named-entity extraction was dropping entities, which weakened the graph channel. Fixed with windowed extraction.

Results

Measured on the demo corpus

pages
407
visual search
734→181 ms
per answer
~$0.002
tests passing
40

Observed during development on the Uber S-1/A. Illustrative, not a published benchmark. The eval harness reports recall@k, nDCG@10, citation precision, groundedness and cost per answer.

What's next

From one filing to real data rooms

  • Multi-tenant access control, with citations scoped to what each user may see
  • Self-hosted models so confidential documents never leave the tenant
  • A native multivector store once the corpus outgrows Postgres

Related: RAG & document intelligence

Working with documents like these? Let's talk.

Talk about this