A local-first, multi-workspace RAG application for asking grounded questions over your documents. Create an account, organize documents into isolated workspaces, and receive answers with source citations—all while keeping models and application data on your machine.
- Workspace isolation — accounts, documents, chat sessions, and retrieval are separated by workspace.
- Document-ready ingestion — upload CSV, DOCX, PDF, PNG, JPG, or JPEG files up to 25 MB.
- Rich extraction — parses document text, OCRs image-based files, and analyzes CSV data.
- Grounded answers — a local Ollama chat model answers with citations to the retrieved source material.
- Privacy-aware observability — local Langfuse traces exclude prompts, document contents, and CSV values.
| Layer | Components | Responsibility |
|---|---|---|
| User interfaces | React frontend, Chainlit | Account access, workspaces, uploads, and chat |
| Application | FastAPI API, ingestion worker | Authentication, chat orchestration, document processing |
| Retrieval | Qdrant, Ollama embeddings | Vector indexing and semantic search |
| Storage | Postgres, MinIO | Application data and uploaded files |
| Observability | Langfuse | Local, metadata-only traces |
All services run through Docker Compose. Ollama remains on the host and is reached from containers at http://host.docker.internal:11434.
- Docker Desktop with Docker Compose
- Ollama available at
http://localhost:11434 - Python (for environment validation and backend tests)
- Node.js and npm (for frontend tests)
Create your local environment file:
cp .env.example .envFill every blank required value in .env. The database URL must use the Compose service hostname—not localhost—for example:
DATABASE_URL=postgresql+psycopg://rag:<password>@postgres:5432/ragSee .env.example for all settings. Keep .env local; it contains secrets and is not committed.
The defaults are deepseek-r1:7b for chat and qwen3-embedding:0.6b for embeddings:
ollama pull deepseek-r1:7b
ollama pull qwen3-embedding:0.6bIf you change CHAT_MODEL or EMBEDDING_MODEL in .env, pull those model names instead.
python scripts/validate_env.py
docker compose up -d --build| Service | URL | Use |
|---|---|---|
| Registration | http://127.0.0.1:8100/register | Create an account |
| Chainlit workspace | http://127.0.0.1:8101 | Use the Chainlit RAG interface |
| React workspace | http://127.0.0.1:8102 | Use the React frontend |
| Langfuse | http://127.0.0.1:3100 | Inspect local traces |
- Register and sign in.
- Create a workspace.
- Upload one or more supported documents.
- Wait for ingestion to finish, then ask a question in that workspace.
- Review the citations attached to the answer.
Chat sessions are persisted per workspace. In Chainlit, choose Account to see the signed-in email and use the user menu to sign out.
The validation script requires non-empty values for the database, object storage, JWT, Chainlit, and Langfuse secrets before startup. The most commonly adjusted settings are:
| Variable | Purpose | Default |
|---|---|---|
CHAT_MODEL |
Ollama model used to generate answers | deepseek-r1:7b |
EMBEDDING_MODEL |
Ollama model used for vector embeddings | qwen3-embedding:0.6b |
EMBEDDING_BASE_URL |
Endpoint used by the embedding service | http://host.docker.internal:11434 |
OCR_LANGUAGES |
Tesseract OCR languages | eng+vie |
For the complete list, comments, and required secret fields, use .env.example.
- Uploaded files are stored in MinIO.
- The ingestion worker extracts text, runs OCR where needed, and chunks the content.
- Non-CSV content is embedded and indexed in Qdrant.
- A question retrieves relevant chunks; Ollama generates a cited answer from that context.
Run the backend tests:
python -m pytestRun the frontend tests:
cd frontend
npm testValidate the Compose configuration:
docker compose config --quietapp/ FastAPI application, RAG graph, and services
worker/ Background document-ingestion worker
frontend/ React workspace frontend
tests/ Backend and integration tests
scripts/ Setup and environment-validation utilities
compose.yaml Local service stack