Skip to main content

Raglan

PyPI CI Coverage License Python

A lightweight, highly configurable RAG retrieval engine. Framework-free, protocol-driven.

Why Raglan?

Standard RAG has one step: vector search → top-K results. Real-world retrieval needs more:

Problem Standard RAG Raglan
Single query misses aspects "return policy" finds policy text, misses refund flow Auto-generates 3 query variants, searches in parallel
Dense-only retrieval Poor short-keyword / jargon matching BM25 sparse + vector dense, RRF hybrid fusion
Small chunks lack context "refund takes 7 days" without surrounding doc Child-chunk match → expanded to full parent context
Vector similarity != semantic match "how to return" vs "I don't want this" look close Cross-Encoder pair-wise reranking filters false positives
One failure kills the pipeline Embedding service timeout → empty results Each stage degrades independently, rest continues

Six-Stage Pipeline

User query
  │
  ▼
┌─────────────────────────────────┐
│ Stage 1: QueryExpander           │  ← LLM generates entity extraction + 3 variants
└──────────────┬──────────────────┘
               │ original + variants = parallel search
               ▼
┌─────────────────────────────────┐
│ Stage 2: Retrievers (parallel)   │
│  · Dense: pgvector / Qdrant / ChromaDB / ...
│  · Sparse: BM25 full-text        │
└──────────────┬──────────────────┘
               │ multi-source results
               ▼
┌─────────────────────────────────┐
│ Stage 3: Fusion                  │  ← RRF / Weighted / RoundRobin
└──────────────┬──────────────────┘
               │ fused candidates
               ▼
┌─────────────────────────────────┐
│ Stage 4: Reranker (optional)     │  ← Cross-Encoder / Cohere Rerank
│ Filters scores below threshold   │
└──────────────┬──────────────────┘
               │ top-N candidates
               ▼
┌─────────────────────────────────┐
│ Stage 5: ContextBuilder          │  ← Parent expansion / window / passthrough
│ Greedy fill up to max_tokens     │
└──────────────┬──────────────────┘
               │
               ▼
         Final Top-N results

Installation

pip install raglan-retrieval

With optional providers:

pip install raglan-retrieval[openai]        # OpenAI embedder + expander
pip install raglan-retrieval[pgvector]      # Postgres + pgvector retriever
pip install raglan-retrieval[huggingface]   # HF embedder + Cross-Encoder reranker
pip install raglan-retrieval[qdrant]        # Qdrant retriever
pip install raglan-retrieval[chromadb]      # ChromaDB retriever
pip install raglan-retrieval[cohere]        # Cohere reranker
pip install raglan-retrieval[dashscope]     # Alibaba DashScope embedder
pip install raglan-retrieval[litellm]       # LiteLLM multi-provider expander
pip install raglan-retrieval[all]           # Everything

5-Minute Quickstart

from raglan import Raglan
from raglan.retrievers import BM25Retriever
import asyncio


async def main():
    # Step 1: Set up a retriever with your data
    bm25 = BM25Retriever()

    async def chunks():
        yield [
            ("doc1", "Return policy: items can be returned within 30 days.", None),
            ("doc2", "Refund process: refunds are issued to the original payment method.", None),
            ("doc3", "Shipping: orders ship within 2 business days.", None),
        ]

    await bm25.index(chunks())

    # Step 2: Build the pipeline (all stages optional beyond retrievers)
    rag = Raglan.builder().with_retrievers([bm25]).build()

    # Step 3: Search
    results, trace = await rag.search("how to return my order")

    for r in results:
        print(f"[{r.score:.3f}] {r.content}")

    print(f"Pipeline took {trace.total_ms:.1f}ms")


asyncio.run(main())

Adding vector search and reranking

from raglan.context_builders import ParentExpander
from raglan.embedders import OpenAIEmbedder
from raglan.expanders import OpenAIExpander
from raglan.rerankers import CrossEncoderReranker
from raglan.retrievers import ConfigurablePgvectorRetriever

