atrium

Quickstart

From an empty directory to a searchable corpus.

What you need

Python3.10 or newer
An embedderAnything with an OpenAI-shaped /v1/embeddings endpoint
A vector storeSQLite (the default — a local file, nothing to run), Qdrant or Postgres with pgvector

The embedder is the one thing you need. Ollama is the easiest one to start with, and it runs on your machine:

ollama serve
ollama pull bge-large

If you would rather not run a server at all, the local extra runs a small ONNX embedding model in your own process:

pip install "atrium-rag[local]"

The vector store does not need a server either. VECTOR_DB=sqlite keeps the corpus in a SQLite file next to your project; switch to Qdrant or pgvector when the corpus outgrows a file.

Install

pip install atrium-rag

Optional extras, when you need them:

pip install "atrium-rag[ocr]"        # Tesseract or RapidOCR
pip install "atrium-rag[rerank]"      # cross-encoder reranking
pip install "atrium-rag[ocr,rerank]"  # several at once

OCR with OCR_PROVIDER=tesseract also needs the Tesseract binary on PATH — brew install tesseract, apt install tesseract-ocr. The rapidocr provider is pip-only and needs no binary.

Configure

atrium init

The wizard writes a .env. It asks five questions, and every answer is a choice you pick from a list with the arrow keys:

  1. The vector store — SQLite, Qdrant or pgvector. SQLite needs nothing; the other two ask for a host and a port.
  2. The embedding provider — a local server, OpenAI, another OpenAI-compatible server, or the in-process one from the local extra.
  3. The model — picked from the list the endpoint actually serves, with its dimension beside it. The models that are not embedding models are named separately, so they cannot be chosen by accident.
  4. OCR — off, or a provider and a language.
  5. Reranking — off, or a provider and a model.
  6. Vision — off, or a model.

Then it shows you what it chose, lets you change any value, verifies the result with a real embedding call, and prints the next command.

To write the file yourself instead:

cp https://raw.githubusercontent.com/ItsMeYash777/atrium/main/.env.example .env

The defaults are laptop-correct — localhost, not a Docker hostname — so a plain .env works on a machine and the container's .env.docker is what compose uses.

Check the result:

atrium validate     # is the file well-formed and consistent with the install?
atrium doctor       # can it reach the embedder and the vector store?

atrium doctor exits non-zero when something is actually broken, so it works as a deploy gate.

Run it

atrium serve

The API is on http://localhost:8000 and the OpenAPI schema is at /docs.

Ingest

From the shell:

atrium ingest ./documents/

It walks directories, parses each file, chunks it, embeds it and upserts the chunks. The output is a table of what was ingested.

Over HTTP:

curl -X POST http://localhost:8000/ingest \
    -F "files=@./report.pdf" \
    -F "files=@./notes.docx"

The response comes back after the document is parsed, embedded and stored:

{
  "jobs": [
    {"job_id": "…", "doc_id": "…", "filename": "report.pdf"}
  ]
}

For a large document you may not want to hold the connection open. POST /jobs queues it and answers immediately with a job_id; a worker picks it up:

python -m atrium.worker

Poll GET /jobs/{job_id} for pending, running, complete or failed.

From the shell:

atrium search "What is the retention policy?"

Over HTTP:

curl -X POST http://localhost:8000/search \
    -H 'Content-Type: application/json' \
    -d '{"query": "What is the retention policy?", "top_k": 8}'

Each result carries the page it came from, the heading path, the element type and the strategy that produced it:

{
  "rank": 1,
  "score": 0.781,
  "doc_id": "policy",
  "text": "Records are retained for 24 months…",
  "page_number": 14,
  "section_path": ["Retention", "Data lifecycle"],
  "element_type": "paragraph",
  "chunking_strategy": "structure_aware",
  "is_parent": false,
  "parent_id": null
}

Look before you store

POST /preview parses and chunks a document and hands back the chunks without embedding or storing anything — the fastest way to find out whether the chunking is right for your corpus before you pay for the embeddings:

curl -X POST http://localhost:8000/preview \
    -F "file=@./report.pdf" \
    -F "chunking_mode=precise"

Re-chunk later

If the strategy was wrong, re-chunk the document with a different one. The previous chunks are replaced, not mixed in:

atrium reingest ./documents/policy.md --doc-id policy --chunking-mode context_rich

Auth

Set API_KEY and every route except /health and /visualize needs a bearer token:

API_KEY=… atrium serve
curl -H "Authorization: Bearer $API_KEY" -X POST http://localhost:8000/search -d '{"query":"…"}'

With Docker

docker compose --profile qdrant up -d

That starts the API, a worker and Qdrant, with a shared volume for the job queue. Scale the workers with docker compose --profile qdrant up -d --scale worker=3.

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.

On this page