Metadata-Version: 2.4
Name: rager
Version: 0.3.2
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>=0.2.0
Requires-Dist: blake3>=1.0.9
Requires-Dist: concresce>=0.1.2
Requires-Dist: dill>=0.4.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 under its own key, then answers a query from the nearest chunk:

```python
chunker = SemanticChunker()
embedder = SentenceTransformerDenseEmbedder()
index = FaissIndex(384, MemoryStore())
chunks = MemoryStore()
generator = TransformersGenerator()

key = 0
for document in documents:
    for chunk in chunker.chunks(document):
        await index.set(key, await embedder.embed(chunk))
        chunks[key] = chunk
        key += 1

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

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

## API

Every stage is a `Protocol` with concrete implementations. Each module also ships an abstract `Base*` helper that derives the protocol from a few core operations, so you can drop in your own implementation. `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`.
- **`BaseParser`** — derives a cached `units()` from `_jar`, `_parse`, and `id`.
- **`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: `chunks(unit) -> list[str]`.
- **`BaseChunker`** — derives a cached `chunks()` from `_jar` and `_split`.
- **`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`.
- **`BaseEmbedder`** — derives a cached `embed()` from `_jar` and `_encode`.
- **`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[K, E]`** — protocol: a `Store[K, E]` of embeddings plus `async similar(embedding, embedding_results=100) -> list[key]`. Ranks by inner product (equals cosine for L2-normalized vectors).
- **`FaissIndex(dimensions, key_map)`** — flat [FAISS](https://github.com/facebookresearch/faiss) index; seals embeddings on disk under `.jar/` and records each key's FAISS id in the injected `key_map` store.
- **`SparseIndex(embedding_map, token_map)`** — inner-product search over sparse weight maps through an inverted token index; the injected stores decide whether embeddings live in memory or on disk, and search only loads the posting lists of the query's tokens.

### Fusers — merge ranked lists

- **`Fuser[V]`** — protocol: `fuse(*rankings) -> list[V]`.
- **`BaseFuser`** — derives `fuse()` from `_weight(rank, size)`.
- **`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`.
- **`BaseScorer`** — derives a cached `score()` from `_jar` and `_predict`.
- **`CrossEncoderScorer`** — cross-encoder reranker (default `cross-encoder/ms-marco-MiniLM-L6-v2`).

### Generators — produce an answer

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

### Stores — map keys to data

- **`Store[K, V]`** — protocol: mapping-style access (`store[key]`, `del store[key]`, `in`, `len()`, iteration) plus `set(key, value)`, `get(key) -> value | None`, `remove(key)`, `clear()`, and `keys()`.
- **`BaseStore`** — derives the full protocol from `keys`, `__setitem__`, `__getitem__`, and `__delitem__`.
- **`MemoryStore[K, V]`** — in-memory map from key to value (chunk text, embeddings, metadata, ...).
- **`FileStore[K, V]`** — like `MemoryStore`, but seals values on disk under `.jar/`, keeping only keys and digests in memory.

### Types

- **`Hash`** — a `blake3` hasher; the content ID returned by parsers.
- **`DenseEmbedding`** — `list[float]`.
- **`SparseEmbedding`** — `dict[int, float]` mapping token id to weight.
