Primitives you can build on.
The benchmark is the reference workload. The library is the useful part: small components with direct names and explicit boundaries.
Retrievers.
All retrievers expose the same search shape and return list[SearchResult]. Choose the implementation that matches your memory and latency budget.
from trivium.retrieval.bm25 import Bm25
from trivium.retrieval.faiss import Faiss
bm25 = Bm25(k1=0.9, b=0.4)
bm25.add_documents(documents)
bm25_hits = bm25.search(query_texts, k=100)
flat = Faiss.Flat()
flat.add_documents(documents, vectors=document_vectors)
vector_hits = flat.search(query_vectors, k=100) Fusion and reranking.
from trivium.fusion.rrf import Rrf
from trivium.reranking.registry import get_reranker
fused = Rrf(k=60).fuse([bm25_hits, vector_hits], top_k=50)
reranker = get_reranker("bge-large")
final_hits = reranker.rerank(query_text, candidates, top_k=10) Registries are the extension point for new embedders, rerankers, fusion strategies, and pipeline modes. Add a concrete implementation to the relevant contract; keep the public surface direct.
Command-line entry points.
| Command | Purpose |
|---|---|
trivium-prepare | Build the corpus, query, qrels, and embedding caches. |
trivium-benchmark | Run registered pipeline modes across one or more scales. |
trivium-summarise | Print a concise summary from a benchmark CSV. |
trivium-gigatoken-bench | Measure tokenizer throughput for a local corpus stream. |