v0.5.0 — now on PyPI

NexRAG

plug swap scale

The infrastructure layer between your RAG components. Configure providers in YAML, swap any stage, and get a production-grade RAG pipeline with zero framework lock-in.

pip install "nexrag[all]"
quickstart.py
from pathlib import Path
from nexrag import NexRAG

pipeline = NexRAG.from_config("nexrag.yaml")

# Ingest your documents — pass file *content*, not a path
result = pipeline.ingest(Path("docs/manual.pdf").read_bytes())
print(f"Wrote {result.chunks_written} chunks")
print(f"Done in {result.latency_ms:.0f}ms")

# Ask anything
result = pipeline.query(
    "What are the termination clauses?"
)
print(result.answer)

for src in result.sources:
    print(f"  [{src.rank}] {src.source}")
Architecture

The full RAG pipeline.

Two pipelines. One shared Embedder. One shared VectorDB. Ten swappable stages, wrapped in end-to-end guardrails. One YAML file to wire it all.

// INGESTION PIPELINE Loader Sanitizer Chunker Embedder Dedup VectorDB reads inherit // QUERY PIPELINE User Query Embedder Retriever Reranker PromptBuilder LLM PipelineResult OBSERVER — emits structured PipelineEvent at every stage · ConsoleObserver | NoOpObserver | custom GUARDRAILS — ingestion · input · retrieved · output guard chains · verdict ALLOW | BLOCK | REDACT · fail_open / fail_closed
Shared instance (Embedder / VectorDB)
Swappable stage
Entry point
Guardrail checkpoint (ALLOW · BLOCK · REDACT)
Cross-pipeline connection
Design

Built on six principles.

01.
Interface-first

Every stage is a contract. All 10 pipeline stages are clean abstract interfaces. Swap anything by extending the base class.

02.
Config-driven

YAML configures the pipeline. Secrets via ${ENV_VAR} substitution. No runtime configuration in application code.

03.
Zero lock-in

Core has no dependency on LangChain, LlamaIndex, or any AI SDK. Bring your model. Swap providers without changing application code.

04.
Explicit over implicit

No hidden defaults. No magic. Every behavior is declared in YAML or documented. What you configure is exactly what runs.

05.
Production-ready

SHA-256 deduplication, idempotent ingestion, exponential backoff with jitter, typed exceptions, and structured JSON observability at every stage.

06.
Async & streaming

Set mode: async in YAML for native async pipelines. Stream token-by-token with stream_query() or astream_query() — no extra setup.

Example

Configure once. Swap anything.

Three lines of Python. One YAML file. The rest is NexRAG.

from pathlib import Path
from nexrag import NexRAG
from dotenv import load_dotenv

load_dotenv()
pipeline = NexRAG.from_config("nexrag.yaml")

# ── Ingest (loaders are converter-only: pass bytes/str, not a path) ──
pdf_bytes = Path("contracts/agreement.pdf").read_bytes()
result = pipeline.ingest(pdf_bytes, metadata={"source": "agreement.pdf"})
print(f"Ingested {result.documents_loaded} doc, {result.chunks_written} chunks")
# → Ingested 1 doc, 48 chunks in 1240.3 ms

# ── Query ────────────────────────────────────────────────────
result = pipeline.query("What are the termination clauses?")
print(result.answer)

for source in result.sources:
    print(f"  [{source.rank}] score={source.score:.3f}  {source.source}")

# ── Runtime overrides ────────────────────────────────────────
result = pipeline.query(
    "What changed in 2024?",
    top_k=10,
    score_threshold=0.75,
    metadata_filter={"year": 2024},
)
from nexrag import NexRAG

pipeline = NexRAG.from_config("nexrag.yaml")

# ── Sync streaming — tokens printed as they arrive ───────────
for token in pipeline.stream_query("Summarize the contract"):
    print(token, end="", flush=True)

# ── Async streaming — for FastAPI / async frameworks ─────────
import asyncio

async def stream_answer():
    async for token in pipeline.astream_query(
        "What are the termination clauses?",
        top_k=8,
    ):
        print(token, end="", flush=True)

asyncio.run(stream_answer())

# ── FastAPI SSE endpoint — wire it straight in ────────────────
from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get("/ask")
async def ask(q: str):
    async def gen():
        async for token in pipeline.astream_query(q):
            yield token
    return StreamingResponse(gen(), media_type="text/plain")
# nexrag.yaml — minimal config

mode: sync           # sync (default) | async — enables native async pipeline

ingestion:
  loader:
    type: pdf

  chunker:
    strategy: recursive
    chunk_size: 512
    chunk_overlap: 64

  embedder:
    provider: openai
    model: text-embedding-3-small
    api_key: ${OPENAI_API_KEY}

  vector_db:
    provider: chroma
    default_collection: documents
    collections:
      documents:
        mode: persistent
        path: ./.nexrag/chroma

query:
  embedder: inherit         # reuse ingestion embedder
  retriever:
    provider: dense
    top_k: 5
  llm:
    provider: openai
    model: gpt-4o
    api_key: ${OPENAI_API_KEY}
    temperature: 0.2

# Swap to Ollama — no API keys, fully local:
#   embedder.provider: ollama / model: nomic-embed-text
#   llm.provider: ollama  / model: llama3.2
# Drop in any custom component. Implement the interface,
# declare it in YAML. Works for all 9 pipeline stages.

# myapp/embedders.py
from nexrag.core.interfaces.embedder import BaseEmbedder

class SentenceTransformerEmbedder(BaseEmbedder):
    def __init__(self, model: str = "all-MiniLM-L6-v2") -> None:
        from sentence_transformers import SentenceTransformer
        self._model = SentenceTransformer(model)

    def embed(self, texts: list[str]) -> list[list[float]]:
        return self._model.encode(texts).tolist()

    def embed_query(self, text: str) -> list[float]:
        return self._model.encode([text])[0].tolist()

---
# nexrag.yaml — wire it in:
ingestion:
  embedder:
    provider: custom
    class:    myapp.embedders.SentenceTransformerEmbedder
    params:
      model:  all-MiniLM-L6-v2
Integrations

Supported providers.

OpenAI, Gemini, Ollama, Anthropic, HuggingFace, ChromaDB, Pinecone, BM25, Cohere, and CrossEncoder available now — plus a full chunking suite and a pluggable guardrails layer. More in v1.

Available now
CategoryProviders
EmbeddersOpenAI, Gemini, Ollama, HuggingFace
LLMsOpenAI, Gemini, Ollama, Anthropic
Vector DBsChromaDB (local, memory, server), Pinecone (serverless)
LoadersPDF, plain text, auto-detect
ChunkersRecursive, Fixed, Token, Sentence, Sentence-window, Markdown, Code, Semantic, Proposition
RetrieversDense (cosine similarity), BM25 (keyword), Hybrid (dense + BM25)
RerankersCohere, CrossEncoder (sentence-transformers)
GuardrailsPII, Access control, Prompt-injection, Groundedness, Topic, Model
Coming in v1
CategoryProviders
Vector DBsWeaviate, Qdrant
LLMsMistral
LoadersWord (.docx), HTML, Excel

Ready to build?

Read the docs, explore the source, or jump straight into a quickstart.