Skip to main content

Build semantic search, multi-provider question answering, and REST APIs over your documents in a few lines of Python.

Project description

raglite-toolkit

Build semantic search, multi-provider question answering, and REST APIs over your documents in a few lines of Python.

raglite-toolkit is a Python port of the raglite-toolkit TypeScript package with full feature parity.


Features

  • ๐Ÿ“„ PDF, TXT, JSON, Markdown, DOCX loaders out of the box
  • ๐Ÿค– Multi-provider LLMs โ€” OpenAI, Anthropic (Claude), Google (Gemini), Mistral, Cohere, Groq, xAI, Ollama
  • ๐Ÿ”ข Multi-provider embeddings โ€” OpenAI, Google, Mistral, Cohere, Voyage, Ollama, or a local offline sentence-transformer (no API key needed)
  • ๐Ÿ“ Cosine similarity scoring with L2-normalized vectors
  • โ™ป๏ธ Content-hash cache โ€” reindexes only when the file actually changes
  • ๐Ÿ—‚ Per-document namespacing โ€” indexes are isolated, two documents never collide
  • ๐ŸŒ REST API via FastAPI with optional bearer-token auth
  • โšก Streaming answers
  • ๐Ÿ Python-native โ€” Pydantic models, type-annotated, fully testable

Install

pip install raglite-toolkit

For local offline embeddings (no API key required):

pip install raglite-toolkit sentence-transformers

sentence-transformers is included by default. The all-MiniLM-L6-v2 model (~90 MB) is downloaded automatically on first use.


Quick Start

from raglite import Document

doc = Document("./policy.pdf", {
    "embeddings": {"provider": "openai", "apiKey": "sk-..."},
    "llm":        {"provider": "anthropic", "apiKey": "sk-ant-..."},
})

doc.build()                              # chunk โ†’ embed โ†’ persist

hits = doc.search("refund policy", top_k=3)

answer = doc.ask("What is the refund policy?")
print(answer.text)

Fully Offline โ€” No API Key Needed

from raglite import Document

doc = Document("./policy.pdf", {
    "embeddings": {"provider": "local"},          # sentence-transformers offline
    "llm":        {"provider": "ollama",          # local Ollama instance
                   "model": "llama3.2",
                   "baseURL": "http://localhost:11434/api"},
})

doc.build()
print(doc.ask("What is the refund policy?").text)

Choose Any LLM at Ask-Time

# Switch LLMs without rebuilding the index โ€” embeddings are reused
for llm in [
    {"provider": "openai",    "model": "gpt-4o",                   "apiKey": "sk-..."},
    {"provider": "anthropic", "model": "claude-3-5-sonnet-20241022","apiKey": "sk-ant-..."},
    {"provider": "google",    "model": "gemini-2.0-flash",         "apiKey": "AI..."},
    {"provider": "groq",      "model": "llama-3.3-70b-versatile",  "apiKey": "gsk_..."},
]:
    answer = doc.ask("Summarize this document", {"llm": llm})
    print(f"[{llm['provider']}] {answer.text[:120]}")

Streaming

for chunk in doc.ask_stream("Explain the introduction"):
    print(chunk, end="", flush=True)

REST API

handle = doc.serve({
    "port": 8085,
    "llm":  {"provider": "openai", "apiKey": "sk-..."},
    "bearerToken": "my-secret-token",
})
print(f"Serving on {handle.url}")

# ... later
handle.close()

Endpoints

Method Path Auth? Description
GET /health โŒ Liveness + index stats
GET /info โœ… Configuration snapshot
POST /search โœ… Semantic search
POST /ask โœ… Question answering

Example curl calls

# Health check (no auth)
curl http://127.0.0.1:8085/health

# Search
curl -X POST http://127.0.0.1:8085/search \
  -H 'Authorization: Bearer my-secret-token' \
  -H 'Content-Type: application/json' \
  -d '{"query": "refund policy", "topK": 3}'

# Ask (non-streaming)
curl -X POST http://127.0.0.1:8085/ask \
  -H 'Authorization: Bearer my-secret-token' \
  -H 'Content-Type: application/json' \
  -d '{"question": "What is the refund policy?"}'

# Ask (streaming)
curl -X POST http://127.0.0.1:8085/ask \
  -H 'Authorization: Bearer my-secret-token' \
  -H 'Content-Type: application/json' \
  -d '{"question": "Summarize the document", "stream": true}'

CLI

# Index a document
raglite index ./policy.pdf --embed-provider local

# Semantic search
raglite search ./policy.pdf "refund policy" --top-k 5

# Ask a question (streaming)
raglite ask ./policy.pdf "What is the refund policy?" \
  --llm-provider openai --llm-key $OPENAI_API_KEY --stream

# Serve a REST API
raglite serve ./policy.pdf \
  --llm-provider openai --llm-key $OPENAI_API_KEY \
  --port 8085 --token $RAGLITE_TOKEN

Supported Providers

LLMs

Provider provider key Default model
OpenAI openai gpt-4o-mini
Anthropic anthropic claude-3-5-sonnet-20241022
Google google gemini-2.0-flash
Mistral mistral mistral-large-latest
Cohere cohere command-r-plus
Groq groq llama-3.3-70b-versatile
xAI (Grok) xai grok-2-latest
Ollama (local) ollama llama3.2

Embeddings

Provider provider key Default model
OpenAI openai text-embedding-3-small
Google google text-embedding-004
Mistral mistral mistral-embed
Cohere cohere embed-english-v3.0
Voyage voyage voyage-3
Ollama (local) ollama nomic-embed-text
Local (offline) local all-MiniLM-L6-v2

