Skip to content

Repository files navigation

RAG FACTORY 🦆

Transforms chaotic PDFs, docs, websites, and APIs into trusted answers using embeddings, retrieval, reranking, and LLMs.

Powered by the Raginator-3000

       ┌─────────────────────────────────────┐
       │  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

Raginator-3000

Python CUDA TensorFlow C++17 License

How it works

1. Upload Documents

You start with uploading documents to the ingest stage and start the pipeline. start-scren

2. Run Pipeline

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

3. Chat with paginator

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

Also supported in Dark mode chat

See also

  • Model Gym — optimize and benchmark the model that powers your RAG pipeline
  • Raginator — build the pipeline around it

RAGINATOR PIPELINE

Stages

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

📟 ./go CLI

drawing

Open Interactive CLI

./go

⚙️ Install dependencies

# 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       

▶️ Run GUI Pipeline

Start React Frontend

./go dev                  # Start UI

Start Python Backend + RAG Pipeline

In a new terminal start server with the RAG pipeline:

./go api                  # Start backend (RAG + Bridge)

API

The pipeline runs end-to-end with pure-Python/numpy defaults (no GPU, no model downloads).

🛠️ Build CPP

./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.

📊 Observability

Prometheus+Grafana

  ./go observe    # docker/podman compose up Prometheus+Grafana, open the dashboard

Brings up Prometheus and Grafana

  • docker compose, falling back to podman compose if docker isn'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".

Dashboard

🔎 Test

./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 + test

Note: ./go typecheck runs mypy once per stage rather than once for the whole tree. Every stage's source dir is named plain src (that's the flattening above), and mypy infers a module's dotted name purely from nested __init__.py directories 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 up raginator.core from the actual installed environment instead of trying to triangulate it from a single package's isolated search path).

🧹 Clean up

./go clean                # remove .venv, native/build, caches

Equivalently, 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, mypy

Each stage's tests also run independently, e.g. pytest raginator/chunk/tests.


Troubleshoot

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

📂 Project Layout

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.


🖼 Assets

./go optimize_images img/screen-shots           # convert jpg/png to jpg
./go optimize_images img/screen-shots -q 90 -r --delete-originals

Thin 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

About

RAG Factory 🦆 (powered by the Raginator-3000) transforms chaotic PDFs, docs, websites, and APIs into trusted answers using embeddings, retrieval, reranking, and LLMs.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages