Limitations
What is weak, what is missing, and what the measurements actually say.
This page is the one to read before you depend on any of it.
Retrieval quality
- The benchmark is ours, but it is a comparison. 23 documents and 700 questions, each system's own parser and chunker, one embedding model for all three: R@5 0.700 against Docling's 0.686 and Unstructured's 0.614. The difference against Docling is inside the noise band at this corpus size, and the report prints the interval rather than a number without one — so read the accuracy as a tie and the cost as the result. The harness, the corpus and the exact commands are public, so the numbers can be re-run.
- Reranking is opt-in and off by default. The cross-encoder lifts
ranking on most corpora, and regresses on forms, slides, mathematics
and OCR'd scans, because it was trained on web question answering.
It is exposed —
rerank: trueon/search— but you have to ask for it. - Hybrid BM25 + dense retrieval is not reachable. The sparse
ranker and its confidence gate are in the library, and
retrieve_and_rerankwill use them if you pass abm25_index. No HTTP endpoint and no CLI command does, so from the product's point of view this feature does not exist yet. It is markedroadmapon the site. - The BM25 tokenizer is not script-aware. CJK and Arabic queries tokenize badly against a corpus of the same script. Dense retrieval is unaffected; the sparse path is not there to be affected.
- Adaptive chunk strategy selection is not shipped.
autoresolves tostructure_awarefor every document.
Memory and latency
Measured on an Apple M4 with 16 GB, in the published container image,
with bge-large and Qdrant, over a 19-document, ~1,000-page corpus.
| Resident, serving search | 111 MB |
| Peak, ingesting the corpus in one process | 729 MB |
| Search, p50 / p95 over ~2,700 chunks | 66 ms / 69 ms |
| Ingesting the corpus | 119 s |
The embedder is a separate process. bge-large costs about 670 MB
in Ollama's process, and it is in none of the numbers above. Atrium's
embedder is HTTP-only by design, so a model is never loaded into the
ingestion process.
RSS does not return to the OS. After a bulk ingest the process holds about 425 MB resident; a server that starts and is handed the store holds 88 MB. A worker that ingests continuously should be recycled between batches.
The two heaviest imports are the Qdrant client (about 90 MB) and pdfminer.six, the layout engine under pdfplumber. Both are imported lazily, so a process that only serves search does not pay for them. PyMuPDF is not a dependency at all — it is an opt-in extra.
Formats
- HTML navigation and asides are not stripped. They end up in the text and therefore in the embedding.
- DOCX and HTML page numbers are derived from headings, not from paper. They are stable and useful; they are not physical pages.
- A spreadsheet is one chunk per sheet. A large sheet is one large chunk. Split it yourself.
- Text inside figures is not text. It needs OCR.
- The RapidOCR model reads Chinese and English only. For other languages, use Tesseract.
- A document with a column layout is read in column order, and the heuristic can be wrong about where a column ends when a full-width figure cuts through it.
- Encrypted PDFs are rejected, not guessed at.
Operations
- There is no distributed job queue. Workers share a single SQLite file. Put it on a shared volume if you run workers on more than one host. There is no Redis, no Kafka, and no Postgres job store.
- A job that dies mid-flight is reclaimed after
JOB_STALE_SECONDS(default 1800) and run again. Set it above the slowest document you expect, or the same document will be ingested twice. mypyis advisory in CI. The package has around thirtyOptional-narrowing findings, mostly in the PDF parser's geometry helpers.- Two parser fixes are known to be missing — SEC 10-K heading
detection and a cross-page form-copy dedup. Both change the chunk
landscape, so both need the benchmark re-run before they can land.
Their tests are marked
xfail(strict=True): they fail today, and landing either fix forces a re-baseline rather than a silent drift.
The project
- v0.1.0 is the first public release. Nothing was published before it, so the version numbers in the changelog history are internal.
- Only bearer-token auth. There is no JWT mode, no SSO, and no per-tenant isolation.
- The retrieval lab is a sandbox, not a second retrieval path: it scores one document against an in-RAM cosine matrix, with no vector store, no sparse ranker and no reranker.
Atrium Cloud
Don't want to run it yourself? Atrium Cloud is coming.
It is not here yet — the list is what there is until it is. The library is free, MIT licensed, and yours either way.