Local-first RAG: ingest PDFs or plain text (books, manuals, reports—any domain), search by meaning, compare the same section across editions, and get summaries with citations. Built for production: multi-tenant auth, rate limiting, caching, async ingestion, and horizontal scaling.
The fastest way is with Docker. You need a .env file (copy from .env.example) and at least POSTGRES_PASSWORD set.
cp .env.example .env
# Edit .env: set POSTGRES_PASSWORD
docker compose up -dThe API is at http://localhost:8080 (Swagger at http://localhost:8080/docs). Before installing Ollama: see Getting started — you can use OpenAI or Anthropic only and skip Ollama; only install Ollama if you want local models. Full steps, local development, and troubleshooting: docs/GETTING_STARTED.md.
| Topic | Document |
|---|---|
| How to run | Getting started — Docker and local run, env, Ollama, troubleshooting |
| Tools & stack | Tech stack — Python, FastAPI, Postgres, Qdrant, Redis, Ollama, Celery, Nginx |
| Models | Models and observability — Ollama, OpenAI, Anthropic; per-task models |
| API | API reference — All endpoints, auth, request/response, examples |
| Features | Features — Ingestion, search, compare, summarize, agents, auth, scaling |
| For | Docs |
|---|---|
| Getting started | Overview & scope · User guide |
| Developers | Architecture & design · Developer guide · Testing guide |
| Production | Deployment · Operations |
Full index: docs/README.md.
- Ingestion: PDF and TXT → structure (book/edition/chapter/section) → semantic chunking → embeddings (Ollama or OpenAI) → Postgres + Qdrant. Sync or async (Celery).
- Search: Semantic search over sections; filter by tenant, book, edition; optional LLM-generated answer; cache and rate limits.
- Compare & summarize: Same section across editions; summarize one or more sections or run a natural-language summary via the agent pipeline.
- Agentic query: Single natural-language question → query understanding → retrieval plan → tools (search, match, compare, summarize) → verification. Citations included.
- Production: Tenant auth (API key), per-tenant rate limits, Redis cache, Nginx LB, PgBouncer, Prometheus metrics, structured logging.
Details: Features.
-
Configure
cp .env.example .env # Set POSTGRES_PASSWORD (and optionally other vars). See .env.example for Phase 1–6 options. -
Start the stack
docker compose up -d
This starts Postgres, Qdrant, Redis, PgBouncer, Nginx (API on port 8080), RAG API, Celery worker, and Next.js web (port 3002). The API is at http://localhost:8080 (Nginx). Open the UI at http://localhost:3002 and the API docs at http://localhost:8080/docs.
Ollama (optional): Only if you want local models — run on the host (port 11434) or in Docker:
docker compose --profile with-ollama up -dand setOLLAMA_HOST=http://ollama. Then pullnomic-embed-textandllama3.2. To use OpenAI/Anthropic only, setCHAT_PROVIDERandEMBED_PROVIDERin.envand skip Ollama; see Getting started. -
Create a tenant and API key (when using auth)
POSTGRES_HOST=localhost POSTGRES_PORT=5433 uv run python -m scripts.create_tenant "My Tenant" my-tenant # Save the printed API key; use header X-API-Key in requests.
-
Ingest or upload
- Upload via API:
POST /upload/document(multipart: file, title, author, edition_name). Useasync_mode=1for async (returns 202 + job_id; pollGET /ingest/status/{job_id}). - CLI:
docker compose run --rm -v $(pwd)/data:/app/data api-service python -m scripts.ingest_book --title "My Book" --author "Author" --edition "2021" --file /app/data/book.txt
- Upload via API:
-
Query
- Search:
POST /searchwith{"query": "...", "limit": 10}(headerX-API-Keyif auth enabled). - Full pipeline:
POST /querywith{"query": "Compare section X between editions"}. - Interactive chat:
API_BASE_URL=http://localhost:8080 AGENT_API_KEY=your-key uv run python -m scripts.chat
- Search:
Unit tests (no services required for Phase 2/3/5/6 logic; Phase 1 endpoint tests need Postgres):
uv run pytest tests/test_phase1_validation.py tests/test_phase2_rate_limit_cache.py \
tests/test_phase3_async_ingest.py tests/test_phase5_pgbouncer.py \
tests/test_phase6_metrics.py tests/test_phase6_logging.py -v --tb=shortLive validation (API + stack at http://localhost:8080):
export API_BASE_URL=http://localhost:8080
uv run python -m scripts.validate_phase1_live # Auth & tenant isolation
uv run python -m scripts.validate_phase2_live # Rate limit & cache
uv run python -m scripts.validate_phase3_live # Async ingestion
uv run python -m scripts.validate_phase4_live # LB & scaling
uv run python -m scripts.validate_phase5_live # PgBouncer & stack
uv run python -m scripts.validate_phase6_live # MetricsFull testing guide (unit + live + E2E + status): docs/TESTING_GUIDE.md.
| Path | Purpose |
|---|---|
config/ |
Settings (env); Postgres, Qdrant, Redis, Ollama, auth, rate limit, cache, Phase 3–6. |
src/api/ |
FastAPI app, auth, rate limit, cache, metrics, middleware, routes (search, compare, summarize, books, upload, ingest, debug). |
src/worker/ |
Celery app and async ingest task (Phase 3). |
src/storage/ |
Postgres and Qdrant clients; Redis. |
src/llm/, src/agents/, src/tools/ |
Embeddings, chat, agents, tools. |
src/ingestion/ |
Pipeline, chunking, vehicle_metadata (design). |
scripts/ |
create_tenant, backfill_tenant, ingest_book, chat, validate_phase*_live. |
docker/ |
Dockerfiles; nginx.conf (Phase 4); PgBouncer via Bitnami in compose. |
docs/ |
Getting started, tech stack, models, API reference, features, user guide, deployment, operations. |
Contributions are welcome. See CONTRIBUTING.md for setup, testing, and how to send patches.
This project is licensed under the MIT License — see LICENSE. You can use, copy, modify, and distribute it for any purpose, including commercial use.
- Local-first: Ollama (or OpenAI) for LLM/embeddings; Qdrant; Postgres; Redis. No vendor lock-in for core RAG.
- Tenant isolation: Every request is scoped to a tenant (API key); data and search are per-tenant.
- Tool-based agents: Each agent has a single responsibility; orchestrator invokes tools explicitly; citations and verification supported.
- Stateless API: Auth and cache are per-request or shared (Redis/DB); run multiple replicas behind Nginx.