Story

Why NexRAG exists.

RAG is not complicated. The pipeline is: load, chunk, embed, store, retrieve, generate. Six steps. What makes it hard is everything the frameworks add on top.

01 — The problem

Frameworks that do too much.

Every serious RAG implementation ends up with the same shape. You load documents. You chunk them. You embed them. You store them in a vector database. When a query arrives, you embed it, retrieve the top chunks, build a prompt, and call the LLM. That is the entire pipeline.

The problem is not the pipeline. The problem is what the popular frameworks bring with them: abstractions on top of abstractions, dependency graphs that pull in half of PyPI, and opinions baked so deep into the core that swapping a single provider means migrating your entire codebase.

You wanted a RAG pipeline. You got a framework lock-in problem.

"You bring the model. NexRAG handles the plumbing."

02 — The idea

Own the shape. Not the components.

NexRAG starts from a single constraint: the core must have zero dependency on any AI SDK or framework. Not LangChain. Not LlamaIndex. Not OpenAI's SDK. The core is interfaces all the way down.

Each pipeline stage — loader, sanitizer, chunker, embedder, vector DB, retriever, reranker (optional), prompt builder, LLM, observer — is a clean abstract base class. NexRAG ships default implementations for every one of them. You can swap any by implementing the interface and declaring a dotted class path in YAML.

The YAML file is not configuration for NexRAG. It is the pipeline. Every behavior that varies between deployments — providers, models, chunk sizes, retrieval thresholds, secrets — lives there. None of it lives in your application code.

03 — Principles

The six rules everything is built on.

Interface-first

Every stage is a contract. Implementation is secondary. If you implement the interface, NexRAG will wire it in.

Config-driven

YAML configures the pipeline. Code defines the logic. Secrets never in config files — only environment variables.

Zero lock-in

No framework dependency at core. Your application depends on NexRAG. NexRAG depends on nothing opinionated.

Explicit over implicit

No hidden defaults. Every behavior is declared or documented. No magic — just interfaces, adapters, and YAML.

Extensible by design

New components plug in without touching core. The extension point is YAML, not a pull request.

Async & streaming

Native async/await pipeline with parallel batch embedding. Token-by-token streaming via stream_query() and astream_query() — no extra setup.

04 — What NexRAG is

The infrastructure layer. Nothing more.

NexRAG is not a chatbot framework. It is not a research tool. It is not trying to be LangChain. It is the layer that sits between your documents and your LLM and handles everything in between — reliably, predictably, and without opinion about which model you use.

NexRAG owns the pipeline shape. You own the components. You point it at your data. You declare your providers in YAML. You call pipeline.ingest() and pipeline.query(). Everything else — deduplication, fingerprinting, batching, retries, observability — is handled.

When your requirements change, you change the YAML. When you outgrow a provider, you swap it. When you need a custom stage, you implement the interface and drop it in. The application code does not change.

05 — What's coming

v0.5.0 makes the query layer stateful. v1 is the platform.

v0.5.0 adds a pluggable query-result cache, multi-turn sessions with window / token-budget context strategies, and a client-side rate limiter — plus truly batched embedding for ingest_batch(). That builds on v0.4.0's Gemini and Pinecone providers, the production chunking suite (token, sentence-window, markdown, code, semantic, proposition) with independently-resolved nested component configs, the pluggable guardrails security layer, and full OpenTelemetry observability — metrics, traces, and logs with Prometheus pull, OTLP push, and LLM-as-judge evaluators — on top of the hybrid retrieval, reranking, and async streaming shipped earlier. What comes next is more remote vector stores and more loaders.

shipped
Full ingestion + query pipeline. Loader → Sanitizer → Chunker → Embedder → VectorDB → Retriever → PromptBuilder → LLM → Result.
shipped
OpenAI, Gemini, Ollama, Anthropic, HuggingFace, ChromaDB, Pinecone. mypy strict, ruff clean.
shipped
Async pipeline + streaming. mode: async enables native async/await with parallel batch embedding. stream_query() and astream_query() stream tokens live — plugs directly into FastAPI SSE.
shipped
Reranking stage. Optional post-retrieval reranker between the retriever and LLM. CohereReranker and CrossEncoderReranker out of the box. Custom rerankers via BaseReranker.
shipped
RunMetrics & observability. Per-run latency breakdown by stage, token counts, and chunks written/retrieved. Access via result.metrics.
shipped
Hybrid retrieval. Dense + BM25 (sparse) fusion with configurable alpha. Retrieve large candidate sets with BM25; rerank precisely with dense. Requires nexrag[bm25].
shipped
Production chunking suite. Token, sentence, sentence-window, markdown, code (tree-sitter), semantic, and proposition strategies — plus nested chunker.embedder / chunker.llm sub-configs resolved independently of the pipeline models (cheap model for chunking, strong model for generation).
shipped
Guardrails. A pluggable security layer — ingestion / input / retrieved / output guard chains with ALLOW · BLOCK · REDACT verdicts and fail-open/fail-closed policies. PII, access control, prompt-injection, groundedness, topic, and model guards. See SECURITY.md.
shipped
Multi-turn sessions. Conversation memory via query_session() with a caller-supplied session_id. Pluggable BaseSessionStore (in-memory default, TTL, persist: false privacy mode) and window / token-budget context strategies. History is injected into the prompt; retrieval always uses the current query.
shipped
Query-result cache. Pluggable BaseQueryCache with an exact-match in-memory default (LRU + TTL) and per-collection invalidation after ingest. Configure under query.cache.
shipped
Client-side rate limiting. A token-bucket throttle applied before every query entry point, raising LLMRateLimitError(retry_after_seconds=...). Configure under query.rate_limit.
v1
More remote vector databases. Weaviate, Qdrant — for teams running at scale. Pinecone serverless and ChromaDB server mode are already available.
v1
More loaders. Word (.docx), HTML, Excel — so you can point NexRAG at any document source.
shipped
OpenTelemetry observability. Full metrics + traces + logs via OTel. Prometheus pull endpoint (/metrics) and OTLP push to any collector. LLM-as-judge evaluators (faithfulness, relevance, completeness, coherence, context diversity) with per-metric model selection. Configure everything under observability: in YAML. Install nexrag[observability].