Skip to main content

Domain-structured RAG pipeline template

Project description

right-rag

PyPI CI

right-rag is a domain-structured RAG template for corpora where plain text chunking loses too much context: laws, policies, contracts, manuals, academic papers, handbooks, and other hierarchical documents.

Instead of starting with "split text every N tokens", right-rag starts with the document's real structure: sections, clauses, rules, definitions, procedures, tables, exceptions, and citations. You customize that structure through small plugins under spec/.

Why right-rag

Most RAG failures are not embedding failures. They are structure failures:

  • the answer is split away from its exception
  • the citation points to a broad page instead of the exact clause
  • metadata is stored but not connected to retrieval
  • a vector index becomes the design instead of one possible implementation

right-rag keeps the core pipeline generic and lets each domain define what its evidence means.

Architecture

flowchart LR
    A[Source documents] --> B[Document loaders]
    B --> C[Unit parsers]
    C --> D[Semantic units]
    D --> E[Chunk parsers]
    E --> F[Retrieval-ready chunks]
    D --> G[Unit savers]
    F --> H[Chunk savers]
    G --> I[Unit artifacts]
    H --> J[Chunk artifacts]
    I --> K[Retrievers]
    J --> K
    K --> L[Answer generator]
    L --> M[Answer with evidence]
    M --> N[Evaluators and reports]

Index and query are separate:

flowchart TD
    subgraph Index
      A[Load] --> B[Parse units] --> C[Parse chunks] --> D[Save artifacts]
    end

    subgraph Query
      E[User query] --> F[Retrievers use artifacts] --> G[Answer generator]
    end

    subgraph Evaluate
      H[Eval cases] --> E
      G --> I[Evaluator] --> J[Report]
    end

Install

Requirements:

  • Python 3.13+

Install from PyPI:

pip install right-rag

Or run without a permanent install:

uvx --from right-rag right-rag --help

Quick Start

Create a new RAG project:

right-rag init my-rag
cd my-rag

Add source documents:

data/documents/

Run the default smoke pipeline:

right-rag index
right-rag query "your question"
right-rag evaluate

Generated local artifacts:

  • output/units/
  • output/chunks/
  • .right-rag-state.json
  • output/evaluation/

The default unit and chunk parsers are smoke-test implementations only. For production, write domain parsers under spec/.

Project Template

right-rag init creates:

my-rag/
  right_rag.toml
  data/documents/
  eval/cases.example.json
  output/
  spec/
    document_loaders/
    unit_parsers/
    chunk_parsers/
    unit_savers/
    chunk_savers/
    retrievers/
    answer_generators/
    evaluators/
    reporters/

You adapt the project by editing spec/, not by forking the framework.

Extension Points

Folder Purpose
spec/document_loaders/ Load source documents from files, APIs, stores, or custom extractors.
spec/unit_parsers/ Convert documents into a faithful ParsedUnit tree.
spec/chunk_parsers/ Convert semantic Unit objects into retrieval-ready Chunk records.
spec/unit_savers/ Persist units and return artifacts that can be used later.
spec/chunk_savers/ Persist chunks and return artifacts that can be used later.
spec/retrievers/ Read artifacts and decide how to retrieve evidence.
spec/answer_generators/ Generate answers from retrieved evidence.
spec/evaluators/ Score query outputs for the domain.
spec/reporters/ Write evaluation reports.

Artifacts are intentionally storage-agnostic. A saver can write JSON, SQL, VectorDB, a graph, an external service, or something domain-specific. The retriever should use artifact capabilities instead of depending on a storage implementation.

Domain Modeling

Start by looking at the source documents, not by picking a retrieval method. Choose units that match the author's structure:

  • laws: act -> chapter -> section -> clause -> subclause
  • contracts: agreement -> article -> clause -> schedule item
  • policies: policy -> section -> rule -> exception
  • manuals: manual -> chapter -> procedure -> step
  • academic papers: paper -> section -> subsection -> paragraph/table/figure note

Good unit parsers:

  • preserve hierarchy with ParsedUnit.subunits
  • set source spans when possible
  • keep fulltext faithful to the source
  • store provenance in attributes or metadata
  • reject unsupported formats visibly
  • avoid catch-all parsers