Configuration Reference

Document("./policy.pdf", {
    # Chunking
    "chunkSize":      500,          # words per chunk (default: 500)
    "overlap":        50,           # overlapping words between chunks (default: 50)

    # Retrieval
    "topK":           5,            # default results returned (default: 5)
    "scoreThreshold": 0.0,          # minimum cosine similarity (0..1, default: 0)

    # Storage
    "storeDir":       ".raglite",   # where indexes are persisted (default: .raglite)

    # Providers
    "embeddings": {"provider": "local"},
    "llm":        {"provider": "openai", "model": "gpt-4o-mini", "apiKey": "sk-..."},

    # Logging
    "logLevel":   "info",           # "silent" | "info" | "debug" (default: info)
})

How Caching Works

Every build() call fingerprints the source file with a SHA-256 content hash and persists it alongside the vectors. The cached index is reused only if all of the following match the stored index:

Factor Triggers rebuild if changed
File content SHA-256 hash differs
Chunk size chunkSize changed
Overlap overlap changed
Embedding provider/model Provider or model string changed
Library version Package version bumped

Pass rebuild=True to build() to force a fresh index regardless.

Each document is stored under .raglite/<sha256-prefix>/, so multiple documents in the same project never overwrite each other.


Advanced Usage

Custom Vector Store

from raglite.vectordb.base import VectorStore

class MyVectorStore(VectorStore):
    # Implement: load, reset, add, search, count,
    #            save_index_metadata, read_index_metadata
    ...

Custom Loader

from raglite.loaders.base import BaseLoader
from raglite.loaders import get_loader

class CsvLoader(BaseLoader):
    def load(self) -> str:
        # read CSV, return string
        ...

Custom Chunker

from raglite.chunking.base import BaseChunker

class SentenceChunker(BaseChunker):
    def split(self, text: str) -> list[str]:
        ...

Direct Embedder Access

from raglite import create_embedder

embedder = create_embedder({"provider": "openai", "apiKey": "sk-..."})
vectors = embedder.embed_documents(["chunk one", "chunk two"])
query_vec = embedder.embed_query("refund policy")

Development

# Clone and set up
git clone <repo>
cd raglite-py

# Create virtual environment
python3.12 -m venv .venv
source .venv/bin/activate    # Windows: .venv\Scripts\activate

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests (76 tests, ~5s, no network required)
pytest

# Run with coverage
pytest --cov=raglite --cov-report=term-missing

# Run examples (uses local offline embeddings)
python examples/basic.py
python examples/multi_provider.py   # requires API keys in env
python examples/serve.py

Test Structure

tests/
โ”œโ”€โ”€ unit/
โ”‚   โ”œโ”€โ”€ test_chunking.py   # RecursiveChunker algorithm
โ”‚   โ”œโ”€โ”€ test_vectordb.py   # MemoryVectorStore (cosine, persistence, isolation)
โ”‚   โ”œโ”€โ”€ test_loaders.py    # TxtLoader, MarkdownLoader, JsonLoader
โ”‚   โ”œโ”€โ”€ test_prompt.py     # system/user prompt builders
โ”‚   โ”œโ”€โ”€ test_errors.py     # exception hierarchy
โ”‚   โ”œโ”€โ”€ test_config.py     # config defaults and overrides
โ”‚   โ”œโ”€โ”€ test_hash.py       # SHA-256 file hashing + namespace generation
โ”‚   โ”œโ”€โ”€ test_retriever.py  # Retriever with mocked embedder
โ”‚   โ””โ”€โ”€ test_cli.py        # CLI commands and argument parsing
โ””โ”€โ”€ integration/
    โ”œโ”€โ”€ test_document.py   # build/cache/search lifecycle (mocked embeddings)
    โ”œโ”€โ”€ test_ask.py        # ask/stream with mocked LLM generation
    โ””โ”€โ”€ test_api.py        # FastAPI endpoints via TestClient

License

MIT

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

raglite_toolkit-1.0.1.tar.gz (37.4 kB view details)

Uploaded Source

Built Distribution

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

raglite_toolkit-1.0.1-py3-none-any.whl (34.3 kB view details)

Uploaded Python 3

File details

Details for the file raglite_toolkit-1.0.1.tar.gz.

File metadata

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

File hashes

Hashes for raglite_toolkit-1.0.1.tar.gz
Algorithm Hash digest
SHA256 749eb3d48725d7d71748e5e83a984aeffcbf83995840f62cc6a34f7c86bed14f
MD5 cc3684e1cec4785a3039461029a9eeb5
BLAKE2b-256 12e051fe5fb8e362f02d7df0344cfebe0f1c0eb16b0703726cd88d4f6402b990

See more details on using hashes here.

Provenance

The following attestation bundles were made for raglite_toolkit-1.0.1.tar.gz:

Publisher: publish.yml on creatorpiyush/raglite-py

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

File details

Details for the file raglite_toolkit-1.0.1-py3-none-any.whl.

File metadata

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

File hashes

Hashes for raglite_toolkit-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 aa8f784ffccdcf667661c825f2a1bf28e888fa25907f7f2d1acc6862fa1bcd2a
MD5 5b165f643546834e3b6e3bb7cfedc1dc
BLAKE2b-256 49fc267f486dc39d658077ac9082f3cf37cf0442c608bfad3c2ab22cb997f0c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for raglite_toolkit-1.0.1-py3-none-any.whl:

Publisher: publish.yml on creatorpiyush/raglite-py

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