Production-grade, self-hosted document ingestion and retrieval service.
- Multi-format parsing: PDF, DOCX, TXT, Markdown with smart layout preservation
- Chunking strategies: Recursive character, Markdown headers
- Image extraction and LLM description: Makes visual content searchable
- OCR fallback: LLM vision for scanned pages
- Vector storage: Milvus with cosine similarity search
- Hybrid retrieval: BM25 keyword search + vector fusion (RRF)
- Cross-encoder reranking: Sentence Transformers for relevance scoring
- ARQ task queue: Background processing with retry and backoff
- SSE status streaming: Real-time ingestion progress
- Pluggable connectors: Local filesystem (ready), S3/Google Drive (pluggable)
- Deduplication: Content hash + source path matching
- Batched embedding: Configurable batch size with retry
- Web dashboard: Responsive dark-themed UI for all operations
- uv Python manager: Fast dependency installation and management
- Makefile: Simplified task management
Upload → Validate → Store → Track (DB) → Queue (ARQ)
┌─── Worker ───────────────────────────────────────┐
│ Parse → Describe images → Chunk → Dedup → Embed → Store (Milvus)
└──────────────────────────────────────────────────┘
↓
SSE Status Events
↓
Query → Search
↓
Web Dashboard ←── You are here
The project includes a responsive dark-themed web dashboard built with Vue 3 (served as static files from the FastAPI application).
Pages:
| Page | Description |
|---|---|
| Dashboard | System health, collection stats, recent documents |
| Documents | Upload (drag & drop), list/filter, delete, retry, download |
| Collections | Create, browse, delete vector collections |
| Search | Semantic search with reranker, multi-collection mode, score visualization |
Access the UI at http://localhost:8100/ (redirects to /ui/).
The frontend is served directly by the API server — no separate build step or
dev server needed. Source lives in the frontend/ directory.
Two workflows are available:
# Install uv (https://github.com/astral-sh/uv)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
make setup
# Create .env from example
cp .env.example .env
# Edit .env with your settings
# Start everything (app + data infra in containers)
make up
# Wait for services to be ready
make wait
# Upload a document
curl -X POST http://localhost:8100/api/v1/documents/upload \
-F "file=@example.pdf"
# Search
curl -X POST http://localhost:8100/api/v1/search \
-H "Content-Type: application/json" \
-d '{"query": "What is the revenue?", "limit": 5}'Run the Python code directly on your machine for instant feedback — only the data stores (Postgres, Valkey, Milvus) run in containers.
# Install uv (https://github.com/astral-sh/uv)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
make setup
# Start ONLY data infrastructure containers
make dev-up
# Create media directory + run database migrations
make dev-setup
# (Terminal 1) Start API with hot-reload
make dev-fast
# (Terminal 2) Start background worker
make dev-fast-worker
# Open http://localhost:8100/ in your browser
# When done, stop data containers
make dev-downChanges to Python files are picked up instantly — no Docker rebuilds needed.
make dev-fast and make dev-fast-worker now depend on make dev-setup,
so DB migrations are always applied before either process starts.
# Install dependencies
uv sync --all-extras
# Run tests
uv run pytest tests/ -v
# Start API server (uses .env)
uv run uvicorn rag_agent.app:create_app --reload --factory
# Start ARQ worker
uv run arq rag_agent.worker.settings.WorkerSettingsGET /health— LivenessGET /ready— Readiness with dependency checksGET /live— Minimal liveness
GET /api/v1/collections— List collectionsPOST /api/v1/collections?name=...— Create collectionGET /api/v1/collections/{name}— Collection statsDELETE /api/v1/collections/{name}— Drop collection
POST /api/v1/documents/upload— Upload file (multipart)GET /api/v1/documents— List tracked documentsGET /api/v1/documents/{id}— Document detailDELETE /api/v1/documents/{id}— Delete (cascade)POST /api/v1/documents/{id}/retry— Re-queue failed ingestionGET /api/v1/documents/{id}/download— Download original
POST /api/v1/search— Vector searchPOST /api/v1/search/multi— Multi-collection searchGET /api/v1/collections/{name}/documents/{id}— Search within a document
POST /api/v1/sync— Trigger directory syncGET /api/v1/sync/logs— Sync historyGET /api/v1/connectors— Available connectorsGET /api/v1/status— SSE stream for progress events
See .env.example for all environment variables.
Key settings:
EMBEDDING_BASE_URL— OpenAI-compatible embedding endpointEMBEDDING_MODEL— Model name (e.g.,all-MiniLM-L6-v2)MILVUS_URI— Milvus connectionCHUNK_SIZE,CHUNK_OVERLAP— Text chunkingENABLE_HYBRID_SEARCH— BM25 + vector fusionENABLE_IMAGE_DESCRIPTION— LLM vision for images
The project includes a comprehensive Makefile for common tasks:
# Show available tasks
make
# ── Setup & Quality ──────────────────────────────────────────
make setup # Install Python dependencies
make test # Run test suite
make lint # Lint code (ruff)
make format # Format code (ruff format)
make typecheck # Type checking (mypy)
make clean # Clean build artifacts
# ── Container Stack (app + data in containers) ──────────────
make up # Start full stack
make down # Stop stack
make logs # Show service logs
make ps # Show running containers
# ── Dev-Fast (app on host, hot-reload) ──────────────────────
make dev-up # Start data infra only (Postgres, Valkey, Milvus)
make dev-down # Stop data infra containers
make dev-logs # Show data infra logs
make dev-setup # Create media dir + run migrations
make dev-fast # Run API with hot-reload (no container)
make dev-fast-worker # Run ARQ worker directly (no container)
make dev-migrate # Run Alembic migrations
make dev-create-tables # Create tables directly (no Alembic)from rag_agent.client import RAGAgentClient
client = RAGAgentClient(base_url="http://localhost:8100")
# Upload
result = await client.upload_document("report.pdf")
# Search
results = await client.search("quarterly earnings")- uv (https://github.com/astral-sh/uv) — Modern Python package installer and resolver
- Python 3.12+ — Runtime environment
- Docker and Docker Compose — For running data infrastructure (Postgres, Valkey, Milvus). Required by both the full container stack and the dev-fast workflow. If you only run unit tests, Docker is optional (tests use SQLite).
MIT