Good chunk parsers:

  • chunk inside a single unit
  • keep rules with their exceptions and limitations
  • carry citation/filter attributes
  • prefer fewer useful chunks over many tiny fragments

Minimal Unit Parser

from collections.abc import Iterable

from right_rag.interfaces import UnitParser
from right_rag.model import Document, ParsedUnit


class SectionParser(UnitParser):
    @property
    def parser_name(self) -> str:
        return "sections"

    def parser_can_handle_document(self, document: Document) -> bool:
        return "Section " in document.text

    def parse_document(self, document: Document) -> Iterable[ParsedUnit]:
        yield ParsedUnit(
            topic="Section 1",
            fulltext="Exact source text for section 1",
            source_start=0,
            source_end=31,
            attributes={
                "unit_type": "section",
                "role": "rule",
                "citation": "Section 1",
            },
        )

Minimal Chunk Parser

from right_rag.interfaces import ChunkParser
from right_rag.model import Chunk, Unit
from right_rag.pipeline_state import stable_hash


class SemanticChunkParser(ChunkParser):
    @property
    def parser_name(self) -> str:
        return "semantic"

    def parse_unit(self, unit: Unit):
        text = f"{unit.temporal_topic}\n\n{unit.fulltext}"
        yield Chunk(
            id=stable_hash({"unit_id": unit.id, "parser": self.parser_name}),
            document_id=unit.document_id,
            unit_id=unit.id,
            topic=unit.topic,
            fulltext=text,
            attributes={
                **unit.attributes,
                "parser_name": self.parser_name,
                "source_unit": unit.temporal_topic,
            },
        )

Evaluation

Evaluation is built into the pipeline:

right-rag evaluate eval/cases.example.json --output output/evaluation/report.md

The default evaluator is intentionally simple. It is useful for smoke tests and regression checks. Real projects should add domain-specific evaluators under spec/evaluators/.

Development

Clone and test the framework:

git clone https://github.com/sunmodza/right-rag.git
cd right-rag
uv sync
python -m compileall src/right_rag
python -m unittest discover -s tests
uv build

Run plugin discovery:

uv run python -c "from right_rag.registry import build_registry; r=build_registry(); print(r.document_loaders, r.unit_parsers, r.chunk_parsers, r.unit_savers, r.chunk_savers)"

Release

CI runs tests and builds the package on pushes to main and pull requests.

Publishing runs on version tags:

git tag v0.1.0
git push origin v0.1.0

PyPI Trusted Publishing is configured for:

  • project: right-rag
  • workflow: publish.yml
  • environment: pypi

Design Rules

  • Put domain logic in spec/.
  • Keep src/right_rag/pipeline.py focused on orchestration.
  • Return ParsedUnit from unit parsers.
  • Let the library create Unit.
  • Treat metadata as stored context, not control flow.
  • Do not couple the framework to vector search, keyword search, SQL, or graph retrieval.
  • Use stdlib before adding dependencies.

Project details


Download files

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

Source Distribution

right_rag-0.1.1.tar.gz (187.1 kB view details)

Uploaded Source

Built Distribution

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

right_rag-0.1.1-py3-none-any.whl (32.4 kB view details)

Uploaded Python 3

File details

Details for the file right_rag-0.1.1.tar.gz.

File metadata

  • Download URL: right_rag-0.1.1.tar.gz
  • Upload date:
  • Size: 187.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for right_rag-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c3f1f8ed2252ecdc2da46629e066768482408bbb5c42ff6875793c188f5b41df
MD5 3b688d6c0eff19a1c003002a7e50a915
BLAKE2b-256 9881d7fa0b810904f7dfbc14fb42216af5c8ca7041d42cbe79926c6b817e006c

See more details on using hashes here.

Provenance

The following attestation bundles were made for right_rag-0.1.1.tar.gz:

Publisher: publish.yml on sunmodza/right-rag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file right_rag-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: right_rag-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 32.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for right_rag-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 710ccd031a5fd2c7844c46c307e563297cd7fd971b73ab41f8dc6ddbbd35070e
MD5 7590f83bd1cb39c6684126da9a9012fd
BLAKE2b-256 141c9eb28f3ae235dc52d4fd8eda065b81150c19fb6bf6cc81a9d0f4e90738b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for right_rag-0.1.1-py3-none-any.whl:

Publisher: publish.yml on sunmodza/right-rag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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