rag = (
    Raglan.builder()
    .with_expander(OpenAIExpander(model="gpt-4o-mini"))
    .with_embedder(OpenAIEmbedder(model="text-embedding-3-small"))
    .with_retrievers(
        [
            ConfigurablePgvectorRetriever(
                connection_string="postgresql://...",
                table="kb.chunks",
                embedding_column="embedding",
                parent_id_column="parent_id",
            ),
            BM25Retriever(),
        ]
    )
    .with_reranker(
        CrossEncoderReranker(
            model_name="ms-marco-TinyBERT-L2-v2",
            min_score=0.5,
        )
    )
    .with_context_builder(
        ParentExpander(
            loader=my_parent_loader,
            max_tokens=6000,
        )
    )
    .with_fallback_mode("degrade")
    .build()
)

results, trace = await rag.search("damaged order return policy")

Design Philosophy

  1. Framework-Free — No dependency on LangChain, LlamaIndex, or any specific vector database or LLM provider. Protocols define the interfaces; you provide the implementations.

  2. Graceful Degradation — Every stage is independent. Query expansion fails? Use the original query. Cross-Encoder not installed? Skip reranking. BM25 unavailable? Pure vector search still works.

  3. Fully Configurable — Every stage's parameters, weights, models, and thresholds are configurable via the Builder or from_dict().

  4. Production-Ready — Extracted from production systems processing thousands of support emails daily. Handles extreme text, multilingual, and high-concurrency scenarios.

Comparison with Existing RAG Frameworks

Tool Positioning vs Raglan
LangChain RAG Full-stack LLM framework's RAG module LC binds to LangChain ecosystem; Raglan is zero-dependency, direct use
LlamaIndex Data→LLM full pipeline LI has many concepts (Node, Index, QueryEngine); Raglan has one: Search
RAGatouille ColBERT-specific RAG RAGatouille focuses on ColBERT; Raglan is general retrieval + reranking
Cohere Rerank Commercial API reranking Cohere charges, sends data to cloud; Raglan runs locally
rerankers (answer.ai) Unified reranking API rerankers only does reranking; Raglan covers retrieval→fusion→reranking

Project Structure

raglan/
├── README.md
├── docs/
│   ├── architecture.md      # Architecture design
│   ├── configuration.md     # Full configuration reference
│   ├── pipeline.md          # Six-stage deep dive
│   └── examples.md          # Multi-scenario examples
├── raglan/
│   ├── __init__.py
│   ├── raglan.py            # Raglan facade + Builder
│   ├── pipeline.py          # Pipeline engine + stage dispatch
│   ├── protocols.py         # User-implementable abstract interfaces
│   ├── types.py             # ScoredChunk, SearchResult, Filter, etc.
│   ├── exceptions.py        # Exception hierarchy
│   ├── observability.py     # Metrics collector
│   ├── expanders/           # Query expansion (OpenAI, LiteLLM, Identity)
│   ├── embedders/           # Embedding (OpenAI, HuggingFace, DashScope)
│   ├── retrievers/          # Search backends (BM25, pgvector, Qdrant, ChromaDB)
│   ├── fusion/              # Result fusion (RRF, Weighted, RoundRobin)
│   ├── rerankers/           # Reranking (CrossEncoder, Cohere)
│   ├── context_builders/    # Context assembly (Parent, Window, Passthrough)
│   ├── middleware/           # Timeout, Retry, CircuitBreaker, Logging
│   └── resilience/          # RateLimiter, RetryBudget, HealthChecker
└── tests/

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

raglan_retrieval-0.1.0.tar.gz (719.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

raglan_retrieval-0.1.0-py3-none-any.whl (69.8 kB view details)

Uploaded Python 3

File details

Details for the file raglan_retrieval-0.1.0.tar.gz.

File metadata

  • Download URL: raglan_retrieval-0.1.0.tar.gz
  • Upload date:
  • Size: 719.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for raglan_retrieval-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3da399ce0ff8731f7eb410b05b978ecc06a3bd086b8e6464984c6e6058792309
MD5 66c2ff1a5f914fe12ee6dbf6a0802abe
BLAKE2b-256 ba407bb2770f267c1796b7c24603032f8136b80c83946288e99c9a3915a5a051

See more details on using hashes here.

File details

Details for the file raglan_retrieval-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for raglan_retrieval-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 23dca74fa2c16cbe8a16f6eb686e900fd35c0a71b7a4d752b43da1746e143415
MD5 7fa2220dabb3db094e98a95d93e48816
BLAKE2b-256 b653019b4d9d79d9ed89f5811dfdf895d8f3c614a99231e0b9ca7ceb592a243d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page