Transforms chaotic PDFs, docs, websites, and APIs into trusted answers using embeddings, retrieval, reranking, and LLMs.
┌─────────────────────────────────────┐ │ RAGINATOR — TRI-STATE RAG MACHINE │ │ Patent Pending — Doofenshmirtz Inc │ └─────────────────────────────────────┘ "Behold! The RAGINATOR!" Point it at ANY data source and it shall RAG-ify everything in the tri-state area! — Dr. Doofenshmirtz, probably
You start with uploading documents to the ingest stage and start the pipeline.

Pipeline runs through all stages and you can see the progress in the GUI.

Once all stages are run you can chat with the RAGINATOR and get answers from your data source.

- Model Gym — optimize and benchmark the model that powers your RAG pipeline
- Raginator — build the pipeline around it
Each stage is a self-contained Python package with its own dependencies, tests, and README. The pipeline orchestrates them in order, passing data from one stage to the next.
It allows to use different implementations of each stage, e.g. you can swap out the embedding model or the vector store without touching the rest of the pipeline. Different teams can own different stages, and the pipeline can be run end-to-end or stage-by-stage.
| Stage | Path | GPU Required | Details |
|---|---|---|---|
| 0 — Ingest 📚 | raginator/ingest/ |
No | README — TextFile, PDF, Docx, Web, GitHub, S3 |
| 1 — Chunk 📑 | raginator/chunk/ |
No | README — Fixed, Recursive, Semantic, Code |
| 2 — Embed 🔢 | raginator/embed/ |
No | README — Hashing, Mistral, OpenAI, HuggingFace, Ollama |
| 3 — Store |
raginator/store/ |
Optional | README — InMemory (+native C++/CUDA), Chroma, pgvector, Pinecone |
| 4 — Retrieve 🐕 | raginator/retrieve/ |
No | README — Dense, Sparse (BM25), Hybrid |
| 5 — Rerank 🔀 | raginator/rerank/ |
No | README — Identity, Cross-Encoder, Mistral |
| 6 — Generate 🧠 | raginator/generate/ |
No | README — Template, Mistral, OpenAI, Ollama |
| 7 — Evaluate 📋 | raginator/evaluate/ |
No | README — Keyword overlap, Retrieval metrics, Generation scores, Cost, Report |
| 8 — Observe 📊 | raginator/observe/ |
No | README — Logging, Prometheus, OpenTelemetry, Structured JSON |
| Core 🧩 | raginator/core/ |
No | README — shared interfaces, types, settings |
| Pipeline 🎛️ | raginator/pipeline/ |
No | README — orchestrator, PipelineConfig |
Open Interactive CLI
./go
# If you want clean install: rm -rf .venv
./go install_tools # create .venv, upgrade pip
# install all stages dependencies + pytest/ruff/mypy)
./go install
# or install a single stage dependency (e.g. ingest) for development:
./go install ingest Start React Frontend
./go dev # Start UI-
GUI start at: http://localhost:5173/
Start Python Backend + RAG Pipeline
In a new terminal start server with the RAG pipeline:
./go api # Start backend (RAG + Bridge)- Backend start at: http://127.0.0.1:8001/
- API Documentation http://127.0.0.1:8001/docs
The pipeline runs end-to-end with pure-Python/numpy defaults (no GPU, no model downloads).
./go build_native # CMake build raginator_native (CPU by default)
./go build_native --cuda. # CMake build raginator_native (CPU by default)./go build_native builds the optional C++/CUDA extension
used by the store stage; if it isn't built, InMemoryVectorStore
transparently falls back to a numpy implementation of the same similarity
scoring.
./go observe # docker/podman compose up Prometheus+Grafana, open the dashboardBrings up Prometheus and Grafana
docker compose, falling back topodman composeifdockerisn't installed,- waits for Grafana's health check, then opens the raginator-3000 dashboard in the browser.
Grafana auto-provisions the Prometheus datasource and loads raginator/observe/dashboards/raginator.json
- no manual setup. It's a local-only stack
- anonymous admin auth, so the dashboard opens with no login prompt
./go metrics_server Run ./go metrics_server alongside it in another shell so
the panels have live data to show instead of "No data".
./go test [stage] # pytest, across everything or one stage
./go lint # ruff check
./go typecheck # mypy, run per stage (see note below)
./go check # lint + typecheck + testNote:
./go typecheckruns mypy once per stage rather than once for the whole tree. Every stage's source dir is named plainsrc(that's the flattening above), and mypy infers a module's dotted name purely from nested__init__.pydirectories on disk — checking them all in one mypy invocation hits "Duplicate module named src". Per-stage invocation avoids that; it's also what made cross-package types resolve correctly (mypy now picks upraginator.corefrom the actual installed environment instead of trying to triangulate it from a single package's isolated search path).
./go clean # remove .venv, native/build, cachesEquivalently, the same selection is available as plain pip extras:
pip install -e ".[all]" # every stage + the orchestrator
pip install -e ".[chunk]" # just Stage 1's deps (chunk has none beyond core)
pip install -e ".[dev]" # all stages + pytest, ruff, mypyEach stage's tests also run independently, e.g. pytest raginator/chunk/tests.
Backend cant be started
Error while attempting to bind on address ('127.0.0.1', 8001): address already in use
Kill orphan Python:
# find pid using port 8001
lsof -i :8001
# kill process
kill -9 1234
RAG-Factory/
├── raginator/ # the raginator package, organized one folder per stage
│ ├── core/ # shared abstract interfaces
│ │ └── src/base.py # __init__.py + base.py live directly in src/
│ ├── ingest/ # Stage 0, The Suck-Inator
│ ├── chunk/ # Stage 1, The Chunk-Inator
│ ├── embed/ # Stage 2, The Embed-Inator
│ ├── store/ # Stage 3, The Store-Inator
│ ├── retrieve/ # Stage 4, The Find-Inator
│ ├── rerank/ # Stage 5, The Better-Find-Inator
│ ├── generate/ # Stage 6, The Answer-Inator
│ ├── evaluate/ # Stage 7, The Evaluate-Inator
│ ├── observe/ # Stage 8, The Observe-Inator
│ └── pipeline/ # orchestrator wiring all 9 stages together
├── native/ # optional C++/CUDA acceleration (own CMake build)
│ ├── CMakeLists.txt # USE_CUDA=OFF by default (builds CPU-only)
│ ├── include/similarity.hpp
│ ├── src/similarity.cpp # CPU cosine similarity
│ ├── src/similarity_cuda.cu # CUDA kernel (built when -DUSE_CUDA=ON)
│ └── bindings/bindings.cpp # pybind11 module: raginator_native
├── docker-compose.yml # Prometheus + Grafana, brought up by `./go observe`
├── docker/
│ ├── prometheus.yml # scrapes host.docker.internal:8000 (the metrics server)
│ └── grafana/provisioning/ # auto-loads raginator/observe/dashboards/raginator.json
├── go # CLI entrypoint — ./go install | dev | test | ...
├── scripts/
│ ├── demo.py # toy pipeline run by `./go demo`
│ └── metrics_server.py # toy pipeline on a loop, exposing :8000/metrics
├── img/
├── pyproject.toml # the one and only project file: deps, extras, ruff/mypy/pytest
├── LICENSE
└── README.md
It's a single distribution (raginator) with one pip extra per stage, just
gating that stage's third-party deps (e.g. embed/store need numpy) — all
the code always ships together, organized by folder for readability and so a
team can own a stage's raginator/<stage>/ folder day to day.
./go optimize_images img/screen-shots # convert jpg/png to jpg
./go optimize_images img/screen-shots -q 90 -r --delete-originalsThin wrapper around scripts/optimize-images.sh (ImageMagick, so -q is
JPEG quality). No default folder -- convert the whole img/ tree recursively
and it'll happily produce a duplicate .jpg next to every existing .jpeg
in img/infographics/, since same-content-different-extension isn't
"already converted" as far as the script can tell. Point it at a specific
folder instead.
© 2026 Hitesh Kumar Sahu · Licensed under Apache 2.0





