Skip to content

Quickstart

From zero to a cited answer. Pick a track: Local runs everything on your machine with no accounts or API keys; Cloud uses Amazon Bedrock for the AI calls.

Installation should be done first, and the OCR server running.

1. Scaffold a configuration

ingestlib init writes the setup files into your current directory — that's where the library looks for them.

uv run ingestlib init --local

This writes a five-choice config.yaml: Ollama for LLM + embeddings, sqlite for vectors, a local folder for artifacts, no reranker. No .env, no accounts, nothing leaves your machine.

Then install Ollama and pull the two models:

ollama pull qwen3.5:9b
ollama pull qwen3-embedding:0.6b
uv run ingestlib init

This writes config.yaml (Bedrock + sqlite + Jina reranking) and a .env with the key slots. Two things to fill in:

aws configure --profile your-aws-profile   # Bedrock-enabled credentials

Set that profile name in config.yaml's aws: section, and put a Jina API key in .env (free tier works) — or set reranker: none and skip it.

2. Verify the stack

uv run ingestlib doctor

Doctor probes every choice with a real call and prints one line per check:

ingestlib doctor
  ✓ python 3.13.13
  ✓ config ./config.yaml (llm=ollama embed=ollama store=sqlite artifacts=local reranker=none)
  ✓ LibreOffice (soffice) found
  ✓ OCR server answering at http://localhost:8111/
  ✓ llm_provider ollama: chat call succeeded
  ✓ embedding_provider ollama: 1024-dim vectors
  - reranker none: retrieve() returns vector order
  ✓ artifacts in local folder ./artifacts
  ✓ vector_store sqlite: reachable

all checks passed — the configured stack is ready

Every failed line prints the fix: a wrong AWS profile lists your actual available profiles, a missing model prints the exact ollama pull.

3. Ingest a document

from ingestlib.services import ingest

result = ingest("report.pdf")
print(result.status, result.category, result.chunks)
# ingested research_paper 24

One call ran the whole pipeline: parse (OCR + chart reading), classify, split into sections and chunks, embed, and upsert into the vector store — with every stage's output persisted to the artifact store.

Run it twice and the second call returns status="skipped": documents are deduplicated by content checksum.

4. Ask a question

from ingestlib.services import retrieve

result = retrieve("how were participants recruited?", top_k=5)

for hit in result.hits:
    print(round(hit.vector_score, 3), hit.citation)
    print("   ", hit.chunk.heading)
# 0.94 doc 7b6b95d79149 · p.4 · methods
#      Participant recruitment

result.context is a numbered, citation-tagged block ready to paste into an LLM prompt — see Build cited answers.


That's the whole loop. Next: What just happened walks through everything those two calls produced — on disk and in the store.