Metadata-Version: 2.4
Name: rager
Version: 0.1.3
Summary: Caching based RAG primitives
Keywords: rag,retrieval-augmented-generation,caching,embeddings,faiss,nlp
Author: Wannes Vantorre
Author-email: Wannes Vantorre <vantorrewannes@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: belljar>=3.0.0
Requires-Dist: blake3>=1.0.9
Requires-Dist: concresce>=0.1.1
Requires-Dist: faiss-cpu>=1.14.3
Requires-Dist: numpy>=2.4.6
Requires-Dist: semantic-chunker>=0.2.0
Requires-Dist: sentence-transformers>=5.6.0
Requires-Dist: tokenizers>=0.22.2
Requires-Dist: transformers>=5.13.1
Requires-Dist: unstructured-inference>=1.6.13
Requires-Dist: unstructured[csv,md,pdf]>=0.24.0
Requires-Dist: torch>=2.13.0 ; extra == 'cpu'
Requires-Dist: torchvision>=0.28.0 ; extra == 'cpu'
Maintainer: Wannes Vantorre
Maintainer-email: Wannes Vantorre <vantorrewannes@gmail.com>
Requires-Python: >=3.14
Project-URL: Homepage, https://github.com/VantorreWannes/rager
Project-URL: Repository, https://github.com/VantorreWannes/rager
Project-URL: Issues, https://github.com/VantorreWannes/rager/issues
Project-URL: Changelog, https://github.com/VantorreWannes/rager/releases
Provides-Extra: cpu
Description-Content-Type: text/markdown

# rager

Composable RAG primitives with caching baked in.

## Install

```
uv add rager
```

## Getting started

```
uv run pytest
uv run prek install
```

For GPU (CUDA/ROCm) torch, add the matching [PyTorch index](https://pytorch.org/get-started/locally/) to your own project and install torch from it — those builds aren't on PyPI.

## Example

Wire the primitives together yourself — there is no hidden pipeline. This chunks documents, embeds and indexes each chunk, then answers a query from the nearest chunk:

```python
chunker = SemanticChunker()
embedder = SentenceTransformerDenseEmbedder()
index = DenseIndex()
chunks = ChunkStore()
generator = TransformersGenerator()

for document in documents:
    for chunk in chunker.chunk(document):
       embedding = await embedder.embed(chunk)
       key = await index.add(embedding)
       chunks.add(key, chunk)

query = "Why do cats purr?"
(key,) = await index.similar(await embedder.embed(query), results=1)
answer = await generator.prompt(f"Answer using only the context.\n{chunks.get(key)}\n{query}")
```

`tests/application/` has full dense and hybrid recipes.

## API

Every stage is a `Protocol` with concrete implementations. `async` methods batch concurrent calls; model-backed methods cache results under `.jar/`.

### Parsers — extract text units from files

- **`Parser`** — protocol: `units(file)` returns text units, `id(file)` returns the content `Hash`.
- **`UnstructuredFileParser`** — parses any file supported by [`unstructured`](https://github.com/Unstructured-IO/unstructured).
- **`PdfFileParser`**, **`MarkdownFileParser`**, **`CsvFileParser`** — aliases of `UnstructuredFileParser` for readable call sites.

### Chunkers — split units into chunks

- **`Chunker`** — protocol: `chunk(unit) -> list[str]`.
- **`SemanticChunker`** — splits on semantic boundaries with a token budget: `SemanticChunker(model_name="gpt-3.5-turbo", chunk_size=1000, overlap=0)`.

### Embedders — turn chunks into vectors

- **`Embedder[E]`** — protocol: `async embed(chunk) -> E`.
- **`SentenceTransformerDenseEmbedder`** — dense, L2-normalized `DenseEmbedding` via [SentenceTransformers](https://www.sbert.net/) (default `all-MiniLM-L6-v2`).
- **`SpladeSparseEmbedder`** — sparse `SparseEmbedding` via a SPLADE encoder (default `prithivida/Splade_PP_en_v1`).

### Indexes — store vectors and search by similarity

- **`Index[E, K]`** — protocol: `async add(embedding) -> key`, `async remove(key)`, `async similar(embedding, results=100) -> list[key]`. Ranks by inner product (equals cosine for L2-normalized vectors). Keys are derived from embedding content, so adding the same vector twice yields one entry.
- **`DenseIndex`** — flat [FAISS](https://github.com/facebookresearch/faiss) index; `DenseIndex(dimensions=None)` infers width from the first vector unless fixed.
- **`SparseIndex`** — inner-product search over sparse weight maps.

### Fusers — merge ranked lists

- **`Fuser[V]`** — protocol: `fuse(*rankings) -> list[V]`.
- **`ReciprocalRankFuser`** — reciprocal rank fusion with smoothing constant `k` (default 60).
- **`BordaCountFuser`** — Borda count fusion.

### Scorers — rerank chunks against a query

- **`Scorer`** — protocol: `async score(query, chunk) -> float`.
- **`CrossEncoderScorer`** — cross-encoder reranker (default `cross-encoder/ms-marco-MiniLM-L6-v2`).

### Generators — produce an answer

- **`Generator`** — protocol: `async prompt(query) -> str`.
- **`TransformersGenerator`** — local [Transformers](https://huggingface.co/docs/transformers) text-generation model (default `HuggingFaceTB/SmolLM2-135M-Instruct`, `max_new_tokens=512`).

### Stores — map index keys back to data

- **`Store[V, K]`** — protocol: `add(key, value)`, `get(key) -> value | None`, `remove(key)`.
- **`ChunkStore`** — in-memory map from key to chunk text, resolving a search hit to its source.
- **`MetadataStore[M: Metadata]`** — in-memory map from key to per-chunk metadata.

### Types

- **`Hash`** — a `blake3` hasher; the content ID returned by parsers.
- **`DenseEmbedding`** — `list[float]`.
- **`SparseEmbedding`** — `dict[int, float]` mapping token id to weight.
- **`Metadata`** — protocol for metadata classes used with `MetadataStore`.
